aboutsummaryrefslogtreecommitdiff
path: root/ntpd
diff options
context:
space:
mode:
authorOllivier Robert <roberto@FreeBSD.org>2013-12-04 21:33:17 +0000
committerOllivier Robert <roberto@FreeBSD.org>2013-12-04 21:33:17 +0000
commit2b45e011ca352ce509bc83ae148230aeee0c7e0d (patch)
treea618007bb41d13153794a598e3d904ace2976324 /ntpd
parent9b5bd0a264b0a21eefac2b929b574c73bd601507 (diff)
downloadsrc-5592cd9e3002995d676cc186b0362f891fead9fc.tar.gz
src-5592cd9e3002995d676cc186b0362f891fead9fc.zip
Virgin import of ntpd 4.2.6p5.vendor/ntp/4.2.6p5
When the series of commits is complete, things like https://cert.litnet.lt/en/docs/ntp-distributed-reflection-dos-attacks should be fixed. PR: bin/148836 (except that we import a newer version) Asked by: Too many MFC after: 2 weeks
Diffstat (limited to 'ntpd')
-rw-r--r--ntpd/Makefile.am282
-rw-r--r--ntpd/Makefile.in1071
-rw-r--r--ntpd/cmd_args.c113
-rw-r--r--ntpd/complete.conf56
-rw-r--r--ntpd/keyword-gen-utd1
-rw-r--r--ntpd/keyword-gen.c663
-rw-r--r--ntpd/ntp_config.c5715
-rw-r--r--ntpd/ntp_control.c1602
-rw-r--r--ntpd/ntp_crypto.c3006
-rw-r--r--ntpd/ntp_data_structures.c199
-rw-r--r--ntpd/ntp_filegen.c452
-rw-r--r--ntpd/ntp_intres.c407
-rw-r--r--ntpd/ntp_io.c4481
-rw-r--r--ntpd/ntp_keyword.h929
-rw-r--r--ntpd/ntp_loopfilter.c723
-rw-r--r--ntpd/ntp_monitor.c164
-rw-r--r--ntpd/ntp_parser.c3630
-rw-r--r--ntpd/ntp_parser.h407
-rw-r--r--ntpd/ntp_parser.y1283
-rw-r--r--ntpd/ntp_peer.c919
-rw-r--r--ntpd/ntp_proto.c3280
-rw-r--r--ntpd/ntp_refclock.c443
-rw-r--r--ntpd/ntp_request.c1146
-rw-r--r--ntpd/ntp_restrict.c921
-rw-r--r--ntpd/ntp_scanner.c659
-rw-r--r--ntpd/ntp_scanner.h132
-rw-r--r--ntpd/ntp_signd.c239
-rw-r--r--ntpd/ntp_timer.c198
-rw-r--r--ntpd/ntp_util.c816
-rw-r--r--ntpd/ntpd-opts.c623
-rw-r--r--ntpd/ntpd-opts.h227
-rw-r--r--ntpd/ntpd-opts.texi456
-rw-r--r--ntpd/ntpd.193
-rw-r--r--ntpd/ntpd.c416
-rw-r--r--ntpd/ntpdbase-opts.def200
-rw-r--r--ntpd/ntpdsim-opts.c1262
-rw-r--r--ntpd/ntpdsim-opts.def15
-rw-r--r--ntpd/ntpdsim-opts.h422
-rw-r--r--ntpd/ntpdsim-opts.menu1
-rw-r--r--ntpd/ntpdsim-opts.texi568
-rw-r--r--ntpd/ntpdsim.1357
-rw-r--r--ntpd/ntpsim.c837
-rw-r--r--ntpd/refclock_acts.c77
-rw-r--r--ntpd/refclock_arbiter.c69
-rw-r--r--ntpd/refclock_arc.c351
-rw-r--r--ntpd/refclock_as2201.c27
-rw-r--r--ntpd/refclock_atom.c402
-rw-r--r--ntpd/refclock_bancomm.c168
-rw-r--r--ntpd/refclock_chronolog.c30
-rw-r--r--ntpd/refclock_chu.c699
-rw-r--r--ntpd/refclock_conf.c8
-rw-r--r--ntpd/refclock_datum.c24
-rw-r--r--ntpd/refclock_dumbclock.c74
-rw-r--r--ntpd/refclock_fg.c10
-rw-r--r--ntpd/refclock_gpsvme.c21
-rw-r--r--ntpd/refclock_heath.c18
-rw-r--r--ntpd/refclock_hopfpci.c44
-rw-r--r--ntpd/refclock_hopfser.c46
-rw-r--r--ntpd/refclock_hpgps.c44
-rw-r--r--ntpd/refclock_irig.c800
-rw-r--r--ntpd/refclock_jjy.c960
-rw-r--r--ntpd/refclock_jupiter.c54
-rw-r--r--ntpd/refclock_leitch.c40
-rw-r--r--ntpd/refclock_local.c88
-rw-r--r--ntpd/refclock_msfees.c33
-rw-r--r--ntpd/refclock_mx4200.c81
-rw-r--r--ntpd/refclock_neoclock4x.c55
-rw-r--r--ntpd/refclock_nmea.c1317
-rw-r--r--ntpd/refclock_oncore.c1432
-rw-r--r--ntpd/refclock_palisade.c977
-rw-r--r--ntpd/refclock_palisade.h61
-rw-r--r--ntpd/refclock_parse.c361
-rw-r--r--ntpd/refclock_pcf.c12
-rw-r--r--ntpd/refclock_pst.c26
-rw-r--r--ntpd/refclock_ripencc.c3533
-rw-r--r--ntpd/refclock_shm.c215
-rw-r--r--ntpd/refclock_tpro.c33
-rw-r--r--ntpd/refclock_trak.c17
-rw-r--r--ntpd/refclock_true.c33
-rw-r--r--ntpd/refclock_tt560.c6
-rw-r--r--ntpd/refclock_ulink.c8
-rw-r--r--ntpd/refclock_wwv.c301
-rw-r--r--ntpd/refclock_wwvb.c219
-rw-r--r--ntpd/refclock_zyfer.c8
84 files changed, 32221 insertions, 19975 deletions
diff --git a/ntpd/Makefile.am b/ntpd/Makefile.am
index 6896b4564b89..144371aaa8fa 100644
--- a/ntpd/Makefile.am
+++ b/ntpd/Makefile.am
@@ -1,108 +1,278 @@
-AUTOMAKE_OPTIONS= ../util/ansi2knr
-
-bindir= ${exec_prefix}/${BINSUBDIR}
+NULL=
+AUTOMAKE_OPTIONS=
+if NTP_BINSUBDIR_IS_BIN
bin_PROGRAMS= ntpd @MAKE_NTPDSIM@
+else
+sbin_PROGRAMS= ntpd @MAKE_NTPDSIM@
+endif
noinst_LIBRARIES= libntpd.a
-AM_CPPFLAGS= -I$(top_srcdir)/include -I../include $(LIBOPTS_CFLAGS)
+AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \
+ -I$(top_srcdir)/lib/isc/nothreads/include \
+ -I$(top_srcdir)/lib/isc/unix/include $(LIBOPTS_CFLAGS)
+
# LDADD might need RESLIB and ADJLIB.
LDADD= version.o libntpd.a @LIBPARSE@
+AM_YFLAGS= -d -t -r all
+
+if SAVECONFIG_ENABLED
+if NTP_CROSSCOMPILE
+CHECK_SAVECONFIG=
+else
+CHECK_SAVECONFIG= check-saveconfig
+endif
+else !SAVECONFIG_ENABLED
+CHECK_SAVECONFIG=
+endif
+
+#
+# VPHACK and VPHACK_AFTER are enabled on non-GNU makes (such as
+# BSD make) to work around issues specific to compiling
+# ntp_parser.y into ntp_parser.h and ntp_parser.c in a vPATH
+# configuration where we would like (for a change) the output
+# files ntp_parser.[ch] to be placed in the source directory,
+# as opposed to the build directory. This allows a single
+# host of a flock configured with Bison to update ntp_parser.[ch]
+# used by the rest.
+#
+
+if VPATH_HACK
+VPHACK= vphack
+VPHACK_AFTER= vphack_after
+else
+VPHACK=
+VPHACK_AFTER=
+endif
+
+vphack:
+ test -e ntp_parser.c || ln -s $(srcdir)/ntp_parser.c .
+ test -e ntp_parser.h || ln -s $(srcdir)/ntp_parser.h .
-BUILT_SOURCES= ntpd-opts.c ntpd-opts.h ntpd.1 ntpd-opts.texi ntpd-opts.menu
-man_MANS= ntpd.1
+#
+# ylwrap script which invokes Bison replaces ntp_parser.h
+# symlink with the updated file, when ntp_parser.h changes.
+# vphack_after detects this and copies the updated file to srcdir
+# and re-creates the ntp_parser.h symlink in its place.
+#
-BUILT_SOURCES+= ntpdsim-opts.c ntpdsim-opts.h ntpdsim.1 ntpdsim-opts.texi ntpdsim-opts.menu
-man_MANS+= ntpdsim.1
+vphack_after:
+ test -L ntp_parser.h || ( \
+ mv ntp_parser.h $(srcdir)/ntp_parser.h && \
+ ln -s $(srcdir)/ntp_parser.h . \
+ )
+
+# BUILT_SOURCES which should also be in EXTRA_DIST
+B_S_DIST= \
+ ntpd-opts.c \
+ ntpd-opts.h \
+ $(NULL)
+
+BUILT_SOURCES= \
+ $(VPHACK) \
+ ntp_parser.c \
+ ntp_parser.h \
+ $(VPHACK_AFTER) \
+ $(B_S_DIST) \
+ $(NULL)
+
+man_MANS= $(srcdir)/ntpd.1
+
+# ntpdsim.1 is a remnant along with all the ntpdsim-opts.* files, the
+# simulator currently uses ntpd-opts.[ch]. This also means there is no
+# longer a reason to have ntpdbase-opts.def split off of ntpd-opts.def.
# 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 @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a
-ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ $(LIBOPTS_LDADD)
+ntpd_LDADD = $(LDADD) $(LIBOPTS_LDADD) ../libntp/libntp.a -lm @LCRYPTO@ @LSCF@
+ntpdsim_LDADD = $(LDADD) $(LIBOPTS_LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ @LSCF@
ntpdsim_CFLAGS = $(CFLAGS) -DSIM
check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
-DISTCLEANFILES = .version version.c
-EXTRA_DIST = ntpd-opts.def ntpdbase-opts.def ntpdsim-opts.def \
+keyword_gen_LDADD = ../libntp/libntp.a # we don't want $(LDADD) here
+
+DISTCLEANFILES = \
+ keyword-gen \
+ .version \
+ version.c \
+ $(NULL)
+
+CLEANFILES = \
+ check-saveconfig \
+ compsave.conf \
+ k-g-u-submake \
+ $(NULL)
+
+EXTRA_DIST = \
+ complete.conf \
+ keyword-gen-utd \
+ ntpd.1 \
+ ntpd-opts.def \
+ ntpd-opts.menu \
+ ntpd-opts.texi \
+ ntpdbase-opts.def \
refclock_msfees.c \
refclock_trak.c \
- $(BUILT_SOURCES)
+ $(B_S_DIST) \
+ $(NULL)
+
ETAGS_ARGS = Makefile.am
### Y2Kfixes
check_PROGRAMS = @MAKE_CHECK_Y2K@
-EXTRA_PROGRAMS = check_y2k ntpdsim
-run_ag = cd $(srcdir) && autogen -L ../include --writable
-std_def_list= $(top_srcdir)/include/debug-opt.def \
- $(top_srcdir)/include/autogen-version.def \
+EXTRA_PROGRAMS = check_y2k ntpdsim keyword-gen
+noinst_DATA = $(srcdir)/ntpd-opts.texi $(srcdir)/ntpd-opts.menu
+run_ag= cd $(srcdir) && env PATH="$(abs_builddir):$(PATH)" \
+ autogen -L ../include --writable
+std_def_list= $(top_srcdir)/include/autogen-version.def \
$(top_srcdir)/include/copyright.def \
$(top_srcdir)/include/version.def
-check-local: @MAKE_CHECK_Y2K@
+check-local: @MAKE_CHECK_Y2K@ $(CHECK_SAVECONFIG)
test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
-# SIM: cmd_args.c ntp_config.c ntp_io.c ntpd.c + ntpsim.c (include/ntpsim.h)
-# ntp_resolver.c is presently unused...
-ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c ntpd-opts.c ntpd-opts.h
-ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c ntpdsim-opts.c ntpdsim-opts.h
-libntpd_a_SOURCES = jupiter.h ntp_control.c \
- ntp_crypto.c ntp_filegen.c \
- ntp_intres.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \
- ntp_proto.c ntp_refclock.c ntp_request.c \
- ntp_restrict.c ntp_timer.c ntp_util.c \
- ppsapi_timepps.h \
- refclock_acts.c refclock_arbiter.c refclock_arc.c refclock_as2201.c \
- refclock_atom.c refclock_bancomm.c refclock_chronolog.c \
- refclock_chu.c refclock_conf.c refclock_datum.c refclock_dumbclock.c \
- refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
- refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
- refclock_jupiter.c refclock_leitch.c refclock_local.c \
- refclock_mx4200.c refclock_neoclock4x.c \
- refclock_nmea.c refclock_oncore.c refclock_palisade.c \
- refclock_palisade.h refclock_parse.c \
- refclock_pcf.c refclock_pst.c refclock_ripencc.c refclock_shm.c \
- refclock_tpro.c refclock_true.c refclock_tt560.c \
- refclock_ulink.c refclock_wwv.c refclock_wwvb.c \
- refclock_zyfer.c
+ntpd_SOURCES = \
+ cmd_args.c \
+ ntp_config.c \
+ ntp_data_structures.c \
+ ntp_keyword.h \
+ ntp_io.c \
+ ntp_parser.y \
+ ntp_scanner.c \
+ ntp_scanner.h \
+ ntpd.c \
+ ntpd-opts.c \
+ ntpd-opts.h \
+ $(NULL)
+
+ntpdsim_SOURCES = \
+ $(ntpd_SOURCES) \
+ ntpsim.c \
+ $(NULL)
+
+# libntpd_a_SOURCES do not use #ifdef SIM
+
+libntpd_a_SOURCES = \
+ jupiter.h \
+ ntp_control.c \
+ ntp_crypto.c \
+ ntp_filegen.c \
+ ntp_intres.c \
+ ntp_loopfilter.c \
+ ntp_monitor.c \
+ ntp_peer.c \
+ ntp_proto.c \
+ ntp_refclock.c \
+ ntp_request.c \
+ ntp_restrict.c \
+ ntp_signd.c \
+ ntp_timer.c \
+ ntp_util.c \
+ ppsapi_timepps.h \
+ refclock_acts.c \
+ refclock_arbiter.c \
+ refclock_arc.c \
+ refclock_as2201.c \
+ refclock_atom.c \
+ refclock_bancomm.c \
+ refclock_chronolog.c \
+ refclock_chu.c \
+ refclock_conf.c \
+ refclock_datum.c \
+ refclock_dumbclock.c \
+ refclock_fg.c \
+ refclock_gpsvme.c \
+ refclock_heath.c \
+ refclock_hopfser.c \
+ refclock_hopfpci.c \
+ refclock_hpgps.c \
+ refclock_irig.c \
+ refclock_jjy.c \
+ refclock_jupiter.c \
+ refclock_leitch.c \
+ refclock_local.c \
+ refclock_mx4200.c \
+ refclock_neoclock4x.c \
+ refclock_nmea.c \
+ refclock_oncore.c \
+ refclock_palisade.c \
+ refclock_palisade.h \
+ refclock_parse.c \
+ refclock_pcf.c \
+ refclock_pst.c \
+ refclock_ripencc.c \
+ refclock_shm.c \
+ refclock_tpro.c \
+ refclock_true.c \
+ refclock_tt560.c \
+ refclock_ulink.c \
+ refclock_wwv.c \
+ refclock_wwvb.c \
+ refclock_zyfer.c \
+ $(NULL)
+
+k-g-u-submake: keyword-gen
+ ./keyword-gen $(srcdir)/ntp_parser.h > k-g.out
+ @grep -v diff_ignore_line < k-g.out > cmp1
+ @grep -v diff_ignore_line < $(srcdir)/ntp_keyword.h > cmp2
+ @cmp cmp1 cmp2 > /dev/null || \
+ { mv -f k-g.out $(srcdir)/ntp_keyword.h && \
+ echo 'Generated changed ntp_keyword.h.' ;}
+ @[ ! -f k-g.out ] || \
+ { rm k-g.out && echo 'ntp_keyword.h is up to date.' ;}
+ @rm cmp1 cmp2
+ @echo 'keyword-gen and ntp_keyword.h are up to date.' > $@
+
+$(srcdir)/keyword-gen-utd: $(srcdir)/keyword-gen.c $(srcdir)/ntp_parser.h
+ $(MAKE) k-g-u-submake # avoid explicit dependency
+ grep diff_ignore_line $(srcdir)/ntp_keyword.h > k-g-u
+ mv -f k-g-u $@
+
+$(srcdir)/ntp_keyword.h: $(srcdir)/keyword-gen-utd
+ @: do-nothing action to avoid default SCCS get
+ @: .h updated if needed by k-g-u-submake rule
$(srcdir)/ntpd-opts.h: $(srcdir)/ntpd-opts.c
+ @: do-nothing action to avoid default SCCS get, .h built with .c
+
$(srcdir)/ntpd-opts.c: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
$(run_ag) ntpd-opts.def
$(srcdir)/ntpd.1: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
$(run_ag) -Tagman1.tpl -bntpd ntpd-opts.def
-$(srcdir)/ntpd-opts.texi $(srcdir)/ntpd-opts.menu: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+$(srcdir)/ntpd-opts.menu: $(srcdir)/ntpd-opts.texi
+ @: do-nothing action to avoid default SCCS get, .menu built with .texi
+
+$(srcdir)/ntpd-opts.texi: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
$(run_ag) -Taginfo.tpl -DLEVEL=section ntpd-opts.def
+ $(top_srcdir)/scripts/check--help $@
-$(srcdir)/ntpdsim-opts.h: $(srcdir)/ntpdsim-opts.c
-$(srcdir)/ntpdsim-opts.c: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
- $(run_ag) ntpdsim-opts.def
+$(PROGRAMS): $(LDADD)
-$(srcdir)/ntpdsim.1: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
- $(run_ag) -Tagman1.tpl -bntpdsim ntpdsim-opts.def
+compsave.conf: ntpd $(srcdir)/complete.conf
+ ./ntpd --configfile $(srcdir)/complete.conf --saveconfigquit $@
-$(srcdir)/ntpdsim-opts.texi $(srcdir)/ntpdsim-opts.menu: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
- $(run_ag) -Taginfo.tpl -DLEVEL=section ntpdsim-opts.def
+check-saveconfig: $(srcdir)/complete.conf compsave.conf
+ cmp $(srcdir)/complete.conf compsave.conf && echo stamp > $@
-$(PROGRAMS): $(LDADD)
+../libopts/libopts.la:
+ cd ../libopts && $(MAKE) libopts.la
../libntp/libntp.a:
cd ../libntp && $(MAKE) libntp.a
-../libntp/libntpsim.a:
- cd ../libntp && $(MAKE) libntpsim.a
-
../libparse/libparse.a:
- cd ../libparse && $(MAKE)
+ cd ../libparse && $(MAKE) libparse.a
-$(top_srcdir)/version :
+$(top_srcdir)/version:
cd $(top_srcdir) && $(MAKE) version
version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ Makefile $(top_srcdir)/version
env CSET=`cat $(top_srcdir)/version` $(top_builddir)/scripts/mkver ntpd
$(COMPILE) -c version.c
-include ../bincheck.mf
+include $(top_srcdir)/bincheck.mf
+include $(top_srcdir)/depsver.mf
diff --git a/ntpd/Makefile.in b/ntpd/Makefile.in
index f92b31fa3b72..1a5c03bf64a1 100644
--- a/ntpd/Makefile.in
+++ b/ntpd/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -20,6 +20,7 @@
# subdir to warn folks if there is another version there.
+
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
@@ -39,16 +40,25 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-ANSI2KNR = ../util/ansi2knr
-bin_PROGRAMS = ntpd$(EXEEXT) @MAKE_NTPDSIM@
-EXTRA_PROGRAMS = check_y2k$(EXEEXT) ntpdsim$(EXEEXT)
-DIST_COMMON = $(srcdir)/../bincheck.mf $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in
+@NTP_BINSUBDIR_IS_BIN_TRUE@bin_PROGRAMS = ntpd$(EXEEXT) @MAKE_NTPDSIM@
+@NTP_BINSUBDIR_IS_BIN_FALSE@sbin_PROGRAMS = ntpd$(EXEEXT) \
+@NTP_BINSUBDIR_IS_BIN_FALSE@ @MAKE_NTPDSIM@ $(am__empty)
+EXTRA_PROGRAMS = check_y2k$(EXEEXT) ntpdsim$(EXEEXT) \
+ keyword-gen$(EXEEXT)
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/bincheck.mf $(top_srcdir)/depsver.mf \
+ ntp_parser.c ntp_parser.h
subdir = ntpd
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/libopts/m4/libopts.m4 \
- $(top_srcdir)/m4/define_dir.m4 \
- $(top_srcdir)/m4/hs_ulong_const.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/sntp/libopts/m4/libopts.m4 \
+ $(top_srcdir)/m4/define_dir.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/ntp_cacheversion.m4 \
+ $(top_srcdir)/m4/ntp_dir_sep.m4 \
+ $(top_srcdir)/m4/ntp_lineeditlibs.m4 \
+ $(top_srcdir)/m4/ntp_openssl.m4 \
+ $(top_srcdir)/m4/ntp_vpathhack.m4 \
$(top_srcdir)/m4/os_cflags.m4 $(top_srcdir)/version.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -61,53 +71,63 @@ LIBRARIES = $(noinst_LIBRARIES)
ARFLAGS = cru
libntpd_a_AR = $(AR) $(ARFLAGS)
libntpd_a_LIBADD =
-am_libntpd_a_OBJECTS = ntp_control$U.$(OBJEXT) ntp_crypto$U.$(OBJEXT) \
- ntp_filegen$U.$(OBJEXT) ntp_intres$U.$(OBJEXT) \
- ntp_loopfilter$U.$(OBJEXT) ntp_monitor$U.$(OBJEXT) \
- ntp_peer$U.$(OBJEXT) ntp_proto$U.$(OBJEXT) \
- ntp_refclock$U.$(OBJEXT) ntp_request$U.$(OBJEXT) \
- ntp_restrict$U.$(OBJEXT) ntp_timer$U.$(OBJEXT) \
- ntp_util$U.$(OBJEXT) refclock_acts$U.$(OBJEXT) \
- refclock_arbiter$U.$(OBJEXT) refclock_arc$U.$(OBJEXT) \
- refclock_as2201$U.$(OBJEXT) refclock_atom$U.$(OBJEXT) \
- refclock_bancomm$U.$(OBJEXT) refclock_chronolog$U.$(OBJEXT) \
- refclock_chu$U.$(OBJEXT) refclock_conf$U.$(OBJEXT) \
- refclock_datum$U.$(OBJEXT) refclock_dumbclock$U.$(OBJEXT) \
- refclock_fg$U.$(OBJEXT) refclock_gpsvme$U.$(OBJEXT) \
- refclock_heath$U.$(OBJEXT) refclock_hopfser$U.$(OBJEXT) \
- refclock_hopfpci$U.$(OBJEXT) refclock_hpgps$U.$(OBJEXT) \
- refclock_irig$U.$(OBJEXT) refclock_jjy$U.$(OBJEXT) \
- refclock_jupiter$U.$(OBJEXT) refclock_leitch$U.$(OBJEXT) \
- refclock_local$U.$(OBJEXT) refclock_mx4200$U.$(OBJEXT) \
- refclock_neoclock4x$U.$(OBJEXT) refclock_nmea$U.$(OBJEXT) \
- refclock_oncore$U.$(OBJEXT) refclock_palisade$U.$(OBJEXT) \
- refclock_parse$U.$(OBJEXT) refclock_pcf$U.$(OBJEXT) \
- refclock_pst$U.$(OBJEXT) refclock_ripencc$U.$(OBJEXT) \
- refclock_shm$U.$(OBJEXT) refclock_tpro$U.$(OBJEXT) \
- refclock_true$U.$(OBJEXT) refclock_tt560$U.$(OBJEXT) \
- refclock_ulink$U.$(OBJEXT) refclock_wwv$U.$(OBJEXT) \
- refclock_wwvb$U.$(OBJEXT) refclock_zyfer$U.$(OBJEXT)
+am__objects_1 =
+am_libntpd_a_OBJECTS = ntp_control.$(OBJEXT) ntp_crypto.$(OBJEXT) \
+ ntp_filegen.$(OBJEXT) ntp_intres.$(OBJEXT) \
+ ntp_loopfilter.$(OBJEXT) ntp_monitor.$(OBJEXT) \
+ ntp_peer.$(OBJEXT) ntp_proto.$(OBJEXT) ntp_refclock.$(OBJEXT) \
+ ntp_request.$(OBJEXT) ntp_restrict.$(OBJEXT) \
+ ntp_signd.$(OBJEXT) ntp_timer.$(OBJEXT) ntp_util.$(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_hopfser.$(OBJEXT) refclock_hopfpci.$(OBJEXT) \
+ refclock_hpgps.$(OBJEXT) refclock_irig.$(OBJEXT) \
+ refclock_jjy.$(OBJEXT) refclock_jupiter.$(OBJEXT) \
+ refclock_leitch.$(OBJEXT) refclock_local.$(OBJEXT) \
+ refclock_mx4200.$(OBJEXT) refclock_neoclock4x.$(OBJEXT) \
+ refclock_nmea.$(OBJEXT) refclock_oncore.$(OBJEXT) \
+ refclock_palisade.$(OBJEXT) refclock_parse.$(OBJEXT) \
+ refclock_pcf.$(OBJEXT) refclock_pst.$(OBJEXT) \
+ refclock_ripencc.$(OBJEXT) refclock_shm.$(OBJEXT) \
+ refclock_tpro.$(OBJEXT) refclock_true.$(OBJEXT) \
+ refclock_tt560.$(OBJEXT) refclock_ulink.$(OBJEXT) \
+ refclock_wwv.$(OBJEXT) refclock_wwvb.$(OBJEXT) \
+ refclock_zyfer.$(OBJEXT) $(am__objects_1)
libntpd_a_OBJECTS = $(am_libntpd_a_OBJECTS)
-am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
-PROGRAMS = $(bin_PROGRAMS)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
+ "$(DESTDIR)$(man1dir)"
+PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
check_y2k_SOURCES = check_y2k.c
-check_y2k_OBJECTS = check_y2k$U.$(OBJEXT)
+check_y2k_OBJECTS = check_y2k.$(OBJEXT)
am__DEPENDENCIES_1 = version.o libntpd.a
check_y2k_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libntp/libntp.a
-am_ntpd_OBJECTS = cmd_args$U.$(OBJEXT) ntp_config$U.$(OBJEXT) \
- ntp_io$U.$(OBJEXT) ntpd$U.$(OBJEXT) ntpd-opts$U.$(OBJEXT)
+keyword_gen_SOURCES = keyword-gen.c
+keyword_gen_OBJECTS = keyword-gen.$(OBJEXT)
+keyword_gen_DEPENDENCIES = ../libntp/libntp.a
+am_ntpd_OBJECTS = cmd_args.$(OBJEXT) ntp_config.$(OBJEXT) \
+ ntp_data_structures.$(OBJEXT) ntp_io.$(OBJEXT) \
+ ntp_parser.$(OBJEXT) ntp_scanner.$(OBJEXT) ntpd.$(OBJEXT) \
+ ntpd-opts.$(OBJEXT) $(am__objects_1)
ntpd_OBJECTS = $(am_ntpd_OBJECTS)
am__DEPENDENCIES_2 =
ntpd_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
../libntp/libntp.a
-am__objects_1 = ntpdsim-cmd_args$U.$(OBJEXT) \
- ntpdsim-ntp_config$U.$(OBJEXT) ntpdsim-ntp_io$U.$(OBJEXT) \
- ntpdsim-ntpd$U.$(OBJEXT) ntpdsim-ntpd-opts$U.$(OBJEXT)
-am_ntpdsim_OBJECTS = $(am__objects_1) ntpdsim-ntpsim$U.$(OBJEXT) \
- ntpdsim-ntpdsim-opts$U.$(OBJEXT)
+am__objects_2 = ntpdsim-cmd_args.$(OBJEXT) \
+ ntpdsim-ntp_config.$(OBJEXT) \
+ ntpdsim-ntp_data_structures.$(OBJEXT) ntpdsim-ntp_io.$(OBJEXT) \
+ ntpdsim-ntp_parser.$(OBJEXT) ntpdsim-ntp_scanner.$(OBJEXT) \
+ ntpdsim-ntpd.$(OBJEXT) ntpdsim-ntpd-opts.$(OBJEXT) \
+ $(am__objects_1)
+am_ntpdsim_OBJECTS = $(am__objects_2) ntpdsim-ntpsim.$(OBJEXT) \
+ $(am__objects_1)
ntpdsim_OBJECTS = $(am_ntpdsim_OBJECTS)
-ntpdsim_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libntp/libntpsim.a \
- $(am__DEPENDENCIES_2)
+ntpdsim_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
+ ../libntp/libntpsim.a
ntpdsim_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(ntpdsim_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
@@ -124,10 +144,14 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) \
- $(ntpdsim_SOURCES)
-DIST_SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) \
- $(ntpdsim_SOURCES)
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+YLWRAP = $(top_srcdir)/ylwrap
+SOURCES = $(libntpd_a_SOURCES) check_y2k.c keyword-gen.c \
+ $(ntpd_SOURCES) $(ntpdsim_SOURCES)
+DIST_SOURCES = $(libntpd_a_SOURCES) check_y2k.c keyword-gen.c \
+ $(ntpd_SOURCES) $(ntpdsim_SOURCES)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -152,13 +176,13 @@ am__base_list = \
man1dir = $(mandir)/man1
NROFF = nroff
MANS = $(man_MANS)
+DATA = $(noinst_DATA)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
-ARLIB_DIR = @ARLIB_DIR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@@ -175,14 +199,18 @@ CYGPATH_W = @CYGPATH_W@
DCFD = @DCFD@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
-ECHO = @ECHO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
+EDITLINE_LIBS = @EDITLINE_LIBS@
EF_LIBS = @EF_LIBS@
EF_PROGS = @EF_PROGS@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
+FGREP = @FGREP@
GREP = @GREP@
HAVE_INLINE = @HAVE_INLINE@
INSTALL = @INSTALL@
@@ -191,6 +219,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCRYPTO = @LCRYPTO@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBOPTS_CFLAGS = @LIBOPTS_CFLAGS@
@@ -199,6 +228,7 @@ LIBOPTS_LDADD = @LIBOPTS_LDADD@
LIBPARSE = @LIBPARSE@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
LN_S = @LN_S@
LSCF = @LSCF@
LTLIBOBJS = @LTLIBOBJS@
@@ -210,15 +240,22 @@ MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@
MAKE_LIBPARSE = @MAKE_LIBPARSE@
MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
MAKE_NTPDSIM = @MAKE_NTPDSIM@
+MAKE_NTPSNMPD = @MAKE_NTPSNMPD@
MAKE_NTPTIME = @MAKE_NTPTIME@
MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
MAKE_TICKADJ = @MAKE_TICKADJ@
MAKE_TIMETRIM = @MAKE_TIMETRIM@
+MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL = @OPENSSL@
OPENSSL_INC = @OPENSSL_INC@
OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -226,29 +263,38 @@ PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_NET_SNMP_CONFIG = @PATH_NET_SNMP_CONFIG@
PATH_PERL = @PATH_PERL@
PATH_SEPARATOR = @PATH_SEPARATOR@
PATH_SH = @PATH_SH@
+PATH_TEST = @PATH_TEST@
+POSIX_SHELL = @POSIX_SHELL@
PROPDELAY = @PROPDELAY@
RANLIB = @RANLIB@
-READLINE_LIBS = @READLINE_LIBS@
+SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_CPPFLAGS = @SNMP_CPPFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
STRIP = @STRIP@
TESTDCF = @TESTDCF@
-U = @U@
VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
-bindir = ${exec_prefix}/${BINSUBDIR}
+bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
@@ -289,71 +335,178 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AUTOMAKE_OPTIONS = ../util/ansi2knr
+NULL =
+AUTOMAKE_OPTIONS =
noinst_LIBRARIES = libntpd.a
-AM_CPPFLAGS = -I$(top_srcdir)/include -I../include $(LIBOPTS_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \
+ -I$(top_srcdir)/lib/isc/nothreads/include \
+ -I$(top_srcdir)/lib/isc/unix/include $(LIBOPTS_CFLAGS)
+
+
# LDADD might need RESLIB and ADJLIB.
LDADD = version.o libntpd.a @LIBPARSE@
-BUILT_SOURCES = ntpd-opts.c ntpd-opts.h ntpd.1 ntpd-opts.texi \
- ntpd-opts.menu ntpdsim-opts.c ntpdsim-opts.h ntpdsim.1 \
- ntpdsim-opts.texi ntpdsim-opts.menu
-man_MANS = ntpd.1 ntpdsim.1
+AM_YFLAGS = -d -t -r all
+@NTP_CROSSCOMPILE_FALSE@@SAVECONFIG_ENABLED_TRUE@CHECK_SAVECONFIG = check-saveconfig
+@NTP_CROSSCOMPILE_TRUE@@SAVECONFIG_ENABLED_TRUE@CHECK_SAVECONFIG =
+@SAVECONFIG_ENABLED_FALSE@CHECK_SAVECONFIG =
+@VPATH_HACK_FALSE@VPHACK =
+
+#
+# VPHACK and VPHACK_AFTER are enabled on non-GNU makes (such as
+# BSD make) to work around issues specific to compiling
+# ntp_parser.y into ntp_parser.h and ntp_parser.c in a vPATH
+# configuration where we would like (for a change) the output
+# files ntp_parser.[ch] to be placed in the source directory,
+# as opposed to the build directory. This allows a single
+# host of a flock configured with Bison to update ntp_parser.[ch]
+# used by the rest.
+#
+@VPATH_HACK_TRUE@VPHACK = vphack
+@VPATH_HACK_FALSE@VPHACK_AFTER =
+@VPATH_HACK_TRUE@VPHACK_AFTER = vphack_after
+
+# BUILT_SOURCES which should also be in EXTRA_DIST
+B_S_DIST = \
+ ntpd-opts.c \
+ ntpd-opts.h \
+ $(NULL)
+
+BUILT_SOURCES = $(VPHACK) ntp_parser.c ntp_parser.h $(VPHACK_AFTER) \
+ $(B_S_DIST) $(NULL) .deps-ver
+man_MANS = $(srcdir)/ntpd.1
+
+# ntpdsim.1 is a remnant along with all the ntpdsim-opts.* files, the
+# simulator currently uses ntpd-opts.[ch]. This also means there is no
+# longer a reason to have ntpdbase-opts.def split off of ntpd-opts.def.
# 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 @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a
-ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ $(LIBOPTS_LDADD)
+ntpd_LDADD = $(LDADD) $(LIBOPTS_LDADD) ../libntp/libntp.a -lm @LCRYPTO@ @LSCF@
+ntpdsim_LDADD = $(LDADD) $(LIBOPTS_LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ @LSCF@
ntpdsim_CFLAGS = $(CFLAGS) -DSIM
check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
-DISTCLEANFILES = .version version.c
-EXTRA_DIST = ntpd-opts.def ntpdbase-opts.def ntpdsim-opts.def \
+keyword_gen_LDADD = ../libntp/libntp.a # we don't want $(LDADD) here
+DISTCLEANFILES = \
+ keyword-gen \
+ .version \
+ version.c \
+ $(NULL)
+
+CLEANFILES = check-saveconfig compsave.conf k-g-u-submake $(NULL) \
+ .deps-ver
+EXTRA_DIST = \
+ complete.conf \
+ keyword-gen-utd \
+ ntpd.1 \
+ ntpd-opts.def \
+ ntpd-opts.menu \
+ ntpd-opts.texi \
+ ntpdbase-opts.def \
refclock_msfees.c \
refclock_trak.c \
- $(BUILT_SOURCES)
+ $(B_S_DIST) \
+ $(NULL)
ETAGS_ARGS = Makefile.am
### Y2Kfixes
check_PROGRAMS = @MAKE_CHECK_Y2K@
-run_ag = cd $(srcdir) && autogen -L ../include --writable
-std_def_list = $(top_srcdir)/include/debug-opt.def \
- $(top_srcdir)/include/autogen-version.def \
+noinst_DATA = $(srcdir)/ntpd-opts.texi $(srcdir)/ntpd-opts.menu
+run_ag = cd $(srcdir) && env PATH="$(abs_builddir):$(PATH)" \
+ autogen -L ../include --writable
+
+std_def_list = $(top_srcdir)/include/autogen-version.def \
$(top_srcdir)/include/copyright.def \
$(top_srcdir)/include/version.def
-
-# SIM: cmd_args.c ntp_config.c ntp_io.c ntpd.c + ntpsim.c (include/ntpsim.h)
-# ntp_resolver.c is presently unused...
-ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c ntpd-opts.c ntpd-opts.h
-ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c ntpdsim-opts.c ntpdsim-opts.h
-libntpd_a_SOURCES = jupiter.h ntp_control.c \
- ntp_crypto.c ntp_filegen.c \
- ntp_intres.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \
- ntp_proto.c ntp_refclock.c ntp_request.c \
- ntp_restrict.c ntp_timer.c ntp_util.c \
- ppsapi_timepps.h \
- refclock_acts.c refclock_arbiter.c refclock_arc.c refclock_as2201.c \
- refclock_atom.c refclock_bancomm.c refclock_chronolog.c \
- refclock_chu.c refclock_conf.c refclock_datum.c refclock_dumbclock.c \
- refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
- refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
- refclock_jupiter.c refclock_leitch.c refclock_local.c \
- refclock_mx4200.c refclock_neoclock4x.c \
- refclock_nmea.c refclock_oncore.c refclock_palisade.c \
- refclock_palisade.h refclock_parse.c \
- refclock_pcf.c refclock_pst.c refclock_ripencc.c refclock_shm.c \
- refclock_tpro.c refclock_true.c refclock_tt560.c \
- refclock_ulink.c refclock_wwv.c refclock_wwvb.c \
- refclock_zyfer.c
+ntpd_SOURCES = \
+ cmd_args.c \
+ ntp_config.c \
+ ntp_data_structures.c \
+ ntp_keyword.h \
+ ntp_io.c \
+ ntp_parser.y \
+ ntp_scanner.c \
+ ntp_scanner.h \
+ ntpd.c \
+ ntpd-opts.c \
+ ntpd-opts.h \
+ $(NULL)
+
+ntpdsim_SOURCES = \
+ $(ntpd_SOURCES) \
+ ntpsim.c \
+ $(NULL)
+
+
+# libntpd_a_SOURCES do not use #ifdef SIM
+libntpd_a_SOURCES = \
+ jupiter.h \
+ ntp_control.c \
+ ntp_crypto.c \
+ ntp_filegen.c \
+ ntp_intres.c \
+ ntp_loopfilter.c \
+ ntp_monitor.c \
+ ntp_peer.c \
+ ntp_proto.c \
+ ntp_refclock.c \
+ ntp_request.c \
+ ntp_restrict.c \
+ ntp_signd.c \
+ ntp_timer.c \
+ ntp_util.c \
+ ppsapi_timepps.h \
+ refclock_acts.c \
+ refclock_arbiter.c \
+ refclock_arc.c \
+ refclock_as2201.c \
+ refclock_atom.c \
+ refclock_bancomm.c \
+ refclock_chronolog.c \
+ refclock_chu.c \
+ refclock_conf.c \
+ refclock_datum.c \
+ refclock_dumbclock.c \
+ refclock_fg.c \
+ refclock_gpsvme.c \
+ refclock_heath.c \
+ refclock_hopfser.c \
+ refclock_hopfpci.c \
+ refclock_hpgps.c \
+ refclock_irig.c \
+ refclock_jjy.c \
+ refclock_jupiter.c \
+ refclock_leitch.c \
+ refclock_local.c \
+ refclock_mx4200.c \
+ refclock_neoclock4x.c \
+ refclock_nmea.c \
+ refclock_oncore.c \
+ refclock_palisade.c \
+ refclock_palisade.h \
+ refclock_parse.c \
+ refclock_pcf.c \
+ refclock_pst.c \
+ refclock_ripencc.c \
+ refclock_shm.c \
+ refclock_tpro.c \
+ refclock_true.c \
+ refclock_tt560.c \
+ refclock_ulink.c \
+ refclock_wwv.c \
+ refclock_wwvb.c \
+ refclock_zyfer.c \
+ $(NULL)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../bincheck.mf $(am__configure_deps)
+.SUFFIXES: .c .lo .o .obj .y
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/bincheck.mf $(top_srcdir)/depsver.mf $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -442,9 +595,60 @@ clean-checkPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
check_y2k$(EXEEXT): $(check_y2k_OBJECTS) $(check_y2k_DEPENDENCIES)
@rm -f check_y2k$(EXEEXT)
$(LINK) $(check_y2k_OBJECTS) $(check_y2k_LDADD) $(LIBS)
+keyword-gen$(EXEEXT): $(keyword_gen_OBJECTS) $(keyword_gen_DEPENDENCIES)
+ @rm -f keyword-gen$(EXEEXT)
+ $(LINK) $(keyword_gen_OBJECTS) $(keyword_gen_LDADD) $(LIBS)
+ntp_parser.h: ntp_parser.c
+ @if test ! -f $@; then \
+ rm -f ntp_parser.c; \
+ $(MAKE) $(AM_MAKEFLAGS) ntp_parser.c; \
+ else :; fi
ntpd$(EXEEXT): $(ntpd_OBJECTS) $(ntpd_DEPENDENCIES)
@rm -f ntpd$(EXEEXT)
$(LINK) $(ntpd_OBJECTS) $(ntpd_LDADD) $(LIBS)
@@ -457,77 +661,79 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-../util/ansi2knr:
- $(am__cd) ../util && $(MAKE) $(AM_MAKEFLAGS) ./ansi2knr
-
-mostlyclean-kr:
- -test "$U" = "" || rm -f *_.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_y2k$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd_args$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_config$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_control$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_crypto$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_filegen$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_intres$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_io$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_loopfilter$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_monitor$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_peer$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_proto$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_refclock$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_request$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_restrict$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_timer$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_util$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpd$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpd-opts$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-cmd_args$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_config$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_io$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpd$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpd-opts$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpsim$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_acts$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_arbiter$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_arc$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_as2201$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_atom$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_bancomm$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_chronolog$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_chu$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_conf$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_datum$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_dumbclock$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_fg$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_gpsvme$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_heath$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hopfpci$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hopfser$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hpgps$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_irig$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_jjy$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_jupiter$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_leitch$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_local$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_mx4200$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_neoclock4x$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_nmea$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_oncore$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_palisade$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_parse$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pcf$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pst$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ripencc$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_shm$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tpro$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_true$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tt560$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ulink$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwv$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwvb$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_zyfer$U.Po@am__quote@
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_y2k.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd_args.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyword-gen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_config.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_control.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_crypto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_data_structures.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_filegen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_intres.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_io.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_loopfilter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_monitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_parser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_peer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_proto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_refclock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_request.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_restrict.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_scanner.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_signd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_timer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpd-opts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-cmd_args.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_config.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_data_structures.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_io.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_parser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_scanner.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpd-opts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpsim.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_acts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_arbiter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_arc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_as2201.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_atom.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_bancomm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_chronolog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_chu.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_conf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_datum.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_dumbclock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_fg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_gpsvme.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_heath.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hopfpci.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hopfser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hpgps.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_irig.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_jjy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_jupiter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_leitch.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_local.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_mx4200.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_neoclock4x.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_nmea.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_oncore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_palisade.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pcf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pst.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ripencc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_shm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tpro.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_true.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tt560.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ulink.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwvb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_zyfer.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -550,266 +756,134 @@ mostlyclean-kr:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-ntpdsim-cmd_args$U.o: cmd_args$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-cmd_args$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-cmd_args$U.Tpo -c -o ntpdsim-cmd_args$U.o `test -f 'cmd_args$U.c' || echo '$(srcdir)/'`cmd_args$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-cmd_args$U.Tpo $(DEPDIR)/ntpdsim-cmd_args$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmd_args$U.c' object='ntpdsim-cmd_args$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-cmd_args.o: cmd_args.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-cmd_args.o -MD -MP -MF $(DEPDIR)/ntpdsim-cmd_args.Tpo -c -o ntpdsim-cmd_args.o `test -f 'cmd_args.c' || echo '$(srcdir)/'`cmd_args.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-cmd_args.Tpo $(DEPDIR)/ntpdsim-cmd_args.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmd_args.c' object='ntpdsim-cmd_args.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-cmd_args.o `test -f 'cmd_args.c' || echo '$(srcdir)/'`cmd_args.c
+
+ntpdsim-cmd_args.obj: cmd_args.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-cmd_args.obj -MD -MP -MF $(DEPDIR)/ntpdsim-cmd_args.Tpo -c -o ntpdsim-cmd_args.obj `if test -f 'cmd_args.c'; then $(CYGPATH_W) 'cmd_args.c'; else $(CYGPATH_W) '$(srcdir)/cmd_args.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-cmd_args.Tpo $(DEPDIR)/ntpdsim-cmd_args.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmd_args.c' object='ntpdsim-cmd_args.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-cmd_args$U.o `test -f 'cmd_args$U.c' || echo '$(srcdir)/'`cmd_args$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-cmd_args.obj `if test -f 'cmd_args.c'; then $(CYGPATH_W) 'cmd_args.c'; else $(CYGPATH_W) '$(srcdir)/cmd_args.c'; fi`
-ntpdsim-cmd_args$U.obj: cmd_args$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-cmd_args$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-cmd_args$U.Tpo -c -o ntpdsim-cmd_args$U.obj `if test -f 'cmd_args$U.c'; then $(CYGPATH_W) 'cmd_args$U.c'; else $(CYGPATH_W) '$(srcdir)/cmd_args$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-cmd_args$U.Tpo $(DEPDIR)/ntpdsim-cmd_args$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmd_args$U.c' object='ntpdsim-cmd_args$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_config.o: ntp_config.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_config.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_config.Tpo -c -o ntpdsim-ntp_config.o `test -f 'ntp_config.c' || echo '$(srcdir)/'`ntp_config.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_config.Tpo $(DEPDIR)/ntpdsim-ntp_config.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_config.c' object='ntpdsim-ntp_config.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-cmd_args$U.obj `if test -f 'cmd_args$U.c'; then $(CYGPATH_W) 'cmd_args$U.c'; else $(CYGPATH_W) '$(srcdir)/cmd_args$U.c'; fi`
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_config.o `test -f 'ntp_config.c' || echo '$(srcdir)/'`ntp_config.c
-ntpdsim-ntp_config$U.o: ntp_config$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_config$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_config$U.Tpo -c -o ntpdsim-ntp_config$U.o `test -f 'ntp_config$U.c' || echo '$(srcdir)/'`ntp_config$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_config$U.Tpo $(DEPDIR)/ntpdsim-ntp_config$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_config$U.c' object='ntpdsim-ntp_config$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_config.obj: ntp_config.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_config.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_config.Tpo -c -o ntpdsim-ntp_config.obj `if test -f 'ntp_config.c'; then $(CYGPATH_W) 'ntp_config.c'; else $(CYGPATH_W) '$(srcdir)/ntp_config.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_config.Tpo $(DEPDIR)/ntpdsim-ntp_config.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_config.c' object='ntpdsim-ntp_config.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_config$U.o `test -f 'ntp_config$U.c' || echo '$(srcdir)/'`ntp_config$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_config.obj `if test -f 'ntp_config.c'; then $(CYGPATH_W) 'ntp_config.c'; else $(CYGPATH_W) '$(srcdir)/ntp_config.c'; fi`
-ntpdsim-ntp_config$U.obj: ntp_config$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_config$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_config$U.Tpo -c -o ntpdsim-ntp_config$U.obj `if test -f 'ntp_config$U.c'; then $(CYGPATH_W) 'ntp_config$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_config$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_config$U.Tpo $(DEPDIR)/ntpdsim-ntp_config$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_config$U.c' object='ntpdsim-ntp_config$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_data_structures.o: ntp_data_structures.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_data_structures.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_data_structures.Tpo -c -o ntpdsim-ntp_data_structures.o `test -f 'ntp_data_structures.c' || echo '$(srcdir)/'`ntp_data_structures.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_data_structures.Tpo $(DEPDIR)/ntpdsim-ntp_data_structures.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_data_structures.c' object='ntpdsim-ntp_data_structures.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_config$U.obj `if test -f 'ntp_config$U.c'; then $(CYGPATH_W) 'ntp_config$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_config$U.c'; fi`
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_data_structures.o `test -f 'ntp_data_structures.c' || echo '$(srcdir)/'`ntp_data_structures.c
-ntpdsim-ntp_io$U.o: ntp_io$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_io$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_io$U.Tpo -c -o ntpdsim-ntp_io$U.o `test -f 'ntp_io$U.c' || echo '$(srcdir)/'`ntp_io$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_io$U.Tpo $(DEPDIR)/ntpdsim-ntp_io$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_io$U.c' object='ntpdsim-ntp_io$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_data_structures.obj: ntp_data_structures.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_data_structures.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_data_structures.Tpo -c -o ntpdsim-ntp_data_structures.obj `if test -f 'ntp_data_structures.c'; then $(CYGPATH_W) 'ntp_data_structures.c'; else $(CYGPATH_W) '$(srcdir)/ntp_data_structures.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_data_structures.Tpo $(DEPDIR)/ntpdsim-ntp_data_structures.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_data_structures.c' object='ntpdsim-ntp_data_structures.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_io$U.o `test -f 'ntp_io$U.c' || echo '$(srcdir)/'`ntp_io$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_data_structures.obj `if test -f 'ntp_data_structures.c'; then $(CYGPATH_W) 'ntp_data_structures.c'; else $(CYGPATH_W) '$(srcdir)/ntp_data_structures.c'; fi`
-ntpdsim-ntp_io$U.obj: ntp_io$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_io$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_io$U.Tpo -c -o ntpdsim-ntp_io$U.obj `if test -f 'ntp_io$U.c'; then $(CYGPATH_W) 'ntp_io$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_io$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_io$U.Tpo $(DEPDIR)/ntpdsim-ntp_io$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_io$U.c' object='ntpdsim-ntp_io$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_io.o: ntp_io.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_io.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_io.Tpo -c -o ntpdsim-ntp_io.o `test -f 'ntp_io.c' || echo '$(srcdir)/'`ntp_io.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_io.Tpo $(DEPDIR)/ntpdsim-ntp_io.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_io.c' object='ntpdsim-ntp_io.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_io$U.obj `if test -f 'ntp_io$U.c'; then $(CYGPATH_W) 'ntp_io$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_io$U.c'; fi`
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_io.o `test -f 'ntp_io.c' || echo '$(srcdir)/'`ntp_io.c
-ntpdsim-ntpd$U.o: ntpd$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd$U.Tpo -c -o ntpdsim-ntpd$U.o `test -f 'ntpd$U.c' || echo '$(srcdir)/'`ntpd$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd$U.Tpo $(DEPDIR)/ntpdsim-ntpd$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd$U.c' object='ntpdsim-ntpd$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_io.obj: ntp_io.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_io.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_io.Tpo -c -o ntpdsim-ntp_io.obj `if test -f 'ntp_io.c'; then $(CYGPATH_W) 'ntp_io.c'; else $(CYGPATH_W) '$(srcdir)/ntp_io.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_io.Tpo $(DEPDIR)/ntpdsim-ntp_io.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_io.c' object='ntpdsim-ntp_io.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd$U.o `test -f 'ntpd$U.c' || echo '$(srcdir)/'`ntpd$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_io.obj `if test -f 'ntp_io.c'; then $(CYGPATH_W) 'ntp_io.c'; else $(CYGPATH_W) '$(srcdir)/ntp_io.c'; fi`
-ntpdsim-ntpd$U.obj: ntpd$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd$U.Tpo -c -o ntpdsim-ntpd$U.obj `if test -f 'ntpd$U.c'; then $(CYGPATH_W) 'ntpd$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd$U.Tpo $(DEPDIR)/ntpdsim-ntpd$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd$U.c' object='ntpdsim-ntpd$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_parser.o: ntp_parser.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_parser.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_parser.Tpo -c -o ntpdsim-ntp_parser.o `test -f 'ntp_parser.c' || echo '$(srcdir)/'`ntp_parser.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_parser.Tpo $(DEPDIR)/ntpdsim-ntp_parser.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_parser.c' object='ntpdsim-ntp_parser.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd$U.obj `if test -f 'ntpd$U.c'; then $(CYGPATH_W) 'ntpd$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd$U.c'; fi`
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_parser.o `test -f 'ntp_parser.c' || echo '$(srcdir)/'`ntp_parser.c
-ntpdsim-ntpd-opts$U.o: ntpd-opts$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd-opts$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo -c -o ntpdsim-ntpd-opts$U.o `test -f 'ntpd-opts$U.c' || echo '$(srcdir)/'`ntpd-opts$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo $(DEPDIR)/ntpdsim-ntpd-opts$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd-opts$U.c' object='ntpdsim-ntpd-opts$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_parser.obj: ntp_parser.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_parser.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_parser.Tpo -c -o ntpdsim-ntp_parser.obj `if test -f 'ntp_parser.c'; then $(CYGPATH_W) 'ntp_parser.c'; else $(CYGPATH_W) '$(srcdir)/ntp_parser.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_parser.Tpo $(DEPDIR)/ntpdsim-ntp_parser.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_parser.c' object='ntpdsim-ntp_parser.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd-opts$U.o `test -f 'ntpd-opts$U.c' || echo '$(srcdir)/'`ntpd-opts$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_parser.obj `if test -f 'ntp_parser.c'; then $(CYGPATH_W) 'ntp_parser.c'; else $(CYGPATH_W) '$(srcdir)/ntp_parser.c'; fi`
-ntpdsim-ntpd-opts$U.obj: ntpd-opts$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd-opts$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo -c -o ntpdsim-ntpd-opts$U.obj `if test -f 'ntpd-opts$U.c'; then $(CYGPATH_W) 'ntpd-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd-opts$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo $(DEPDIR)/ntpdsim-ntpd-opts$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd-opts$U.c' object='ntpdsim-ntpd-opts$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_scanner.o: ntp_scanner.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_scanner.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_scanner.Tpo -c -o ntpdsim-ntp_scanner.o `test -f 'ntp_scanner.c' || echo '$(srcdir)/'`ntp_scanner.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_scanner.Tpo $(DEPDIR)/ntpdsim-ntp_scanner.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_scanner.c' object='ntpdsim-ntp_scanner.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd-opts$U.obj `if test -f 'ntpd-opts$U.c'; then $(CYGPATH_W) 'ntpd-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd-opts$U.c'; fi`
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_scanner.o `test -f 'ntp_scanner.c' || echo '$(srcdir)/'`ntp_scanner.c
-ntpdsim-ntpsim$U.o: ntpsim$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpsim$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpsim$U.Tpo -c -o ntpdsim-ntpsim$U.o `test -f 'ntpsim$U.c' || echo '$(srcdir)/'`ntpsim$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpsim$U.Tpo $(DEPDIR)/ntpdsim-ntpsim$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpsim$U.c' object='ntpdsim-ntpsim$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntp_scanner.obj: ntp_scanner.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_scanner.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntp_scanner.Tpo -c -o ntpdsim-ntp_scanner.obj `if test -f 'ntp_scanner.c'; then $(CYGPATH_W) 'ntp_scanner.c'; else $(CYGPATH_W) '$(srcdir)/ntp_scanner.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntp_scanner.Tpo $(DEPDIR)/ntpdsim-ntp_scanner.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_scanner.c' object='ntpdsim-ntp_scanner.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpsim$U.o `test -f 'ntpsim$U.c' || echo '$(srcdir)/'`ntpsim$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_scanner.obj `if test -f 'ntp_scanner.c'; then $(CYGPATH_W) 'ntp_scanner.c'; else $(CYGPATH_W) '$(srcdir)/ntp_scanner.c'; fi`
-ntpdsim-ntpsim$U.obj: ntpsim$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpsim$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpsim$U.Tpo -c -o ntpdsim-ntpsim$U.obj `if test -f 'ntpsim$U.c'; then $(CYGPATH_W) 'ntpsim$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpsim$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpsim$U.Tpo $(DEPDIR)/ntpdsim-ntpsim$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpsim$U.c' object='ntpdsim-ntpsim$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntpd.o: ntpd.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd.Tpo -c -o ntpdsim-ntpd.o `test -f 'ntpd.c' || echo '$(srcdir)/'`ntpd.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd.Tpo $(DEPDIR)/ntpdsim-ntpd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd.c' object='ntpdsim-ntpd.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpsim$U.obj `if test -f 'ntpsim$U.c'; then $(CYGPATH_W) 'ntpsim$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpsim$U.c'; fi`
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd.o `test -f 'ntpd.c' || echo '$(srcdir)/'`ntpd.c
-ntpdsim-ntpdsim-opts$U.o: ntpdsim-opts$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpdsim-opts$U.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo -c -o ntpdsim-ntpdsim-opts$U.o `test -f 'ntpdsim-opts$U.c' || echo '$(srcdir)/'`ntpdsim-opts$U.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo $(DEPDIR)/ntpdsim-ntpdsim-opts$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpdsim-opts$U.c' object='ntpdsim-ntpdsim-opts$U.o' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntpd.obj: ntpd.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd.Tpo -c -o ntpdsim-ntpd.obj `if test -f 'ntpd.c'; then $(CYGPATH_W) 'ntpd.c'; else $(CYGPATH_W) '$(srcdir)/ntpd.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd.Tpo $(DEPDIR)/ntpdsim-ntpd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd.c' object='ntpdsim-ntpd.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpdsim-opts$U.o `test -f 'ntpdsim-opts$U.c' || echo '$(srcdir)/'`ntpdsim-opts$U.c
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd.obj `if test -f 'ntpd.c'; then $(CYGPATH_W) 'ntpd.c'; else $(CYGPATH_W) '$(srcdir)/ntpd.c'; fi`
-ntpdsim-ntpdsim-opts$U.obj: ntpdsim-opts$U.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpdsim-opts$U.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo -c -o ntpdsim-ntpdsim-opts$U.obj `if test -f 'ntpdsim-opts$U.c'; then $(CYGPATH_W) 'ntpdsim-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpdsim-opts$U.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo $(DEPDIR)/ntpdsim-ntpdsim-opts$U.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpdsim-opts$U.c' object='ntpdsim-ntpdsim-opts$U.obj' libtool=no @AMDEPBACKSLASH@
+ntpdsim-ntpd-opts.o: ntpd-opts.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd-opts.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd-opts.Tpo -c -o ntpdsim-ntpd-opts.o `test -f 'ntpd-opts.c' || echo '$(srcdir)/'`ntpd-opts.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd-opts.Tpo $(DEPDIR)/ntpdsim-ntpd-opts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd-opts.c' object='ntpdsim-ntpd-opts.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpdsim-opts$U.obj `if test -f 'ntpdsim-opts$U.c'; then $(CYGPATH_W) 'ntpdsim-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpdsim-opts$U.c'; fi`
-check_y2k_.c: check_y2k.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/check_y2k.c; then echo $(srcdir)/check_y2k.c; else echo check_y2k.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-cmd_args_.c: cmd_args.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/cmd_args.c; then echo $(srcdir)/cmd_args.c; else echo cmd_args.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_config_.c: ntp_config.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_config.c; then echo $(srcdir)/ntp_config.c; else echo ntp_config.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_control_.c: ntp_control.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_control.c; then echo $(srcdir)/ntp_control.c; else echo ntp_control.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_crypto_.c: ntp_crypto.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_crypto.c; then echo $(srcdir)/ntp_crypto.c; else echo ntp_crypto.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_filegen_.c: ntp_filegen.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_filegen.c; then echo $(srcdir)/ntp_filegen.c; else echo ntp_filegen.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_intres_.c: ntp_intres.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_intres.c; then echo $(srcdir)/ntp_intres.c; else echo ntp_intres.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_io_.c: ntp_io.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_io.c; then echo $(srcdir)/ntp_io.c; else echo ntp_io.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_loopfilter_.c: ntp_loopfilter.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_loopfilter.c; then echo $(srcdir)/ntp_loopfilter.c; else echo ntp_loopfilter.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_monitor_.c: ntp_monitor.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_monitor.c; then echo $(srcdir)/ntp_monitor.c; else echo ntp_monitor.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_peer_.c: ntp_peer.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_peer.c; then echo $(srcdir)/ntp_peer.c; else echo ntp_peer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_proto_.c: ntp_proto.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_proto.c; then echo $(srcdir)/ntp_proto.c; else echo ntp_proto.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_refclock_.c: ntp_refclock.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_refclock.c; then echo $(srcdir)/ntp_refclock.c; else echo ntp_refclock.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_request_.c: ntp_request.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_request.c; then echo $(srcdir)/ntp_request.c; else echo ntp_request.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_restrict_.c: ntp_restrict.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_restrict.c; then echo $(srcdir)/ntp_restrict.c; else echo ntp_restrict.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_timer_.c: ntp_timer.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_timer.c; then echo $(srcdir)/ntp_timer.c; else echo ntp_timer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_util_.c: ntp_util.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_util.c; then echo $(srcdir)/ntp_util.c; else echo ntp_util.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntpd_.c: ntpd.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpd.c; then echo $(srcdir)/ntpd.c; else echo ntpd.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntpd-opts_.c: ntpd-opts.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpd-opts.c; then echo $(srcdir)/ntpd-opts.c; else echo ntpd-opts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntpdsim-opts_.c: ntpdsim-opts.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpdsim-opts.c; then echo $(srcdir)/ntpdsim-opts.c; else echo ntpdsim-opts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntpsim_.c: ntpsim.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpsim.c; then echo $(srcdir)/ntpsim.c; else echo ntpsim.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_acts_.c: refclock_acts.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_acts.c; then echo $(srcdir)/refclock_acts.c; else echo refclock_acts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_arbiter_.c: refclock_arbiter.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_arbiter.c; then echo $(srcdir)/refclock_arbiter.c; else echo refclock_arbiter.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_arc_.c: refclock_arc.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_arc.c; then echo $(srcdir)/refclock_arc.c; else echo refclock_arc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_as2201_.c: refclock_as2201.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_as2201.c; then echo $(srcdir)/refclock_as2201.c; else echo refclock_as2201.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_atom_.c: refclock_atom.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_atom.c; then echo $(srcdir)/refclock_atom.c; else echo refclock_atom.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_bancomm_.c: refclock_bancomm.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_bancomm.c; then echo $(srcdir)/refclock_bancomm.c; else echo refclock_bancomm.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_chronolog_.c: refclock_chronolog.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_chronolog.c; then echo $(srcdir)/refclock_chronolog.c; else echo refclock_chronolog.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_chu_.c: refclock_chu.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_chu.c; then echo $(srcdir)/refclock_chu.c; else echo refclock_chu.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_conf_.c: refclock_conf.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_conf.c; then echo $(srcdir)/refclock_conf.c; else echo refclock_conf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_datum_.c: refclock_datum.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_datum.c; then echo $(srcdir)/refclock_datum.c; else echo refclock_datum.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_dumbclock_.c: refclock_dumbclock.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_dumbclock.c; then echo $(srcdir)/refclock_dumbclock.c; else echo refclock_dumbclock.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_fg_.c: refclock_fg.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_fg.c; then echo $(srcdir)/refclock_fg.c; else echo refclock_fg.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_gpsvme_.c: refclock_gpsvme.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_gpsvme.c; then echo $(srcdir)/refclock_gpsvme.c; else echo refclock_gpsvme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_heath_.c: refclock_heath.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_heath.c; then echo $(srcdir)/refclock_heath.c; else echo refclock_heath.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_hopfpci_.c: refclock_hopfpci.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hopfpci.c; then echo $(srcdir)/refclock_hopfpci.c; else echo refclock_hopfpci.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_hopfser_.c: refclock_hopfser.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hopfser.c; then echo $(srcdir)/refclock_hopfser.c; else echo refclock_hopfser.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_hpgps_.c: refclock_hpgps.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hpgps.c; then echo $(srcdir)/refclock_hpgps.c; else echo refclock_hpgps.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_irig_.c: refclock_irig.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_irig.c; then echo $(srcdir)/refclock_irig.c; else echo refclock_irig.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_jjy_.c: refclock_jjy.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_jjy.c; then echo $(srcdir)/refclock_jjy.c; else echo refclock_jjy.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_jupiter_.c: refclock_jupiter.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_jupiter.c; then echo $(srcdir)/refclock_jupiter.c; else echo refclock_jupiter.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_leitch_.c: refclock_leitch.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_leitch.c; then echo $(srcdir)/refclock_leitch.c; else echo refclock_leitch.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_local_.c: refclock_local.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_local.c; then echo $(srcdir)/refclock_local.c; else echo refclock_local.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_mx4200_.c: refclock_mx4200.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_mx4200.c; then echo $(srcdir)/refclock_mx4200.c; else echo refclock_mx4200.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_neoclock4x_.c: refclock_neoclock4x.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_neoclock4x.c; then echo $(srcdir)/refclock_neoclock4x.c; else echo refclock_neoclock4x.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_nmea_.c: refclock_nmea.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_nmea.c; then echo $(srcdir)/refclock_nmea.c; else echo refclock_nmea.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_oncore_.c: refclock_oncore.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_oncore.c; then echo $(srcdir)/refclock_oncore.c; else echo refclock_oncore.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_palisade_.c: refclock_palisade.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_palisade.c; then echo $(srcdir)/refclock_palisade.c; else echo refclock_palisade.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_parse_.c: refclock_parse.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_parse.c; then echo $(srcdir)/refclock_parse.c; else echo refclock_parse.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_pcf_.c: refclock_pcf.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pcf.c; then echo $(srcdir)/refclock_pcf.c; else echo refclock_pcf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_pst_.c: refclock_pst.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pst.c; then echo $(srcdir)/refclock_pst.c; else echo refclock_pst.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_ripencc_.c: refclock_ripencc.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ripencc.c; then echo $(srcdir)/refclock_ripencc.c; else echo refclock_ripencc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_shm_.c: refclock_shm.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_shm.c; then echo $(srcdir)/refclock_shm.c; else echo refclock_shm.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_tpro_.c: refclock_tpro.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_tpro.c; then echo $(srcdir)/refclock_tpro.c; else echo refclock_tpro.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_true_.c: refclock_true.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_true.c; then echo $(srcdir)/refclock_true.c; else echo refclock_true.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_tt560_.c: refclock_tt560.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_tt560.c; then echo $(srcdir)/refclock_tt560.c; else echo refclock_tt560.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_ulink_.c: refclock_ulink.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ulink.c; then echo $(srcdir)/refclock_ulink.c; else echo refclock_ulink.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_wwv_.c: refclock_wwv.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwv.c; then echo $(srcdir)/refclock_wwv.c; else echo refclock_wwv.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_wwvb_.c: refclock_wwvb.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwvb.c; then echo $(srcdir)/refclock_wwvb.c; else echo refclock_wwvb.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_zyfer_.c: refclock_zyfer.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_zyfer.c; then echo $(srcdir)/refclock_zyfer.c; else echo refclock_zyfer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-check_y2k_.$(OBJEXT) check_y2k_.lo cmd_args_.$(OBJEXT) cmd_args_.lo \
-ntp_config_.$(OBJEXT) ntp_config_.lo ntp_control_.$(OBJEXT) \
-ntp_control_.lo ntp_crypto_.$(OBJEXT) ntp_crypto_.lo \
-ntp_filegen_.$(OBJEXT) ntp_filegen_.lo ntp_intres_.$(OBJEXT) \
-ntp_intres_.lo ntp_io_.$(OBJEXT) ntp_io_.lo ntp_loopfilter_.$(OBJEXT) \
-ntp_loopfilter_.lo ntp_monitor_.$(OBJEXT) ntp_monitor_.lo \
-ntp_peer_.$(OBJEXT) ntp_peer_.lo ntp_proto_.$(OBJEXT) ntp_proto_.lo \
-ntp_refclock_.$(OBJEXT) ntp_refclock_.lo ntp_request_.$(OBJEXT) \
-ntp_request_.lo ntp_restrict_.$(OBJEXT) ntp_restrict_.lo \
-ntp_timer_.$(OBJEXT) ntp_timer_.lo ntp_util_.$(OBJEXT) ntp_util_.lo \
-ntpd_.$(OBJEXT) ntpd_.lo ntpd-opts_.$(OBJEXT) ntpd-opts_.lo \
-ntpdsim-opts_.$(OBJEXT) ntpdsim-opts_.lo ntpsim_.$(OBJEXT) ntpsim_.lo \
-refclock_acts_.$(OBJEXT) refclock_acts_.lo refclock_arbiter_.$(OBJEXT) \
-refclock_arbiter_.lo refclock_arc_.$(OBJEXT) refclock_arc_.lo \
-refclock_as2201_.$(OBJEXT) refclock_as2201_.lo \
-refclock_atom_.$(OBJEXT) refclock_atom_.lo refclock_bancomm_.$(OBJEXT) \
-refclock_bancomm_.lo refclock_chronolog_.$(OBJEXT) \
-refclock_chronolog_.lo refclock_chu_.$(OBJEXT) refclock_chu_.lo \
-refclock_conf_.$(OBJEXT) refclock_conf_.lo refclock_datum_.$(OBJEXT) \
-refclock_datum_.lo refclock_dumbclock_.$(OBJEXT) \
-refclock_dumbclock_.lo refclock_fg_.$(OBJEXT) refclock_fg_.lo \
-refclock_gpsvme_.$(OBJEXT) refclock_gpsvme_.lo \
-refclock_heath_.$(OBJEXT) refclock_heath_.lo \
-refclock_hopfpci_.$(OBJEXT) refclock_hopfpci_.lo \
-refclock_hopfser_.$(OBJEXT) refclock_hopfser_.lo \
-refclock_hpgps_.$(OBJEXT) refclock_hpgps_.lo refclock_irig_.$(OBJEXT) \
-refclock_irig_.lo refclock_jjy_.$(OBJEXT) refclock_jjy_.lo \
-refclock_jupiter_.$(OBJEXT) refclock_jupiter_.lo \
-refclock_leitch_.$(OBJEXT) refclock_leitch_.lo \
-refclock_local_.$(OBJEXT) refclock_local_.lo \
-refclock_mx4200_.$(OBJEXT) refclock_mx4200_.lo \
-refclock_neoclock4x_.$(OBJEXT) refclock_neoclock4x_.lo \
-refclock_nmea_.$(OBJEXT) refclock_nmea_.lo refclock_oncore_.$(OBJEXT) \
-refclock_oncore_.lo refclock_palisade_.$(OBJEXT) refclock_palisade_.lo \
-refclock_parse_.$(OBJEXT) refclock_parse_.lo refclock_pcf_.$(OBJEXT) \
-refclock_pcf_.lo refclock_pst_.$(OBJEXT) refclock_pst_.lo \
-refclock_ripencc_.$(OBJEXT) refclock_ripencc_.lo \
-refclock_shm_.$(OBJEXT) refclock_shm_.lo refclock_tpro_.$(OBJEXT) \
-refclock_tpro_.lo refclock_true_.$(OBJEXT) refclock_true_.lo \
-refclock_tt560_.$(OBJEXT) refclock_tt560_.lo refclock_ulink_.$(OBJEXT) \
-refclock_ulink_.lo refclock_wwv_.$(OBJEXT) refclock_wwv_.lo \
-refclock_wwvb_.$(OBJEXT) refclock_wwvb_.lo refclock_zyfer_.$(OBJEXT) \
-refclock_zyfer_.lo : $(ANSI2KNR)
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd-opts.o `test -f 'ntpd-opts.c' || echo '$(srcdir)/'`ntpd-opts.c
+
+ntpdsim-ntpd-opts.obj: ntpd-opts.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd-opts.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpd-opts.Tpo -c -o ntpdsim-ntpd-opts.obj `if test -f 'ntpd-opts.c'; then $(CYGPATH_W) 'ntpd-opts.c'; else $(CYGPATH_W) '$(srcdir)/ntpd-opts.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpd-opts.Tpo $(DEPDIR)/ntpdsim-ntpd-opts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd-opts.c' object='ntpdsim-ntpd-opts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd-opts.obj `if test -f 'ntpd-opts.c'; then $(CYGPATH_W) 'ntpd-opts.c'; else $(CYGPATH_W) '$(srcdir)/ntpd-opts.c'; fi`
+
+ntpdsim-ntpsim.o: ntpsim.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpsim.o -MD -MP -MF $(DEPDIR)/ntpdsim-ntpsim.Tpo -c -o ntpdsim-ntpsim.o `test -f 'ntpsim.c' || echo '$(srcdir)/'`ntpsim.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpsim.Tpo $(DEPDIR)/ntpdsim-ntpsim.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpsim.c' object='ntpdsim-ntpsim.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpsim.o `test -f 'ntpsim.c' || echo '$(srcdir)/'`ntpsim.c
+
+ntpdsim-ntpsim.obj: ntpsim.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpsim.obj -MD -MP -MF $(DEPDIR)/ntpdsim-ntpsim.Tpo -c -o ntpdsim-ntpsim.obj `if test -f 'ntpsim.c'; then $(CYGPATH_W) 'ntpsim.c'; else $(CYGPATH_W) '$(srcdir)/ntpsim.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ntpdsim-ntpsim.Tpo $(DEPDIR)/ntpdsim-ntpsim.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpsim.c' object='ntpdsim-ntpsim.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpsim.obj `if test -f 'ntpsim.c'; then $(CYGPATH_W) 'ntpsim.c'; else $(CYGPATH_W) '$(srcdir)/ntpsim.c'; fi`
+
+.y.c:
+ $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
mostlyclean-libtool:
-rm -f *.lo
@@ -955,9 +1029,9 @@ check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) check-local
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
-all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS)
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) $(DATA)
installdirs:
- for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: $(BUILT_SOURCES)
@@ -978,6 +1052,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -987,11 +1062,14 @@ distclean-generic:
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 ntp_parser.c
+ -rm -f ntp_parser.h
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- clean-libtool clean-noinstLIBRARIES mostlyclean-am
+ clean-libtool clean-noinstLIBRARIES clean-sbinPROGRAMS \
+ mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -1017,7 +1095,7 @@ install-dvi: install-dvi-am
install-dvi-am:
-install-exec-am: install-binPROGRAMS
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
install-html: install-html-am
@@ -1047,7 +1125,7 @@ maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
-mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr \
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
@@ -1058,66 +1136,107 @@ ps: ps-am
ps-am:
-uninstall-am: uninstall-binPROGRAMS uninstall-man
+uninstall-am: uninstall-binPROGRAMS uninstall-man \
+ uninstall-sbinPROGRAMS
uninstall-man: uninstall-man1
-.MAKE: ../util/ansi2knr all check check-am install install-am \
- install-exec-am install-strip
+.MAKE: all check check-am install install-am install-exec-am \
+ install-strip
.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- clean-libtool clean-noinstLIBRARIES ctags distclean \
- distclean-compile distclean-generic distclean-libtool \
- distclean-tags distdir dvi dvi-am html html-am info info-am \
- install install-am install-binPROGRAMS install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-exec-hook install-html install-html-am \
- install-info install-info-am install-man install-man1 \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-kr \
- mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
- uninstall-am uninstall-binPROGRAMS uninstall-man \
- uninstall-man1
-
-
-check-local: @MAKE_CHECK_Y2K@
+ clean-libtool clean-noinstLIBRARIES clean-sbinPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-exec-hook install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man1 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-man uninstall-man1 uninstall-sbinPROGRAMS
+
+
+vphack:
+ test -e ntp_parser.c || ln -s $(srcdir)/ntp_parser.c .
+ test -e ntp_parser.h || ln -s $(srcdir)/ntp_parser.h .
+
+#
+# ylwrap script which invokes Bison replaces ntp_parser.h
+# symlink with the updated file, when ntp_parser.h changes.
+# vphack_after detects this and copies the updated file to srcdir
+# and re-creates the ntp_parser.h symlink in its place.
+#
+
+vphack_after:
+ test -L ntp_parser.h || ( \
+ mv ntp_parser.h $(srcdir)/ntp_parser.h && \
+ ln -s $(srcdir)/ntp_parser.h . \
+ )
+
+check-local: @MAKE_CHECK_Y2K@ $(CHECK_SAVECONFIG)
test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
+k-g-u-submake: keyword-gen
+ ./keyword-gen $(srcdir)/ntp_parser.h > k-g.out
+ @grep -v diff_ignore_line < k-g.out > cmp1
+ @grep -v diff_ignore_line < $(srcdir)/ntp_keyword.h > cmp2
+ @cmp cmp1 cmp2 > /dev/null || \
+ { mv -f k-g.out $(srcdir)/ntp_keyword.h && \
+ echo 'Generated changed ntp_keyword.h.' ;}
+ @[ ! -f k-g.out ] || \
+ { rm k-g.out && echo 'ntp_keyword.h is up to date.' ;}
+ @rm cmp1 cmp2
+ @echo 'keyword-gen and ntp_keyword.h are up to date.' > $@
+
+$(srcdir)/keyword-gen-utd: $(srcdir)/keyword-gen.c $(srcdir)/ntp_parser.h
+ $(MAKE) k-g-u-submake # avoid explicit dependency
+ grep diff_ignore_line $(srcdir)/ntp_keyword.h > k-g-u
+ mv -f k-g-u $@
+
+$(srcdir)/ntp_keyword.h: $(srcdir)/keyword-gen-utd
+ @: do-nothing action to avoid default SCCS get
+ @: .h updated if needed by k-g-u-submake rule
+
$(srcdir)/ntpd-opts.h: $(srcdir)/ntpd-opts.c
+ @: do-nothing action to avoid default SCCS get, .h built with .c
+
$(srcdir)/ntpd-opts.c: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
$(run_ag) ntpd-opts.def
$(srcdir)/ntpd.1: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
$(run_ag) -Tagman1.tpl -bntpd ntpd-opts.def
-$(srcdir)/ntpd-opts.texi $(srcdir)/ntpd-opts.menu: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+$(srcdir)/ntpd-opts.menu: $(srcdir)/ntpd-opts.texi
+ @: do-nothing action to avoid default SCCS get, .menu built with .texi
+
+$(srcdir)/ntpd-opts.texi: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
$(run_ag) -Taginfo.tpl -DLEVEL=section ntpd-opts.def
+ $(top_srcdir)/scripts/check--help $@
-$(srcdir)/ntpdsim-opts.h: $(srcdir)/ntpdsim-opts.c
-$(srcdir)/ntpdsim-opts.c: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
- $(run_ag) ntpdsim-opts.def
+$(PROGRAMS): $(LDADD)
-$(srcdir)/ntpdsim.1: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
- $(run_ag) -Tagman1.tpl -bntpdsim ntpdsim-opts.def
+compsave.conf: ntpd $(srcdir)/complete.conf
+ ./ntpd --configfile $(srcdir)/complete.conf --saveconfigquit $@
-$(srcdir)/ntpdsim-opts.texi $(srcdir)/ntpdsim-opts.menu: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
- $(run_ag) -Taginfo.tpl -DLEVEL=section ntpdsim-opts.def
+check-saveconfig: $(srcdir)/complete.conf compsave.conf
+ cmp $(srcdir)/complete.conf compsave.conf && echo stamp > $@
-$(PROGRAMS): $(LDADD)
+../libopts/libopts.la:
+ cd ../libopts && $(MAKE) libopts.la
../libntp/libntp.a:
cd ../libntp && $(MAKE) libntp.a
-../libntp/libntpsim.a:
- cd ../libntp && $(MAKE) libntpsim.a
-
../libparse/libparse.a:
- cd ../libparse && $(MAKE)
+ cd ../libparse && $(MAKE) libparse.a
-$(top_srcdir)/version :
+$(top_srcdir)/version:
cd $(top_srcdir) && $(MAKE) version
version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ Makefile $(top_srcdir)/version
@@ -1125,16 +1244,80 @@ version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ Makefile $(top_srcdir)/
$(COMPILE) -c version.c
install-exec-hook:
- @case ${BINSUBDIR} in \
- bin) ODIR=${exec_prefix}/sbin ;; \
- sbin) ODIR=${exec_prefix}/bin ;; \
- esac; \
- test -z "${bin_PROGRAMS}${bin_SCRIPTS}" \
+ @case ${BINSUBDIR} in \
+ bin) ODIR=${sbindir} ;; \
+ sbin) ODIR=${bindir} ;; \
+ esac; \
+ test -z "${bin_PROGRAMS}${bin_SCRIPTS}" \
|| for i in ${bin_PROGRAMS} ${bin_SCRIPTS} " "; do \
test ! -f $$ODIR/$$i || echo "*** $$i is also in $$ODIR!"; \
done
#
+$(DEPDIR)/deps-ver: $(top_srcdir)/deps-ver
+ @[ -f $@ ] || \
+ cp $(top_srcdir)/deps-ver $@
+ @[ -w $@ ] || \
+ chmod ug+w $@
+ @cmp $(top_srcdir)/deps-ver $@ > /dev/null || ( \
+ $(MAKE) clean && \
+ echo -n "Prior $(subdir)/$(DEPDIR) version " && \
+ cat $@ && \
+ rm -rf $(DEPDIR) && \
+ mkdir $(DEPDIR) && \
+ case "$(top_builddir)" in \
+ .) \
+ ./config.status Makefile depfiles \
+ ;; \
+ ..) \
+ cd .. && \
+ ./config.status $(subdir)/Makefile depfiles && \
+ cd $(subdir) \
+ ;; \
+ *) \
+ echo 'Fatal: depsver.mf Automake fragment limited' \
+ 'to immediate subdirectories.' && \
+ echo "top_builddir: $(top_builddir)" && \
+ echo "subdir: $(subdir)" && \
+ exit 1 \
+ ;; \
+ esac && \
+ echo -n "Cleaned $(subdir)/$(DEPDIR) version " && \
+ cat $(top_srcdir)/deps-ver \
+ )
+ cp $(top_srcdir)/deps-ver $@
+
+.deps-ver: $(top_srcdir)/deps-ver
+ @[ ! -d $(DEPDIR) ] || $(MAKE) $(DEPDIR)/deps-ver
+ @touch $@
+
+#
+# depsver.mf included in Makefile.am for directories with .deps
+#
+# When building in the same directory with sources that change over
+# time, such as when tracking using bk, the .deps files can become
+# stale with respect to moved, deleted, or superceded headers. Most
+# commonly, this would exhibit as make reporting a failure to make a
+# header file which is no longer in the location given. To address
+# this issue, we use a deps-ver file which is updated with each change
+# that breaks old .deps files. A copy of deps-ver is made into
+# $(DEPDIR) if not already present. If $(DEPDIR)/deps-ver is present
+# with different contents than deps-ver, we make clean to ensure all
+# .o files built before the incompatible change are rebuilt along with
+# their updated .deps files, then remove $(DEPDIR) and recreate it as
+# empty stubs.
+#
+# It is normal when configured with --disable-dependency-tracking for
+# the DEPDIR to not have been created. For this reason, we use the
+# intermediate target .deps-ver, which invokes make recursively if
+# DEPDIR exists.
+#
+# If you modify depsver.mf, please make the changes to the master
+# copy, the one in sntp is copied by the bootstrap script from it.
+#
+# This comment block follows rather than leads the related code so that
+# it stays with it in the generated Makefile.in and Makefile.
+#
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/ntpd/cmd_args.c b/ntpd/cmd_args.c
index 7843bc317162..49a9b465269e 100644
--- a/ntpd/cmd_args.c
+++ b/ntpd/cmd_args.c
@@ -9,21 +9,13 @@
#include "ntp_stdlib.h"
#include "ntp_cmdargs.h"
-#ifdef SIM
-# include "ntpsim.h"
-# include "ntpdsim-opts.h"
-# define OPTSTRUCT ntpdsimOptions
-#else
-# include "ntpd-opts.h"
-# define OPTSTRUCT ntpdOptions
-#endif /* SIM */
+#include "ntpd-opts.h"
/*
* Definitions of things either imported from or exported to outside
*/
extern char const *progname;
extern const char *specific_interface;
-extern short default_ai_family;
#ifdef HAVE_NETINFO
extern int check_netinfo;
@@ -41,29 +33,29 @@ getCmdOpts(
{
extern const char *config_file;
int errflg;
- tOptions *myOptions = &OPTSTRUCT;
+ tOptions *myOptions = &ntpdOptions;
/*
* Initialize, initialize
*/
errflg = 0;
- switch (WHICH_IDX_IPV4) {
- case INDEX_OPT_IPV4:
- default_ai_family = AF_INET;
- break;
- case INDEX_OPT_IPV6:
- default_ai_family = AF_INET6;
- break;
- default:
- /* ai_fam_templ = ai_fam_default; */
- break;
- }
+ if (ipv4_works && ipv6_works) {
+ if (HAVE_OPT( IPV4 ))
+ ipv6_works = 0;
+ else if (HAVE_OPT( IPV6 ))
+ ipv4_works = 0;
+ } else if (!ipv4_works && !ipv6_works) {
+ msyslog(LOG_ERR, "Neither IPv4 nor IPv6 networking detected, fatal.");
+ exit(1);
+ } else if (HAVE_OPT( IPV4 ) && !ipv4_works)
+ msyslog(LOG_WARNING, "-4/--ipv4 ignored, IPv4 networking not found.");
+ else if (HAVE_OPT( IPV6 ) && !ipv6_works)
+ msyslog(LOG_WARNING, "-6/--ipv6 ignored, IPv6 networking not found.");
if (HAVE_OPT( AUTHREQ ))
proto_config(PROTO_AUTHENTICATE, 1, 0., NULL);
-
- if (HAVE_OPT( AUTHNOREQ ))
+ else if (HAVE_OPT( AUTHNOREQ ))
proto_config(PROTO_AUTHENTICATE, 0, 0., NULL);
if (HAVE_OPT( BCASTSYNC ))
@@ -82,24 +74,12 @@ getCmdOpts(
if (HAVE_OPT( PANICGATE ))
allow_panic = TRUE;
- if (HAVE_OPT( JAILDIR )) {
#ifdef HAVE_DROPROOT
- droproot = 1;
- chrootdir = OPT_ARG( JAILDIR );
-#else
- fprintf(stderr,
- "command line -i option (jaildir) is not supported by this binary"
-# ifndef SYS_WINNT
- ",\n" "can not drop root privileges. See configure options\n"
- "--enable-clockctl and --enable-linuxcaps.\n");
-# else
- ".\n");
-# endif
- msyslog(LOG_ERR,
- "command line -i option (jaildir) is not supported by this binary.");
- errflg++;
-#endif
+ if (HAVE_OPT( JAILDIR )) {
+ droproot = 1;
+ chrootdir = OPT_ARG( JAILDIR );
}
+#endif
if (HAVE_OPT( KEYFILE ))
getauthkeys(OPT_ARG( KEYFILE ));
@@ -146,30 +126,15 @@ getCmdOpts(
} while (--ct > 0);
}
- if (HAVE_OPT( USER )) {
#ifdef HAVE_DROPROOT
- char *ntp_optarg = OPT_ARG( USER );
-
+ if (HAVE_OPT( USER )) {
droproot = 1;
- user = emalloc(strlen(ntp_optarg) + 1);
- (void)strncpy(user, ntp_optarg, strlen(ntp_optarg) + 1);
+ user = estrdup(OPT_ARG( USER ));
group = rindex(user, ':');
if (group)
*group++ = '\0'; /* get rid of the ':' */
-#else
- fprintf(stderr,
- "command line -u/--user option is not supported by this binary"
-# ifndef SYS_WINNT
- ",\n" "can not drop root privileges. See configure options\n"
- "--enable-clockctl and --enable-linuxcaps.\n");
-# else
- ".\n");
-# endif
- msyslog(LOG_ERR,
- "command line -u/--user option is not supported by this binary.");
- errflg++;
-#endif
}
+#endif
if (HAVE_OPT( VAR )) {
int ct = STACKCT_OPT( VAR );
@@ -195,9 +160,10 @@ getCmdOpts(
} while (--ct > 0);
}
- if (HAVE_OPT( SLEW ))
+ if (HAVE_OPT( SLEW )) {
clock_max = 600;
-
+ kern_enable = 0;
+ }
if (HAVE_OPT( UPDATEINTERVAL )) {
long val = OPT_VALUE_UPDATEINTERVAL;
@@ -214,32 +180,11 @@ getCmdOpts(
}
}
#ifdef SIM
- if (HAVE_OPT( SIMBROADCASTDELAY ))
- sscanf(OPT_ARG( SIMBROADCASTDELAY ), "%lf", &ntp_node.bdly);
-
- if (HAVE_OPT( PHASENOISE ))
- sscanf(OPT_ARG( PHASENOISE ), "%lf", &ntp_node.snse);
-
- if (HAVE_OPT( SIMSLEW ))
- sscanf(OPT_ARG( SIMSLEW ), "%lf", &ntp_node.slew);
- if (HAVE_OPT( SERVERTIME ))
- sscanf(OPT_ARG( SERVERTIME ), "%lf", &ntp_node.clk_time);
-
- if (HAVE_OPT( ENDSIMTIME ))
- sscanf(OPT_ARG( ENDSIMTIME ), "%lf", &ntp_node.sim_time);
-
- if (HAVE_OPT( FREQERR ))
- sscanf(OPT_ARG( FREQERR ), "%lf", &ntp_node.ferr);
-
- if (HAVE_OPT( WALKNOISE ))
- sscanf(OPT_ARG( WALKNOISE ), "%lf", &ntp_node.fnse);
-
- if (HAVE_OPT( NDELAY ))
- sscanf(OPT_ARG( NDELAY ), "%lf", &ntp_node.ndly);
-
- if (HAVE_OPT( PDELAY ))
- sscanf(OPT_ARG( PDELAY ), "%lf", &ntp_node.pdly);
+ /* SK:
+ * The simulator no longer takes any command line arguments. Hence,
+ * all the code that was here has been removed.
+ */
#endif /* SIM */
diff --git a/ntpd/complete.conf b/ntpd/complete.conf
new file mode 100644
index 000000000000..5a390c4d90f7
--- /dev/null
+++ b/ntpd/complete.conf
@@ -0,0 +1,56 @@
+saveconfigdir "/etc/ntp/conf"
+driftfile "/etc/ntp.drift"
+logfile "/var/log/ntp.log"
+logconfig =allall -allinfo -allevents -allstatistics -allstatus +allall -clockinfo -clockevents -clockstatistics -clockstatus +clockall -syncinfo -syncevents -syncstatistics -syncstatus +syncall -sysinfo -sysevents -sysstatistics -sysstatus +sysall
+statsdir "/etc/ntp/stats"
+statistics loopstats peerstats
+filegen clockstats file clockstats type none enable
+filegen cryptostats file cryptostats type pid link disable
+filegen loopstats file loopstats type day nolink enable
+filegen peerstats file peerstats type week enable
+filegen protostats file stats type month enable
+filegen rawstats file rawstats type year nolink enable
+filegen sysstats file sysstats type age enable
+filegen timingstats file timingstats type none disable
+crypto digest md5 host myhostname ident wedent pw cryptopass randfile /.rnd
+revoke 10
+keysdir "/etc/ntp/keys"
+keys "/etc/ntp.keys"
+trustedkey 1 2 3 4 5 6 7 8 9 10 11 12 (14 ... 16) 18 (32768 ... 65534)
+controlkey 12
+requestkey 12
+enable auth ntp monitor
+disable bclient calibrate kernel
+tos beacon 3600 ceiling 16 cohort 0 floor 1 maxclock 10 maxdist 1.5 minclock 3 mindist 0.001 minsane 1 orphan 16
+tinker allan 1500 dispersion 15 freq 0 huffpuff 7200 panic 1000 step 0.128 stepout 900
+broadcastclient
+server 127.127.1.0 mode 64 prefer true
+fudge 127.127.1.0 time1 0 time2 1.1 stratum 7 refid Abcd
+pool 0.north-america.pool.ntp.org. iburst preempt
+server 1.north-america.pool.ntp.org. iburst
+server -4 2.north-america.pool.ntp.org. minpoll 6 maxpoll 10 iburst
+server -6 ntp.davehart.net. minpoll 6 maxpoll 10 version 5 burst iburst
+peer -6 davehart.broker.freenet6.net. xleave autokey
+peer -4 192.168.192.168 key 1 bias 3.1416 noselect
+broadcast 192.168.192.255
+manycastclient 224.0.1.1
+manycastclient ff05::101
+manycastserver 224.0.1.1 ff05::101
+multicastclient 224.0.1.1 ff05::101
+discard minimum 1 average 3 monitor 1
+restrict default nomodify limited kod
+restrict trusted.host.name.example.com. nomodify
+restrict [fe80::1] mask [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]
+restrict 127.0.0.1 mask 255.255.255.255
+restrict ::1
+interface drop ipv6
+interface ignore ipv4
+interface drop wildcard
+interface listen eth0
+interface listen ipv6
+interface listen 192.168.192.0/24
+interface listen 192.168.193.1
+setvar varnondef = "this variable does not have default after the value"
+setvar vanity = "name plate" default
+trap 127.0.0.1 interface 127.0.0.1 port 1234
+trap 127.0.0.2
diff --git a/ntpd/keyword-gen-utd b/ntpd/keyword-gen-utd
new file mode 100644
index 000000000000..539a48f56f06
--- /dev/null
+++ b/ntpd/keyword-gen-utd
@@ -0,0 +1 @@
+ * Generated 2010-04-06 04:38:11 UTC diff_ignore_line
diff --git a/ntpd/keyword-gen.c b/ntpd/keyword-gen.c
new file mode 100644
index 000000000000..e1b747d03b30
--- /dev/null
+++ b/ntpd/keyword-gen.c
@@ -0,0 +1,663 @@
+/*
+ * keyword-gen.c -- generate keyword scanner finite state machine and
+ * keyword_text array.
+ * This program is run to generate ntp_keyword.h
+ */
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <ntp_stdlib.h>
+#include <ntp_config.h>
+#include <lib_strbuf.h>
+#include "ntp_scanner.h"
+#include "ntp_parser.h"
+
+
+#ifdef QSORT_USES_VOID_P
+typedef const void * QSORTP;
+#else
+typedef char * QSORTP;
+#endif
+
+/* Define a structure to hold a (keyword, token) pair */
+struct key_tok {
+ char * key; /* Keyword */
+ int token; /* Associated Token */
+ follby followedby; /* nonzero indicates the next token(s)
+ forced to be string(s) */
+};
+
+struct key_tok ntp_keywords[] = {
+{ "...", T_Ellipsis, FOLLBY_TOKEN },
+{ "automax", T_Automax, FOLLBY_TOKEN },
+{ "broadcast", T_Broadcast, FOLLBY_STRING },
+{ "broadcastclient", T_Broadcastclient, FOLLBY_TOKEN },
+{ "broadcastdelay", T_Broadcastdelay, FOLLBY_TOKEN },
+{ "calldelay", T_Calldelay, FOLLBY_TOKEN },
+{ "disable", T_Disable, FOLLBY_TOKEN },
+{ "driftfile", T_Driftfile, FOLLBY_STRING },
+{ "enable", T_Enable, FOLLBY_TOKEN },
+{ "end", T_End, FOLLBY_TOKEN },
+{ "filegen", T_Filegen, FOLLBY_TOKEN },
+{ "fudge", T_Fudge, FOLLBY_STRING },
+{ "includefile", T_Includefile, FOLLBY_STRING },
+{ "leapfile", T_Leapfile, FOLLBY_STRING },
+{ "logconfig", T_Logconfig, FOLLBY_STRINGS_TO_EOC },
+{ "logfile", T_Logfile, FOLLBY_STRING },
+{ "manycastclient", T_Manycastclient, FOLLBY_STRING },
+{ "manycastserver", T_Manycastserver, FOLLBY_STRINGS_TO_EOC },
+{ "multicastclient", T_Multicastclient, FOLLBY_STRINGS_TO_EOC },
+{ "peer", T_Peer, FOLLBY_STRING },
+{ "phone", T_Phone, FOLLBY_STRINGS_TO_EOC },
+{ "pidfile", T_Pidfile, FOLLBY_STRING },
+{ "pool", T_Pool, FOLLBY_STRING },
+{ "discard", T_Discard, FOLLBY_TOKEN },
+{ "restrict", T_Restrict, FOLLBY_TOKEN },
+{ "server", T_Server, FOLLBY_STRING },
+{ "setvar", T_Setvar, FOLLBY_STRING },
+{ "statistics", T_Statistics, FOLLBY_TOKEN },
+{ "statsdir", T_Statsdir, FOLLBY_STRING },
+{ "tick", T_Tick, FOLLBY_TOKEN },
+{ "tinker", T_Tinker, FOLLBY_TOKEN },
+{ "tos", T_Tos, FOLLBY_TOKEN },
+{ "trap", T_Trap, FOLLBY_STRING },
+{ "unconfig", T_Unconfig, FOLLBY_STRING },
+{ "unpeer", T_Unpeer, FOLLBY_STRING },
+/* authentication_command */
+{ "controlkey", T_ControlKey, FOLLBY_TOKEN },
+{ "crypto", T_Crypto, FOLLBY_TOKEN },
+{ "keys", T_Keys, FOLLBY_STRING },
+{ "keysdir", T_Keysdir, FOLLBY_STRING },
+{ "ntpsigndsocket", T_NtpSignDsocket, FOLLBY_STRING },
+{ "requestkey", T_Requestkey, FOLLBY_TOKEN },
+{ "revoke", T_Revoke, FOLLBY_TOKEN },
+{ "trustedkey", T_Trustedkey, FOLLBY_TOKEN },
+/* IPv4/IPv6 protocol override flag */
+{ "-4", T_Ipv4_flag, FOLLBY_TOKEN },
+{ "-6", T_Ipv6_flag, FOLLBY_TOKEN },
+/* option */
+{ "autokey", T_Autokey, FOLLBY_TOKEN },
+{ "bias", T_Bias, FOLLBY_TOKEN },
+{ "burst", T_Burst, FOLLBY_TOKEN },
+{ "iburst", T_Iburst, FOLLBY_TOKEN },
+{ "key", T_Key, FOLLBY_TOKEN },
+{ "maxpoll", T_Maxpoll, FOLLBY_TOKEN },
+{ "minpoll", T_Minpoll, FOLLBY_TOKEN },
+{ "mode", T_Mode, FOLLBY_TOKEN },
+{ "noselect", T_Noselect, FOLLBY_TOKEN },
+{ "preempt", T_Preempt, FOLLBY_TOKEN },
+{ "true", T_True, FOLLBY_TOKEN },
+{ "prefer", T_Prefer, FOLLBY_TOKEN },
+{ "ttl", T_Ttl, FOLLBY_TOKEN },
+{ "version", T_Version, FOLLBY_TOKEN },
+{ "xleave", T_Xleave, FOLLBY_TOKEN },
+/* crypto_command */
+{ "host", T_Host, FOLLBY_STRING },
+{ "ident", T_Ident, FOLLBY_STRING },
+{ "pw", T_Pw, FOLLBY_STRING },
+{ "randfile", T_Randfile, FOLLBY_STRING },
+{ "sign", T_Sign, FOLLBY_STRING },
+{ "digest", T_Digest, FOLLBY_STRING },
+/*** MONITORING COMMANDS ***/
+/* stat */
+{ "clockstats", T_Clockstats, FOLLBY_TOKEN },
+{ "cryptostats", T_Cryptostats, FOLLBY_TOKEN },
+{ "loopstats", T_Loopstats, FOLLBY_TOKEN },
+{ "peerstats", T_Peerstats, FOLLBY_TOKEN },
+{ "rawstats", T_Rawstats, FOLLBY_TOKEN },
+{ "sysstats", T_Sysstats, FOLLBY_TOKEN },
+{ "protostats", T_Protostats, FOLLBY_TOKEN },
+{ "timingstats", T_Timingstats, FOLLBY_TOKEN },
+/* filegen_option */
+{ "file", T_File, FOLLBY_STRING },
+{ "link", T_Link, FOLLBY_TOKEN },
+{ "nolink", T_Nolink, FOLLBY_TOKEN },
+{ "type", T_Type, FOLLBY_TOKEN },
+/* filegen_type */
+{ "age", T_Age, FOLLBY_TOKEN },
+{ "day", T_Day, FOLLBY_TOKEN },
+{ "month", T_Month, FOLLBY_TOKEN },
+{ "none", T_None, FOLLBY_TOKEN },
+{ "pid", T_Pid, FOLLBY_TOKEN },
+{ "week", T_Week, FOLLBY_TOKEN },
+{ "year", T_Year, FOLLBY_TOKEN },
+/*** ORPHAN MODE COMMANDS ***/
+/* tos_option */
+{ "minclock", T_Minclock, FOLLBY_TOKEN },
+{ "maxclock", T_Maxclock, FOLLBY_TOKEN },
+{ "minsane", T_Minsane, FOLLBY_TOKEN },
+{ "floor", T_Floor, FOLLBY_TOKEN },
+{ "ceiling", T_Ceiling, FOLLBY_TOKEN },
+{ "cohort", T_Cohort, FOLLBY_TOKEN },
+{ "mindist", T_Mindist, FOLLBY_TOKEN },
+{ "maxdist", T_Maxdist, FOLLBY_TOKEN },
+{ "beacon", T_Beacon, FOLLBY_TOKEN },
+{ "orphan", T_Orphan, FOLLBY_TOKEN },
+/* access_control_flag */
+{ "default", T_Default, FOLLBY_TOKEN },
+{ "flake", T_Flake, FOLLBY_TOKEN },
+{ "ignore", T_Ignore, FOLLBY_TOKEN },
+{ "limited", T_Limited, FOLLBY_TOKEN },
+{ "mssntp", T_Mssntp, FOLLBY_TOKEN },
+{ "kod", T_Kod, FOLLBY_TOKEN },
+{ "lowpriotrap", T_Lowpriotrap, FOLLBY_TOKEN },
+{ "mask", T_Mask, FOLLBY_TOKEN },
+{ "nomodify", T_Nomodify, FOLLBY_TOKEN },
+{ "nopeer", T_Nopeer, FOLLBY_TOKEN },
+{ "noquery", T_Noquery, FOLLBY_TOKEN },
+{ "noserve", T_Noserve, FOLLBY_TOKEN },
+{ "notrap", T_Notrap, FOLLBY_TOKEN },
+{ "notrust", T_Notrust, FOLLBY_TOKEN },
+{ "ntpport", T_Ntpport, FOLLBY_TOKEN },
+/* discard_option */
+{ "average", T_Average, FOLLBY_TOKEN },
+{ "minimum", T_Minimum, FOLLBY_TOKEN },
+{ "monitor", T_Monitor, FOLLBY_TOKEN },
+/* fudge_factor */
+{ "flag1", T_Flag1, FOLLBY_TOKEN },
+{ "flag2", T_Flag2, FOLLBY_TOKEN },
+{ "flag3", T_Flag3, FOLLBY_TOKEN },
+{ "flag4", T_Flag4, FOLLBY_TOKEN },
+{ "refid", T_Refid, FOLLBY_STRING },
+{ "stratum", T_Stratum, FOLLBY_TOKEN },
+{ "time1", T_Time1, FOLLBY_TOKEN },
+{ "time2", T_Time2, FOLLBY_TOKEN },
+/* system_option */
+{ "auth", T_Auth, FOLLBY_TOKEN },
+{ "bclient", T_Bclient, FOLLBY_TOKEN },
+{ "calibrate", T_Calibrate, FOLLBY_TOKEN },
+{ "kernel", T_Kernel, FOLLBY_TOKEN },
+{ "ntp", T_Ntp, FOLLBY_TOKEN },
+{ "stats", T_Stats, FOLLBY_TOKEN },
+/* tinker_option */
+{ "step", T_Step, FOLLBY_TOKEN },
+{ "panic", T_Panic, FOLLBY_TOKEN },
+{ "dispersion", T_Dispersion, FOLLBY_TOKEN },
+{ "stepout", T_Stepout, FOLLBY_TOKEN },
+{ "allan", T_Allan, FOLLBY_TOKEN },
+{ "huffpuff", T_Huffpuff, FOLLBY_TOKEN },
+{ "freq", T_Freq, FOLLBY_TOKEN },
+/* miscellaneous_command */
+{ "port", T_Port, FOLLBY_TOKEN },
+{ "interface", T_Interface, FOLLBY_TOKEN },
+{ "qos", T_Qos, FOLLBY_TOKEN },
+{ "saveconfigdir", T_Saveconfigdir, FOLLBY_STRING },
+/* interface_command (ignore and interface already defined) */
+{ "nic", T_Nic, FOLLBY_TOKEN },
+{ "all", T_All, FOLLBY_TOKEN },
+{ "ipv4", T_Ipv4, FOLLBY_TOKEN },
+{ "ipv6", T_Ipv6, FOLLBY_TOKEN },
+{ "wildcard", T_Wildcard, FOLLBY_TOKEN },
+{ "listen", T_Listen, FOLLBY_TOKEN },
+{ "drop", T_Drop, FOLLBY_TOKEN },
+/* simulator commands */
+{ "simulate", T_Simulate, FOLLBY_TOKEN },
+{ "simulation_duration",T_Sim_Duration, FOLLBY_TOKEN },
+{ "beep_delay", T_Beep_Delay, FOLLBY_TOKEN },
+{ "duration", T_Duration, FOLLBY_TOKEN },
+{ "server_offset", T_Server_Offset, FOLLBY_TOKEN },
+{ "freq_offset", T_Freq_Offset, FOLLBY_TOKEN },
+{ "wander", T_Wander, FOLLBY_TOKEN },
+{ "jitter", T_Jitter, FOLLBY_TOKEN },
+{ "prop_delay", T_Prop_Delay, FOLLBY_TOKEN },
+{ "proc_delay", T_Proc_Delay, FOLLBY_TOKEN },
+};
+
+
+typedef struct big_scan_state_tag {
+ char ch; /* Character this state matches on */
+ char followedby; /* Forces next token(s) to T_String */
+ u_short finishes_token; /* nonzero ID if last keyword char */
+ u_short match_next_s; /* next state to check matching ch */
+ u_short other_next_s; /* next state to check if not ch */
+} big_scan_state;
+
+/*
+ * Note: to increase MAXSTATES beyond 2048, be aware it is currently
+ * crammed into 11 bits in scan_state form. Raising to 4096 would be
+ * relatively easy by storing the followedby value in a separate
+ * array with one entry per token, and shrinking the char value to
+ * 7 bits to free a bit for accepting/non-accepting. More than 4096
+ * states will require expanding scan_state beyond 32 bits each.
+ */
+#define MAXSTATES 2048
+
+const char * current_keyword;/* for error reporting */
+big_scan_state sst[MAXSTATES]; /* scanner FSM state entries */
+int sst_highwater; /* next entry index to consider */
+char * symb[1024]; /* map token ID to symbolic name */
+
+/* for libntp */
+const char * progname = "keyword-gen";
+volatile int debug = 1;
+
+int main (int, char **);
+static void generate_preamble (void);
+static void generate_fsm (void);
+static void generate_token_text (void);
+static int create_keyword_scanner (void);
+static int create_scan_states (char *, int, follby, int);
+int compare_key_tok_id (QSORTP, QSORTP);
+int compare_key_tok_text (QSORTP, QSORTP);
+void populate_symb (char *);
+const char * symbname (int);
+
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage:\n%s t_header.h\n", argv[0]);
+ exit(1);
+ }
+ populate_symb(argv[1]);
+
+ generate_preamble();
+ generate_token_text();
+ generate_fsm();
+
+ return 0;
+}
+
+
+static void
+generate_preamble(void)
+{
+ time_t now;
+ char timestamp[128];
+ char preamble[] =
+"/*\n"
+" * ntp_keyword.h\n"
+" * \n"
+" * NOTE: edit this file with caution, it is generated by keyword-gen.c\n"
+" *\t Generated %s UTC diff_ignore_line\n"
+" *\n"
+" */\n"
+"#include \"ntp_scanner.h\"\n"
+"#include \"ntp_parser.h\"\n"
+"\n";
+
+ time(&now);
+ if (!strftime(timestamp, sizeof(timestamp),
+ "%Y-%m-%d %H:%M:%S", gmtime(&now)))
+ timestamp[0] = '\0';
+
+ printf(preamble, timestamp);
+}
+
+
+static void
+generate_fsm(void)
+{
+ char token_id_comment[128];
+ int initial_state;
+ int i;
+ int token;
+
+ /*
+ * Sort ntp_keywords in alphabetical keyword order. This is
+ * not necessary, but minimizes nonfunctional changes in the
+ * generated finite state machine when keywords are modified.
+ */
+ qsort(ntp_keywords, COUNTOF(ntp_keywords),
+ sizeof(ntp_keywords[0]), compare_key_tok_text);
+
+ /*
+ * To save space, reserve the state array entry matching each
+ * token number for its terminal state, so the token identifier
+ * does not need to be stored in each state, but can be
+ * recovered trivially. To mark the entry reserved,
+ * finishes_token is nonzero.
+ */
+
+ for (i = 0; i < COUNTOF(ntp_keywords); i++) {
+ token = ntp_keywords[i].token;
+ if (1 > token || token >= COUNTOF(sst)) {
+ fprintf(stderr,
+ "keyword-gen sst[%u] too small "
+ "for keyword '%s' id %d\n",
+ COUNTOF(sst),
+ ntp_keywords[i].key,
+ token);
+ exit(4);
+ }
+ sst[token].finishes_token = token;
+ }
+
+ initial_state = create_keyword_scanner();
+
+ fprintf(stderr,
+ "%d keywords consumed %d states of %d max.\n",
+ (int)COUNTOF(ntp_keywords),
+ sst_highwater - 1,
+ (int)COUNTOF(sst) - 1);
+
+ printf("#define SCANNER_INIT_S %d\n\n", initial_state);
+
+ printf("const scan_state sst[%d] = {\n"
+ "/*SS_T( ch,\tf-by, match, other ),\t\t\t\t */\n"
+ " 0,\t\t\t\t /* %5d %-17s */\n",
+ sst_highwater,
+ 0, "");
+
+ for (i = 1; i < sst_highwater; i++) {
+
+ /* verify fields will fit */
+ if (sst[i].followedby & ~0x3) {
+ fprintf(stderr,
+ "keyword-gen internal error "
+ "sst[%d].followedby %d too big\n",
+ i, sst[i].followedby);
+ exit(7);
+ }
+
+ if (sst_highwater <= sst[i].match_next_s
+ || sst[i].match_next_s & ~0x7ff) {
+ fprintf(stderr,
+ "keyword-gen internal error "
+ "sst[%d].match_next_s %d too big\n",
+ i, sst[i].match_next_s);
+ exit(8);
+ }
+
+ if (sst_highwater <= sst[i].other_next_s
+ || sst[i].other_next_s & ~0x7ff) {
+ fprintf(stderr,
+ "keyword-gen internal error "
+ "sst[%d].other_next_s %d too big\n",
+ i, sst[i].other_next_s);
+ exit(9);
+ }
+
+ if (!sst[i].finishes_token)
+ snprintf(token_id_comment,
+ sizeof(token_id_comment), "%5d %-17s",
+ i, (initial_state == i)
+ ? "initial state"
+ : "");
+ else {
+ snprintf(token_id_comment,
+ sizeof(token_id_comment), "%5d %-17s",
+ i, symbname(sst[i].finishes_token));
+ if (i != sst[i].finishes_token) {
+ fprintf(stderr,
+ "keyword-gen internal error "
+ "entry %d finishes token %d\n",
+ i, sst[i].finishes_token);
+ exit(5);
+ }
+ }
+
+ printf(" S_ST( '%c',\t%d, %5u, %5u )%s /* %s */\n",
+ sst[i].ch,
+ sst[i].followedby,
+ sst[i].match_next_s,
+ sst[i].other_next_s,
+ (i + 1 < sst_highwater)
+ ? ","
+ : " ",
+ token_id_comment);
+ }
+
+ printf("};\n\n");
+}
+
+
+/* Define a function to create the states of the scanner. This function
+ * is used by the create_keyword_scanner function below.
+ *
+ * This function takes a suffix of a keyword, the token to be returned on
+ * recognizing the complete keyword, and any pre-existing state that exists
+ * for some other keyword that has the same prefix as the current one.
+ */
+static int
+create_scan_states(
+ char * text,
+ int token,
+ follby followedby,
+ int prev_state
+ )
+{
+ int my_state;
+ int return_state;
+ int prev_char_s;
+ int curr_char_s;
+
+ return_state = prev_state;
+ curr_char_s = prev_state;
+ prev_char_s = 0;
+
+ /* Find the correct position to insert the state.
+ * All states should be in alphabetical order
+ */
+ while (curr_char_s && (text[0] < sst[curr_char_s].ch)) {
+ prev_char_s = curr_char_s;
+ curr_char_s = sst[curr_char_s].other_next_s;
+ }
+
+ /*
+ * Check if a previously seen keyword has the same prefix as
+ * the current keyword. If so, simply use the state for that
+ * keyword as my_state, otherwise, allocate a new state.
+ */
+ if (curr_char_s && (text[0] == sst[curr_char_s].ch)) {
+ my_state = curr_char_s;
+ if ('\0' == text[1]) {
+ fprintf(stderr,
+ "Duplicate entries for keyword '%s' in"
+ " keyword_gen.c ntp_keywords[].\n",
+ current_keyword);
+ exit(2);
+ }
+ } else {
+ do
+ my_state = sst_highwater++;
+ while (my_state < COUNTOF(sst)
+ && sst[my_state].finishes_token);
+ if (my_state >= COUNTOF(sst)) {
+ fprintf(stderr,
+ "fatal, keyword scanner state array "
+ "sst[%d] is too small, modify\n"
+ "keyword-gen.c to increase.\n",
+ (int)COUNTOF(sst));
+ exit(3);
+ }
+ /* Store the next character of the keyword */
+ sst[my_state].ch = text[0];
+ sst[my_state].other_next_s = curr_char_s;
+ sst[my_state].followedby = FOLLBY_NON_ACCEPTING;
+
+ if (prev_char_s)
+ sst[prev_char_s].other_next_s = my_state;
+ else
+ return_state = my_state;
+ }
+
+ /* Check if the next character is '\0'.
+ * If yes, we are done with the recognition and this is an accepting
+ * state.
+ * If not, we need to continue scanning
+ */
+ if ('\0' == text[1]) {
+ sst[my_state].finishes_token = (u_short)token;
+ sst[my_state].followedby = (char)followedby;
+
+ if (sst[token].finishes_token != (u_short)token) {
+ fprintf(stderr,
+ "fatal, sst[%d] not reserved for %s.\n",
+ token, symbname(token));
+ exit(6);
+ }
+ /* relocate so token id is sst[] index */
+ if (my_state != token) {
+ sst[token] = sst[my_state];
+ memset(&sst[my_state], 0,
+ sizeof(sst[my_state]));
+ do
+ sst_highwater--;
+ while (sst[sst_highwater].finishes_token);
+ my_state = token;
+ if (prev_char_s)
+ sst[prev_char_s].other_next_s = my_state;
+ else
+ return_state = my_state;
+ }
+ } else
+ sst[my_state].match_next_s =
+ create_scan_states(
+ &text[1],
+ token,
+ followedby,
+ sst[my_state].match_next_s);
+
+ return return_state;
+}
+
+
+/* Define a function that takes a list of (keyword, token) values and
+ * creates a keywords scanner out of it.
+ */
+
+static int
+create_keyword_scanner(void)
+{
+ int scanner;
+ int i;
+
+ sst_highwater = 1; /* index 0 invalid, unused */
+ scanner = 0;
+
+ for (i = 0; i < COUNTOF(ntp_keywords); i++) {
+ current_keyword = ntp_keywords[i].key;
+ scanner =
+ create_scan_states(
+ ntp_keywords[i].key,
+ ntp_keywords[i].token,
+ ntp_keywords[i].followedby,
+ scanner);
+ }
+
+ return scanner;
+}
+
+
+static void
+generate_token_text(void)
+{
+ int lowest_id;
+ int highest_id;
+ int id_count;
+ int id;
+ int i;
+
+ /* sort ntp_keywords in token ID order */
+ qsort(ntp_keywords, COUNTOF(ntp_keywords),
+ sizeof(ntp_keywords[0]), compare_key_tok_id);
+
+ lowest_id = ntp_keywords[0].token;
+ highest_id = ntp_keywords[COUNTOF(ntp_keywords) - 1].token;
+ id_count = highest_id - lowest_id + 1;
+
+ printf("#define LOWEST_KEYWORD_ID %d\n\n", lowest_id);
+
+ printf("const char * const keyword_text[%d] = {", id_count);
+
+ id = lowest_id;
+ i = 0;
+ while (i < COUNTOF(ntp_keywords)) {
+ while (id < ntp_keywords[i].token) {
+ printf(",\n\t/* %-5d %5d %20s */\tNULL",
+ id - lowest_id, id, symbname(id));
+ id++;
+ }
+ if (i > 0)
+ printf(",");
+ printf("\n\t/* %-5d %5d %20s */\t\"%s\"",
+ id - lowest_id, id, symbname(id),
+ ntp_keywords[i].key);
+ i++;
+ id++;
+ }
+
+ printf("\n};\n\n");
+}
+
+
+int
+compare_key_tok_id(
+ QSORTP a1,
+ QSORTP a2
+ )
+{
+ const struct key_tok *p1 = (const void *)a1;
+ const struct key_tok *p2 = (const void *)a2;
+
+ if (p1->token == p2->token)
+ return 0;
+
+ if (p1->token < p2->token)
+ return -1;
+ else
+ return 1;
+}
+
+
+int
+compare_key_tok_text(
+ QSORTP a1,
+ QSORTP a2
+ )
+{
+ const struct key_tok *p1 = (const void *)a1;
+ const struct key_tok *p2 = (const void *)a2;
+
+ return strcmp(p1->key, p2->key);
+}
+
+
+/*
+ * populate_symb() - populate symb[] lookup array with symbolic token
+ * names such that symb[T_Age] == "T_Age", etc.
+ */
+void
+populate_symb(
+ char *header_file
+ )
+{
+ FILE * yh;
+ char line[128];
+ char name[128];
+ int token;
+
+ yh = fopen(header_file, "r");
+ if (NULL == yh) {
+ perror("unable to open yacc/bison header file");
+ exit(4);
+ }
+
+ while (NULL != fgets(line, sizeof(line), yh))
+ if (2 == sscanf(line, "#define %s %d", name, &token)
+ && 'T' == name[0] && '_' == name[1] && token >= 0
+ && token < COUNTOF(symb))
+
+ symb[token] = estrdup(name);
+
+ fclose(yh);
+}
+
+
+const char *
+symbname(
+ int token
+ )
+{
+ char *name;
+
+ if (token >= 0 && token < COUNTOF(symb) && symb[token] != NULL)
+ return symb[token];
+
+ LIB_GETBUF(name);
+ snprintf(name, LIB_BUFLENGTH, "%d", token);
+ return name;
+}
diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c
index beb4c4847e71..db9682a74cbd 100644
--- a/ntpd/ntp_config.c
+++ b/ntpd/ntp_config.c
@@ -1,6 +1,14 @@
-/*
- * ntp_config.c - read and apply configuration information
+/* ntp_config.c
+ *
+ * This file contains the ntpd configuration code.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Some parts borrowed from the older ntp_config.c
+ * Copyright (c) 2006
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -9,20 +17,30 @@
# include <netinfo/ni.h>
#endif
+#include "ntp.h"
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_filegen.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+#include "ntpd-opts.h"
+/*
+ * Sim header. Currently unconditionally included
+ * PDMXXX This needs to be a conditional include
+ */
+#include "ntpsim.h"
+
#include <ntp_random.h>
+#include "ntp_intres.h"
#include <isc/net.h>
#include <isc/result.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
+# include <sys/param.h>
#endif
#include <signal.h>
#ifndef SIGCHLD
@@ -36,7 +54,6 @@
#ifdef SYS_WINNT
# include <io.h>
-static HANDLE ResolverThreadHandle = NULL;
HANDLE ResolverEventHandle;
#else
int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
@@ -50,288 +67,55 @@ int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent p
#include "ntp_config.h"
#include "ntp_cmdargs.h"
-extern int priority_done;
-
-/*
- * These routines are used to read the configuration file at
- * startup time. An entry in the file must fit on a single line.
- * Entries are processed as multiple tokens separated by white space
- * Lines are considered terminated when a '#' is encountered. Blank
- * lines are ignored.
- */
-/*
- * Translation table - keywords to function index
- */
-struct keyword {
- const char *text;
- int keytype;
-};
-
-/*
- * Command keywords
- */
-static struct keyword keywords[] = {
- { "automax", CONFIG_AUTOMAX },
- { "broadcast", CONFIG_BROADCAST },
- { "broadcastclient", CONFIG_BROADCASTCLIENT },
- { "broadcastdelay", CONFIG_BDELAY },
- { "calldelay", CONFIG_CDELAY},
-#ifdef OPENSSL
- { "crypto", CONFIG_CRYPTO },
-#endif /* OPENSSL */
- { "controlkey", CONFIG_CONTROLKEY },
- { "disable", CONFIG_DISABLE },
- { "driftfile", CONFIG_DRIFTFILE },
- { "enable", CONFIG_ENABLE },
- { "end", CONFIG_END },
- { "filegen", CONFIG_FILEGEN },
- { "fudge", CONFIG_FUDGE },
- { "includefile", CONFIG_INCLUDEFILE },
- { "keys", CONFIG_KEYS },
- { "keysdir", CONFIG_KEYSDIR },
- { "logconfig", CONFIG_LOGCONFIG },
- { "logfile", CONFIG_LOGFILE },
- { "manycastclient", CONFIG_MANYCASTCLIENT },
- { "manycastserver", CONFIG_MANYCASTSERVER },
- { "multicastclient", CONFIG_MULTICASTCLIENT },
- { "peer", CONFIG_PEER },
- { "phone", CONFIG_PHONE },
- { "pidfile", CONFIG_PIDFILE },
- { "discard", CONFIG_DISCARD },
- { "requestkey", CONFIG_REQUESTKEY },
- { "restrict", CONFIG_RESTRICT },
- { "revoke", CONFIG_REVOKE },
- { "server", CONFIG_SERVER },
- { "setvar", CONFIG_SETVAR },
- { "statistics", CONFIG_STATISTICS },
- { "statsdir", CONFIG_STATSDIR },
- { "tick", CONFIG_ADJ },
- { "tinker", CONFIG_TINKER },
- { "tos", CONFIG_TOS },
- { "trap", CONFIG_TRAP },
- { "trustedkey", CONFIG_TRUSTEDKEY },
- { "ttl", CONFIG_TTL },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "peer", "server", "broadcast" modifier keywords
- */
-static struct keyword mod_keywords[] = {
- { "autokey", CONF_MOD_SKEY },
- { "burst", CONF_MOD_BURST },
- { "iburst", CONF_MOD_IBURST },
- { "key", CONF_MOD_KEY },
- { "maxpoll", CONF_MOD_MAXPOLL },
- { "minpoll", CONF_MOD_MINPOLL },
- { "mode", CONF_MOD_MODE }, /* refclocks */
- { "noselect", CONF_MOD_NOSELECT },
- { "preempt", CONF_MOD_PREEMPT },
- { "true", CONF_MOD_TRUE },
- { "prefer", CONF_MOD_PREFER },
- { "ttl", CONF_MOD_TTL }, /* NTP peers */
- { "version", CONF_MOD_VERSION },
- { "dynamic", CONF_MOD_DYNAMIC },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "restrict" modifier keywords
- */
-static struct keyword res_keywords[] = {
- { "ignore", CONF_RES_IGNORE },
- { "limited", CONF_RES_LIMITED },
- { "kod", CONF_RES_DEMOBILIZE },
- { "lowpriotrap", CONF_RES_LPTRAP },
- { "mask", CONF_RES_MASK },
- { "nomodify", CONF_RES_NOMODIFY },
- { "nopeer", CONF_RES_NOPEER },
- { "noquery", CONF_RES_NOQUERY },
- { "noserve", CONF_RES_NOSERVE },
- { "notrap", CONF_RES_NOTRAP },
- { "notrust", CONF_RES_NOTRUST },
- { "ntpport", CONF_RES_NTPPORT },
- { "version", CONF_RES_VERSION },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "trap" modifier keywords
- */
-static struct keyword trap_keywords[] = {
- { "port", CONF_TRAP_PORT },
- { "interface", CONF_TRAP_INTERFACE },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "fudge" modifier keywords
- */
-static struct keyword fudge_keywords[] = {
- { "flag1", CONF_FDG_FLAG1 },
- { "flag2", CONF_FDG_FLAG2 },
- { "flag3", CONF_FDG_FLAG3 },
- { "flag4", CONF_FDG_FLAG4 },
- { "refid", CONF_FDG_REFID }, /* this mapping should be cleaned up (endianness, \0) - kd 20041031 */
- { "stratum", CONF_FDG_STRATUM },
- { "time1", CONF_FDG_TIME1 },
- { "time2", CONF_FDG_TIME2 },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "filegen" modifier keywords
- */
-static struct keyword filegen_keywords[] = {
- { "disable", CONF_FGEN_FLAG_DISABLE },
- { "enable", CONF_FGEN_FLAG_ENABLE },
- { "file", CONF_FGEN_FILE },
- { "link", CONF_FGEN_FLAG_LINK },
- { "nolink", CONF_FGEN_FLAG_NOLINK },
- { "type", CONF_FGEN_TYPE },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "type" modifier keywords
- */
-static struct keyword fgen_types[] = {
- { "age", FILEGEN_AGE },
- { "day", FILEGEN_DAY },
- { "month", FILEGEN_MONTH },
- { "none", FILEGEN_NONE },
- { "pid", FILEGEN_PID },
- { "week", FILEGEN_WEEK },
- { "year", FILEGEN_YEAR },
- { "", CONFIG_UNKNOWN}
-};
-
-/*
- * "enable", "disable" modifier keywords
- */
-static struct keyword flags_keywords[] = {
- { "auth", PROTO_AUTHENTICATE },
- { "bclient", PROTO_BROADCLIENT },
- { "calibrate", PROTO_CAL },
- { "kernel", PROTO_KERNEL },
- { "monitor", PROTO_MONITOR },
- { "ntp", PROTO_NTP },
- { "stats", PROTO_FILEGEN },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "discard" modifier keywords
- */
-static struct keyword discard_keywords[] = {
- { "average", CONF_DISCARD_AVERAGE },
- { "minimum", CONF_DISCARD_MINIMUM },
- { "monitor", CONF_DISCARD_MONITOR },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "tinker" modifier keywords
- */
-static struct keyword tinker_keywords[] = {
- { "step", CONF_CLOCK_MAX },
- { "panic", CONF_CLOCK_PANIC },
- { "dispersion", CONF_CLOCK_PHI },
- { "stepout", CONF_CLOCK_MINSTEP },
- { "allan", CONF_CLOCK_ALLAN },
- { "huffpuff", CONF_CLOCK_HUFFPUFF },
- { "freq", CONF_CLOCK_FREQ },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "tos" modifier keywords
- */
-static struct keyword tos_keywords[] = {
- { "minclock", CONF_TOS_MINCLOCK },
- { "maxclock", CONF_TOS_MAXCLOCK },
- { "minsane", CONF_TOS_MINSANE },
- { "floor", CONF_TOS_FLOOR },
- { "ceiling", CONF_TOS_CEILING },
- { "cohort", CONF_TOS_COHORT },
- { "mindist", CONF_TOS_MINDISP },
- { "maxdist", CONF_TOS_MAXDIST },
- { "maxhop", CONF_TOS_MAXHOP },
- { "beacon", CONF_TOS_BEACON },
- { "orphan", CONF_TOS_ORPHAN },
- { "", CONFIG_UNKNOWN }
-};
-
-#ifdef OPENSSL
-/*
- * "crypto" modifier keywords
- */
-static struct keyword crypto_keywords[] = {
- { "cert", CONF_CRYPTO_CERT },
- { "gqpar", CONF_CRYPTO_GQPAR },
- { "host", CONF_CRYPTO_RSA },
- { "ident", CONF_CRYPTO_IDENT },
- { "iffpar", CONF_CRYPTO_IFFPAR },
- { "leap", CONF_CRYPTO_LEAP },
- { "mvpar", CONF_CRYPTO_MVPAR },
- { "pw", CONF_CRYPTO_PW },
- { "randfile", CONF_CRYPTO_RAND },
- { "sign", CONF_CRYPTO_SIGN },
- { "", CONFIG_UNKNOWN }
-};
-#endif /* OPENSSL */
+#include "ntp_scanner.h"
+#include "ntp_parser.h"
+#include "ntp_data_structures.h"
-/*
- * Address type selection, IPv4 or IPv4.
- * Used on various lines.
- */
-static struct keyword addr_type[] = {
- { "-4", CONF_ADDR_IPV4 },
- { "-6", CONF_ADDR_IPV6 },
- { "", CONFIG_UNKNOWN }
-};
/*
* "logconfig" building blocks
*/
struct masks {
- const char *name;
- unsigned long mask;
+ const char * const name;
+ const u_int32 mask;
};
static struct masks logcfg_class[] = {
- { "clock", NLOG_OCLOCK },
- { "peer", NLOG_OPEER },
- { "sync", NLOG_OSYNC },
- { "sys", NLOG_OSYS },
- { (char *)0, 0 }
+ { "clock", NLOG_OCLOCK },
+ { "peer", NLOG_OPEER },
+ { "sync", NLOG_OSYNC },
+ { "sys", NLOG_OSYS },
+ { NULL, 0 }
};
-static struct masks logcfg_item[] = {
+/* logcfg_noclass_items[] masks are complete and must not be shifted */
+static struct masks logcfg_noclass_items[] = {
+ { "allall", NLOG_SYSMASK | NLOG_PEERMASK | NLOG_CLOCKMASK | NLOG_SYNCMASK },
+ { "allinfo", NLOG_SYSINFO | NLOG_PEERINFO | NLOG_CLOCKINFO | NLOG_SYNCINFO },
+ { "allevents", NLOG_SYSEVENT | NLOG_PEEREVENT | NLOG_CLOCKEVENT | NLOG_SYNCEVENT },
+ { "allstatus", NLOG_SYSSTATUS | NLOG_PEERSTATUS | NLOG_CLOCKSTATUS | NLOG_SYNCSTATUS },
+ { "allstatistics", NLOG_SYSSTATIST | NLOG_PEERSTATIST | NLOG_CLOCKSTATIST | NLOG_SYNCSTATIST },
+ /* the remainder are misspellings of clockall, peerall, sysall, and syncall. */
+ { "allclock", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OCLOCK },
+ { "allpeer", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OPEER },
+ { "allsys", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYS },
+ { "allsync", (NLOG_INFO | NLOG_STATIST | NLOG_EVENT | NLOG_STATUS) << NLOG_OSYNC },
+ { NULL, 0 }
+};
+
+/* logcfg_class_items[] masks are shiftable by NLOG_O* counts */
+static struct masks logcfg_class_items[] = {
+ { "all", NLOG_INFO | NLOG_EVENT | NLOG_STATUS | NLOG_STATIST },
{ "info", NLOG_INFO },
- { "allinfo", NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO },
{ "events", NLOG_EVENT },
- { "allevents", NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT },
{ "status", NLOG_STATUS },
- { "allstatus", NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS },
{ "statistics", NLOG_STATIST },
- { "allstatistics", NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST },
- { "allclock", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK },
- { "allpeer", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER },
- { "allsys", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
- { "allsync", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
- { "all", NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
- { (char *)0, 0 }
+ { NULL, 0 }
};
-/*
- * Limits on things
- */
-#define MAXTOKENS 20 /* 20 tokens on line */
-#define MAXLINE 1024 /* maximum length of line */
+/* Limits */
#define MAXPHONE 10 /* maximum number of phone strings */
#define MAXPPS 20 /* maximum length of PPS device string */
-#define MAXINCLUDELEVEL 5 /* maximum include file levels */
/*
* Miscellaneous macros
@@ -341,14 +125,11 @@ 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.
*/
int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
-static FILE *res_fp;
#ifndef SYS_WINNT
static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
#define RES_TEMPFILE "/tmp/ntpXXXXXX"
@@ -359,25 +140,38 @@ static char res_file[MAX_PATH];
/*
* Definitions of things either imported from or exported to outside
*/
-
-short default_ai_family = AF_UNSPEC; /* Default either IPv4 or IPv6 */
-char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
-char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
+extern int yydebug; /* ntp_parser.c (.y) */
+int curr_include_level; /* The current include level */
+struct FILE_INFO *fp[MAXINCLUDELEVEL+1];
+FILE *res_fp;
+struct config_tree cfgt; /* Parser output stored here */
+struct config_tree *cfg_tree_history = NULL; /* History of configs */
+char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
+char default_keysdir[] = NTP_KEYSDIR;
+char *keysdir = default_keysdir; /* crypto keys directory */
+char * saveconfigdir;
#if defined(HAVE_SCHED_SETSCHEDULER)
int config_priority_override = 0;
int config_priority;
#endif
const char *config_file;
+char default_ntp_signd_socket[] =
+#ifdef NTP_SIGND_PATH
+ NTP_SIGND_PATH;
+#else
+ "";
+#endif
+char *ntp_signd_socket = default_ntp_signd_socket;
#ifdef HAVE_NETINFO
- struct netinfo_config_state *config_netinfo = NULL;
- int check_netinfo = 1;
+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];
+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
@@ -393,1513 +187,3744 @@ struct netinfo_config_state {
};
#endif
+struct REMOTE_CONFIG_INFO remote_config; /* Remote configuration buffer and
+ pointer info */
+int input_from_file = 1; /* A boolean flag, which when set, indicates that
+ the input is to be taken from the configuration
+ file, instead of the remote-configuration buffer
+ */
+
+int old_config_style = 1; /* A boolean flag, which when set,
+ * indicates that the old configuration
+ * format with a newline at the end of
+ * every command is being used
+ */
+int cryptosw; /* crypto command called */
+
+extern int sys_maxclock;
+extern char *stats_drift_file; /* name of the driftfile */
+extern char *leapseconds_file_name; /*name of the leapseconds file */
+#ifdef HAVE_IPTOS_SUPPORT
+extern unsigned int qos; /* QoS setting */
+#endif /* HAVE_IPTOS_SUPPORT */
+
+#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
/*
- * Function prototypes
+ * backwards compatibility flags
*/
-static unsigned long get_pfxmatch P((char **, struct masks *));
-static unsigned long get_match P((char *, struct masks *));
-static unsigned long get_logmask P((char *));
-#ifdef HAVE_NETINFO
-static struct netinfo_config_state *get_netinfo_config P((void));
-static void free_netinfo_config P((struct netinfo_config_state *));
-static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
+bc_entry bc_list[] = {
+ { T_Bc_bugXXXX, 1 } /* default enabled */
+};
+
+/*
+ * declare an int pointer for each flag for quick testing without
+ * walking bc_list. If the pointer is consumed by libntp rather
+ * than ntpd, declare it in a libntp source file pointing to storage
+ * initialized with the appropriate value for other libntp clients, and
+ * redirect it to point into bc_list during ntpd startup.
+ */
+int *p_bcXXXX_enabled = &bc_list[0].enabled;
#endif
-static int gettokens P((FILE *, char *, char **, int *));
-static int matchkey P((char *, struct keyword *, int));
+
+/* FUNCTION PROTOTYPES */
+
+static void apply_enable_disable(queue *q, int enable);
+static void init_syntax_tree(struct config_tree *);
+
+#ifdef FREE_CFG_T
+static void free_auth_node(struct config_tree *);
+
+static void free_config_other_modes(struct config_tree *);
+static void free_config_auth(struct config_tree *);
+static void free_config_tos(struct config_tree *);
+static void free_config_monitor(struct config_tree *);
+static void free_config_access(struct config_tree *);
+static void free_config_tinker(struct config_tree *);
+static void free_config_system_opts(struct config_tree *);
+static void free_config_logconfig(struct config_tree *);
+static void free_config_phone(struct config_tree *);
+static void free_config_qos(struct config_tree *);
+static void free_config_setvar(struct config_tree *);
+static void free_config_ttl(struct config_tree *);
+static void free_config_trap(struct config_tree *);
+static void free_config_fudge(struct config_tree *);
+static void free_config_vars(struct config_tree *);
+static void free_config_peers(struct config_tree *);
+static void free_config_unpeers(struct config_tree *);
+static void free_config_nic_rules(struct config_tree *);
+#ifdef SIM
+static void free_config_sim(struct config_tree *);
+#endif
+
+ void free_all_config_trees(void); /* atexit() */
+static void free_config_tree(struct config_tree *ptree);
+#endif /* FREE_CFG_T */
+
+double *create_dval(double val);
+void destroy_restrict_node(struct restrict_node *my_node);
+static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
+static int get_correct_host_mode(int hmode);
+static void save_and_apply_config_tree(void);
+void getconfig(int argc,char *argv[]);
+#if !defined(SIM)
+static sockaddr_u *get_next_address(struct address_node *addr);
+#endif
+
+static void config_other_modes(struct config_tree *);
+static void config_auth(struct config_tree *);
+static void config_tos(struct config_tree *);
+static void config_monitor(struct config_tree *);
+static void config_access(struct config_tree *);
+static void config_tinker(struct config_tree *);
+static void config_system_opts(struct config_tree *);
+static void config_logconfig(struct config_tree *);
+static void config_phone(struct config_tree *);
+static void config_qos(struct config_tree *);
+static void config_setvar(struct config_tree *);
+static void config_ttl(struct config_tree *);
+static void config_trap(struct config_tree *);
+static void config_fudge(struct config_tree *);
+static void config_vars(struct config_tree *);
+static void config_peers(struct config_tree *);
+static void config_unpeers(struct config_tree *);
+static void config_nic_rules(struct config_tree *);
+
+#ifdef SIM
+static void config_sim(struct config_tree *);
+static void config_ntpdsim(struct config_tree *);
+#else
+static void config_ntpd(struct config_tree *);
+#endif
+
enum gnn_type {
t_UNK, /* Unknown */
t_REF, /* Refclock */
t_MSK /* Network Mask */
- };
-static int getnetnum P((const char *, struct sockaddr_storage *, int,
- enum gnn_type));
-static void save_resolve P((char *, int, int, int, int, u_int, int,
- keyid_t, u_char *));
-static void do_resolve_internal P((void));
-static void abort_resolve P((void));
-#if !defined(VMS) && !defined(SYS_WINNT)
-static RETSIGTYPE catchchild P((int));
-#endif /* VMS */
+};
-/*
- * get_pfxmatch - find value for prefixmatch
- * and update char * accordingly
+#define DESTROY_QUEUE(q) \
+do { \
+ if (q) { \
+ destroy_queue(q); \
+ (q) = NULL; \
+ } \
+} while (0)
+
+void ntpd_set_tod_using(const char *);
+static u_int32 get_pfxmatch(const char **, struct masks *);
+static u_int32 get_match(const char *, struct masks *);
+static u_int32 get_logmask(const char *);
+static int getnetnum(const char *num,sockaddr_u *addr, int complain,
+ enum gnn_type a_type);
+static int get_multiple_netnums(const char *num, sockaddr_u *addr,
+ struct addrinfo **res, int complain,
+ enum gnn_type a_type);
+static void save_resolve(char *name, int no_needed, int type,
+ int mode, int version, int minpoll, int maxpoll,
+ u_int flags, int ttl, keyid_t keyid, u_char *keystr);
+static void abort_resolve(void);
+static void do_resolve_internal(void);
+
+
+
+/* FUNCTIONS FOR INITIALIZATION
+ * ----------------------------
*/
-static unsigned long
-get_pfxmatch(
- char ** s,
- struct masks *m
+
+#ifdef FREE_CFG_T
+static void
+free_auth_node(
+ struct config_tree *ptree
)
{
- while (m->name) {
- if (strncmp(*s, m->name, strlen(m->name)) == 0) {
- *s += strlen(m->name);
- return m->mask;
- } else {
- m++;
- }
+ if (ptree->auth.keys) {
+ free(ptree->auth.keys);
+ ptree->auth.keys = NULL;
}
- return 0;
-}
-/*
- * get_match - find logmask value
- */
-static unsigned long
-get_match(
- char *s,
- struct masks *m
- )
-{
- while (m->name) {
- if (strcmp(s, m->name) == 0) {
- return m->mask;
- } else {
- m++;
- }
+ if (ptree->auth.keysdir) {
+ free(ptree->auth.keysdir);
+ ptree->auth.keysdir = NULL;
+ }
+
+ if (ptree->auth.ntp_signd_socket) {
+ free(ptree->auth.ntp_signd_socket);
+ ptree->auth.ntp_signd_socket = NULL;
}
- return 0;
}
+#endif /* DEBUG */
-/*
- * get_logmask - build bitmask for ntp_syslogmask
- */
-static unsigned long
-get_logmask(
- char *s
+
+static void
+init_syntax_tree(
+ struct config_tree *ptree
)
{
- char *t;
- unsigned long offset;
- unsigned long mask;
+ memset(ptree, 0, sizeof(*ptree));
+
+ ptree->peers = create_queue();
+ ptree->unpeers = create_queue();
+ ptree->orphan_cmds = create_queue();
+ ptree->manycastserver = create_queue();
+ ptree->multicastclient = create_queue();
+ ptree->stats_list = create_queue();
+ ptree->filegen_opts = create_queue();
+ ptree->discard_opts = create_queue();
+ ptree->restrict_opts = create_queue();
+ ptree->enable_opts = create_queue();
+ ptree->disable_opts = create_queue();
+ ptree->tinker = create_queue();
+ ptree->fudge = create_queue();
+ ptree->logconfig = create_queue();
+ ptree->phone = create_queue();
+ ptree->qos = create_queue();
+ ptree->setvar = create_queue();
+ ptree->ttl = create_queue();
+ ptree->trap = create_queue();
+ ptree->vars = create_queue();
+ ptree->nic_rules = create_queue();
+ ptree->auth.crypto_cmd_list = create_queue();
+ ptree->auth.trusted_key_list = create_queue();
+}
- t = s;
- offset = get_pfxmatch(&t, logcfg_class);
- mask = get_match(t, logcfg_item);
- if (mask)
- return mask << offset;
- else
- msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
+#ifdef FREE_CFG_T
+void
+free_all_config_trees(void)
+{
+ struct config_tree *ptree;
+ struct config_tree *pnext;
- return 0;
+ ptree = cfg_tree_history;
+
+ while (ptree != NULL) {
+ pnext = ptree->link;
+ free_config_tree(ptree);
+ ptree = pnext;
+ }
}
-/*
- * getconfig - get command line options and read the configuration file
- */
-void
-getconfig(
- int argc,
- char *argv[]
+static void
+free_config_tree(
+ struct config_tree *ptree
)
{
- register int i;
- int c;
- int errflg;
- int status;
- int istart;
- int peerversion;
- int minpoll;
- int maxpoll;
- int ttl;
- long stratum;
- unsigned long ul;
- keyid_t peerkey;
- u_char *peerkeystr;
- u_long fudgeflag;
- u_int peerflags;
- int hmode;
- struct sockaddr_storage peeraddr;
- struct sockaddr_storage maskaddr;
- FILE *fp[MAXINCLUDELEVEL+1];
- FILE *includefile;
- int includelevel = 0;
- char line[MAXLINE];
- char *(tokens[MAXTOKENS]);
- int ntokens = 0;
- int tok = CONFIG_UNKNOWN;
- struct interface *localaddr;
- struct refclockstat clock_stat;
- FILEGEN *filegen;
+#if defined(_MSC_VER) && defined (_DEBUG)
+ _CrtCheckMemory();
+#endif
+ if (ptree->source.value.s != NULL)
+ free(ptree->source.value.s);
+
+ free_config_other_modes(ptree);
+ free_config_auth(ptree);
+ free_config_tos(ptree);
+ free_config_monitor(ptree);
+ free_config_access(ptree);
+ free_config_tinker(ptree);
+ free_config_system_opts(ptree);
+ free_config_logconfig(ptree);
+ free_config_phone(ptree);
+ free_config_qos(ptree);
+ free_config_setvar(ptree);
+ free_config_ttl(ptree);
+ free_config_trap(ptree);
+ free_config_fudge(ptree);
+ free_config_vars(ptree);
+ free_config_peers(ptree);
+ free_config_unpeers(ptree);
+ free_config_nic_rules(ptree);
+#ifdef SIM
+ free_config_sim(ptree);
+#endif
/*
- * Initialize, initialize
+ * Most of these DESTROY_QUEUE()s are handled already by the
+ * free_config_*() routines above but it's safe to use twice.
+ * Please feel free to remove ones you verified are handled
+ * in a free_config_*() routine.
*/
- errflg = 0;
-
-#ifndef SYS_WINNT
- config_file = CONFIG_FILE;
-#else
- temp = CONFIG_FILE;
- if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
- msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
- exit(1);
- }
- config_file = config_file_storage;
+ DESTROY_QUEUE(ptree->peers);
+ DESTROY_QUEUE(ptree->unpeers);
+ DESTROY_QUEUE(ptree->orphan_cmds);
+ DESTROY_QUEUE(ptree->manycastserver);
+ DESTROY_QUEUE(ptree->multicastclient);
+ DESTROY_QUEUE(ptree->stats_list);
+ DESTROY_QUEUE(ptree->filegen_opts);
+ DESTROY_QUEUE(ptree->discard_opts);
+ DESTROY_QUEUE(ptree->restrict_opts);
+ DESTROY_QUEUE(ptree->enable_opts);
+ DESTROY_QUEUE(ptree->disable_opts);
+ DESTROY_QUEUE(ptree->tinker);
+ DESTROY_QUEUE(ptree->fudge);
+ DESTROY_QUEUE(ptree->logconfig);
+ DESTROY_QUEUE(ptree->phone);
+ DESTROY_QUEUE(ptree->qos);
+ DESTROY_QUEUE(ptree->setvar);
+ DESTROY_QUEUE(ptree->ttl);
+ DESTROY_QUEUE(ptree->trap);
+ DESTROY_QUEUE(ptree->vars);
+
+ free_auth_node(ptree);
+
+ free(ptree);
+
+#if defined(_MSC_VER) && defined (_DEBUG)
+ _CrtCheckMemory();
+#endif
+}
+#endif /* FREE_CFG_T */
- temp = ALT_CONFIG_FILE;
- if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
- msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
- exit(1);
+
+#ifdef SAVECONFIG
+/* Dump all trees */
+int
+dump_all_config_trees(
+ FILE *df,
+ int comment
+ )
+{
+ struct config_tree *cfg_ptr = cfg_tree_history;
+ int return_value = 0;
+
+ for (cfg_ptr = cfg_tree_history;
+ cfg_ptr != NULL;
+ cfg_ptr = cfg_ptr->link)
+ return_value |= dump_config_tree(cfg_ptr, df, comment);
+
+ return return_value;
+}
+
+
+/* The config dumper */
+int
+dump_config_tree(
+ struct config_tree *ptree,
+ FILE *df,
+ int comment
+ )
+{
+ struct peer_node *peer = NULL;
+ struct unpeer_node *unpeers = NULL;
+ struct attr_val *atrv = NULL;
+ struct address_node *addr = NULL;
+ struct address_node *peer_addr;
+ struct address_node *fudge_addr;
+ struct filegen_node *fgen_node = NULL;
+ struct restrict_node *rest_node = NULL;
+ struct addr_opts_node *addr_opts = NULL;
+ struct setvar_node *setv_node = NULL;
+ nic_rule_node *rule_node;
+
+ char **pstr = NULL;
+ char *s1;
+ char *s2;
+ int *intp = NULL;
+ void *fudge_ptr;
+ void *list_ptr = NULL;
+ void *options = NULL;
+ void *opt_ptr = NULL;
+ int *flags = NULL;
+ void *opts = NULL;
+ char timestamp[80];
+ int enable;
+
+ DPRINTF(1, ("dump_config_tree(%p)\n", ptree));
+
+ if (comment) {
+ if (!strftime(timestamp, sizeof(timestamp),
+ "%Y-%m-%d %H:%M:%S",
+ localtime(&ptree->timestamp)))
+ timestamp[0] = '\0';
+
+ fprintf(df, "# %s %s %s\n",
+ timestamp,
+ (CONF_SOURCE_NTPQ == ptree->source.attr)
+ ? "ntpq remote config from"
+ : "startup configuration file",
+ ptree->source.value.s);
}
- alt_config_file = alt_config_file_storage;
-#endif /* SYS_WINNT */
- res_fp = NULL;
- ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
+ /* For options I didn't find documentation I'll just output its name and the cor. value */
+ list_ptr = queue_head(ptree->vars);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
- /*
- * install a non default variable with this daemon version
- */
- (void) sprintf(line, "daemon_version=\"%s\"", Version);
- set_sys_var(line, strlen(line)+1, RO);
+ atrv = (struct attr_val *) list_ptr;
- /*
- * Say how we're setting the time of day
- */
- (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
- set_sys_var(line, strlen(line)+1, RO);
+ switch (atrv->attr) {
- /*
- * Initialize the loop.
- */
- loop_config(LOOP_DRIFTINIT, 0.);
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown vars token %s\n",
+ token_name(atrv->attr));
+ break;
- getCmdOpts(argc, argv);
+ /* doubles */
+ case T_Broadcastdelay:
+ case T_Tick:
+ case T_WanderThreshold:
+ fprintf(df, "%s %g\n",
+ keyword(atrv->attr),
+ atrv->value.d);
+ break;
+
+ /* ints */
+ case T_Calldelay:
+#ifdef OPENSSL
+ case T_Automax:
+#endif
+ fprintf(df, "%s %d\n",
+ keyword(atrv->attr),
+ atrv->value.i);
+ break;
- if (
- (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
-#ifdef HAVE_NETINFO
- /* If there is no config_file, try NetInfo. */
- && check_netinfo && !(config_netinfo = get_netinfo_config())
-#endif /* HAVE_NETINFO */
- ) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
-#ifdef SYS_WINNT
- /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
+ /* strings */
+ case T_Driftfile:
+ case T_Leapfile:
+ case T_Logfile:
+ case T_Pidfile:
+ case T_Saveconfigdir:
+ fprintf(df, "%s \"%s\"\n",
+ keyword(atrv->attr),
+ atrv->value.s);
+ break;
+ }
+ }
- if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
+ list_ptr = queue_head(ptree->logconfig);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "logconfig");
- /*
- * Broadcast clients can sometimes run without
- * a configuration file.
- */
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
- return;
+ atrv = list_ptr;
+ fprintf(df, " %c%s", atrv->attr, atrv->value.s);
}
-#else /* not SYS_WINNT */
- return;
-#endif /* not SYS_WINNT */
+ fprintf(df, "\n");
}
- for (;;) {
- if (tok == CONFIG_END)
- break;
- 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 (ptree->stats_dir)
+ fprintf(df, "statsdir \"%s\"\n", ptree->stats_dir);
- if (tok == CONFIG_UNKNOWN) {
- if (includelevel > 0) {
- fclose(fp[includelevel--]);
- continue;
- } else {
- break;
- }
- }
-
- switch(tok) {
- case CONFIG_PEER:
- case CONFIG_SERVER:
- case CONFIG_MANYCASTCLIENT:
- case CONFIG_BROADCAST:
- if (tok == CONFIG_PEER)
- hmode = MODE_ACTIVE;
- else if (tok == CONFIG_SERVER)
- hmode = MODE_CLIENT;
- else if (tok == CONFIG_MANYCASTCLIENT)
- hmode = MODE_CLIENT;
- else
- hmode = MODE_BROADCAST;
+ list_ptr = queue_head(ptree->stats_list);
+ if (list_ptr != NULL) {
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "No address for %s, line ignored",
- tokens[0]);
+ fprintf(df, "statistics");
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ intp = list_ptr;
+
+ fprintf(df, " %s", keyword(*intp));
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->filegen_opts);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ fgen_node = list_ptr;
+ opt_ptr = queue_head(fgen_node->options);
+
+ if (opt_ptr != NULL)
+ fprintf(df, "filegen %s",
+ keyword(fgen_node->filegen_token));
+
+ for(; opt_ptr != NULL;
+ opt_ptr = next_node(opt_ptr)) {
+
+ atrv = opt_ptr;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown filegen option token %s\n"
+ "filegen %s",
+ token_name(atrv->attr),
+ keyword(fgen_node->filegen_token));
break;
- }
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
+ case T_File:
+ fprintf(df, " file %s",
+ atrv->value.s);
break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
+
+ case T_Type:
+ fprintf(df, " type %s",
+ keyword(atrv->value.i));
+ break;
+
+ case T_Flag:
+ fprintf(df, " %s",
+ keyword(atrv->value.i));
break;
}
- status = getnetnum(tokens[istart], &peeraddr, 0, t_UNK);
- if (status == -1)
- break; /* Found IPv6 address */
- if(status != 1) {
- errflg = -1;
- } else {
- errflg = 0;
+ }
- if (
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- ISBADADR(&peeraddr)) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
- break;
- }
- /*
- * Shouldn't be able to specify multicast
- * address for server/peer!
- * and unicast address for manycastclient!
- */
- if (peeraddr.ss_family == AF_INET) {
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->auth.crypto_cmd_list);
+ if (list_ptr != NULL) {
+ fprintf(df, "crypto");
+
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s %s", keyword(atrv->attr),
+ atrv->value.s);
+ }
+ fprintf(df, "\n");
+ }
+
+ if (ptree->auth.revoke != 0)
+ fprintf(df, "revoke %d\n", ptree->auth.revoke);
+
+ if (NULL != ptree->auth.keysdir)
+ fprintf(df, "keysdir \"%s\"\n", ptree->auth.keysdir);
+
+ if (NULL != ptree->auth.keys)
+ fprintf(df, "keys \"%s\"\n", ptree->auth.keys);
+
+ atrv = queue_head(ptree->auth.trusted_key_list);
+ if (atrv != NULL) {
+ fprintf(df, "trustedkey");
+ do {
+ if ('i' == atrv->attr)
+ fprintf(df, " %d", atrv->value.i);
+ else if ('-' == atrv->attr)
+ fprintf(df, " (%u ... %u)",
+ atrv->value.u >> 16,
+ atrv->value.u & 0xffff);
+ else
+ fprintf(df, "\n# dump error:\n"
+ "# unknown trustedkey attr %d\n"
+ "trustedkey", atrv->attr);
+ } while (NULL != (atrv = next_node(atrv)));
+ fprintf(df, "\n");
+ }
+
+ if (ptree->auth.control_key)
+ fprintf(df, "controlkey %d\n", ptree->auth.control_key);
+
+ if (ptree->auth.request_key)
+ fprintf(df, "requestkey %d\n", ptree->auth.request_key);
+
+ /* dump enable list, then disable list */
+ for (enable = 1; enable >= 0; enable--) {
+
+ list_ptr = (enable)
+ ? queue_head(ptree->enable_opts)
+ : queue_head(ptree->disable_opts);
+
+ if (list_ptr != NULL) {
+ fprintf(df, (enable)
+ ? "enable"
+ : "disable");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = (struct attr_val *) list_ptr;
+
+ fprintf(df, " %s",
+ keyword(atrv->value.i));
+ }
+ fprintf(df, "\n");
+ }
+ }
+
+ list_ptr = queue_head(ptree->orphan_cmds);
+ if (list_ptr != NULL)
+ fprintf(df, "tos");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown tos token %s\n"
+ "tos", token_name(atrv->attr));
+ break;
+
+ /* ints */
+ case T_Ceiling:
+ case T_Floor:
+ case T_Cohort:
+ case T_Orphan:
+ case T_Minclock:
+ case T_Maxclock:
+ case T_Minsane:
+ case T_Beacon:
+ fprintf(df, " %s %d", keyword(atrv->attr),
+ (int)atrv->value.d);
+ break;
+
+ /* doubles */
+ case T_Mindist:
+ case T_Maxdist:
+ fprintf(df, " %s %g", keyword(atrv->attr),
+ atrv->value.d);
+ break;
+ }
+ }
+ if (queue_head(ptree->orphan_cmds) != NULL)
+ fprintf(df, "\n");
+
+ list_ptr = queue_head(ptree->tinker);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "tinker");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s %g", keyword(atrv->attr),
+ atrv->value.d);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ if (ptree->broadcastclient)
+ fprintf(df, "broadcastclient\n");
+
+ list_ptr = queue_head(ptree->peers);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ peer = list_ptr;
+ addr = peer->addr;
+ fprintf(df, "%s", keyword(peer->host_mode));
+
+ switch (addr->type) {
+
+ default:
+ fprintf(df, "# dump error:\n"
+ "# unknown peer family %d for:\n"
+ "peer", addr->type);
+ break;
+
+ case AF_UNSPEC:
+ break;
+
+ case AF_INET:
+ fprintf(df, " -4");
+ break;
+
+ case AF_INET6:
+ fprintf(df, " -6");
+ break;
+ }
+ fprintf(df, " %s", addr->address);
+
+ if (peer->minpoll != 0)
+ fprintf(df, " minpoll %d", peer->minpoll);
+
+ if (peer->maxpoll != 0)
+ fprintf(df, " maxpoll %d", peer->maxpoll);
+
+ if (peer->ttl != 0) {
+ if (strlen(addr->address) > 8
+ && !memcmp(addr->address, "127.127.", 8))
+ fprintf(df, " mode %d", peer->ttl);
+ else
+ fprintf(df, " ttl %d", peer->ttl);
+ }
+
+ if (peer->peerversion != NTP_VERSION)
+ fprintf(df, " version %d", peer->peerversion);
+
+ if (peer->peerkey != 0)
+ fprintf(df, " key %d", peer->peerkey);
+
+ if (peer->bias != 0.)
+ fprintf(df, " bias %g", peer->bias);
+
+ for (atrv = queue_head(peer->peerflags);
+ atrv != NULL;
+ atrv = next_node(atrv)) {
+
+ NTP_INSIST(T_Flag == atrv->attr);
+ NTP_INSIST(T_Integer == atrv->type);
+
+ fprintf(df, " %s", keyword(atrv->value.i));
+ }
+
+ fprintf(df, "\n");
+
+ fudge_ptr = queue_head(ptree->fudge);
+ for(; fudge_ptr != NULL;
+ fudge_ptr = next_node(fudge_ptr)) {
+
+
+ addr_opts = (struct addr_opts_node *) fudge_ptr;
+ peer_addr = peer->addr;
+ fudge_addr = addr_opts->addr;
+
+ s1 = peer_addr->address;
+ s2 = fudge_addr->address;
+
+ if (!strcmp(s1, s2)) {
+
+ fprintf(df, "fudge %s", addr_opts->addr->address);
+
+ opts = queue_head(addr_opts->options);
+
+ for(; opts != NULL; opts = next_node(opts)) {
+ atrv = (struct attr_val *) opts;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown fudge option %s\n"
+ "fudge %s",
+ token_name(atrv->attr),
+ addr_opts->addr->address);
break;
- }
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
+
+ /* doubles */
+ case T_Time1:
+ case T_Time2:
+ fprintf(df, " %s %g",
+ keyword(atrv->attr),
+ atrv->value.d);
+ break;
+
+ /* ints */
+ case T_Stratum:
+ case T_Flag1:
+ case T_Flag2:
+ case T_Flag3:
+ case T_Flag4:
+ fprintf(df, " %s %d",
+ keyword(atrv->attr),
+ atrv->value.i);
+ break;
+
+ /* strings */
+ case T_Refid:
+ fprintf(df, " %s %s",
+ keyword(atrv->attr),
+ atrv->value.s);
break;
}
}
- else if(peeraddr.ss_family == AF_INET6) {
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
- msyslog(LOG_ERR,
- "attempt to configure in valid address %s",
- stoa(&peeraddr));
- break;
- }
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
- msyslog(LOG_ERR,
- "attempt to configure in valid address %s",
- stoa(&peeraddr));
- break;
- }
- }
+ fprintf(df, "\n");
}
- if (peeraddr.ss_family == AF_INET6 &&
- isc_net_probeipv6() != ISC_R_SUCCESS)
- break;
+ }
+ }
- peerversion = NTP_VERSION;
- minpoll = NTP_MINDPOLL;
- maxpoll = NTP_MAXDPOLL;
- peerkey = 0;
- peerkeystr = (u_char *)"*";
- peerflags = 0;
- ttl = 0;
- istart++;
- for (i = istart; i < ntokens; i++)
- switch (matchkey(tokens[i], mod_keywords, 1)) {
- case CONF_MOD_VERSION:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "peer/server version requires an argument");
- errflg = 1;
- break;
- }
- peerversion = atoi(tokens[++i]);
- if ((u_char)peerversion > NTP_VERSION
- || (u_char)peerversion < NTP_OLDVERSION) {
- msyslog(LOG_ERR,
- "inappropriate version number %s, line ignored",
- tokens[i]);
- errflg = 1;
- }
- break;
-
- case CONF_MOD_KEY:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "key: argument required");
- errflg = 1;
- break;
- }
- peerkey = (int)atol(tokens[++i]);
- peerflags |= FLAG_AUTHENABLE;
- break;
-
- case CONF_MOD_MINPOLL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "minpoll: argument required");
- errflg = 1;
- break;
- }
- minpoll = atoi(tokens[++i]);
- if (minpoll < NTP_MINPOLL) {
- msyslog(LOG_INFO,
- "minpoll: provided value (%d) is below minimum (%d)",
- minpoll, NTP_MINPOLL);
- minpoll = NTP_MINPOLL;
- }
- break;
-
- case CONF_MOD_MAXPOLL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "maxpoll: argument required"
- );
- errflg = 1;
- break;
- }
- maxpoll = atoi(tokens[++i]);
- if (maxpoll > NTP_MAXPOLL) {
- msyslog(LOG_INFO,
- "maxpoll: provided value (%d) is above maximum (%d)",
- maxpoll, NTP_MAXPOLL);
- maxpoll = NTP_MAXPOLL;
- }
- break;
-
- case CONF_MOD_PREFER:
- peerflags |= FLAG_PREFER;
- break;
-
- case CONF_MOD_PREEMPT:
- peerflags |= FLAG_PREEMPT;
- break;
-
- case CONF_MOD_NOSELECT:
- peerflags |= FLAG_NOSELECT;
- break;
-
- case CONF_MOD_TRUE:
- peerflags |= FLAG_TRUE;
-
- case CONF_MOD_BURST:
- peerflags |= FLAG_BURST;
- break;
-
- case CONF_MOD_IBURST:
- peerflags |= FLAG_IBURST;
- break;
-
- case CONF_MOD_DYNAMIC:
- msyslog(LOG_WARNING,
- "Warning: the \"dynamic\" keyword has been obsoleted"
- " and will be removed in the next release\n");
- break;
+ list_ptr = queue_head(ptree->manycastserver);
+ if (list_ptr != NULL) {
+ addr = list_ptr;
+ fprintf(df, "manycastserver %s", addr->address);
+ for (addr = next_node(addr);
+ addr != NULL;
+ addr = next_node(addr))
+ fprintf(df, " %s", addr->address);
+ fprintf(df, "\n");
+ }
-#ifdef OPENSSL
- case CONF_MOD_SKEY:
- peerflags |= FLAG_SKEY |
- FLAG_AUTHENABLE;
- break;
-#endif /* OPENSSL */
+ list_ptr = queue_head(ptree->multicastclient);
+ if (list_ptr != NULL) {
+ addr = list_ptr;
+ fprintf(df, "multicastclient %s", addr->address);
+ for (addr = next_node(addr);
+ addr != NULL;
+ addr = next_node(addr))
+ fprintf(df, " %s", addr->address);
+ fprintf(df, "\n");
+ }
- case CONF_MOD_TTL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "ttl: argument required");
- errflg = 1;
- break;
- }
- ttl = atoi(tokens[++i]);
- if (ttl >= MAX_TTL) {
- msyslog(LOG_ERR,
- "ttl: invalid argument");
- errflg = 1;
- }
- break;
+ list_ptr = queue_head(ptree->unpeers);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ unpeers = (struct unpeer_node *) list_ptr;
+
+ fprintf(df, "unpeer %s\n", (unpeers->addr)->address);
+ }
- case CONF_MOD_MODE:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "mode: argument required");
- errflg = 1;
- break;
- }
- ttl = atoi(tokens[++i]);
- break;
-
- case CONFIG_UNKNOWN:
- errflg = 1;
- break;
- }
- if (minpoll > maxpoll) {
- msyslog(LOG_ERR,
- "config error: minpoll > maxpoll");
- errflg = 1;
+ list_ptr = queue_head(ptree->discard_opts);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "discard");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s %d", keyword(atrv->attr),
+ atrv->value.i);
+ }
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->restrict_opts);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ rest_node = list_ptr;
+ if (NULL == rest_node->addr)
+ s1 = "default";
+ else
+ s1 = rest_node->addr->address;
+
+ fprintf(df, "restrict %s", s1);
+
+ if (rest_node->mask != NULL)
+ fprintf(df, " mask %s",
+ rest_node->mask->address);
+
+ flags = queue_head(rest_node->flags);
+ for (; flags != NULL; flags = next_node(flags))
+ fprintf(df, " %s", keyword(*flags));
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->nic_rules);
+ for (; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ rule_node = list_ptr;
+ fprintf(df, "interface %s %s\n",
+ keyword(rule_node->action),
+ (rule_node->match_class)
+ ? keyword(rule_node->match_class)
+ : rule_node->if_name);
+ }
+
+ list_ptr = queue_head(ptree->phone);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "phone");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ pstr = list_ptr;
+ fprintf(df, " %s", *pstr);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->qos);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "qos");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ atrv = list_ptr;
+ fprintf(df, " %s", atrv->value.s);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->setvar);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ setv_node = list_ptr;
+ s1 = quote_if_needed(setv_node->var);
+ s2 = quote_if_needed(setv_node->val);
+ fprintf(df, "setvar %s = %s", s1, s2);
+ free(s1);
+ free(s2);
+
+ if (setv_node->isdefault)
+ fprintf(df, " default");
+
+ fprintf(df, "\n");
+ }
+
+
+ list_ptr = queue_head(ptree->ttl);
+ if (list_ptr != NULL) {
+
+ fprintf(df, "ttl");
+
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ intp = list_ptr;
+ fprintf(df, " %d", *intp);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ list_ptr = queue_head(ptree->trap);
+ for(; list_ptr != NULL;
+ list_ptr = next_node(list_ptr)) {
+
+ addr_opts = list_ptr;
+ addr = addr_opts->addr;
+
+ fprintf(df, "trap %s", addr->address);
+
+ options = queue_head(addr_opts->options);
+
+ for(; options != NULL;
+ options = next_node(options)) {
+
+ atrv = options;
+
+ switch (atrv->attr) {
+
+ default:
+ fprintf(df, "\n# dump error:\n"
+ "# unknown trap token %d\n"
+ "trap %s", atrv->attr,
+ addr->address);
+ break;
+
+ case T_Port:
+ fprintf(df, " port %d", atrv->value.i);
+ break;
+
+ case T_Interface:
+ addr = (struct address_node *) atrv->value.p;
+ fprintf(df, " interface %s", addr->address);
+ break;
}
- if (errflg == 0) {
- if (peer_config(&peeraddr,
- ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
- peerversion, minpoll, maxpoll, peerflags,
- ttl, peerkey, peerkeystr) == 0) {
- msyslog(LOG_ERR,
- "configuration of %s failed",
- stoa(&peeraddr));
- }
- } else if (errflg == -1) {
- save_resolve(tokens[1], hmode, peerversion,
- minpoll, maxpoll, peerflags, ttl,
- peerkey, peerkeystr);
+ }
+
+ fprintf(df, "\n");
+ }
+
+ return 0;
+}
+#endif /* SAVECONFIG */
+
+
+/* FUNCTIONS FOR CREATING NODES ON THE SYNTAX TREE
+ * -----------------------------------------------
+ */
+
+queue *
+enqueue_in_new_queue(
+ void *my_node
+ )
+{
+ queue *my_queue = create_queue();
+
+ enqueue(my_queue, my_node);
+ return my_queue;
+}
+
+struct attr_val *
+create_attr_dval(
+ int attr,
+ double value
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.d = value;
+ my_val->type = T_Double;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_ival(
+ int attr,
+ int value
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.i = value;
+ my_val->type = T_Integer;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_shorts(
+ int attr,
+ ntp_u_int16_t val1,
+ ntp_u_int16_t val2
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.u = (val1 << 16) | val2;
+ my_val->type = T_Integer;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_sval(
+ int attr,
+ char *s
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ if (NULL == s) /* free() hates NULL */
+ s = estrdup("");
+ my_val->value.s = s;
+ my_val->type = T_String;
+ return my_val;
+}
+
+struct attr_val *
+create_attr_pval(
+ int attr,
+ void *p
+ )
+{
+ struct attr_val *my_val;
+
+ my_val = get_node(sizeof *my_val);
+ my_val->attr = attr;
+ my_val->value.p = p;
+ my_val->type = T_Void;
+ return my_val;
+}
+
+int *
+create_ival(
+ int val
+ )
+{
+ int *p = get_node(sizeof *p);
+
+ *p = val;
+ return p;
+}
+
+double *
+create_dval(
+ double val
+ )
+{
+ double *p = get_node(sizeof *p);
+
+ *p = val;
+ return p;
+}
+
+void **
+create_pval(
+ void *val
+ )
+{
+ void **p = get_node(sizeof *p);
+
+ *p = val;
+ return p;
+}
+
+struct address_node *
+create_address_node(
+ char *addr,
+ int type
+ )
+{
+ struct address_node *my_node;
+
+ NTP_REQUIRE(NULL != addr);
+
+ my_node = get_node(sizeof *my_node);
+
+ my_node->address = addr;
+ my_node->type = type;
+
+ return my_node;
+}
+
+
+void
+destroy_address_node(
+ struct address_node *my_node
+ )
+{
+ NTP_REQUIRE(NULL != my_node);
+ NTP_REQUIRE(NULL != my_node->address);
+
+ free(my_node->address);
+ free_node(my_node);
+}
+
+
+struct peer_node *
+create_peer_node(
+ int hmode,
+ struct address_node *addr,
+ queue *options
+ )
+{
+ struct peer_node *my_node;
+ struct attr_val *option;
+ int freenode;
+ int errflag = 0;
+
+ my_node = get_node(sizeof(*my_node));
+
+ /* Initialize node values to default */
+ my_node->minpoll = 0;
+ my_node->maxpoll = 0;
+ my_node->ttl = 0;
+ my_node->peerversion = NTP_VERSION;
+ my_node->peerkey = 0;
+ my_node->bias = 0;
+ my_node->peerflags = create_queue();
+
+ /* Now set the node to the read values */
+ my_node->host_mode = hmode;
+ my_node->addr = addr;
+
+ /*
+ * the options list mixes items that will be saved in the
+ * peer_node as explicit members, such as minpoll, and
+ * those that are moved from the options queue intact
+ * to the peer_node's peerflags queue. The options
+ * queue is consumed and destroyed here.
+ */
+
+ while (options && NULL != (option = dequeue(options))) {
+
+ freenode = 1;
+ /* Check the kind of option being set */
+ switch (option->attr) {
+
+ case T_Flag:
+ enqueue(my_node->peerflags, option);
+ freenode = 0;
+ break;
+
+ case T_Minpoll:
+ if (option->value.i < NTP_MINPOLL) {
+ msyslog(LOG_INFO,
+ "minpoll: provided value (%d) is below minimum (%d)",
+ option->value.i, NTP_MINPOLL);
+ my_node->minpoll = NTP_MINPOLL;
}
+ else
+ my_node->minpoll = option->value.i;
break;
- case CONFIG_DRIFTFILE:
- if (ntokens >= 2)
- stats_config(STATS_FREQ_FILE, tokens[1]);
+ case T_Maxpoll:
+ if (option->value.i > NTP_MAXPOLL) {
+ msyslog(LOG_INFO,
+ "maxpoll: provided value (%d) is above maximum (%d)",
+ option->value.i, NTP_MAXPOLL);
+ my_node->maxpoll = NTP_MAXPOLL;
+ }
else
- stats_config(STATS_FREQ_FILE, (char *)0);
- stats_write_period = stats_write_tolerance = 0;
- if (ntokens >= 3)
- stats_write_period = 60 * atol(tokens[2]);
- if (stats_write_period <= 0)
- stats_write_period = 3600;
- if (ntokens >= 4) {
- double ftemp;
- sscanf(tokens[3], "%lf", &ftemp);
- stats_write_tolerance = ftemp / 100;
+ my_node->maxpoll = option->value.i;
+ break;
+
+ case T_Ttl:
+ if (my_node->ttl >= MAX_TTL) {
+ msyslog(LOG_ERR, "ttl: invalid argument");
+ errflag = 1;
}
+ else
+ my_node->ttl = option->value.i;
+ break;
+
+ case T_Mode:
+ my_node->ttl = option->value.i;
+ break;
+
+ case T_Key:
+ my_node->peerkey = option->value.i;
+ break;
+
+ case T_Version:
+ my_node->peerversion = option->value.i;
break;
+
+ case T_Bias:
+ my_node->bias = option->value.d;
+ break;
+
+ default:
+ msyslog(LOG_ERR,
+ "Unknown peer/server option token %s",
+ token_name(option->attr));
+ errflag = 1;
+ }
+ if (freenode)
+ free_node(option);
+ }
+ DESTROY_QUEUE(options);
+
+ /* Check if errors were reported. If yes, ignore the node */
+ if (errflag) {
+ free_node(my_node);
+ my_node = NULL;
+ }
+ return my_node;
+}
+
+
+struct unpeer_node *
+create_unpeer_node(
+ struct address_node *addr
+ )
+{
+ struct unpeer_node * my_node;
+ char * pch;
+
+ my_node = get_node(sizeof(*my_node));
+
+ /*
+ * From the parser's perspective an association ID fits into
+ * its generic T_String definition of a name/address "address".
+ * We treat all valid 16-bit numbers as association IDs.
+ */
+ pch = addr->address;
+ while (*pch && isdigit(*pch))
+ pch++;
+
+ if (!*pch
+ && 1 == sscanf(addr->address, "%u", &my_node->assocID)
+ && my_node->assocID <= USHRT_MAX) {
+
+ destroy_address_node(addr);
+ my_node->addr = NULL;
+ } else {
+ my_node->assocID = 0;
+ my_node->addr = addr;
+ }
+
+ return my_node;
+}
+
+struct filegen_node *
+create_filegen_node(
+ int filegen_token,
+ queue * options
+ )
+{
+ struct filegen_node *my_node;
- case CONFIG_PIDFILE:
- if (ntokens >= 2)
- stats_config(STATS_PID_FILE, tokens[1]);
- else
- stats_config(STATS_PID_FILE, (char *)0);
+ my_node = get_node(sizeof *my_node);
+ my_node->filegen_token = filegen_token;
+ my_node->options = options;
+
+ return my_node;
+}
+
+
+struct restrict_node *
+create_restrict_node(
+ struct address_node *addr,
+ struct address_node *mask,
+ queue *flags,
+ int line_no
+ )
+{
+ struct restrict_node *my_node;
+
+ my_node = get_node(sizeof *my_node);
+
+ my_node->addr = addr;
+ my_node->mask = mask;
+ my_node->flags = flags;
+ my_node->line_no = line_no;
+
+ return my_node;
+}
+
+void
+destroy_restrict_node(
+ struct restrict_node *my_node
+ )
+{
+ /* With great care, free all the memory occupied by
+ * the restrict node
+ */
+ if (my_node->addr)
+ destroy_address_node(my_node->addr);
+ if (my_node->mask)
+ destroy_address_node(my_node->mask);
+ DESTROY_QUEUE(my_node->flags);
+ free_node(my_node);
+}
+
+
+struct setvar_node *
+create_setvar_node(
+ char * var,
+ char * val,
+ int isdefault
+ )
+{
+ char * pch;
+ struct setvar_node *my_node;
+
+ /* do not allow = in the variable name */
+ if (NULL != (pch = strchr(var, '=')))
+ *pch = '\0';
+
+ /* Now store the string into a setvar_node */
+ my_node = get_node(sizeof *my_node);
+ my_node->var = var;
+ my_node->val = val;
+ my_node->isdefault = isdefault;
+
+ return my_node;
+}
+
+
+nic_rule_node *
+create_nic_rule_node(
+ int match_class,
+ char *if_name, /* interface name or numeric address */
+ int action
+ )
+{
+ nic_rule_node *my_node;
+
+ NTP_REQUIRE(match_class != 0 || if_name != NULL);
+
+ my_node = get_node(sizeof(*my_node));
+ my_node->match_class = match_class;
+ my_node->if_name = if_name;
+ my_node->action = action;
+
+ return my_node;
+}
+
+
+struct addr_opts_node *
+create_addr_opts_node(
+ struct address_node *addr,
+ queue *options
+ )
+{
+ struct addr_opts_node *my_node;
+
+ my_node = get_node(sizeof *my_node);
+ my_node->addr = addr;
+ my_node->options = options;
+ return my_node;
+}
+
+script_info *
+create_sim_script_info(
+ double duration,
+ queue *script_queue
+ )
+{
+#ifdef SIM
+ return NULL;
+#else
+ script_info *my_info;
+ struct attr_val *my_attr_val;
+
+ my_info = get_node(sizeof *my_info);
+
+ /* Initialize Script Info with default values*/
+ my_info->duration = duration;
+ my_info->freq_offset = 0;
+ my_info->wander = 0;
+ my_info->jitter = 0;
+ my_info->prop_delay = NET_DLY;
+ my_info->proc_delay = PROC_DLY;
+
+ /* Traverse the script_queue and fill out non-default values */
+ my_attr_val = queue_head(script_queue);
+ while (my_attr_val != NULL) {
+ /* Set the desired value */
+ switch (my_attr_val->attr) {
+
+ case T_Freq_Offset:
+ my_info->freq_offset = my_attr_val->value.d;
break;
- case CONFIG_END:
- for ( i = 0; i <= includelevel; i++ ) {
- fclose(fp[i]);
- }
+ case T_Wander:
+ my_info->wander = my_attr_val->value.d;
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;
+
+ case T_Jitter:
+ my_info->jitter = my_attr_val->value.d;
break;
- case CONFIG_LOGFILE:
- if (ntokens >= 2) {
- FILE *new_file;
+ case T_Prop_Delay:
+ my_info->prop_delay = my_attr_val->value.d;
+ break;
- new_file = fopen(tokens[1], "a");
- if (new_file != NULL) {
- NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
- if (syslog_file != NULL &&
- fileno(syslog_file) != fileno(new_file))
- (void)fclose(syslog_file);
+ case T_Proc_Delay:
+ my_info->proc_delay = my_attr_val->value.d;
+ break;
- syslog_file = new_file;
- syslogit = 0;
- }
- else
- msyslog(LOG_ERR,
- "Cannot open log file %s",
- tokens[1]);
- }
- else
- msyslog(LOG_ERR, "logfile needs one argument");
- break;
-
- case CONFIG_LOGCONFIG:
- for (i = 1; i < ntokens; i++)
- {
- int add = 1;
- int equals = 0;
- char * s = &tokens[i][0];
-
- switch (*s) {
- case '+':
- case '-':
- case '=':
- add = *s == '+';
- equals = *s == '=';
- s++;
- break;
+ default:
+ msyslog(LOG_ERR,
+ "Unknown script token %d",
+ my_attr_val->attr);
+ }
+ }
+ return (my_info);
+#endif
+}
- default:
- break;
- }
- if (equals) {
- ntp_syslogmask = get_logmask(s);
- } else {
- if (add) {
- ntp_syslogmask |= get_logmask(s);
- } else {
- ntp_syslogmask &= ~get_logmask(s);
- }
- }
-#ifdef DEBUG
- if (debug)
- printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
+
+#if !defined(SIM)
+
+#define ADDR_LENGTH 16 + 1
+
+static sockaddr_u *
+get_next_address(
+ struct address_node *addr
+ )
+{
+ const char addr_prefix[] = "192.168.0.";
+ static int curr_addr_no = 1;
+ char addr_string[ADDR_LENGTH];
+ sockaddr_u *final_addr;
+ struct addrinfo *ptr;
+ int retval;
+
+ final_addr = emalloc(sizeof *final_addr);
+
+ if (addr->type == T_String) {
+ snprintf(addr_string, ADDR_LENGTH, "%s%d", addr_prefix, curr_addr_no++);
+ printf("Selecting ip address %s for hostname %s\n", addr_string, addr->address);
+ retval = getaddrinfo(addr_string, "ntp", NULL, &ptr);
+ } else
+ retval = getaddrinfo(addr->address, "ntp", NULL, &ptr);
+
+ if (!retval) {
+ memcpy(final_addr, ptr->ai_addr, ptr->ai_addrlen);
+ fprintf(stderr, "Successful in setting ip address of simulated server to: %s\n", stoa(final_addr));
+ }
+ else {
+ fprintf(stderr, "ERROR!! Could not get a new address\n");
+ exit(1);
+ }
+ freeaddrinfo(ptr);
+ return final_addr;
+}
+#endif /* !SIM */
+
+
+server_info *
+create_sim_server(
+ struct address_node *addr,
+ double server_offset,
+ queue *script
+ )
+{
+#ifdef SIM
+ return NULL;
+#else
+ server_info *my_info;
+
+ my_info = get_node(sizeof *my_info);
+
+ my_info->server_time = server_offset;
+ my_info->addr = get_next_address(addr);
+ my_info->script = script;
+ my_info->curr_script = dequeue(my_info->script);
+ return my_info;
+#endif /* SIM */
+}
+
+struct sim_node *
+create_sim_node(
+ queue *init_opts,
+ queue *servers
+ )
+{
+ struct sim_node *my_node;
+
+ my_node = get_node(sizeof *my_node);
+
+ my_node->init_opts = init_opts;
+ my_node->servers = servers;
+ return my_node;
+}
+
+
+
+
+/* FUNCTIONS FOR PERFORMING THE CONFIGURATION
+ * ------------------------------------------
+ */
+
+static void
+config_other_modes(
+ struct config_tree *ptree
+ )
+{
+ sockaddr_u addr_sock;
+ struct address_node *addr_node;
+
+ if (ptree->broadcastclient)
+ proto_config(PROTO_BROADCLIENT, ptree->broadcastclient, 0., NULL);
+
+ /* Configure the many-cast servers */
+ addr_node = queue_head(ptree->manycastserver);
+ if (addr_node != NULL) {
+ do {
+ ZERO_SOCK(&addr_sock);
+ AF(&addr_sock) = (u_short)addr_node->type;
+
+ if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK) == 1)
+ proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
+
+ addr_node = next_node(addr_node);
+ } while (addr_node != NULL);
+ sys_manycastserver = 1;
+ }
+
+ /* Configure the multicast clients */
+ addr_node = queue_head(ptree->multicastclient);
+ if (addr_node != NULL) {
+ do {
+ ZERO_SOCK(&addr_sock);
+ AF(&addr_sock) = (u_short)addr_node->type;
+
+ if (getnetnum(addr_node->address, &addr_sock, 1, t_UNK) == 1)
+ proto_config(PROTO_MULTICAST_ADD, 0, 0., &addr_sock);
+
+ addr_node = next_node(addr_node);
+ } while (addr_node != NULL);
+ proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_other_modes(
+ struct config_tree *ptree
+ )
+{
+ struct address_node *addr_node;
+
+ while (NULL != (addr_node = dequeue(ptree->manycastserver)))
+ destroy_address_node(addr_node);
+
+ while (NULL != (addr_node = dequeue(ptree->multicastclient)))
+ destroy_address_node(addr_node);
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_auth(
+ struct config_tree *ptree
+ )
+{
+ ntp_u_int16_t ufirst;
+ ntp_u_int16_t ulast;
+ ntp_u_int16_t u;
+ struct attr_val *my_val;
+#ifdef OPENSSL
+#ifndef NO_INTRES
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int digest_len;
+ EVP_MD_CTX ctx;
#endif
- }
+ int item;
+#endif
+
+ /* Crypto Command */
+#ifdef OPENSSL
+ item = -1; /* quiet warning */
+ my_val = queue_head(ptree->auth.crypto_cmd_list);
+ while (my_val != NULL) {
+ switch (my_val->attr) {
+
+ default:
+ NTP_INSIST(0);
break;
- case CONFIG_BROADCASTCLIENT:
- if (ntokens == 1) {
- proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
- } else {
- proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
- }
+ case T_Host:
+ item = CRYPTO_CONF_PRIV;
break;
- case CONFIG_MULTICASTCLIENT:
- case CONFIG_MANYCASTSERVER:
- if (ntokens > 1) {
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart],
- addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
- break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
- break;
- }
- /*
- * Abuse maskaddr to store the prefered ip
- * version.
- */
- memset((char *)&maskaddr, 0, sizeof(maskaddr));
- maskaddr.ss_family = peeraddr.ss_family;
-
- for (i = istart; i < ntokens; i++) {
- memset((char *)&peeraddr, 0,
- sizeof(peeraddr));
- peeraddr.ss_family = maskaddr.ss_family;
- if (getnetnum(tokens[i], &peeraddr, 1,
- t_UNK) == 1)
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., &peeraddr);
- }
- } else
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., NULL);
- if (tok == CONFIG_MULTICASTCLIENT)
- proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
- else if (tok == CONFIG_MANYCASTSERVER)
- sys_manycastserver = 1;
+ case T_Ident:
+ item = CRYPTO_CONF_IDENT;
break;
- case CONFIG_KEYS:
- if (ntokens >= 2) {
- getauthkeys(tokens[1]);
- }
+ case T_Pw:
+ item = CRYPTO_CONF_PW;
break;
- case CONFIG_KEYSDIR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "Keys directory name required");
- break;
- }
- keysdir = (char *)emalloc(strlen(tokens[1]) + 1);
- strcpy(keysdir, tokens[1]);
+ case T_Randfile:
+ item = CRYPTO_CONF_RAND;
break;
- case CONFIG_TINKER:
- for (i = 1; i < ntokens; i++) {
- int temp;
- double ftemp;
+ case T_Sign:
+ item = CRYPTO_CONF_SIGN;
+ break;
- temp = matchkey(tokens[i++], tinker_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "tinker: missing argument");
- errflg++;
- break;
- }
- sscanf(tokens[i], "%lf", &ftemp);
- switch(temp) {
+ case T_Digest:
+ item = CRYPTO_CONF_NID;
+ break;
+ }
+ crypto_config(item, my_val->value.s);
+ my_val = next_node(my_val);
+ }
+#endif /* OPENSSL */
- case CONF_CLOCK_MAX:
- loop_config(LOOP_MAX, ftemp);
- break;
+ /* Keysdir Command */
+ if (ptree->auth.keysdir) {
+ if (keysdir != default_keysdir)
+ free(keysdir);
+ keysdir = estrdup(ptree->auth.keysdir);
+ }
- case CONF_CLOCK_PANIC:
- loop_config(LOOP_PANIC, ftemp);
- break;
- case CONF_CLOCK_PHI:
- loop_config(LOOP_PHI, ftemp);
- break;
+ /* ntp_signd_socket Command */
+ if (ptree->auth.ntp_signd_socket) {
+ if (ntp_signd_socket != default_ntp_signd_socket)
+ free(ntp_signd_socket);
+ ntp_signd_socket = estrdup(ptree->auth.ntp_signd_socket);
+ }
- case CONF_CLOCK_MINSTEP:
- loop_config(LOOP_MINSTEP, ftemp);
- break;
+#ifdef OPENSSL
+ if (ptree->auth.cryptosw && !cryptosw) {
+ crypto_setup();
+ cryptosw = 1;
+ }
+#endif /* OPENSSL */
- case CONF_CLOCK_ALLAN:
- loop_config(LOOP_ALLAN, ftemp);
- break;
+ /* Keys Command */
+ if (ptree->auth.keys)
+ getauthkeys(ptree->auth.keys);
- case CONF_CLOCK_HUFFPUFF:
- loop_config(LOOP_HUFFPUFF, ftemp);
- break;
+ /* Control Key Command */
+ if (ptree->auth.control_key)
+ ctl_auth_keyid = (keyid_t)ptree->auth.control_key;
- case CONF_CLOCK_FREQ:
- loop_config(LOOP_FREQ, ftemp);
- break;
- }
- }
- break;
+ /* Requested Key Command */
+ if (ptree->auth.request_key) {
+ DPRINTF(4, ("set info_auth_keyid to %08lx\n",
+ (u_long) ptree->auth.request_key));
+ info_auth_keyid = (keyid_t)ptree->auth.request_key;
+ }
- case CONFIG_TOS:
- for (i = 1; i < ntokens; i++) {
- int temp;
- double ftemp;
+ /* Trusted Key Command */
+ my_val = queue_head(ptree->auth.trusted_key_list);
+ for (; my_val != NULL; my_val = next_node(my_val)) {
+ if ('i' == my_val->attr)
+ authtrust(my_val->value.i, 1);
+ else if ('-' == my_val->attr) {
+ ufirst = my_val->value.u >> 16;
+ ulast = my_val->value.u & 0xffff;
+ for (u = ufirst; u <= ulast; u++)
+ authtrust(u, 1);
+ }
+ }
- temp = matchkey(tokens[i++], tos_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "tos: missing argument");
- errflg++;
- break;
- }
- sscanf(tokens[i], "%lf", &ftemp);
- switch(temp) {
+#ifdef OPENSSL
+ /* crypto revoke command */
+ if (ptree->auth.revoke)
+ sys_revoke = ptree->auth.revoke;
+#endif /* OPENSSL */
- case CONF_TOS_MINCLOCK:
- proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
- break;
+#ifndef NO_INTRES
+ /* find a keyid */
+ if (info_auth_keyid == 0)
+ req_keyid = 65535;
+ else
+ req_keyid = info_auth_keyid;
- case CONF_TOS_MAXCLOCK:
- proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
- break;
+ /* if doesn't exist, make up one at random */
+ if (authhavekey(req_keyid)) {
+ req_keytype = cache_type;
+#ifndef OPENSSL
+ req_hashlen = 16;
+#else /* OPENSSL follows */
+ EVP_DigestInit(&ctx, EVP_get_digestbynid(req_keytype));
+ EVP_DigestFinal(&ctx, digest, &digest_len);
+ req_hashlen = digest_len;
+#endif
+ } else {
+ int rankey;
- case CONF_TOS_MINSANE:
- proto_config(PROTO_MINSANE, 0, ftemp, NULL);
- break;
+ rankey = ntp_random();
+ req_keytype = NID_md5;
+ req_hashlen = 16;
+ MD5auth_setkey(req_keyid, req_keytype,
+ (u_char *)&rankey, sizeof(rankey));
+ authtrust(req_keyid, 1);
+ }
- case CONF_TOS_FLOOR:
- proto_config(PROTO_FLOOR, 0, ftemp, NULL);
- break;
+ /* save keyid so we will accept config requests with it */
+ info_auth_keyid = req_keyid;
+#endif /* !NO_INTRES */
- case CONF_TOS_CEILING:
- proto_config(PROTO_CEILING, 0, ftemp, NULL);
- break;
+}
- case CONF_TOS_COHORT:
- proto_config(PROTO_COHORT, 0, ftemp, NULL);
- break;
- case CONF_TOS_MINDISP:
- proto_config(PROTO_MINDISP, 0, ftemp, NULL);
- break;
+#ifdef FREE_CFG_T
+static void
+free_config_auth(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_val;
- case CONF_TOS_MAXDIST:
- proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
- break;
+ while (NULL !=
+ (my_val = dequeue(ptree->auth.crypto_cmd_list))) {
- case CONF_TOS_MAXHOP:
- proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
- break;
+ free(my_val->value.s);
+ free_node(my_val);
+ }
+ DESTROY_QUEUE(ptree->auth.crypto_cmd_list);
- case CONF_TOS_ORPHAN:
- proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
- break;
+ DESTROY_QUEUE(ptree->auth.trusted_key_list);
+}
+#endif /* FREE_CFG_T */
- case CONF_TOS_BEACON:
- proto_config(PROTO_BEACON, 0, ftemp, NULL);
- break;
- }
- }
+
+static void
+config_tos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tos;
+ int item;
+
+ item = -1; /* quiet warning */
+ tos = queue_head(ptree->orphan_cmds);
+ while (tos != NULL) {
+ switch(tos->attr) {
+
+ default:
+ NTP_INSIST(0);
break;
- case CONFIG_TTL:
- for (i = 1; i < ntokens && i < MAX_TTL; i++) {
- sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
- sys_ttlmax = i - 1;
- }
+ case T_Ceiling:
+ item = PROTO_CEILING;
break;
- case CONFIG_DISCARD:
- for (i = 1; i < ntokens; i++) {
- int temp;
+ case T_Floor:
+ item = PROTO_FLOOR;
+ break;
- temp = matchkey(tokens[i++],
- discard_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "discard: missing argument");
- errflg++;
- break;
- }
- switch(temp) {
- case CONF_DISCARD_AVERAGE:
- res_avg_interval = atoi(tokens[i]);
- break;
+ case T_Cohort:
+ item = PROTO_COHORT;
+ break;
+
+ case T_Orphan:
+ item = PROTO_ORPHAN;
+ break;
- case CONF_DISCARD_MINIMUM:
- res_min_interval = atoi(tokens[i]);
+ case T_Mindist:
+ item = PROTO_MINDISP;
+ break;
+
+ case T_Maxdist:
+ item = PROTO_MAXDIST;
+ break;
+
+ case T_Minclock:
+ item = PROTO_MINCLOCK;
+ break;
+
+ case T_Maxclock:
+ item = PROTO_MAXCLOCK;
+ break;
+
+ case T_Minsane:
+ item = PROTO_MINSANE;
+ break;
+
+ case T_Beacon:
+ item = PROTO_BEACON;
+ break;
+ }
+ proto_config(item, 0, tos->value.d, NULL);
+ tos = next_node(tos);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_tos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tos;
+
+ while (!empty(ptree->orphan_cmds)) {
+ tos = dequeue(ptree->orphan_cmds);
+ free_node(tos);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_monitor(
+ struct config_tree *ptree
+ )
+{
+ int *pfilegen_token;
+ const char *filegen_string;
+ const char *filegen_file;
+ FILEGEN *filegen;
+ struct filegen_node *my_node;
+ struct attr_val *my_opts;
+ int filegen_type;
+ int filegen_flag;
+
+ /* Set the statistics directory */
+ if (ptree->stats_dir)
+ stats_config(STATS_STATSDIR, ptree->stats_dir);
+
+ /* NOTE:
+ * Calling filegen_get is brain dead. Doing a string
+ * comparison to find the relavant filegen structure is
+ * expensive.
+ *
+ * Through the parser, we already know which filegen is
+ * being specified. Hence, we should either store a
+ * pointer to the specified structure in the syntax tree
+ * or an index into a filegen array.
+ *
+ * Need to change the filegen code to reflect the above.
+ */
+
+ /* Turn on the specified statistics */
+ pfilegen_token = queue_head(ptree->stats_list);
+ while (pfilegen_token != NULL) {
+ filegen_string = keyword(*pfilegen_token);
+ filegen = filegen_get(filegen_string);
+
+ DPRINTF(4, ("enabling filegen for %s statistics '%s%s'\n",
+ filegen_string, filegen->prefix,
+ filegen->basename));
+ filegen->flag |= FGEN_FLAG_ENABLED;
+ pfilegen_token = next_node(pfilegen_token);
+ }
+
+ /* Configure the statistics with the options */
+ my_node = queue_head(ptree->filegen_opts);
+ while (my_node != NULL) {
+ filegen_file = keyword(my_node->filegen_token);
+ filegen = filegen_get(filegen_file);
+
+ /* Initialize the filegen variables to their pre-configurtion states */
+ filegen_flag = filegen->flag;
+ filegen_type = filegen->type;
+
+ /* "filegen ... enabled" is the default (when filegen is used) */
+ filegen_flag |= FGEN_FLAG_ENABLED;
+
+ my_opts = queue_head(my_node->options);
+ while (my_opts != NULL) {
+
+ switch (my_opts->attr) {
+
+ case T_File:
+ filegen_file = my_opts->value.p;
break;
- case CONF_DISCARD_MONITOR:
- mon_age = atoi(tokens[i]);
+ case T_Type:
+ switch (my_opts->value.i) {
+
+ default:
+ NTP_INSIST(0);
+ break;
+
+ case T_None:
+ filegen_type = FILEGEN_NONE;
+ break;
+
+ case T_Pid:
+ filegen_type = FILEGEN_PID;
+ break;
+
+ case T_Day:
+ filegen_type = FILEGEN_DAY;
+ break;
+
+ case T_Week:
+ filegen_type = FILEGEN_WEEK;
+ break;
+
+ case T_Month:
+ filegen_type = FILEGEN_MONTH;
+ break;
+
+ case T_Year:
+ filegen_type = FILEGEN_YEAR;
+ break;
+
+ case T_Age:
+ filegen_type = FILEGEN_AGE;
+ break;
+ }
break;
- default:
- msyslog(LOG_ERR,
- "discard: unknown keyword");
+ case T_Flag:
+ switch (my_opts->value.i) {
+
+ case T_Link:
+ filegen_flag |= FGEN_FLAG_LINK;
+ break;
+
+ case T_Nolink:
+ filegen_flag &= ~FGEN_FLAG_LINK;
+ break;
+
+ case T_Enable:
+ filegen_flag |= FGEN_FLAG_ENABLED;
+ break;
+
+ case T_Disable:
+ filegen_flag &= ~FGEN_FLAG_ENABLED;
+ break;
+
+ default:
+ msyslog(LOG_ERR,
+ "Unknown filegen flag token %d",
+ my_opts->value.i);
+ exit(1);
+ }
break;
- }
+ default:
+ msyslog(LOG_ERR,
+ "Unknown filegen option token %d",
+ my_opts->attr);
+ exit(1);
}
+ my_opts = next_node(my_opts);
+ }
+ filegen_config(filegen, filegen_file, filegen_type,
+ filegen_flag);
+ my_node = next_node(my_node);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_monitor(
+ struct config_tree *ptree
+ )
+{
+ char **filegen_string;
+ struct filegen_node *my_node;
+ struct attr_val *my_opts;
+
+ if (ptree->stats_dir) {
+ free(ptree->stats_dir);
+ ptree->stats_dir = NULL;
+ }
+
+ while (NULL != (filegen_string = dequeue(ptree->stats_list)))
+ free_node(filegen_string);
+
+ while (NULL != (my_node = dequeue(ptree->filegen_opts))) {
+
+ while (NULL != (my_opts = dequeue(my_node->options)))
+ free_node(my_opts);
+
+ free_node(my_node);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_access(
+ struct config_tree *ptree
+ )
+{
+ static int warned_signd;
+ struct attr_val * my_opt;
+ struct restrict_node * my_node;
+ int * curr_flag;
+ sockaddr_u addr_sock;
+ sockaddr_u addr_mask;
+ u_short flags;
+ u_short mflags;
+ int restrict_default;
+ const char * signd_warning =
+#ifdef HAVE_NTP_SIGND
+ "MS-SNTP signd operations currently block ntpd degrading service to all clients.";
+#else
+ "mssntp restrict bit ignored, this ntpd was configured without --enable-ntp-signd.";
+#endif
+
+ /* Configure the discard options */
+ my_opt = queue_head(ptree->discard_opts);
+ while (my_opt != NULL) {
+
+ switch(my_opt->attr) {
+
+ case T_Average:
+ ntp_minpoll = my_opt->value.i;
break;
-#ifdef OPENSSL
- case CONFIG_REVOKE:
- if (ntokens >= 2)
- sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
+ case T_Minimum:
+ ntp_minpkt = my_opt->value.i;
break;
- case CONFIG_AUTOMAX:
- if (ntokens >= 2)
- sys_automax = 1 << max(atoi(tokens[1]), 10);
+ case T_Monitor:
+ mon_age = my_opt->value.i;
break;
- case CONFIG_CRYPTO:
- if (ntokens == 1) {
- crypto_config(CRYPTO_CONF_NONE, NULL);
- break;
- }
- for (i = 1; i < ntokens; i++) {
- int temp;
+ default:
+ msyslog(LOG_ERR,
+ "Unknown discard option token %d",
+ my_opt->attr);
+ exit(1);
+ }
+ my_opt = next_node(my_opt);
+ }
+
+ /* Configure the restrict options */
+ for (my_node = queue_head(ptree->restrict_opts);
+ my_node != NULL;
+ my_node = next_node(my_node)) {
+
+ ZERO_SOCK(&addr_sock);
+
+ if (NULL == my_node->addr) {
+ /*
+ * The user specified a default rule without a
+ * -4 / -6 qualifier, add to both lists
+ */
+ restrict_default = 1;
+ ZERO_SOCK(&addr_mask);
+ } else {
+ restrict_default = 0;
+ /* Resolve the specified address */
+ AF(&addr_sock) = (u_short)my_node->addr->type;
+
+ if (getnetnum(my_node->addr->address,
+ &addr_sock, 1, t_UNK) != 1) {
- temp = matchkey(tokens[i++],
- crypto_keywords, 1);
- if (i > ntokens - 1) {
msyslog(LOG_ERR,
- "crypto: missing argument");
- errflg++;
+ "restrict: error in address '%s' on line %d. Ignoring...",
+ my_node->addr->address, my_node->line_no);
+ continue;
+ }
+
+ SET_HOSTMASK(&addr_mask, AF(&addr_sock));
+
+ /* Resolve the mask */
+ if (my_node->mask) {
+ ZERO_SOCK(&addr_mask);
+ AF(&addr_mask) = (u_short)my_node->mask->type;
+ if (getnetnum(my_node->mask->address, &addr_mask, 1, t_MSK) != 1) {
+
+ msyslog(LOG_ERR,
+ "restrict: error in mask '%s' on line %d. Ignoring...",
+ my_node->mask->address, my_node->line_no);
+ continue;
+ }
+ }
+ }
+
+ /* Parse the flags */
+ flags = 0;
+ mflags = 0;
+
+ curr_flag = queue_head(my_node->flags);
+ while (curr_flag != NULL) {
+ switch (*curr_flag) {
+
+ default:
+ NTP_INSIST(0);
break;
- }
- switch(temp) {
- case CONF_CRYPTO_CERT:
- crypto_config(CRYPTO_CONF_CERT,
- tokens[i]);
+ case T_Ntpport:
+ mflags |= RESM_NTPONLY;
break;
- case CONF_CRYPTO_RSA:
- crypto_config(CRYPTO_CONF_PRIV,
- tokens[i]);
+ case T_Flake:
+ flags |= RES_TIMEOUT;
break;
- case CONF_CRYPTO_IDENT:
- crypto_config(CRYPTO_CONF_IDENT,
- tokens[i]);
+ case T_Ignore:
+ flags |= RES_IGNORE;
break;
- case CONF_CRYPTO_IFFPAR:
- crypto_config(CRYPTO_CONF_IFFPAR,
- tokens[i]);
+ case T_Kod:
+ flags |= RES_KOD;
break;
- case CONF_CRYPTO_GQPAR:
- crypto_config(CRYPTO_CONF_GQPAR,
- tokens[i]);
+ case T_Mssntp:
+ flags |= RES_MSSNTP;
break;
- case CONF_CRYPTO_MVPAR:
- crypto_config(CRYPTO_CONF_MVPAR,
- tokens[i]);
+ case T_Limited:
+ flags |= RES_LIMITED;
break;
- case CONF_CRYPTO_LEAP:
- crypto_config(CRYPTO_CONF_LEAP,
- tokens[i]);
+ case T_Lowpriotrap:
+ flags |= RES_LPTRAP;
break;
- case CONF_CRYPTO_PW:
- crypto_config(CRYPTO_CONF_PW,
- tokens[i]);
+ case T_Nomodify:
+ flags |= RES_NOMODIFY;
break;
- case CONF_CRYPTO_RAND:
- crypto_config(CRYPTO_CONF_RAND,
- tokens[i]);
+ case T_Nopeer:
+ flags |= RES_NOPEER;
break;
- case CONF_CRYPTO_SIGN:
- crypto_config(CRYPTO_CONF_SIGN,
- tokens[i]);
+ case T_Noquery:
+ flags |= RES_NOQUERY;
break;
- default:
- msyslog(LOG_ERR,
- "crypto: unknown keyword");
+ case T_Noserve:
+ flags |= RES_DONTSERVE;
break;
- }
- }
- break;
-#endif /* OPENSSL */
- case CONFIG_RESTRICT:
- if (ntokens < 2) {
- msyslog(LOG_ERR, "restrict requires an address");
+ case T_Notrap:
+ flags |= RES_NOTRAP;
break;
- }
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
+
+ case T_Notrust:
+ flags |= RES_DONTTRUST;
break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
+
+ case T_Version:
+ flags |= RES_VERSION;
break;
}
+ curr_flag = next_node(curr_flag);
+ }
+
+ /* Set the flags */
+ if (restrict_default) {
+ AF(&addr_sock) = AF_INET;
+ hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
+ mflags, flags);
+
+ AF(&addr_sock) = AF_INET6;
+ }
+
+ hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask,
+ mflags, flags);
+
+ if ((RES_MSSNTP & flags) && !warned_signd) {
+ warned_signd = 1;
+ fprintf(stderr, "%s\n", signd_warning);
+ msyslog(LOG_WARNING, signd_warning);
+ }
+ }
+}
+
+#ifdef FREE_CFG_T
+static void
+free_config_access(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val * my_opt;
+ struct restrict_node * my_node;
+ int * curr_flag;
+
+ while (NULL != (my_opt = dequeue(ptree->discard_opts)))
+ free_node(my_opt);
+
+ while (NULL != (my_node = dequeue(ptree->restrict_opts))) {
+ while (NULL != (curr_flag = dequeue(my_node->flags)))
+ free_node(curr_flag);
+
+ destroy_restrict_node(my_node);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_tinker(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tinker;
+ int item;
+
+ item = -1; /* quiet warning */
+ tinker = queue_head(ptree->tinker);
+ while (tinker != NULL) {
+ switch (tinker->attr) {
+
+ default:
+ NTP_INSIST(0);
+ break;
+
+ case T_Allan:
+ item = LOOP_ALLAN;
+ break;
+
+ case T_Dispersion:
+ item = LOOP_PHI;
+ break;
+
+ case T_Freq:
+ item = LOOP_FREQ;
+ break;
+
+ case T_Huffpuff:
+ item = LOOP_HUFFPUFF;
+ break;
+
+ case T_Panic:
+ item = LOOP_PANIC;
+ break;
+
+ case T_Step:
+ item = LOOP_MAX;
+ break;
+
+ case T_Stepout:
+ item = LOOP_MINSTEP;
+ break;
+ }
+ loop_config(item, tinker->value.d);
+ tinker = next_node(tinker);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_tinker(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *tinker;
+
+ while (NULL != (tinker = dequeue(ptree->tinker)))
+ free_node(tinker);
+}
+#endif /* FREE_CFG_T */
+
+
+/*
+ * config_nic_rules - apply interface listen/ignore/drop items
+ */
+void
+config_nic_rules(
+ struct config_tree *ptree
+ )
+{
+ nic_rule_node * curr_node;
+ sockaddr_u addr;
+ nic_rule_match match_type;
+ nic_rule_action action;
+ char * if_name;
+ char * pchSlash;
+ int prefixlen;
+ int addrbits;
+
+ curr_node = queue_head(ptree->nic_rules);
+
+ if (curr_node != NULL
+ && (HAVE_OPT( NOVIRTUALIPS ) || HAVE_OPT( INTERFACE ))) {
+ msyslog(LOG_ERR,
+ "interface/nic rules are not allowed with --interface (-I) or --novirtualips (-L)%s",
+ (input_from_file) ? ", exiting" : "");
+ if (input_from_file)
+ exit(1);
+ else
+ return;
+ }
+
+ for (;
+ curr_node != NULL;
+ curr_node = next_node(curr_node)) {
+
+ prefixlen = -1;
+ if_name = curr_node->if_name;
+ if (if_name != NULL)
+ if_name = estrdup(if_name);
+
+ switch (curr_node->match_class) {
+
+ default:
/*
- * Assume default means an IPv4 address, except
- * if forced by a -4 or -6.
+ * this assignment quiets a gcc "may be used
+ * uninitialized" warning and is here for no
+ * other reason.
*/
- if (STREQ(tokens[istart], "default")) {
- if (peeraddr.ss_family == 0)
- peeraddr.ss_family = AF_INET;
- } else if (getnetnum(tokens[istart], &peeraddr, 1,
- t_UNK) != 1)
- break;
+ match_type = MATCH_ALL;
+ NTP_INSIST(0);
+ break;
+ case 0:
/*
- * Use peerversion as flags, peerkey as mflags. Ick.
+ * 0 is out of range for valid token T_...
+ * and in a nic_rules_node indicates the
+ * interface descriptor is either a name or
+ * address, stored in if_name in either case.
*/
- peerversion = 0;
- peerkey = 0;
- errflg = 0;
- SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
- istart++;
- for (i = istart; i < ntokens; i++) {
- switch (matchkey(tokens[i], res_keywords, 1)) {
- case CONF_RES_MASK:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "mask keyword needs argument");
- errflg++;
- break;
- }
- i++;
- if (getnetnum(tokens[i], &maskaddr, 1,
- t_MSK) != 1)
- errflg++;
- break;
+ NTP_INSIST(if_name != NULL);
+ pchSlash = strchr(if_name, '/');
+ if (pchSlash != NULL)
+ *pchSlash = '\0';
+ if (is_ip_address(if_name, &addr)) {
+ match_type = MATCH_IFADDR;
+ if (pchSlash != NULL) {
+ sscanf(pchSlash + 1, "%d",
+ &prefixlen);
+ addrbits = 8 *
+ SIZEOF_INADDR(AF(&addr));
+ prefixlen = max(-1, prefixlen);
+ prefixlen = min(prefixlen,
+ addrbits);
+ }
+ } else {
+ match_type = MATCH_IFNAME;
+ if (pchSlash != NULL)
+ *pchSlash = '/';
+ }
+ break;
- case CONF_RES_IGNORE:
- peerversion |= RES_IGNORE;
- break;
+ case T_All:
+ match_type = MATCH_ALL;
+ break;
- case CONF_RES_NOSERVE:
- peerversion |= RES_DONTSERVE;
- break;
+ case T_Ipv4:
+ match_type = MATCH_IPV4;
+ break;
- case CONF_RES_NOTRUST:
- peerversion |= RES_DONTTRUST;
- break;
+ case T_Ipv6:
+ match_type = MATCH_IPV6;
+ break;
- case CONF_RES_NOQUERY:
- peerversion |= RES_NOQUERY;
- break;
+ case T_Wildcard:
+ match_type = MATCH_WILDCARD;
+ break;
+ }
- case CONF_RES_NOMODIFY:
- peerversion |= RES_NOMODIFY;
- break;
+ switch (curr_node->action) {
- case CONF_RES_NOPEER:
- peerversion |= RES_NOPEER;
- break;
+ default:
+ /*
+ * this assignment quiets a gcc "may be used
+ * uninitialized" warning and is here for no
+ * other reason.
+ */
+ action = ACTION_LISTEN;
+ NTP_INSIST(0);
+ break;
- case CONF_RES_NOTRAP:
- peerversion |= RES_NOTRAP;
- break;
+ case T_Listen:
+ action = ACTION_LISTEN;
+ break;
- case CONF_RES_LPTRAP:
- peerversion |= RES_LPTRAP;
- break;
+ case T_Ignore:
+ action = ACTION_IGNORE;
+ break;
- case CONF_RES_NTPPORT:
- peerkey |= RESM_NTPONLY;
- break;
+ case T_Drop:
+ action = ACTION_DROP;
+ break;
+ }
- case CONF_RES_VERSION:
- peerversion |= RES_VERSION;
- break;
+ add_nic_rule(match_type, if_name, prefixlen,
+ action);
+ timer_interfacetimeout(current_time + 2);
+ if (if_name != NULL)
+ free(if_name);
+ }
+}
- case CONF_RES_DEMOBILIZE:
- peerversion |= RES_DEMOBILIZE;
- break;
- case CONF_RES_LIMITED:
- peerversion |= RES_LIMITED;
- break;
+#ifdef FREE_CFG_T
+static void
+free_config_nic_rules(
+ struct config_tree *ptree
+ )
+{
+ nic_rule_node *curr_node;
- case CONFIG_UNKNOWN:
- errflg++;
- break;
- }
- }
- if (SOCKNUL(&peeraddr))
- ANYSOCK(&maskaddr);
- if (!errflg)
- hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
- (int)peerkey, peerversion);
+ while (NULL != (curr_node = dequeue(ptree->nic_rules))) {
+ if (curr_node->if_name != NULL)
+ free(curr_node->if_name);
+ free_node(curr_node);
+ }
+ DESTROY_QUEUE(ptree->nic_rules);
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+apply_enable_disable(
+ queue * q,
+ int enable
+ )
+{
+ struct attr_val *curr_flag;
+ int option;
+#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
+ bc_entry *pentry;
+#endif
+
+ for (curr_flag = queue_head(q);
+ curr_flag != NULL;
+ curr_flag = next_node(curr_flag)) {
+
+ option = curr_flag->value.i;
+ switch (option) {
+
+ default:
+ msyslog(LOG_ERR,
+ "can not apply enable/disable token %d, unknown",
+ option);
break;
- case CONFIG_BDELAY:
- if (ntokens >= 2) {
- double tmp;
+ case T_Auth:
+ proto_config(PROTO_AUTHENTICATE, enable, 0., NULL);
+ break;
- if (sscanf(tokens[1], "%lf", &tmp) != 1) {
- msyslog(LOG_ERR,
- "broadcastdelay value %s undecodable",
- tokens[1]);
- } else {
- proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
- }
- }
+ case T_Bclient:
+ proto_config(PROTO_BROADCLIENT, enable, 0., NULL);
break;
- case CONFIG_CDELAY:
- if (ntokens >= 2) {
- u_long ui;
+ case T_Calibrate:
+ proto_config(PROTO_CAL, enable, 0., NULL);
+ break;
- if (sscanf(tokens[1], "%ld", &ui) != 1)
- msyslog(LOG_ERR,
- "illegal value - line ignored");
- else
- proto_config(PROTO_CALLDELAY, ui, 0, NULL);
- }
+ case T_Kernel:
+ proto_config(PROTO_KERNEL, enable, 0., NULL);
break;
- case CONFIG_TRUSTEDKEY:
- for (i = 1; i < ntokens; i++) {
- keyid_t tkey;
+ case T_Monitor:
+ proto_config(PROTO_MONITOR, enable, 0., NULL);
+ break;
- tkey = atol(tokens[i]);
- if (tkey == 0) {
- msyslog(LOG_ERR,
- "trusted key %s unlikely",
- tokens[i]);
- } else {
- authtrust(tkey, 1);
- }
+ case T_Ntp:
+ proto_config(PROTO_NTP, enable, 0., NULL);
+ break;
+
+ case T_Stats:
+ proto_config(PROTO_FILEGEN, enable, 0., NULL);
+ break;
+
+#ifdef BC_LIST_FRAMEWORK_NOT_YET_USED
+ case T_Bc_bugXXXX:
+ pentry = bc_list;
+ while (pentry->token) {
+ if (pentry->token == option)
+ break;
+ pentry++;
}
+ if (!pentry->token) {
+ msyslog(LOG_ERR,
+ "compat token %d not in bc_list[]",
+ option);
+ continue;
+ }
+ pentry->enabled = enable;
break;
+#endif
+ }
+ }
+}
- case CONFIG_REQUESTKEY:
- if (ntokens >= 2) {
- if (!atouint(tokens[1], &ul)) {
- msyslog(LOG_ERR,
- "%s is undecodable as request key",
- tokens[1]);
- } else if (ul == 0) {
- msyslog(LOG_ERR,
- "%s makes a poor request keyid",
- tokens[1]);
- } else {
-#ifdef DEBUG
- if (debug > 3)
- printf(
- "set info_auth_key to %08lx\n", ul);
+
+static void
+config_system_opts(
+ struct config_tree *ptree
+ )
+{
+ apply_enable_disable(ptree->enable_opts, 1);
+ apply_enable_disable(ptree->disable_opts, 0);
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_system_opts(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *flag;
+
+ while (NULL != (flag = dequeue(ptree->enable_opts)))
+ free_node(flag);
+
+ while (NULL != (flag = dequeue(ptree->disable_opts)))
+ free_node(flag);
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_logconfig(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_logconfig;
+
+ my_logconfig = queue_head(ptree->logconfig);
+ while (my_logconfig != NULL) {
+
+ switch (my_logconfig->attr) {
+ case '+':
+ ntp_syslogmask |= get_logmask(my_logconfig->value.s);
+ break;
+ case '-':
+ ntp_syslogmask &= ~get_logmask(my_logconfig->value.s);
+ break;
+ case '=':
+ ntp_syslogmask = get_logmask(my_logconfig->value.s);
+ break;
+ }
+ my_logconfig = next_node(my_logconfig);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_logconfig(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_logconfig;
+
+ while (NULL != (my_logconfig = dequeue(ptree->logconfig))) {
+ free(my_logconfig->value.s);
+ free_node(my_logconfig);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_phone(
+ struct config_tree *ptree
+ )
+{
+ int i = 0;
+ char **s;
+
+ s = queue_head(ptree->phone);
+ while (s != NULL) {
+ if (i < COUNTOF(sys_phone) - 1) {
+ sys_phone[i++] = estrdup(*s);
+ sys_phone[i] = NULL;
+ } else {
+ msyslog(LOG_INFO,
+ "phone: Number of phone entries exceeds %lu. Ignoring phone %s...",
+ (u_long)(COUNTOF(sys_phone) - 1), *s);
+ }
+ s = next_node(s);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_phone(
+ struct config_tree *ptree
+ )
+{
+ char **s;
+
+ while (NULL != (s = dequeue(ptree->phone))) {
+ free(*s);
+ free_node(s);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_qos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_qosconfig;
+ char *s;
+#ifdef HAVE_IPTOS_SUPPORT
+ unsigned int qtos = 0;
#endif
- info_auth_keyid = (keyid_t)ul;
+
+ my_qosconfig = queue_head(ptree->qos);
+ while (my_qosconfig != NULL) {
+ s = my_qosconfig->value.s;
+#ifdef HAVE_IPTOS_SUPPORT
+ if (!strcmp(s, "lowdelay"))
+ qtos = CONF_QOS_LOWDELAY;
+ else if (!strcmp(s, "throughput"))
+ qtos = CONF_QOS_THROUGHPUT;
+ else if (!strcmp(s, "reliability"))
+ qtos = CONF_QOS_RELIABILITY;
+ else if (!strcmp(s, "mincost"))
+ qtos = CONF_QOS_MINCOST;
+#ifdef IPTOS_PREC_INTERNETCONTROL
+ else if (!strcmp(s, "routine") || !strcmp(s, "cs0"))
+ qtos = CONF_QOS_CS0;
+ else if (!strcmp(s, "priority") || !strcmp(s, "cs1"))
+ qtos = CONF_QOS_CS1;
+ else if (!strcmp(s, "immediate") || !strcmp(s, "cs2"))
+ qtos = CONF_QOS_CS2;
+ else if (!strcmp(s, "flash") || !strcmp(s, "cs3"))
+ qtos = CONF_QOS_CS3; /* overlapping prefix on keyword */
+ if (!strcmp(s, "flashoverride") || !strcmp(s, "cs4"))
+ qtos = CONF_QOS_CS4;
+ else if (!strcmp(s, "critical") || !strcmp(s, "cs5"))
+ qtos = CONF_QOS_CS5;
+ else if(!strcmp(s, "internetcontrol") || !strcmp(s, "cs6"))
+ qtos = CONF_QOS_CS6;
+ else if (!strcmp(s, "netcontrol") || !strcmp(s, "cs7"))
+ qtos = CONF_QOS_CS7;
+#endif /* IPTOS_PREC_INTERNETCONTROL */
+ if (qtos == 0)
+ msyslog(LOG_ERR, "parse error, qos %s not accepted\n", s);
+ else
+ qos = qtos;
+#endif /* HAVE IPTOS_SUPPORT */
+ /*
+ * value is set, but not being effective. Need code to
+ * change the current connections to notice. Might
+ * also consider logging a message about the action.
+ * XXX msyslog(LOG_INFO, "QoS %s requested by config\n", s);
+ */
+ my_qosconfig = next_node(my_qosconfig);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_qos(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *my_qosconfig;
+
+ while (NULL != (my_qosconfig = dequeue(ptree->qos))) {
+ free(my_qosconfig->value.s);
+ free_node(my_qosconfig);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_setvar(
+ struct config_tree *ptree
+ )
+{
+ struct setvar_node *my_node;
+ size_t varlen, vallen, octets;
+ char * str;
+
+ str = NULL;
+ my_node = queue_head(ptree->setvar);
+ while (my_node != NULL) {
+ varlen = strlen(my_node->var);
+ vallen = strlen(my_node->val);
+ octets = varlen + vallen + 1 + 1;
+ str = erealloc(str, octets);
+ snprintf(str, octets, "%s=%s", my_node->var,
+ my_node->val);
+ set_sys_var(str, octets, (my_node->isdefault)
+ ? DEF
+ : 0);
+ my_node = next_node(my_node);
+ }
+ if (str != NULL)
+ free(str);
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_setvar(
+ struct config_tree *ptree
+ )
+{
+ struct setvar_node *my_node;
+
+ while (NULL != (my_node = dequeue(ptree->setvar))) {
+ free(my_node->var);
+ free(my_node->val);
+ free_node(my_node);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_ttl(
+ struct config_tree *ptree
+ )
+{
+ int i = 0;
+ int *curr_ttl;
+
+ curr_ttl = queue_head(ptree->ttl);
+ while (curr_ttl != NULL) {
+ if (i < COUNTOF(sys_ttl))
+ sys_ttl[i++] = (u_char)*curr_ttl;
+ else
+ msyslog(LOG_INFO,
+ "ttl: Number of TTL entries exceeds %lu. Ignoring TTL %d...",
+ (u_long)COUNTOF(sys_ttl), *curr_ttl);
+
+ curr_ttl = next_node(curr_ttl);
+ }
+ sys_ttlmax = i - 1;
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_ttl(
+ struct config_tree *ptree
+ )
+{
+ /* coming DESTROY_QUEUE(ptree->ttl) is enough */
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_trap(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_trap;
+ struct attr_val *curr_opt;
+ sockaddr_u addr_sock;
+ sockaddr_u peeraddr;
+ struct address_node *addr_node;
+ struct interface *localaddr;
+ u_short port_no;
+ int err_flag;
+
+ /* silence warning about addr_sock potentially uninitialized */
+ AF(&addr_sock) = AF_UNSPEC;
+
+ for (curr_trap = queue_head(ptree->trap);
+ curr_trap != NULL;
+ curr_trap = next_node(curr_trap)) {
+
+ err_flag = 0;
+ port_no = 0;
+ localaddr = NULL;
+
+ curr_opt = queue_head(curr_trap->options);
+ while (curr_opt != NULL) {
+ if (T_Port == curr_opt->attr) {
+ if (curr_opt->value.i < 1
+ || curr_opt->value.i > USHRT_MAX) {
+ msyslog(LOG_ERR,
+ "invalid port number "
+ "%d, trap ignored",
+ curr_opt->value.i);
+ err_flag = 1;
}
+ port_no = (u_short)curr_opt->value.i;
}
- break;
+ else if (T_Interface == curr_opt->attr) {
+ addr_node = curr_opt->value.p;
+
+ /* Resolve the interface address */
+ ZERO_SOCK(&addr_sock);
+ AF(&addr_sock) = (u_short)addr_node->type;
+
+ if (getnetnum(addr_node->address,
+ &addr_sock, 1, t_UNK) != 1) {
+ err_flag = 1;
+ break;
+ }
- case CONFIG_CONTROLKEY:
- if (ntokens >= 2) {
- keyid_t ckey;
+ localaddr = findinterface(&addr_sock);
- ckey = atol(tokens[1]);
- if (ckey == 0) {
+ if (NULL == localaddr) {
msyslog(LOG_ERR,
- "%s makes a poor control keyid",
- tokens[1]);
- } else {
- ctl_auth_keyid = ckey;
+ "can't find interface with address %s",
+ stoa(&addr_sock));
+ err_flag = 1;
}
}
- break;
+ curr_opt = next_node(curr_opt);
+ }
- case CONFIG_TRAP:
- if (ntokens < 2) {
+ /* Now process the trap for the specified interface
+ * and port number
+ */
+ if (!err_flag) {
+ ZERO_SOCK(&peeraddr);
+ if (1 != getnetnum(curr_trap->addr->address,
+ &peeraddr, 1, t_UNK))
+ continue;
+
+ /* port is at same location for v4 and v6 */
+ SET_PORT(&peeraddr, port_no ? port_no : TRAPPORT);
+
+ if (NULL == localaddr)
+ localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
+ else
+ AF(&peeraddr) = AF(&addr_sock);
+
+ if (!ctlsettrap(&peeraddr, localaddr, 0,
+ NTP_VERSION))
msyslog(LOG_ERR,
- "no address for trap command, line ignored");
- break;
+ "can't set trap for %s",
+ stoa(&peeraddr));
+ }
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_trap(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_trap;
+ struct attr_val *curr_opt;
+ struct address_node *addr_node;
+
+ while (NULL != (curr_trap = dequeue(ptree->trap))) {
+ while (curr_trap->options != NULL && NULL !=
+ (curr_opt = dequeue(curr_trap->options))) {
+
+ if (T_Interface == curr_opt->attr) {
+ addr_node = curr_opt->value.p;
+ destroy_address_node(addr_node);
}
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- peeraddr.ss_family = default_ai_family;
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
+ free_node(curr_opt);
+ }
+ DESTROY_QUEUE(curr_trap->options);
+ free_node(curr_trap);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_fudge(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_fudge;
+ struct attr_val *curr_opt;
+ sockaddr_u addr_sock;
+ struct address_node *addr_node;
+ struct refclockstat clock_stat;
+ int err_flag;
+
+ curr_fudge = queue_head(ptree->fudge);
+ while (curr_fudge != NULL) {
+ err_flag = 0;
+
+ /* Get the reference clock address and
+ * ensure that it is sane
+ */
+ addr_node = curr_fudge->addr;
+ ZERO_SOCK(&addr_sock);
+ if (getnetnum(addr_node->address, &addr_sock, 1, t_REF)
+ != 1)
+ err_flag = 1;
+
+ if (!ISREFCLOCKADR(&addr_sock)) {
+ msyslog(LOG_ERR,
+ "inappropriate address %s for the fudge command, line ignored",
+ stoa(&addr_sock));
+ err_flag = 1;
+ }
+
+ /* Parse all the options to the fudge command */
+ memset(&clock_stat, 0, sizeof(clock_stat));
+ curr_opt = queue_head(curr_fudge->options);
+ while (curr_opt != NULL) {
+ switch (curr_opt->attr) {
+ case T_Time1:
+ clock_stat.haveflags |= CLK_HAVETIME1;
+ clock_stat.fudgetime1 = curr_opt->value.d;
+ break;
+ case T_Time2:
+ clock_stat.haveflags |= CLK_HAVETIME2;
+ clock_stat.fudgetime2 = curr_opt->value.d;
+ break;
+ case T_Stratum:
+ clock_stat.haveflags |= CLK_HAVEVAL1;
+ clock_stat.fudgeval1 = curr_opt->value.i;
break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
+ case T_Refid:
+ clock_stat.haveflags |= CLK_HAVEVAL2;
+ clock_stat.fudgeval2 = 0;
+ memcpy(&clock_stat.fudgeval2,
+ curr_opt->value.s,
+ min(strlen(curr_opt->value.s), 4));
break;
+ case T_Flag1:
+ clock_stat.haveflags |= CLK_HAVEFLAG1;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG1;
+ else
+ clock_stat.flags &= ~CLK_FLAG1;
+ break;
+ case T_Flag2:
+ clock_stat.haveflags |= CLK_HAVEFLAG2;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG2;
+ else
+ clock_stat.flags &= ~CLK_FLAG2;
+ break;
+ case T_Flag3:
+ clock_stat.haveflags |= CLK_HAVEFLAG3;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG3;
+ else
+ clock_stat.flags &= ~CLK_FLAG3;
+ break;
+ case T_Flag4:
+ clock_stat.haveflags |= CLK_HAVEFLAG4;
+ if (curr_opt->value.i)
+ clock_stat.flags |= CLK_FLAG4;
+ else
+ clock_stat.flags &= ~CLK_FLAG4;
+ break;
+ default:
+ msyslog(LOG_ERR,
+ "Unexpected fudge internal flag 0x%x for %s\n",
+ curr_opt->attr, stoa(&addr_sock));
+ exit(curr_opt->attr ? curr_opt->attr : 1);
}
- if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
- break;
+ curr_opt = next_node(curr_opt);
+ }
- /*
- * Use peerversion for port number. Barf.
- */
- errflg = 0;
- peerversion = 0;
- localaddr = 0;
- istart++;
- for (i = istart; i < ntokens-1; i++)
- switch (matchkey(tokens[i], trap_keywords, 1)) {
- case CONF_TRAP_PORT:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "trap port requires an argument");
- errflg = 1;
- break;
- }
- peerversion = atoi(tokens[++i]);
- if (peerversion <= 0
- || peerversion > 32767) {
- msyslog(LOG_ERR,
- "invalid port number %s, trap ignored",
- tokens[i]);
- errflg = 1;
- }
- break;
-
- case CONF_TRAP_INTERFACE:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "trap interface requires an argument");
- errflg = 1;
- break;
- }
-
- memset((char *)&maskaddr, 0,
- sizeof(maskaddr));
- maskaddr.ss_family = peeraddr.ss_family;
- if (getnetnum(tokens[++i],
- &maskaddr, 1, t_UNK) != 1) {
- errflg = 1;
- break;
- }
-
- localaddr = findinterface(&maskaddr);
- if (localaddr == NULL) {
- msyslog(LOG_ERR,
- "can't find interface with address %s",
- stoa(&maskaddr));
- errflg = 1;
- }
- break;
-
- case CONFIG_UNKNOWN:
- errflg++;
- break;
- }
-
- if (!errflg) {
- if (peerversion != 0)
- ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
- else
- ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
- if (localaddr == NULL)
- localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
- if (!ctlsettrap(&peeraddr, localaddr, 0,
- NTP_VERSION))
- msyslog(LOG_ERR,
- "can't set trap for %s, no resources",
- stoa(&peeraddr));
+#ifdef REFCLOCK
+ if (!err_flag)
+ refclock_control(&addr_sock, &clock_stat,
+ (struct refclockstat *)0);
+#endif
+
+ curr_fudge = next_node(curr_fudge);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_fudge(
+ struct config_tree *ptree
+ )
+{
+ struct addr_opts_node *curr_fudge;
+ struct attr_val *curr_opt;
+
+ while (NULL != (curr_fudge = dequeue(ptree->fudge))) {
+ while (NULL != (curr_opt = dequeue(curr_fudge->options))) {
+
+ switch (curr_opt->attr) {
+ case CLK_HAVEVAL2:
+ free(curr_opt->value.s);
}
- break;
- case CONFIG_FUDGE:
- if (ntokens < 2) {
+ free_node(curr_opt);
+ }
+
+ DESTROY_QUEUE(curr_fudge->options);
+ free_node(curr_fudge);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+static void
+config_vars(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *curr_var;
+ FILE *new_file;
+ int len;
+
+ curr_var = queue_head(ptree->vars);
+ while (curr_var != NULL) {
+ /* Determine which variable to set and set it */
+ switch (curr_var->attr) {
+ case T_Broadcastdelay:
+ proto_config(PROTO_BROADDELAY, 0, curr_var->value.d, NULL);
+ break;
+ case T_Calldelay:
+ proto_config(PROTO_CALLDELAY, curr_var->value.i, 0, NULL);
+ break;
+ case T_Tick:
+ proto_config(PROTO_ADJ, 0, curr_var->value.d, NULL);
+ break;
+ case T_Driftfile:
+ if ('\0' == curr_var->value.s[0]) {
+ stats_drift_file = 0;
+ msyslog(LOG_INFO, "config: driftfile disabled\n");
+ } else
+ stats_config(STATS_FREQ_FILE, curr_var->value.s);
+ break;
+ case T_WanderThreshold:
+ wander_threshold = curr_var->value.d;
+ break;
+ case T_Leapfile:
+ stats_config(STATS_LEAP_FILE, curr_var->value.s);
+ break;
+ case T_Pidfile:
+ stats_config(STATS_PID_FILE, curr_var->value.s);
+ break;
+ case T_Logfile:
+ new_file = fopen(curr_var->value.s, "a");
+ if (new_file != NULL) {
+ NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
+ msyslog(LOG_NOTICE, "logging to file %s", curr_var->value.s);
+ if (syslog_file != NULL &&
+ fileno(syslog_file) != fileno(new_file))
+ (void)fclose(syslog_file);
+
+ syslog_file = new_file;
+ syslogit = 0;
+ }
+ else
msyslog(LOG_ERR,
- "no address for fudge command, line ignored");
+ "Cannot open log file %s",
+ curr_var->value.s);
+ break;
+
+ case T_Saveconfigdir:
+ if (saveconfigdir != NULL)
+ free(saveconfigdir);
+ len = strlen(curr_var->value.s);
+ if (0 == len)
+ saveconfigdir = NULL;
+ else if (DIR_SEP != curr_var->value.s[len - 1]
+#ifdef SYS_WINNT /* slash is also a dir. sep. on Windows */
+ && '/' != curr_var->value.s[len - 1]
+#endif
+ ) {
+ len++;
+ saveconfigdir = emalloc(len + 1);
+ snprintf(saveconfigdir, len + 1,
+ "%s%c",
+ curr_var->value.s,
+ DIR_SEP);
+ } else
+ saveconfigdir = estrdup(
+ curr_var->value.s);
+ break;
+
+ case T_Automax:
+#ifdef OPENSSL
+ sys_automax = curr_var->value.i;
+#endif
+ break;
+
+ default:
+ msyslog(LOG_ERR,
+ "config_vars(): unexpected token %d",
+ curr_var->attr);
+ }
+ curr_var = next_node(curr_var);
+ }
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_vars(
+ struct config_tree *ptree
+ )
+{
+ struct attr_val *curr_var;
+
+ while (NULL != (curr_var = dequeue(ptree->vars))) {
+ /* Determine which variable to set and set it */
+ switch (curr_var->attr) {
+ case T_Driftfile:
+ case T_Leapfile:
+ case T_Pidfile:
+ case T_Logfile:
+ free(curr_var->value.s);
+ }
+ free_node(curr_var);
+ }
+}
+#endif /* FREE_CFG_T */
+
+
+/* Define a function to check if a resolved address is sane.
+ * If yes, return 1, else return 0;
+ */
+static int
+is_sane_resolved_address(
+ sockaddr_u * peeraddr,
+ int hmode
+ )
+{
+ if (!ISREFCLOCKADR(peeraddr) && ISBADADR(peeraddr)) {
+ msyslog(LOG_ERR,
+ "attempt to configure invalid address %s",
+ stoa(peeraddr));
+ return 0;
+ }
+ /*
+ * Shouldn't be able to specify multicast
+ * address for server/peer!
+ * and unicast address for manycastclient!
+ */
+ if ((T_Server == hmode || T_Peer == hmode || T_Pool == hmode)
+ && IS_MCAST(peeraddr)) {
+ msyslog(LOG_ERR,
+ "attempt to configure invalid address %s",
+ stoa(peeraddr));
+ return 0;
+ }
+ if (T_Manycastclient == hmode && !IS_MCAST(peeraddr)) {
+ msyslog(LOG_ERR,
+ "attempt to configure invalid address %s",
+ stoa(peeraddr));
+ return 0;
+ }
+
+ if (IS_IPV6(peeraddr) && !ipv6_works)
+ return 0;
+
+ /* Ok, all tests succeeded, now we can return 1 */
+ return 1;
+}
+
+static int
+get_correct_host_mode(
+ int hmode
+ )
+{
+ switch (hmode) {
+ case T_Server:
+ case T_Pool:
+ case T_Manycastclient:
+ return MODE_CLIENT;
+ break;
+ case T_Peer:
+ return MODE_ACTIVE;
+ break;
+ case T_Broadcast:
+ return MODE_BROADCAST;
+ break;
+ default:
+ return -1;
+ }
+}
+
+static void
+config_peers(
+ struct config_tree *ptree
+ )
+{
+ struct addrinfo *res, *res_bak;
+ sockaddr_u peeraddr;
+ struct peer_node *curr_peer;
+ struct attr_val *option;
+ int hmode;
+ int peerflags;
+ int status;
+ int no_needed;
+ int i;
+
+ curr_peer = queue_head(ptree->peers);
+ while (curr_peer != NULL) {
+ /* Find the number of associations needed.
+ * If a pool coomand is specified, then sys_maxclock needed
+ * else, only one is needed
+ */
+ no_needed = (T_Pool == curr_peer->host_mode)
+ ? sys_maxclock
+ : 1;
+
+ /* Find the correct host-mode */
+ hmode = get_correct_host_mode(curr_peer->host_mode);
+ NTP_INSIST(hmode != -1);
+
+ /* translate peerflags options to bits */
+ peerflags = 0;
+ option = queue_head(curr_peer->peerflags);
+ for (; option != NULL; option = next_node(option))
+ switch (option->value.i) {
+
+ default:
+ NTP_INSIST(0);
break;
- }
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
- break;
- if (!ISREFCLOCKADR(&peeraddr)) {
- msyslog(LOG_ERR,
- "%s is inappropriate address for the fudge command, line ignored",
- stoa(&peeraddr));
+ case T_Autokey:
+ peerflags |= FLAG_SKEY;
break;
- }
- memset((void *)&clock_stat, 0, sizeof clock_stat);
- fudgeflag = 0;
- errflg = 0;
- for (i = 2; i < ntokens-1; i++) {
- switch (c = matchkey(tokens[i],
- fudge_keywords, 1)) {
- case CONF_FDG_TIME1:
- if (sscanf(tokens[++i], "%lf",
- &clock_stat.fudgetime1) != 1) {
- msyslog(LOG_ERR,
- "fudge %s time1 value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.haveflags |= CLK_HAVETIME1;
- break;
+ case T_Burst:
+ peerflags |= FLAG_BURST;
+ break;
- case CONF_FDG_TIME2:
- if (sscanf(tokens[++i], "%lf",
- &clock_stat.fudgetime2) != 1) {
- msyslog(LOG_ERR,
- "fudge %s time2 value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.haveflags |= CLK_HAVETIME2;
- break;
+ case T_Iburst:
+ peerflags |= FLAG_IBURST;
+ break;
+ case T_Noselect:
+ peerflags |= FLAG_NOSELECT;
+ break;
- case CONF_FDG_STRATUM:
- if (!atoint(tokens[++i], &stratum))
- {
- msyslog(LOG_ERR,
- "fudge %s stratum value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.fudgeval1 = stratum;
- clock_stat.haveflags |= CLK_HAVEVAL1;
- break;
+ case T_Preempt:
+ peerflags |= FLAG_PREEMPT;
+ break;
- case CONF_FDG_REFID:
- i++;
- memcpy(&clock_stat.fudgeval2,
- tokens[i], min(strlen(tokens[i]),
- 4));
- clock_stat.haveflags |= CLK_HAVEVAL2;
- break;
+ case T_Prefer:
+ peerflags |= FLAG_PREFER;
+ break;
- case CONF_FDG_FLAG1:
- case CONF_FDG_FLAG2:
- case CONF_FDG_FLAG3:
- case CONF_FDG_FLAG4:
- if (!atouint(tokens[++i], &fudgeflag)
- || fudgeflag > 1) {
- msyslog(LOG_ERR,
- "fudge %s flag value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- switch(c) {
- case CONF_FDG_FLAG1:
- c = CLK_FLAG1;
- clock_stat.haveflags|=CLK_HAVEFLAG1;
- break;
- case CONF_FDG_FLAG2:
- c = CLK_FLAG2;
- clock_stat.haveflags|=CLK_HAVEFLAG2;
- break;
- case CONF_FDG_FLAG3:
- c = CLK_FLAG3;
- clock_stat.haveflags|=CLK_HAVEFLAG3;
- break;
- case CONF_FDG_FLAG4:
- c = CLK_FLAG4;
- clock_stat.haveflags|=CLK_HAVEFLAG4;
- break;
- }
- if (fudgeflag == 0)
- clock_stat.flags &= ~c;
- else
- clock_stat.flags |= c;
- break;
+ case T_True:
+ peerflags |= FLAG_TRUE;
+ break;
- case CONFIG_UNKNOWN:
- errflg = -1;
- break;
- }
+ case T_Xleave:
+ peerflags |= FLAG_XLEAVE;
+ break;
}
-#ifdef REFCLOCK
+ /* Attempt to resolve the address */
+ ZERO_SOCK(&peeraddr);
+ AF(&peeraddr) = (u_short)curr_peer->addr->type;
+
+ status = get_multiple_netnums(curr_peer->addr->address,
+ &peeraddr, &res, 0, t_UNK);
+
+#ifdef FORCE_DEFER_DNS
+ /* Hack for debugging Deferred DNS
+ * Pretend working names didn't work.
+ */
+ if (status == 1) {
+ /* Deferring everything breaks refclocks. */
+ memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
+ if (!ISREFCLOCKADR(&peeraddr)) {
+ status = 0; /* force deferred DNS path */
+ msyslog(LOG_INFO, "Forcing Deferred DNS for %s, %s",
+ curr_peer->addr->address, stoa(&peeraddr));
+ } else {
+ msyslog(LOG_INFO, "NOT Deferring DNS for %s, %s",
+ curr_peer->addr->address, stoa(&peeraddr));
+ }
+ }
+#endif
+
+ /* I don't know why getnetnum would return -1.
+ * The old code had this test, so I guess it must be
+ * useful
+ */
+ if (status == -1) {
+ /* Do nothing, apparently we found an IPv6
+ * address and can't do anything about it */
+ }
+ /* Check if name resolution failed. If yes, store the
+ * peer information in a file for asynchronous
+ * resolution later
+ */
+ else if (status != 1) {
+ msyslog(LOG_INFO, "Deferring DNS for %s %d", curr_peer->addr->address, no_needed);
+ save_resolve(curr_peer->addr->address,
+ no_needed,
+ curr_peer->addr->type,
+ hmode,
+ curr_peer->peerversion,
+ curr_peer->minpoll,
+ curr_peer->maxpoll,
+ peerflags,
+ curr_peer->ttl,
+ curr_peer->peerkey,
+ (u_char *)"*");
+ }
+ /* Yippie!! Name resolution has succeeded!!!
+ * Now we can proceed to some more sanity checks on
+ * the resolved address before we start to configure
+ * the peer
+ */
+ else {
+ res_bak = res;
+
/*
- * If reference clock support isn't defined the
- * fudge line will still be accepted and syntax
- * checked, but will essentially do nothing.
+ * Loop to configure the desired number of
+ * associations
*/
- if (!errflg) {
- refclock_control(&peeraddr, &clock_stat,
- (struct refclockstat *)0);
+ for (i = 0; (i < no_needed) && res; res =
+ res->ai_next) {
+ ++i;
+ memcpy(&peeraddr, res->ai_addr,
+ res->ai_addrlen);
+ if (is_sane_resolved_address(
+ &peeraddr,
+ curr_peer->host_mode))
+
+ peer_config(&peeraddr,
+ NULL,
+ hmode,
+ curr_peer->peerversion,
+ curr_peer->minpoll,
+ curr_peer->maxpoll,
+ peerflags,
+ curr_peer->ttl,
+ curr_peer->peerkey,
+ (u_char *)"*");
}
-#endif
- break;
+ freeaddrinfo(res_bak);
+ }
+ curr_peer = next_node(curr_peer);
+ }
+}
- case CONFIG_STATSDIR:
- if (ntokens >= 2)
- stats_config(STATS_STATSDIR,tokens[1]);
- break;
- case CONFIG_STATISTICS:
- for (i = 1; i < ntokens; i++) {
- filegen = filegen_get(tokens[i]);
+#ifdef FREE_CFG_T
+static void
+free_config_peers(
+ struct config_tree *ptree
+ )
+{
+ struct peer_node *curr_peer;
- if (filegen == NULL) {
- msyslog(LOG_ERR,
- "no statistics named %s available",
- tokens[i]);
- continue;
- }
-#ifdef DEBUG
- if (debug > 3)
- printf("enabling filegen for %s statistics \"%s%s\"\n",
- tokens[i], filegen->prefix, filegen->basename);
-#endif
- filegen->flag |= FGEN_FLAG_ENABLED;
- }
- break;
+ while (NULL != (curr_peer = dequeue(ptree->peers))) {
+ destroy_address_node(curr_peer->addr);
+ DESTROY_QUEUE(curr_peer->peerflags);
+ free_node(curr_peer);
+ }
+}
+#endif /* FREE_CFG_T */
- case CONFIG_FILEGEN:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no id for filegen command, line ignored");
- break;
- }
- filegen = filegen_get(tokens[1]);
- if (filegen == NULL) {
- msyslog(LOG_ERR,
- "unknown filegen \"%s\" ignored",
- tokens[1]);
- break;
- }
+static void
+config_unpeers(
+ struct config_tree *ptree
+ )
+{
+ struct addrinfo *res, *res_bak;
+ sockaddr_u peeraddr;
+ struct unpeer_node *curr_unpeer;
+ struct peer *peer;
+ int status;
+ int found;
+
+ for (curr_unpeer = queue_head(ptree->unpeers);
+ curr_unpeer != NULL;
+ curr_unpeer = next_node(curr_unpeer)) {
+
+ /*
+ * Either AssocID will be zero, and we unpeer by name/
+ * address addr, or it is nonzero and addr NULL.
+ */
+ if (curr_unpeer->assocID) {
+ peer = findpeerbyassoc((u_int)curr_unpeer->assocID);
+ if (peer != NULL) {
+ peer_clear(peer, "GONE");
+ unpeer(peer);
+ }
+
+ continue;
+ }
+
+ /* Attempt to resolve the name or address */
+ ZERO_SOCK(&peeraddr);
+ AF(&peeraddr) = (u_short)curr_unpeer->addr->type;
+
+ status = get_multiple_netnums(
+ curr_unpeer->addr->address, &peeraddr, &res, 0,
+ t_UNK);
+
+ /* I don't know why getnetnum would return -1.
+ * The old code had this test, so I guess it must be
+ * useful
+ */
+ if (status == -1) {
+ /* Do nothing, apparently we found an IPv6
+ * address and can't do anything about it */
+ }
+ /* Check if name resolution failed. If yes, throw
+ * up our hands.
+ */
+ else if (status != 1) {
+ /* Do nothing */
+ }
+ /* Yippie!! Name resolution has succeeded!!!
+ */
+ else {
+ res_bak = res;
+
/*
- * peerversion is (ab)used for filegen file (index)
- * peerkey is (ab)used for filegen type
- * peerflags is (ab)used for filegen flags
+ * Loop through the addresses found
*/
- peerversion = 0;
- peerkey = filegen->type;
- peerflags = filegen->flag;
- errflg = 0;
-
- for (i = 2; i < ntokens; i++) {
- switch (matchkey(tokens[i],
- filegen_keywords, 1)) {
- case CONF_FGEN_FILE:
- if (i >= ntokens - 1) {
- msyslog(LOG_ERR,
- "filegen %s file requires argument",
- tokens[1]);
- errflg = i;
- break;
- }
- peerversion = ++i;
- break;
- case CONF_FGEN_TYPE:
- if (i >= ntokens -1) {
- msyslog(LOG_ERR,
- "filegen %s type requires argument",
- tokens[1]);
- errflg = i;
- break;
- }
- peerkey = matchkey(tokens[++i],
- fgen_types, 1);
- if (peerkey == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "filegen %s unknown type \"%s\"",
- tokens[1], tokens[i]);
- errflg = i;
- break;
- }
- break;
+ while (res) {
+ memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
- case CONF_FGEN_FLAG_LINK:
- peerflags |= FGEN_FLAG_LINK;
- break;
+ found = 0;
+ peer = NULL;
- case CONF_FGEN_FLAG_NOLINK:
- peerflags &= ~FGEN_FLAG_LINK;
- break;
+ DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
- case CONF_FGEN_FLAG_ENABLE:
- peerflags |= FGEN_FLAG_ENABLED;
- break;
+ while (!found) {
+ peer = findexistingpeer(&peeraddr, peer, -1, 0);
+ if (!peer)
+ break;
+ if (peer->flags & FLAG_CONFIG)
+ found = 1;
+ }
- case CONF_FGEN_FLAG_DISABLE:
- peerflags &= ~FGEN_FLAG_ENABLED;
- break;
+ if (found) {
+ peer_clear(peer, "GONE");
+ unpeer(peer);
}
- }
- if (!errflg)
- filegen_config(filegen, tokens[peerversion],
- (u_char)peerkey, (u_char)peerflags);
- break;
- case CONFIG_SETVAR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no value for setvar command - line ignored");
- } else {
- set_sys_var(tokens[1], strlen(tokens[1])+1,
- (u_short) (RW |
- ((((ntokens > 2)
- && !strcmp(tokens[2],
- "default")))
- ? DEF
- : 0)));
+ res = res->ai_next;
}
- break;
+ freeaddrinfo(res_bak);
+ }
+ }
+}
- case CONFIG_ENABLE:
- for (i = 1; i < ntokens; i++) {
- int flag;
- flag = matchkey(tokens[i], flags_keywords, 1);
- if (flag == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "enable unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- proto_config(flag, 1, 0., NULL);
- }
- break;
+#ifdef FREE_CFG_T
+static void
+free_config_unpeers(
+ struct config_tree *ptree
+ )
+{
+ struct unpeer_node *curr_unpeer;
+
+ while (NULL != (curr_unpeer = dequeue(ptree->unpeers))) {
+ destroy_address_node(curr_unpeer->addr);
+ free_node(curr_unpeer);
+ }
+}
+#endif /* FREE_CFG_T */
- case CONFIG_DISABLE:
- for (i = 1; i < ntokens; i++) {
- int flag;
- flag = matchkey(tokens[i], flags_keywords, 1);
- if (flag == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "disable unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- proto_config(flag, 0, 0., NULL);
- }
- break;
+#ifdef SIM
+static void
+config_sim(
+ struct config_tree *ptree
+ )
+{
+ int i;
+ server_info *serv_info;
+ struct attr_val *init_stmt;
- case CONFIG_PHONE:
- for (i = 1; i < ntokens && i < MAXPHONE - 1; i++) {
- sys_phone[i - 1] =
- emalloc(strlen(tokens[i]) + 1);
- strcpy(sys_phone[i - 1], tokens[i]);
- }
- sys_phone[i] = NULL;
- break;
+ /* Check if a simulate block was found in the configuration code.
+ * If not, return an error and exit
+ */
+ if (NULL == ptree->sim_details) {
+ fprintf(stderr, "ERROR!! I couldn't find a \"simulate\" block for configuring the simulator.\n");
+ fprintf(stderr, "\tCheck your configuration file.\n");
+ exit(1);
+ }
- case CONFIG_ADJ: {
- double ftemp;
+ /* Process the initialization statements
+ * -------------------------------------
+ */
+ init_stmt = queue_head(ptree->sim_details->init_opts);
+ while (init_stmt != NULL) {
- sscanf(tokens[1], "%lf", &ftemp);
- proto_config(PROTO_ADJ, 0, ftemp, NULL);
- }
+ switch(init_stmt->attr) {
+
+ case T_Beep_Delay:
+ simulation.beep_delay = init_stmt->value.d;
break;
+ case T_Sim_Duration:
+ simulation.end_time = init_stmt->value.d;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Unknown simulator init token %d\n",
+ init_stmt->attr);
+ exit(1);
}
+ init_stmt = next_node(init_stmt);
+ }
+
+
+ /* Process the server list
+ * -----------------------
+ */
+ simulation.num_of_servers =
+ get_no_of_elements(ptree->sim_details->servers);
+ simulation.servers = emalloc(simulation.num_of_servers
+ * sizeof(server_info));
+
+ serv_info = queue_head(ptree->sim_details->servers);
+ for (i = 0;i < simulation.num_of_servers; i++) {
+ if (NULL == serv_info) {
+ fprintf(stderr, "Simulator server list is corrupt\n");
+ exit(1);
+ } else
+ memcpy(&simulation.servers[i], serv_info, sizeof(server_info));
+ serv_info = next_node(serv_info);
}
- if (fp[0])
- (void)fclose(fp[0]);
+ /* Create server associations */
+ printf("Creating server associations\n");
+ create_server_associations();
+ fprintf(stderr,"\tServer associations successfully created!!\n");
+}
+
+
+#ifdef FREE_CFG_T
+static void
+free_config_sim(
+ struct config_tree *ptree
+ )
+{
+ if (NULL == ptree->sim_details)
+ return;
+
+ DESTROY_QUEUE(ptree->sim_details->init_opts);
+ DESTROY_QUEUE(ptree->sim_details->servers);
+
+ /* Free the sim_node memory and set the sim_details as NULL */
+ free_node(ptree->sim_details);
+ ptree->sim_details = NULL;
+}
+#endif /* FREE_CFG_T */
+#endif /* SIM */
+
+
+/* Define two different config functions. One for the daemon and the other for
+ * the simulator. The simulator ignores a lot of the standard ntpd configuration
+ * options
+ */
+#ifndef SIM
+static void
+config_ntpd(
+ struct config_tree *ptree
+ )
+{
+ config_nic_rules(ptree);
+ io_open_sockets();
+ config_monitor(ptree);
+ config_auth(ptree);
+ config_tos(ptree);
+ config_access(ptree);
+ config_tinker(ptree);
+ config_system_opts(ptree);
+ config_logconfig(ptree);
+ config_phone(ptree);
+ config_setvar(ptree);
+ config_ttl(ptree);
+ config_trap(ptree);
+ config_vars(ptree);
+ config_other_modes(ptree);
+ config_peers(ptree);
+ config_unpeers(ptree);
+ config_fudge(ptree);
+ config_qos(ptree);
+}
+#endif /* !SIM */
+
+
+#ifdef SIM
+static void
+config_ntpdsim(
+ struct config_tree *ptree
+ )
+{
+ printf("Configuring Simulator...\n");
+ printf("Some ntpd-specific commands in the configuration file will be ignored.\n");
+
+ config_tos(ptree);
+ config_monitor(ptree);
+ config_tinker(ptree);
+ config_system_opts(ptree);
+ config_logconfig(ptree);
+ config_vars(ptree);
+ config_sim(ptree);
+}
+#endif /* SIM */
+
+
+/*
+ * config_remotely() - implements ntpd side of ntpq :config
+ */
+void
+config_remotely(
+ sockaddr_u * remote_addr
+ )
+{
+ struct FILE_INFO remote_cuckoo;
+ char origin[128];
+
+ snprintf(origin, sizeof(origin), "remote config from %s",
+ stoa(remote_addr));
+ memset(&remote_cuckoo, 0, sizeof(remote_cuckoo));
+ remote_cuckoo.fname = origin;
+ remote_cuckoo.line_no = 1;
+ remote_cuckoo.col_no = 1;
+ ip_file = &remote_cuckoo;
+ input_from_file = 0;
+
+ init_syntax_tree(&cfgt);
+ yyparse();
+ cfgt.source.attr = CONF_SOURCE_NTPQ;
+ cfgt.timestamp = time(NULL);
+ cfgt.source.value.s = estrdup(stoa(remote_addr));
+
+ DPRINTF(1, ("Finished Parsing!!\n"));
+
+ save_and_apply_config_tree();
+
+ input_from_file = 1;
+}
+
+
+/*
+ * getconfig() - process startup configuration file e.g /etc/ntp.conf
+ */
+void
+getconfig(
+ int argc,
+ char *argv[]
+ )
+{
+ char line[MAXLINE];
+
+#ifdef DEBUG
+ atexit(free_all_config_trees);
+#endif
+#ifndef SYS_WINNT
+ config_file = CONFIG_FILE;
+#else
+ temp = CONFIG_FILE;
+ if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
+ msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
+ exit(1);
+ }
+ config_file = config_file_storage;
+
+ temp = ALT_CONFIG_FILE;
+ if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
+ msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
+ exit(1);
+ }
+ alt_config_file = alt_config_file_storage;
+
+#endif /* SYS_WINNT */
+ res_fp = NULL;
+ ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
+
+ /*
+ * install a non default variable with this daemon version
+ */
+ snprintf(line, sizeof(line), "daemon_version=\"%s\"", Version);
+ set_sys_var(line, strlen(line)+1, RO);
+
+ /*
+ * Set up for the first time step to install a variable showing
+ * which syscall is being used to step.
+ */
+ set_tod_using = &ntpd_set_tod_using;
+
+ /*
+ * On Windows, the variable has already been set, on the rest,
+ * initialize it to "UNKNOWN".
+ */
+#ifndef SYS_WINNT
+ strncpy(line, "settimeofday=\"UNKNOWN\"", sizeof(line));
+ set_sys_var(line, strlen(line) + 1, RO);
+#endif
+
+ /*
+ * Initialize the loop.
+ */
+ loop_config(LOOP_DRIFTINIT, 0.);
+
+ getCmdOpts(argc, argv);
+
+ init_syntax_tree(&cfgt);
+
+ curr_include_level = 0;
+ if (
+ (fp[curr_include_level] = F_OPEN(FindConfig(config_file), "r")) == NULL
#ifdef HAVE_NETINFO
- if (config_netinfo)
- free_netinfo_config(config_netinfo);
+ /* If there is no config_file, try NetInfo. */
+ && check_netinfo && !(config_netinfo = get_netinfo_config())
#endif /* HAVE_NETINFO */
+ ) {
+ msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
+#ifndef SYS_WINNT
+ io_open_sockets();
-#if !defined(VMS) && !defined(SYS_VXWORKS)
- /* find a keyid */
- if (info_auth_keyid == 0)
- req_keyid = 65535;
- else
- req_keyid = info_auth_keyid;
+ return;
+#else
+ /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
- /* if doesn't exist, make up one at random */
- if (!authhavekey(req_keyid)) {
- char rankey[9];
- int j;
-
- for (i = 0; i < 8; i++)
- for (j = 1; j < 100; ++j) {
- rankey[i] = (char) (ntp_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? */
+ if ((fp[curr_include_level] = F_OPEN(FindConfig(alt_config_file), "r")) == NULL) {
+
+ /*
+ * Broadcast clients can sometimes run without
+ * a configuration file.
+ */
+ msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
+ io_open_sockets();
+
+ return;
}
- }
+ cfgt.source.value.s = estrdup(alt_config_file);
+#endif /* SYS_WINNT */
+ } else
+ cfgt.source.value.s = estrdup(config_file);
- /* save keyid so we will accept config requests with it */
- info_auth_keyid = req_keyid;
-#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
+
+ /*** BULK OF THE PARSER ***/
+#ifdef DEBUG
+ yydebug = !!(debug >= 5);
+#endif
+ ip_file = fp[curr_include_level];
+ yyparse();
+
+ DPRINTF(1, ("Finished Parsing!!\n"));
+
+ cfgt.source.attr = CONF_SOURCE_FILE;
+ cfgt.timestamp = time(NULL);
+
+ save_and_apply_config_tree();
+
+ while (curr_include_level != -1)
+ FCLOSE(fp[curr_include_level--]);
+
+#ifdef HAVE_NETINFO
+ if (config_netinfo)
+ free_netinfo_config(config_netinfo);
+#endif /* HAVE_NETINFO */
+
+ /*
+ printf("getconfig: res_fp <%p> call_resolver: %d", res_fp, call_resolver);
+ */
if (res_fp != NULL) {
if (call_resolver) {
@@ -1912,19 +3937,180 @@ getconfig(
}
+void
+save_and_apply_config_tree(void)
+{
+ struct config_tree *ptree;
+#ifndef SAVECONFIG
+ struct config_tree *punlinked;
+#endif
+
+ /*
+ * Keep all the configuration trees applied since startup in
+ * a list that can be used to dump the configuration back to
+ * a text file.
+ */
+ ptree = emalloc(sizeof(*ptree));
+ memcpy(ptree, &cfgt, sizeof(*ptree));
+ memset(&cfgt, 0, sizeof(cfgt));
+
+ LINK_TAIL_SLIST(cfg_tree_history, ptree, link,
+ struct config_tree);
+
+#ifdef SAVECONFIG
+ if (HAVE_OPT( SAVECONFIGQUIT )) {
+ FILE *dumpfile;
+ int err;
+ int dumpfailed;
+
+ dumpfile = fopen(OPT_ARG( SAVECONFIGQUIT ), "w");
+ if (NULL == dumpfile) {
+ err = errno;
+ fprintf(stderr,
+ "can not create save file %s, error %d %s\n",
+ OPT_ARG( SAVECONFIGQUIT ), err,
+ strerror(err));
+ exit(err);
+ }
+
+ dumpfailed = dump_all_config_trees(dumpfile, 0);
+ if (dumpfailed)
+ fprintf(stderr,
+ "--saveconfigquit %s error %d\n",
+ OPT_ARG( SAVECONFIGQUIT ),
+ dumpfailed);
+ else
+ fprintf(stderr,
+ "configuration saved to %s\n",
+ OPT_ARG( SAVECONFIGQUIT ));
+
+ exit(dumpfailed);
+ }
+#endif /* SAVECONFIG */
+
+ /* The actual configuration done depends on whether we are configuring the
+ * simulator or the daemon. Perform a check and call the appropriate
+ * function as needed.
+ */
+
+#ifndef SIM
+ config_ntpd(ptree);
+#else
+ config_ntpdsim(ptree);
+#endif
+
+ /*
+ * With configure --disable-saveconfig, there's no use keeping
+ * the config tree around after application, so free it.
+ */
+#ifndef SAVECONFIG
+ UNLINK_SLIST(punlinked, cfg_tree_history, ptree, link,
+ struct config_tree);
+ NTP_INSIST(punlinked == ptree);
+ free_config_tree(ptree);
+#endif
+}
+
+
+void
+ntpd_set_tod_using(
+ const char *which
+ )
+{
+ char line[128];
+
+ snprintf(line, sizeof(line), "settimeofday=\"%s\"", which);
+ set_sys_var(line, strlen(line) + 1, RO);
+}
+
+
+/* FUNCTIONS COPIED FROM THE OLDER ntp_config.c
+ * --------------------------------------------
+ */
+
+
+/*
+ * get_pfxmatch - find value for prefixmatch
+ * and update char * accordingly
+ */
+static u_int32
+get_pfxmatch(
+ const char ** pstr,
+ struct masks * m
+ )
+{
+ while (m->name != NULL) {
+ if (strncmp(*pstr, m->name, strlen(m->name)) == 0) {
+ *pstr += strlen(m->name);
+ return m->mask;
+ } else {
+ m++;
+ }
+ }
+ return 0;
+}
+
+/*
+ * get_match - find logmask value
+ */
+static u_int32
+get_match(
+ const char * str,
+ struct masks * m
+ )
+{
+ while (m->name != NULL) {
+ if (strcmp(str, m->name) == 0)
+ return m->mask;
+ else
+ m++;
+ }
+ return 0;
+}
+
+/*
+ * get_logmask - build bitmask for ntp_syslogmask
+ */
+static u_int32
+get_logmask(
+ const char * str
+ )
+{
+ const char * t;
+ u_int32 offset;
+ u_int32 mask;
+
+ mask = get_match(str, logcfg_noclass_items);
+ if (mask != 0)
+ return mask;
+
+ t = str;
+ offset = get_pfxmatch(&t, logcfg_class);
+ mask = get_match(t, logcfg_class_items);
+
+ if (mask)
+ return mask << offset;
+ else
+ msyslog(LOG_ERR, "logconfig: '%s' not recognized - ignored",
+ str);
+
+ return 0;
+}
+
+
#ifdef HAVE_NETINFO
-/*
+/*
* get_netinfo_config - find the nearest NetInfo domain with an ntp
* configuration and initialize the configuration state.
*/
static struct netinfo_config_state *
-get_netinfo_config()
+get_netinfo_config(void)
{
ni_status status;
void *domain;
ni_id config_dir;
- struct netinfo_config_state *config;
+ struct netinfo_config_state *config;
if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
@@ -1942,12 +4128,12 @@ get_netinfo_config()
return NULL;
}
- config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
- config->domain = domain;
- config->config_dir = config_dir;
- config->prop_index = 0;
- config->val_index = 0;
- config->val_list = NULL;
+ config = emalloc(sizeof(*config));
+ config->domain = domain;
+ config->config_dir = config_dir;
+ config->prop_index = 0;
+ config->val_index = 0;
+ config->val_list = NULL;
return config;
}
@@ -1958,7 +4144,9 @@ get_netinfo_config()
* free_netinfo_config - release NetInfo configuration state
*/
static void
-free_netinfo_config(struct netinfo_config_state *config)
+free_netinfo_config(
+ struct netinfo_config_state *config
+ )
{
ni_free(config->domain);
free(config);
@@ -1983,35 +4171,39 @@ gettokens_netinfo (
/*
* Iterate through each keyword and look for a property that matches it.
*/
- again:
+ again:
if (!val_list) {
- for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
- {
- ni_namelist namelist;
+ for (; prop_index < COUNTOF(keywords); prop_index++)
+ {
+ ni_namelist namelist;
struct keyword current_prop = keywords[prop_index];
+ ni_index index;
/*
* For each value associated in the property, we're going to return
* a separate line. We squirrel away the values in the config state
* so the next time through, we don't need to do this lookup.
*/
- NI_INIT(&namelist);
- if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
- ni_index index;
+ NI_INIT(&namelist);
+ if (NI_OK == ni_lookupprop(config->domain,
+ &config->config_dir, current_prop.text,
+ &namelist)) {
/* Found the property, but it has no values */
if (namelist.ni_namelist_len == 0) continue;
- if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
- { msyslog(LOG_ERR, "out of memory while configuring"); break; }
+ config->val_list =
+ emalloc(sizeof(char*) *
+ (namelist.ni_namelist_len + 1));
+ val_list = config->val_list;
- for (index = 0; index < namelist.ni_namelist_len; index++) {
- char *value = namelist.ni_namelist_val[index];
-
- if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
- { msyslog(LOG_ERR, "out of memory while configuring"); break; }
-
- strcpy(val_list[index], value);
+ for (index = 0;
+ index < namelist.ni_namelist_len;
+ index++) {
+ char *value;
+
+ value = namelist.ni_namelist_val[index];
+ val_list[index] = estrdup(value);
}
val_list[index] = NULL;
@@ -2023,14 +4215,14 @@ gettokens_netinfo (
}
/* No list; we're done here. */
- if (!val_list) return CONFIG_UNKNOWN;
+ if (!val_list)
+ return CONFIG_UNKNOWN;
/*
* We have a list of values for the current property.
* Iterate through them and return each in order.
*/
- if (val_list[val_index])
- {
+ if (val_list[val_index]) {
int ntok = 1;
int quoted = 0;
char *tokens = val_list[val_index];
@@ -2048,16 +4240,18 @@ gettokens_netinfo (
break;
} else { /* must be space */
*tokens++ = '\0';
- while (ISSPACE(*tokens)) tokens++;
- if (ISEOL(*tokens)) break;
+ while (ISSPACE(*tokens))
+ tokens++;
+ if (ISEOL(*tokens))
+ break;
}
}
if (ntok == MAXTOKENS) {
/* HMS: chomp it to lose the EOL? */
msyslog(LOG_ERR,
- "gettokens_netinfo: too many tokens. Ignoring: %s",
- tokens);
+ "gettokens_netinfo: too many tokens. Ignoring: %s",
+ tokens);
} else {
*ntokens = ntok + 1;
}
@@ -2073,220 +4267,144 @@ gettokens_netinfo (
/* Free val_list and reset counters. */
for (val_index = 0; val_list[val_index]; val_index++)
free(val_list[val_index]);
- free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
+ free(val_list);
+ val_list = config->val_list = NULL;
+ val_index = config->val_index = 0;
goto again;
}
#endif /* HAVE_NETINFO */
-
/*
- * gettokens - read a line and return tokens
+ * getnetnum - return a net number (this is crude, but careful)
+ *
+ * returns 1 for success, and mysteriously, 0 or -1 for failure
*/
static int
-gettokens (
- FILE *fp,
- char *line,
- char **tokenlist,
- int *ntokens
+getnetnum(
+ const char *num,
+ sockaddr_u *addr,
+ int complain,
+ enum gnn_type a_type
)
{
- register char *cp;
- register int ntok;
- register int quoted = 0;
-
- /*
- * Find start of first token
- */
- again:
- while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
- cp = line;
- while (ISSPACE(*cp))
- cp++;
- if (!ISEOL(*cp))
- break;
- }
- if (cp == NULL) {
- *ntokens = 0;
- return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
- }
-
- /*
- * Now separate out the tokens
- */
- for (ntok = 0; ntok < MAXTOKENS; ntok++) {
- tokenlist[ntok] = cp;
- while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
- quoted ^= (*cp++ == '"');
-
- if (ISEOL(*cp)) {
- *cp = '\0';
- break;
- } else { /* must be space */
- *cp++ = '\0';
- while (ISSPACE(*cp))
- cp++;
- if (ISEOL(*cp))
- break;
- }
- }
+ int retval;
+ struct addrinfo *res;
- /* Heiko: Remove leading and trailing quotes around tokens */
- {
- int i,j = 0;
-
-
- for (i = 0; i < ntok; i++) {
- /* Now check if the first char is a quote and remove that */
- if ( tokenlist[ntok][0] == '"' )
- tokenlist[ntok]++;
-
- /* Now check the last char ... */
- j = strlen(tokenlist[ntok])-1;
- if ( tokenlist[ntok][j] == '"' )
- tokenlist[ntok][j] = '\0';
- }
-
- }
+ /* Get all the addresses that resolve to this name */
+ retval = get_multiple_netnums(num, addr, &res, complain, a_type);
- if (ntok == MAXTOKENS) {
- --ntok;
- /* HMS: chomp it to lose the EOL? */
- msyslog(LOG_ERR,
- "gettokens: too many tokens on the line. Ignoring %s",
- cp);
- } else {
- /*
- * Return the match
- */
- *ntokens = ntok + 1;
- ntok = matchkey(tokenlist[0], keywords, 1);
- if (ntok == CONFIG_UNKNOWN)
- goto again;
+ if (retval != 1) {
+ /* Name resolution failed */
+ return retval;
}
- return ntok;
-}
-
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
-/*
- * matchkey - match a keyword to a list
- */
-static int
-matchkey(
- register char *word,
- register struct keyword *keys,
- int complain
- )
-{
- for (;;) {
- if (keys->keytype == CONFIG_UNKNOWN) {
- if (complain)
- msyslog(LOG_ERR,
- "configure: keyword \"%s\" unknown, line ignored",
- word);
- return CONFIG_UNKNOWN;
- }
- if (STRSAME(word, keys->text))
- return keys->keytype;
- keys++;
- }
+ freeaddrinfo(res);
+ return 1;
}
/*
- * getnetnum - return a net number (this is crude, but careful)
+ * get_multiple_netnums
+ *
+ * returns 1 for success, and mysteriously, 0 or -1 for failure
*/
static int
-getnetnum(
- const char *num,
- struct sockaddr_storage *addr,
+get_multiple_netnums(
+ const char *nameornum,
+ sockaddr_u *addr,
+ struct addrinfo **res,
int complain,
enum gnn_type a_type
)
{
+ char lookbuf[1024];
+ const char *lookup;
+ char *pch;
struct addrinfo hints;
struct addrinfo *ptr;
int retval;
+ sockaddr_u ipaddr;
-#if 0
- printf("getnetnum: <%s> is a %s (%d)\n",
- num,
- (a_type == t_UNK)
- ? "t_UNK"
- : (a_type == t_REF)
- ? "t_REF"
- : (a_type == t_MSK)
- ? "t_MSK"
- : "???",
- a_type);
-#endif
-
- /* Get host address. Looking for UDP datagram connection */
- memset(&hints, 0, sizeof (hints));
- if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
- hints.ai_family = addr->ss_family;
- else
- hints.ai_family = AF_UNSPEC;
- /*
- * If we don't have an IPv6 stack, just look up IPv4 addresses
- */
- if (isc_net_probeipv6() != ISC_R_SUCCESS)
- hints.ai_family = AF_INET;
+ memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_DGRAM;
+ if (strlen(nameornum) >= sizeof(lookbuf)) {
+ NTP_INSIST(strlen(nameornum) < sizeof(lookbuf));
+ return 0;
+ }
- if (a_type != t_UNK) {
+ lookup = nameornum;
+ if (is_ip_address(nameornum, &ipaddr)) {
hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF(&ipaddr);
+ if ('[' == nameornum[0]) {
+ lookup = lookbuf;
+ strncpy(lookbuf, &nameornum[1],
+ sizeof(lookbuf));
+ pch = strchr(lookbuf, ']');
+ if (pch != NULL)
+ *pch = '\0';
+ }
+ pch = strchr(lookup, '%');
+ if (pch != NULL) {
+ if (lookup != lookbuf) {
+ lookup = lookbuf;
+ strncpy(lookbuf, nameornum,
+ sizeof(lookbuf));
+ pch = strchr(lookup, '%');
+ }
+ *pch = '\0';
+ }
}
-#ifdef DEBUG
- if (debug > 3)
- printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
-#endif
- retval = getaddrinfo(num, "ntp", &hints, &ptr);
- if (retval != 0 ||
- (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
+ if (AF_INET6 == hints.ai_family && !ipv6_works)
+ return 0;
+
+ if (AF_UNSPEC == hints.ai_family) {
+ if (!ipv6_works)
+ hints.ai_family = AF_INET;
+ else if (!ipv4_works)
+ hints.ai_family = AF_INET6;
+ else if (IS_IPV4(addr) || IS_IPV6(addr))
+ hints.ai_family = AF(addr);
+ }
+
+ /* Get host address. Looking for UDP datagram connection */
+ hints.ai_socktype = SOCK_DGRAM;
+
+ DPRINTF(4, ("getaddrinfo %s%s\n",
+ (AF_UNSPEC == hints.ai_family)
+ ? ""
+ : (AF_INET == hints.ai_family)
+ ? "v4 "
+ : "v6 ",
+ lookup));
+
+ retval = getaddrinfo(lookup, "ntp", &hints, &ptr);
+
+ if (retval || (AF_INET6 == ptr->ai_family && !ipv6_works)) {
if (complain)
msyslog(LOG_ERR,
"getaddrinfo: \"%s\" invalid host address, ignored",
- num);
-#ifdef DEBUG
- if (debug > 0)
- printf(
- "getaddrinfo: \"%s\" invalid host address%s.\n",
- num, (complain)
- ? ", ignored"
- : "");
-#endif
- if (retval == 0 &&
- ptr->ai_family == AF_INET6 &&
- isc_net_probeipv6() != ISC_R_SUCCESS)
- {
+ lookup);
+ else
+ DPRINTF(1, ("getaddrinfo: \"%s\" invalid host address.\n",
+ lookup));
+
+ if (!retval) {
+ freeaddrinfo(ptr);
return -1;
- }
- else {
+ } else {
return 0;
}
}
+ *res = ptr;
- memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
-#ifdef DEBUG
- if (debug > 1)
- printf("getnetnum given %s, got %s (%s/%d)\n",
- num, stoa(addr),
- (a_type == t_UNK)
- ? "t_UNK"
- : (a_type == t_REF)
- ? "t_REF"
- : (a_type == t_MSK)
- ? "t_MSK"
- : "???",
- a_type);
-#endif
- freeaddrinfo(ptr);
return 1;
}
@@ -2318,6 +4436,8 @@ catchchild(
static void
save_resolve(
char *name,
+ int no_needed,
+ int type,
int mode,
int version,
int minpoll,
@@ -2331,16 +4451,26 @@ save_resolve(
#ifndef SYS_VXWORKS
if (res_fp == NULL) {
#ifndef SYS_WINNT
- (void) strcpy(res_file, RES_TEMPFILE);
+ strcpy(res_file, RES_TEMPFILE);
#else
+ int len;
+
/* no /tmp directory under NT */
- {
- if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
- msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
- return;
- }
- (void) strcat(res_file, "ntpdXXXXXX");
+ if (!GetTempPath(sizeof res_file, res_file)) {
+ msyslog(LOG_ERR, "can not get temp dir: %m");
+ exit(1);
}
+
+ len = strlen(res_file);
+ if (sizeof res_file < len + sizeof "ntpdXXXXXX") {
+ msyslog(LOG_ERR,
+ "temporary directory path %s too long",
+ res_file);
+ exit(1);
+ }
+
+ memmove(res_file + len, "ntpdXXXXXX",
+ sizeof "ntpdXXXXXX");
#endif /* SYS_WINNT */
#ifdef HAVE_MKSTEMP
{
@@ -2351,7 +4481,7 @@ save_resolve(
res_fp = fdopen(fd, "r+");
}
#else
- (void) mktemp(res_file);
+ mktemp(res_file);
res_fp = fopen(res_file, "w");
#endif
if (res_fp == NULL) {
@@ -2365,12 +4495,15 @@ save_resolve(
}
#endif
- (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
- mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
+ (void)fprintf(res_fp, "%s %d %d %d %d %d %d %d %d %u %s\n",
+ name, no_needed, type,
+ mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
#ifdef DEBUG
if (debug > 1)
- printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
- version, minpoll, maxpoll, flags, ttl, keyid, keystr);
+ printf("config: %s %d %d %d %d %d %d %x %d %u %s\n",
+ name, no_needed, type,
+ mode, version, minpoll, maxpoll, flags,
+ ttl, keyid, keystr);
#endif
#else /* SYS_VXWORKS */
@@ -2397,7 +4530,10 @@ abort_resolve(void)
#ifndef SYS_VXWORKS /* we don't open the file to begin with */
#if !defined(VMS)
- (void) unlink(res_file);
+ if (unlink(res_file))
+ msyslog(LOG_WARNING,
+ "Unable to remove temporary resolver file %s, %m",
+ res_file);
#else
(void) delete(res_file);
#endif /* VMS */
@@ -2407,9 +4543,9 @@ abort_resolve(void)
/*
* do_resolve_internal - start up the resolver function (not program)
- */
-/*
- * On VMS, this routine will simply refuse to resolve anything.
+ *
+ * On VMS, VxWorks, and Unix-like systems lacking fork(), this routine
+ * will simply refuse to resolve anything.
*
* Possible implementation: keep `res_file' in memory, do async
* name resolution via QIO, update from within completion AST.
@@ -2418,7 +4554,9 @@ abort_resolve(void)
static void
do_resolve_internal(void)
{
+#ifndef SYS_WINNT
int i;
+#endif
if (res_fp == NULL) {
/* belch */
@@ -2431,12 +4569,11 @@ do_resolve_internal(void)
(void) fclose(res_fp);
res_fp = NULL;
-#if !defined(VMS) && !defined (SYS_VXWORKS)
+#ifndef NO_INTRES
req_file = res_file; /* set up pointer to res file */
#ifndef SYS_WINNT
(void) signal_no_reset(SIGCHLD, catchchild);
-#ifndef SYS_VXWORKS
/* the parent process will write to the pipe
* in order to wake up to child process
* which may be waiting in a select() call
@@ -2487,36 +4624,19 @@ do_resolve_internal(void)
* THUS:
*/
- /* This is the child process who will read the pipe,
- * so we close the write fd */
- close(resolver_pipe_fd[1]);
+ /*
+ msyslog(LOG_INFO, "do_resolve_internal: pre-closelog");
+ */
closelog();
kill_asyncio(0);
(void) signal_no_reset(SIGCHLD, SIG_DFL);
-#ifdef DEBUG
- if (0)
- debug = 2;
-#endif
-
-# ifndef LOG_DAEMON
- openlog("ntpd_initres", LOG_PID);
-# else /* LOG_DAEMON */
-
-# ifndef LOG_NTP
-# define LOG_NTP LOG_DAEMON
-# endif
- openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
-#ifndef SYS_CYGWIN32
-# ifdef DEBUG
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
- else
-# endif /* DEBUG */
- setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
-# endif /* LOG_DAEMON */
-#endif
+ init_logging("ntpd_intres", 0);
+ setup_logfile();
+ /*
+ msyslog(LOG_INFO, "do_resolve_internal: post-closelog");
+ */
ntp_intres();
@@ -2528,52 +4648,47 @@ do_resolve_internal(void)
abort_resolve();
exit(1);
}
-#else
- /* vxWorks spawns a thread... -casey */
- i = sp (ntp_intres);
- /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
-#endif
if (i == -1) {
msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
(void) signal_no_reset(SIGCHLD, SIG_DFL);
abort_resolve();
- }
- else {
+ } else
/* This is the parent process who will write to the pipe,
* so we close the read fd */
close(resolver_pipe_fd[0]);
- }
#else /* SYS_WINNT */
{
/* NT's equivalent of fork() is _spawn(), but the start point
* of the new process is an executable filename rather than
* a function name as desired here.
*/
- DWORD dwThreadId;
+ unsigned thread_id;
+ uintptr_t res_thd_handle;
+
fflush(stdout);
ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ResolverEventHandle == NULL) {
msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
abort_resolve();
}
- ResolverThreadHandle = CreateThread(
- NULL, /* no security attributes */
- 0, /* use default stack size */
- (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */
- NULL, /* argument to thread function */
- 0, /* use default creation flags */
- &dwThreadId); /* returns the thread identifier */
- if (ResolverThreadHandle == NULL) {
- msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
+ res_thd_handle = _beginthreadex(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ ntp_intres_thread, /* thread function */
+ NULL, /* argument to thread function */
+ 0, /* use default creation flags */
+ &thread_id); /* receives thread identifier */
+ if (!res_thd_handle) {
+ msyslog(LOG_ERR, "_beginthreadex ntp_intres_thread failed %m");
CloseHandle(ResolverEventHandle);
ResolverEventHandle = NULL;
abort_resolve();
}
}
#endif /* SYS_WINNT */
-#else /* VMS VX_WORKS */
+#else /* NO_INTRES follows */
msyslog(LOG_ERR,
- "Name resolution not implemented for VMS - use numeric addresses");
+ "Deferred DNS not implemented - use numeric addresses");
abort_resolve();
-#endif /* VMS VX_WORKS */
+#endif
}
diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c
index 64603d37f527..a2abf0716868 100644
--- a/ntpd/ntp_control.c
+++ b/ntpd/ntp_control.c
@@ -1,8 +1,9 @@
/*
* ntp_control.c - respond to control messages and send async traps
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include "ntpd.h"
@@ -11,73 +12,75 @@
#include "ntp_control.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include "ntp_config.h"
+#include "ntp_crypto.h"
+#include "ntp_assert.h"
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
+#include <sys/stat.h>
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
#include <arpa/inet.h>
/*
* Structure to hold request procedure information
*/
-#define NOAUTH 0
-#define AUTH 1
-
-#define NO_REQUEST (-1)
struct ctl_proc {
short control_code; /* defined request code */
+#define NO_REQUEST (-1)
u_short flags; /* flags word */
- void (*handler) P((struct recvbuf *, int)); /* handle request */
-};
-
-/*
- * Only one flag. Authentication required or not.
- */
+ /* Only one flag. Authentication required or not. */
#define NOAUTH 0
#define AUTH 1
+ void (*handler) (struct recvbuf *, int); /* handle request */
+};
+
/*
* Request processing routines
*/
-static void ctl_error P((int));
+static void ctl_error (int);
#ifdef REFCLOCK
-static u_short ctlclkstatus P((struct refclockstat *));
-#endif
-static void ctl_flushpkt P((int));
-static void ctl_putdata P((const char *, unsigned int, int));
-static void ctl_putstr P((const char *, const char *,
- unsigned int));
-static void ctl_putdbl P((const char *, double));
-static void ctl_putuint P((const char *, u_long));
-static void ctl_puthex P((const char *, u_long));
-static void ctl_putint P((const char *, long));
-static void ctl_putts P((const char *, l_fp *));
-static void ctl_putadr P((const char *, u_int32, struct sockaddr_storage*));
-static void ctl_putid P((const char *, char *));
-static void ctl_putarray P((const char *, double *, int));
-static void ctl_putsys P((int));
-static void ctl_putpeer P((int, struct peer *));
-#ifdef OPENSSL
-static void ctl_putfs P((const char *, tstamp_t));
+static u_short ctlclkstatus (struct refclockstat *);
#endif
+static void ctl_flushpkt (int);
+static void ctl_putdata (const char *, unsigned int, int);
+static void ctl_putstr (const char *, const char *,
+ unsigned int);
+static void ctl_putdbl (const char *, double);
+static void ctl_putuint (const char *, u_long);
+static void ctl_puthex (const char *, u_long);
+static void ctl_putint (const char *, long);
+static void ctl_putts (const char *, l_fp *);
+static void ctl_putadr (const char *, u_int32,
+ sockaddr_u *);
+static void ctl_putrefid (const char *, u_int32);
+static void ctl_putarray (const char *, double *, int);
+static void ctl_putsys (int);
+static void ctl_putpeer (int, struct peer *);
+static void ctl_putfs (const char *, tstamp_t);
#ifdef REFCLOCK
-static void ctl_putclock P((int, struct refclockstat *, int));
+static void ctl_putclock (int, struct refclockstat *, int);
#endif /* REFCLOCK */
-static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
-static u_long count_var P((struct ctl_var *));
-static void control_unspec P((struct recvbuf *, int));
-static void read_status P((struct recvbuf *, int));
-static void read_variables P((struct recvbuf *, int));
-static void write_variables P((struct recvbuf *, int));
-static void read_clock_status P((struct recvbuf *, int));
-static void write_clock_status P((struct recvbuf *, int));
-static void set_trap P((struct recvbuf *, int));
-static void unset_trap P((struct recvbuf *, int));
-static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
- struct interface *));
+static struct ctl_var *ctl_getitem (struct ctl_var *, char **);
+static u_long count_var (struct ctl_var *);
+static void control_unspec (struct recvbuf *, int);
+static void read_status (struct recvbuf *, int);
+static void read_variables (struct recvbuf *, int);
+static void write_variables (struct recvbuf *, int);
+static void read_clock_status (struct recvbuf *, int);
+static void write_clock_status (struct recvbuf *, int);
+static void set_trap (struct recvbuf *, int);
+static void unset_trap (struct recvbuf *, int);
+static void configure (struct recvbuf *, int);
+static void save_config (struct recvbuf *, int);
+static struct ctl_trap *ctlfindtrap (sockaddr_u *,
+ struct interface *);
static struct ctl_proc control_codes[] = {
{ CTL_OP_UNSPEC, NOAUTH, control_unspec },
@@ -88,6 +91,8 @@ static struct ctl_proc control_codes[] = {
{ CTL_OP_WRITECLOCK, NOAUTH, write_clock_status },
{ CTL_OP_SETTRAP, NOAUTH, set_trap },
{ CTL_OP_UNSETTRAP, NOAUTH, unset_trap },
+ { CTL_OP_SAVECONFIG, AUTH, save_config },
+ { CTL_OP_CONFIGURE, AUTH, configure },
{ NO_REQUEST, 0 }
};
@@ -101,35 +106,36 @@ static struct ctl_var sys_var[] = {
{ CS_STRATUM, RO, "stratum" }, /* 2 */
{ CS_PRECISION, RO, "precision" }, /* 3 */
{ CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */
- { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
+ { CS_ROOTDISPERSION, RO, "rootdisp" }, /* 5 */
{ CS_REFID, RO, "refid" }, /* 6 */
{ CS_REFTIME, RO, "reftime" }, /* 7 */
- { CS_POLL, RO, "poll" }, /* 8 */
+ { CS_POLL, RO, "tc" }, /* 8 */
{ CS_PEERID, RO, "peer" }, /* 9 */
- { CS_STATE, RO, "state" }, /* 10 */
- { CS_OFFSET, RO, "offset" }, /* 11 */
- { CS_DRIFT, RO, "frequency" }, /* 12 */
- { CS_JITTER, RO, "jitter" }, /* 13 */
- { CS_ERROR, RO, "noise" }, /* 14 */
- { CS_CLOCK, RO, "clock" }, /* 15 */
- { CS_PROCESSOR, RO, "processor" }, /* 16 */
- { CS_SYSTEM, RO, "system" }, /* 17 */
- { CS_VERSION, RO, "version" }, /* 18 */
- { CS_STABIL, RO, "stability" }, /* 19 */
- { CS_VARLIST, RO, "sys_var_list" }, /* 20 */
+ { CS_OFFSET, RO, "offset" }, /* 10 */
+ { CS_DRIFT, RO, "frequency" }, /* 11 */
+ { CS_JITTER, RO, "sys_jitter" }, /* 12 */
+ { CS_ERROR, RO, "clk_jitter" }, /* 13 */
+ { CS_CLOCK, RO, "clock" }, /* 14 */
+ { CS_PROCESSOR, RO, "processor" }, /* 15 */
+ { CS_SYSTEM, RO, "system" }, /* 16 */
+ { CS_VERSION, RO, "version" }, /* 17 */
+ { CS_STABIL, RO, "clk_wander" }, /* 18 */
+ { CS_VARLIST, RO, "sys_var_list" }, /* 19 */
+ { CS_TAI, RO, "tai" }, /* 20 */
+ { CS_LEAPTAB, RO, "leapsec" }, /* 21 */
+ { CS_LEAPEND, RO, "expire" }, /* 22 */
+ { CS_RATE, RO, "mintc" }, /* 23 */
#ifdef OPENSSL
- { CS_FLAGS, RO, "flags" }, /* 21 */
- { CS_HOST, RO, "hostname" }, /* 22 */
- { CS_PUBLIC, RO, "update" }, /* 23 */
- { CS_CERTIF, RO, "cert" }, /* 24 */
- { CS_REVTIME, RO, "expire" }, /* 25 */
- { CS_LEAPTAB, RO, "leapsec" }, /* 26 */
- { CS_TAI, RO, "tai" }, /* 27 */
- { CS_DIGEST, RO, "signature" }, /* 28 */
- { CS_IDENT, RO, "ident" }, /* 29 */
- { CS_REVOKE, RO, "expire" }, /* 30 */
+ { CS_FLAGS, RO, "flags" }, /* 24 */
+ { CS_HOST, RO, "host" }, /* 25 */
+ { CS_PUBLIC, RO, "update" }, /* 26 */
+ { CS_CERTIF, RO, "cert" }, /* 27 */
+ { CS_SIGNATURE, RO, "signature" }, /* 28 */
+ { CS_REVTIME, RO, "until" }, /* 29 */
+ { CS_GROUP, RO, "group" }, /* 30 */
+ { CS_DIGEST, RO, "digest" }, /* 31 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 21/31 */
+ { 0, EOV, "" } /* 24/3 2*/
};
static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
@@ -147,25 +153,27 @@ static u_char def_sys_var[] = {
CS_PRECISION,
CS_ROOTDELAY,
CS_ROOTDISPERSION,
- CS_PEERID,
CS_REFID,
CS_REFTIME,
- CS_POLL,
CS_CLOCK,
- CS_STATE,
+ CS_PEERID,
+ CS_POLL,
+ CS_RATE,
CS_OFFSET,
CS_DRIFT,
CS_JITTER,
CS_ERROR,
CS_STABIL,
+ CS_TAI,
+ CS_LEAPTAB,
+ CS_LEAPEND,
#ifdef OPENSSL
CS_HOST,
- CS_DIGEST,
+ CS_GROUP,
CS_FLAGS,
+ CS_DIGEST,
+ CS_SIGNATURE,
CS_PUBLIC,
- CS_IDENT,
- CS_LEAPTAB,
- CS_TAI,
CS_CERTIF,
#endif /* OPENSSL */
0
@@ -191,12 +199,12 @@ static struct ctl_var peer_var[] = {
{ CP_HPOLL, RO, "hpoll" }, /* 12 */
{ CP_PRECISION, RO, "precision" }, /* 13 */
{ CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
- { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
+ { CP_ROOTDISPERSION, RO, "rootdisp" }, /* 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_XMT, RO, "xleave" }, /* 20 */
{ CP_REACH, RO, "reach" }, /* 21 */
{ CP_UNREACH, RO, "unreach" }, /* 22 */
{ CP_TIMER, RO, "timer" }, /* 23 */
@@ -214,17 +222,20 @@ static struct ctl_var peer_var[] = {
{ CP_FLASH, RO, "flash" }, /* 35 */
{ CP_TTL, RO, "ttl" }, /* 36 */
{ CP_VARLIST, RO, "peer_var_list" }, /* 37 */
+ { CP_IN, RO, "in" }, /* 38 */
+ { CP_OUT, RO, "out" }, /* 39 */
+ { CP_RATE, RO, "headway" }, /* 40 */
+ { CP_BIAS, RO, "bias" }, /* 41 */
#ifdef OPENSSL
- { CP_FLAGS, RO, "flags" }, /* 38 */
- { CP_HOST, RO, "hostname" }, /* 39 */
- { CP_VALID, RO, "valid" }, /* 40 */
- { CP_INITSEQ, RO, "initsequence" }, /* 41 */
- { CP_INITKEY, RO, "initkey" }, /* 42 */
- { CP_INITTSP, RO, "timestamp" }, /* 43 */
- { CP_DIGEST, RO, "signature" }, /* 44 */
- { CP_IDENT, RO, "trust" }, /* 45 */
+ { CP_FLAGS, RO, "flags" }, /* 42 */
+ { CP_HOST, RO, "host" }, /* 43 */
+ { CP_VALID, RO, "valid" }, /* 44 */
+ { CP_INITSEQ, RO, "initsequence" }, /* 45 */
+ { CP_INITKEY, RO, "initkey" }, /* 46 */
+ { CP_INITTSP, RO, "timestamp" }, /* 47 */
+ { CP_SIGNATURE, RO, "signature" }, /* 48 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 38/46 */
+ { 0, EOV, "" } /* 42/49 */
};
@@ -236,18 +247,23 @@ static u_char def_peer_var[] = {
CP_SRCPORT,
CP_DSTADR,
CP_DSTPORT,
+ CP_OUT,
+ CP_IN,
CP_LEAP,
CP_STRATUM,
CP_PRECISION,
CP_ROOTDELAY,
CP_ROOTDISPERSION,
CP_REFID,
+ CP_REFTIME,
+ CP_REC,
CP_REACH,
CP_UNREACH,
CP_HMODE,
CP_PMODE,
CP_HPOLL,
CP_PPOLL,
+ CP_RATE,
CP_FLASH,
CP_KEYID,
CP_TTL,
@@ -255,19 +271,16 @@ static u_char def_peer_var[] = {
CP_DELAY,
CP_DISPERSION,
CP_JITTER,
- CP_REFTIME,
- CP_ORG,
- CP_REC,
CP_XMT,
+ CP_BIAS,
CP_FILTDELAY,
CP_FILTOFFSET,
CP_FILTERROR,
#ifdef OPENSSL
CP_HOST,
- CP_DIGEST,
- CP_VALID,
CP_FLAGS,
- CP_IDENT,
+ CP_SIGNATURE,
+ CP_VALID,
CP_INITSEQ,
#endif /* OPENSSL */
0
@@ -326,7 +339,7 @@ static u_char def_clock_var[] = {
# define STR_SYSTEM "UNIX"
# endif
# ifndef STR_PROCESSOR
-# define STR_PROCESSOR "unknown"
+# define STR_PROCESSOR "unknown"
# endif
static char str_system[] = STR_SYSTEM;
@@ -388,8 +401,8 @@ static u_char clocktypes[] = {
CTL_SST_TS_NTP, /* not used (24) */
CTL_SST_TS_NTP, /* not used (25) */
CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
+ CTL_SST_TS_LF, /* REFCLK_ARCRON_MSF (27) */
+ CTL_SST_TS_UHF, /* REFCLK_SHM (28) */
CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */
CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
@@ -397,7 +410,7 @@ static u_char clocktypes[] = {
CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (33) */
CTL_SST_TS_LF, /* REFCLK_ULINK (34) */
CTL_SST_TS_LF, /* REFCLK_PCF (35) */
- CTL_SST_TS_LF, /* REFCLK_WWV (36) */
+ CTL_SST_TS_HF, /* 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) */
@@ -456,7 +469,7 @@ static u_char * datapt;
static u_char * dataend;
static int datalinelen;
static int datanotbinflag;
-static struct sockaddr_storage *rmt_addr;
+static sockaddr_u *rmt_addr;
static struct interface *lcl_inter;
static u_char res_authenticate;
@@ -505,16 +518,14 @@ ctl_error(
int errcode
)
{
-#ifdef DEBUG
- if (debug >= 4)
- printf("sending control error %d\n", errcode);
-#endif
+ DPRINTF(3, ("sending control error %d\n", errcode));
+
/*
* 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));
+ CTL_OP_MASK));
rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
rpkt.count = 0;
@@ -524,19 +535,137 @@ ctl_error(
if (res_authenticate && sys_authenticate) {
int maclen;
- *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
- htonl(res_keyid);
maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
- CTL_HEADER_LEN);
+ 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++;
}
+/*
+ * save_config - Implements ntpq -c "saveconfig <filename>"
+ * Writes current configuration including any runtime
+ * changes by ntpq's :config or config-from-file
+ */
+void
+save_config(
+ struct recvbuf *rbufp,
+ int restrict_mask
+ )
+{
+ char reply[128];
+#ifdef SAVECONFIG
+ char filespec[128];
+ char filename[128];
+ char fullpath[512];
+ const char savedconfig_eq[] = "savedconfig=";
+ char savedconfig[sizeof(savedconfig_eq) + sizeof(filename)];
+ time_t now;
+ int fd;
+ FILE *fptr;
+#endif
+
+ if (restrict_mask & RES_NOMODIFY) {
+ snprintf(reply, sizeof(reply),
+ "saveconfig prohibited by restrict ... nomodify");
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "saveconfig from %s rejected due to nomodify restriction",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+#ifdef SAVECONFIG
+ if (NULL == saveconfigdir) {
+ snprintf(reply, sizeof(reply),
+ "saveconfig prohibited, no saveconfigdir configured");
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "saveconfig from %s rejected, no saveconfigdir",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+ if (0 == reqend - reqpt)
+ return;
+
+ strncpy(filespec, reqpt, sizeof(filespec));
+ filespec[sizeof(filespec) - 1] = '\0';
+
+ time(&now);
+
+ /*
+ * allow timestamping of the saved config filename with
+ * strftime() format such as:
+ * ntpq -c "saveconfig ntp-%Y%m%d-%H%M%S.conf"
+ */
+ if (0 == strftime(filename, sizeof(filename), filespec,
+ localtime(&now)))
+ strncpy(filename, filespec, sizeof(filename));
+
+ filename[sizeof(filename) - 1] = '\0';
+
+ if (strchr(filename, '\\') || strchr(filename, '/')) {
+ snprintf(reply, sizeof(reply),
+ "saveconfig does not allow directory in filename");
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "saveconfig with path from %s rejected",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+ snprintf(fullpath, sizeof(fullpath), "%s%s",
+ saveconfigdir, filename);
+
+ fd = open(fullpath, O_CREAT | O_TRUNC | O_WRONLY,
+ S_IRUSR | S_IWUSR);
+ if (-1 == fd)
+ fptr = NULL;
+ else
+ fptr = fdopen(fd, "w");
+
+ if (NULL == fptr || -1 == dump_all_config_trees(fptr, 1)) {
+ snprintf(reply, sizeof(reply),
+ "Unable to save configuration to file %s",
+ filename);
+ msyslog(LOG_ERR,
+ "saveconfig %s from %s failed", filename,
+ stoa(&rbufp->recv_srcadr));
+ } else {
+ snprintf(reply, sizeof(reply),
+ "Configuration saved to %s", filename);
+ msyslog(LOG_NOTICE,
+ "Configuration saved to %s (requested by %s)",
+ fullpath, stoa(&rbufp->recv_srcadr));
+ /*
+ * save the output filename in system variable
+ * savedconfig, retrieved with:
+ * ntpq -c "rv 0 savedconfig"
+ */
+ snprintf(savedconfig, sizeof(savedconfig), "%s%s",
+ savedconfig_eq, filename);
+ set_sys_var(savedconfig, strlen(savedconfig) + 1, RO);
+ }
+
+ if (NULL != fptr)
+ fclose(fptr);
+#else /* !SAVECONFIG follows */
+ snprintf(reply, sizeof(reply),
+ "saveconfig unavailable, configured with --disable-saveconfig");
+#endif
+
+ ctl_putdata(reply, strlen(reply), 0);
+ ctl_flushpkt(0);
+}
+
/*
* process_control - process an incoming control message
@@ -554,10 +683,7 @@ process_control(
int properlen;
int maclen;
-#ifdef DEBUG
- if (debug > 2)
- printf("in process_control()\n");
-#endif
+ DPRINTF(3, ("in process_control()\n"));
/*
* Save the addresses for error responses
@@ -574,10 +700,7 @@ process_control(
if (rbufp->recv_length < CTL_HEADER_LEN
|| pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
|| pkt->offset != 0) {
-#ifdef DEBUG
- if (debug)
- printf("invalid format in control packet\n");
-#endif
+ DPRINTF(1, ("invalid format in control packet\n"));
if (rbufp->recv_length < CTL_HEADER_LEN)
numctltooshort++;
if (pkt->r_m_e_op & CTL_RESPONSE)
@@ -592,11 +715,8 @@ process_control(
}
res_version = PKT_VERSION(pkt->li_vn_mode);
if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
-#ifdef DEBUG
- if (debug)
- printf("unknown version %d in control packet\n",
- res_version);
-#endif
+ DPRINTF(1, ("unknown version %d in control packet\n",
+ res_version));
numctlbadversion++;
return;
}
@@ -606,7 +726,7 @@ process_control(
* responses
*/
rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
- MODE_CONTROL);
+ MODE_CONTROL);
res_opcode = pkt->r_m_e_op;
rpkt.sequence = pkt->sequence;
rpkt.associd = pkt->associd;
@@ -617,12 +737,16 @@ process_control(
res_authenticate = 0;
res_keyid = 0;
res_authokay = 0;
- req_count = (int)htons(pkt->count);
+ req_count = (int)ntohs(pkt->count);
datanotbinflag = 0;
datalinelen = 0;
datapt = rpkt.data;
dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
+ if ((rbufp->recv_length & 0x3) != 0)
+ DPRINTF(3, ("Control packet length %d unrounded\n",
+ rbufp->recv_length));
+
/*
* We're set up now. Make sure we've got at least enough
* incoming data space to match the count.
@@ -635,46 +759,30 @@ 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);
-#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 &&
+ if ((rbufp->recv_length & 3) == 0 &&
maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
sys_authenticate) {
res_authenticate = 1;
res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
- properlen));
-
-#ifdef DEBUG
- if (debug > 2)
- printf(
- "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
- rbufp->recv_length, properlen, res_keyid, maclen);
-#endif
- if (!authistrusted(res_keyid)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("invalid keyid %08x\n",
- res_keyid);
-#endif
- } else if (authdecrypt(res_keyid, (u_int32 *)pkt,
- rbufp->recv_length - maclen, maclen)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("authenticated okay\n");
-#endif
+ properlen));
+
+ DPRINTF(3, ("recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
+ rbufp->recv_length, properlen, res_keyid,
+ maclen));
+
+ if (!authistrusted(res_keyid))
+ DPRINTF(3, ("invalid keyid %08x\n", res_keyid));
+ else if (authdecrypt(res_keyid, (u_int32 *)pkt,
+ rbufp->recv_length - maclen,
+ maclen)) {
+ DPRINTF(3, ("authenticated okay\n"));
res_authokay = 1;
} else {
-#ifdef DEBUG
- if (debug > 2)
- printf("authentication failed\n");
-#endif
+ DPRINTF(3, ("authentication failed\n"));
res_keyid = 0;
}
}
@@ -690,13 +798,11 @@ process_control(
*/
for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
if (cc->control_code == res_opcode) {
-#ifdef DEBUG
- if (debug > 2)
- printf("opcode %d, found command handler\n",
- res_opcode);
-#endif
- if (cc->flags == AUTH && (!res_authokay ||
- res_keyid != ctl_auth_keyid)) {
+ DPRINTF(3, ("opcode %d, found command handler\n",
+ res_opcode));
+ if (cc->flags == AUTH
+ && (!res_authokay
+ || res_keyid != ctl_auth_keyid)) {
ctl_error(CERR_PERMISSION);
return;
}
@@ -722,17 +828,19 @@ ctlpeerstatus(
register struct peer *peer
)
{
- register u_short status;
+ u_short status;
status = peer->status;
- if (peer->flags & FLAG_CONFIG)
+ if (!(peer->flags & FLAG_PREEMPT))
status |= CTL_PST_CONFIG;
- if (peer->flags & FLAG_AUTHENABLE)
+ if (peer->keyid != 0)
status |= CTL_PST_AUTHENABLE;
if (peer->flags & FLAG_AUTHENTIC)
status |= CTL_PST_AUTHENTIC;
if (peer->reach != 0)
status |= CTL_PST_REACH;
+ if (peer->cast_flags & (MDF_BCAST | MDF_MCAST | MDF_ACAST))
+ status |= CTL_PST_BCAST;
return (u_short)CTL_PEER_STATUS(status, peer->num_events,
peer->last_event);
}
@@ -747,8 +855,8 @@ ctlclkstatus(
struct refclockstat *this_clock
)
{
- return ((u_short)(((this_clock->currentstatus) << 8) |
- (this_clock->lastevent)));
+ return (u_short)CTL_PEER_STATUS(0, this_clock->lastevent,
+ this_clock->currentstatus);
}
#endif
@@ -766,16 +874,15 @@ ctlsysstatus(void)
if (sys_peer != 0) {
if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
this_clock = sys_peer->sstclktype;
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
} else {
if (sys_peer->refclktype < sizeof(clocktypes))
this_clock =
clocktypes[sys_peer->refclktype];
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
}
}
+#else /* REFCLOCK */
+ if (sys_peer != 0)
+ this_clock = CTL_SST_TS_NTP;
#endif /* REFCLOCK */
return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
ctl_sys_num_events, ctl_sys_last_event);
@@ -816,7 +923,7 @@ 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));
+ CTL_OP_MASK));
rpkt.count = htons((u_short) dlen);
rpkt.offset = htons( (u_short) res_offset);
if (res_async) {
@@ -826,8 +933,8 @@ ctl_flushpkt(
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);
+ ctl_trap[i].tr_version,
+ MODE_CONTROL);
rpkt.sequence =
htons(ctl_trap[i].tr_sequence);
sendpkt(&ctl_trap[i].tr_addr,
@@ -855,12 +962,12 @@ ctl_flushpkt(
}
memcpy(datapt, &keyid, sizeof keyid);
maclen = authencrypt(res_keyid,
- (u_int32 *)&rpkt, totlen);
+ (u_int32 *)&rpkt, totlen);
sendpkt(rmt_addr, lcl_inter, -5,
- (struct pkt *)&rpkt, totlen + maclen);
+ (struct pkt *)&rpkt, totlen + maclen);
} else {
sendpkt(rmt_addr, lcl_inter, -6,
- (struct pkt *)&rpkt, sendlen);
+ (struct pkt *)&rpkt, sendlen);
}
if (more)
numctlfrags++;
@@ -897,7 +1004,7 @@ ctl_putdata(
*datapt++ = ',';
datalinelen++;
if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
- {
+ {
*datapt++ = '\r';
*datapt++ = '\n';
datalinelen = 0;
@@ -972,10 +1079,10 @@ ctl_putdbl(
while (*cq != '\0')
*cp++ = *cq++;
*cp++ = '=';
- (void)sprintf(cp, "%.3f", ts);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%.3f", ts);
+ cp += strlen(cp);
+ ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
/*
@@ -997,16 +1104,15 @@ ctl_putuint(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "%lu", uval);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%lu", uval);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
/*
* ctl_putfs - write a decoded filestamp into the response
*/
-#ifdef OPENSSL
static void
ctl_putfs(
const char *tag,
@@ -1027,20 +1133,20 @@ ctl_putfs(
*cp++ = '=';
fstamp = uval - JAN_1970;
tm = gmtime(&fstamp);
- if (tm == NULL)
+ if (NULL == tm)
return;
-
- sprintf(cp, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
- tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer),
+ "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
-#endif
/*
- * ctl_puthex - write a tagged unsigned integer, in hex, into the response
+ * ctl_puthex - write a tagged unsigned integer, in hex, into the
+ * response
*/
static void
ctl_puthex(
@@ -1058,9 +1164,9 @@ ctl_puthex(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "0x%lx", uval);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "0x%lx", uval);
+ cp += strlen(cp);
ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
}
@@ -1084,9 +1190,9 @@ ctl_putint(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "%ld", ival);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%ld", ival);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1110,11 +1216,10 @@ ctl_putts(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "0x%08lx.%08lx",
- ts->l_ui & ULONG_CONST(0xffffffff),
- ts->l_uf & ULONG_CONST(0xffffffff));
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "0x%08lx.%08lx",
+ ts->l_ui & 0xffffffffUL, ts->l_uf & 0xffffffffUL);
+ cp += strlen(cp);
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1126,7 +1231,7 @@ static void
ctl_putadr(
const char *tag,
u_int32 addr32,
- struct sockaddr_storage* addr
+ sockaddr_u *addr
)
{
register char *cp;
@@ -1139,38 +1244,54 @@ ctl_putadr(
*cp++ = *cq++;
*cp++ = '=';
- if (addr == NULL)
+ if (NULL == addr)
cq = numtoa(addr32);
else
cq = stoa(addr);
- while (*cq != '\0')
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer), "%s", cq);
+ cp += strlen(cp);
+ ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
+
/*
- * ctl_putid - write a tagged clock ID into the response
+ * ctl_putrefid - send a u_int32 refid as printable text
*/
static void
-ctl_putid(
- const char *tag,
- char *id
+ctl_putrefid(
+ const char * tag,
+ u_int32 refid
)
{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- cq = id;
- while (*cq != '\0' && (cq - id) < 4)
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+ char output[16];
+ char * optr;
+ char * oplim;
+ char * iptr;
+ char * iplim;
+ char * past_eq;
+
+ optr = output;
+ oplim = output + sizeof(output);
+ while (optr < oplim && '\0' != *tag)
+ *optr++ = *tag++;
+ if (optr < oplim) {
+ *optr++ = '=';
+ past_eq = optr;
+ }
+ if (!(optr < oplim))
+ return;
+ iptr = (char *)&refid;
+ iplim = iptr + sizeof(refid);
+ for ( ; optr < oplim && iptr < iplim && '\0' != *iptr;
+ iptr++, optr++)
+ if (isprint(*iptr))
+ *optr = *iptr;
+ else
+ *optr = '.';
+ if (!(optr <= oplim))
+ optr = past_eq;
+ ctl_putdata(output, (u_int)(optr - output), FALSE);
}
@@ -1197,9 +1318,10 @@ ctl_putarray(
if (i == 0)
i = NTP_SHIFT;
i--;
- (void)sprintf(cp, " %.2f", arr[i] * 1e3);
- while (*cp != '\0')
- cp++;
+ NTP_INSIST((cp - buffer) < sizeof(buffer));
+ snprintf(cp, sizeof(buffer) - (cp - buffer),
+ " %.2f", arr[i] * 1e3);
+ cp += strlen(cp);
} while(i != start);
ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
@@ -1222,237 +1344,239 @@ ctl_putsys(
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:
+ case CS_ROOTDELAY:
ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
- 1e3);
+ 1e3);
break;
- case CS_ROOTDISPERSION:
+ case CS_ROOTDISPERSION:
ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
- sys_rootdispersion * 1e3);
+ sys_rootdisp * 1e3);
break;
- case CS_REFID:
+ case CS_REFID:
if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
- ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL);
+ ctl_putadr(sys_var[varid].text, sys_refid, NULL);
else
- ctl_putid(sys_var[CS_REFID].text,
- (char *)&sys_refid);
+ ctl_putrefid(sys_var[varid].text, 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);
+ sys_peer->associd);
break;
- 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_JITTER:
+ case CS_JITTER:
ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
break;
- case CS_ERROR:
+ case CS_ERROR:
ctl_putdbl(sys_var[CS_ERROR].text, clock_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));
+ 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
- sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
+ snprintf(str, sizeof(str), "%s/%s", utsnamebuf.sysname,
+ utsnamebuf.release);
ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
#endif /* HAVE_UNAME */
break;
- case CS_VERSION:
+ case CS_VERSION:
ctl_putstr(sys_var[CS_VERSION].text, Version,
- strlen(Version));
+ strlen(Version));
break;
- case CS_STABIL:
+ case CS_STABIL:
ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
- 1e6);
- break;
-
- case CS_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(sys_var[CS_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, sys_var[CS_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = sys_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
- i = strlen(k->text);
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
+ 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);
+ if (s + strlen(sys_var[CS_VARLIST].text) + 4 > be)
+ break; /* really long var name */
+
+ snprintf(s, sizeof(buf), "%s=\"",
+ sys_var[CS_VARLIST].text);
+ s += strlen(s);
+ t = s;
+ for (k = sys_var; !(k->flags & EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+ i = strlen(k->text);
+ if (s+i+1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, i);
+ s += i;
+ }
+
+ for (k = ext_sys_var; k && !(k->flags & EOV);
+ k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ ss = k->text;
+ if (!ss)
+ continue;
+
+ while (*ss && *ss != '=')
+ ss++;
+ i = ss - k->text;
+ if (s + i + 1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text,
+ (unsigned)i);
+ s += i;
+ }
+ if (s+2 >= be)
+ break;
- for (k = ext_sys_var; k && !(k->flags &EOV);
- k++) {
- if (k->flags & PADDING)
- continue;
+ *s++ = '"';
+ *s = '\0';
- ss = k->text;
- if (!ss)
- continue;
+ ctl_putdata(buf, (unsigned)( s - buf ),
+ 0);
+ }
+ break;
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s + i + 1 >= be)
- break;
+ case CS_TAI:
+ if (sys_tai > 0)
+ ctl_putuint(sys_var[CS_TAI].text, sys_tai);
+ break;
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text,
- (unsigned)i);
- s += i;
- }
- if (s+2 >= be)
- break;
+ case CS_LEAPTAB:
+ if (leap_sec > 0)
+ ctl_putfs(sys_var[CS_LEAPTAB].text,
+ leap_sec);
+ break;
- *s++ = '"';
- *s = '\0';
+ case CS_LEAPEND:
+ if (leap_expire > 0)
+ ctl_putfs(sys_var[CS_LEAPEND].text,
+ leap_expire);
+ break;
- ctl_putdata(buf, (unsigned)( s - buf ),
- 0);
- }
+ case CS_RATE:
+ ctl_putuint(sys_var[CS_RATE].text, ntp_minpoll);
break;
#ifdef OPENSSL
- case CS_FLAGS:
+ case CS_FLAGS:
+ if (crypto_flags)
+ ctl_puthex(sys_var[CS_FLAGS].text,
+ crypto_flags);
+ break;
+
+ case CS_DIGEST:
if (crypto_flags) {
- ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
+ strcpy(str, OBJ_nid2ln(crypto_nid));
+ ctl_putstr(sys_var[CS_DIGEST].text, str,
+ strlen(str));
}
break;
- case CS_DIGEST:
+ case CS_SIGNATURE:
if (crypto_flags) {
const EVP_MD *dp;
dp = EVP_get_digestbynid(crypto_flags >> 16);
strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(sys_var[CS_DIGEST].text, str,
+ ctl_putstr(sys_var[CS_SIGNATURE].text, str,
strlen(str));
}
break;
- case CS_HOST:
+ case CS_HOST:
if (sys_hostname != NULL)
ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
strlen(sys_hostname));
break;
- case CS_CERTIF:
+ case CS_GROUP:
+ if (sys_groupname != NULL)
+ ctl_putstr(sys_var[CS_GROUP].text, sys_groupname,
+ strlen(sys_groupname));
+ break;
+
+ case CS_CERTIF:
for (cp = cinfo; cp != NULL; cp = cp->link) {
- sprintf(cbuf, "%s %s 0x%x", cp->subject,
- cp->issuer, cp->flags);
+ snprintf(cbuf, sizeof(cbuf), "%s %s 0x%x",
+ cp->subject, cp->issuer, cp->flags);
ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
strlen(cbuf));
- ctl_putfs(sys_var[CS_REVOKE].text, cp->last);
+ ctl_putfs(sys_var[CS_REVTIME].text, cp->last);
}
break;
- case CS_PUBLIC:
- if (hostval.fstamp != 0)
- ctl_putfs(sys_var[CS_PUBLIC].text,
- ntohl(hostval.tstamp));
- break;
-
- case CS_REVTIME:
+ case CS_PUBLIC:
if (hostval.tstamp != 0)
- ctl_putfs(sys_var[CS_REVTIME].text,
+ ctl_putfs(sys_var[CS_PUBLIC].text,
ntohl(hostval.tstamp));
break;
-
- case CS_IDENT:
- if (iffpar_pkey != NULL)
- ctl_putstr(sys_var[CS_IDENT].text,
- iffpar_file, strlen(iffpar_file));
- if (gqpar_pkey != NULL)
- ctl_putstr(sys_var[CS_IDENT].text,
- gqpar_file, strlen(gqpar_file));
- if (mvpar_pkey != NULL)
- ctl_putstr(sys_var[CS_IDENT].text,
- mvpar_file, strlen(mvpar_file));
- break;
-
- case CS_LEAPTAB:
- if (tai_leap.fstamp != 0)
- ctl_putfs(sys_var[CS_LEAPTAB].text,
- ntohl(tai_leap.fstamp));
- break;
-
- case CS_TAI:
- ctl_putuint(sys_var[CS_TAI].text, sys_tai);
- break;
#endif /* OPENSSL */
}
}
@@ -1475,32 +1599,32 @@ 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_PREEMPT) == 0));
break;
- case CP_AUTHENABLE:
+ case CP_AUTHENABLE:
ctl_putuint(peer_var[CP_AUTHENABLE].text,
- (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
+ (unsigned)(peer->keyid != 0));
break;
- case CP_AUTHENTIC:
+ case CP_AUTHENTIC:
ctl_putuint(peer_var[CP_AUTHENTIC].text,
(unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
break;
- case CP_SRCADR:
+ case CP_SRCADR:
ctl_putadr(peer_var[CP_SRCADR].text, 0,
&peer->srcadr);
break;
- case CP_SRCPORT:
+ case CP_SRCPORT:
ctl_putuint(peer_var[CP_SRCPORT].text,
ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
break;
- case CP_DSTADR:
+ case CP_DSTADR:
if (peer->dstadr) {
ctl_putadr(peer_var[CP_DSTADR].text, 0,
&(peer->dstadr->sin));
@@ -1510,226 +1634,251 @@ ctl_putpeer(
}
break;
- case CP_DSTPORT:
+ case CP_DSTPORT:
ctl_putuint(peer_var[CP_DSTPORT].text,
(u_long)(peer->dstadr ?
ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
break;
- case CP_LEAP:
+ case CP_IN:
+ if (peer->r21 > 0)
+ ctl_putdbl(peer_var[CP_IN].text,
+ peer->r21 / 1e3);
+ break;
+
+ case CP_OUT:
+ if (peer->r34 >0)
+ ctl_putdbl(peer_var[CP_OUT].text,
+ peer->r34 / 1e3);
+ break;
+
+ case CP_RATE:
+ ctl_putuint(peer_var[CP_RATE].text, peer->throttle);
+ break;
+
+ 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:
+ case CP_PRECISION:
ctl_putint(peer_var[CP_PRECISION].text,
- peer->precision);
+ peer->precision);
break;
- case CP_ROOTDELAY:
+ case CP_ROOTDELAY:
ctl_putdbl(peer_var[CP_ROOTDELAY].text,
- peer->rootdelay * 1e3);
+ peer->rootdelay * 1e3);
break;
- case CP_ROOTDISPERSION:
+ case CP_ROOTDISPERSION:
ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
- peer->rootdispersion * 1e3);
+ peer->rootdisp * 1e3);
break;
- case CP_REFID:
+ case CP_REFID:
+#ifdef REFCLOCK
if (peer->flags & FLAG_REFCLOCK) {
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
- } else {
- if (peer->stratum > 1 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
+ ctl_putrefid(peer_var[varid].text, peer->refid);
+ break;
}
+#endif
+ if (peer->stratum > 1 && peer->stratum < STRATUM_UNSPEC)
+ ctl_putadr(peer_var[varid].text, peer->refid,
+ NULL);
+ else
+ ctl_putrefid(peer_var[varid].text, peer->refid);
break;
- case CP_REFTIME:
+ case CP_REFTIME:
ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
break;
- case CP_ORG:
- ctl_putts(peer_var[CP_ORG].text, &peer->org);
+ case CP_ORG:
+ ctl_putts(peer_var[CP_ORG].text, &peer->aorg);
break;
- case CP_REC:
- ctl_putts(peer_var[CP_REC].text, &peer->rec);
+ case CP_REC:
+ ctl_putts(peer_var[CP_REC].text, &peer->dst);
break;
- case CP_XMT:
- ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
+ case CP_XMT:
+ if (peer->xleave != 0)
+ ctl_putdbl(peer_var[CP_XMT].text, peer->xleave *
+ 1e3);
break;
- case CP_REACH:
+ case CP_BIAS:
+ if (peer->bias != 0)
+ ctl_putdbl(peer_var[CP_BIAS].text, peer->bias *
+ 1e3);
+ break;
+
+ case CP_REACH:
ctl_puthex(peer_var[CP_REACH].text, peer->reach);
break;
- case CP_FLASH:
+ case CP_FLASH:
temp = peer->flash;
ctl_puthex(peer_var[CP_FLASH].text, temp);
break;
- case CP_TTL:
- ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
+ case CP_TTL:
+ if (peer->ttl > 0)
+ ctl_putint(peer_var[CP_TTL].text,
+ sys_ttl[peer->ttl]);
break;
- case CP_UNREACH:
+ case CP_UNREACH:
ctl_putuint(peer_var[CP_UNREACH].text, peer->unreach);
break;
- case CP_TIMER:
+ 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:
+ case CP_OFFSET:
ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
- 1e3);
+ 1e3);
break;
- case CP_JITTER:
- ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter * 1e3);
+ case CP_JITTER:
+ ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter *
+ 1e3);
break;
- case CP_DISPERSION:
+ case CP_DISPERSION:
ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
- 1e3);
+ 1e3);
break;
- case CP_KEYID:
- ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
+ case CP_KEYID:
+ if (peer->keyid > NTP_MAXKEY)
+ ctl_puthex(peer_var[CP_KEYID].text,
+ peer->keyid);
+ else
+ 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 */
-
- strcpy(s, peer_var[CP_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = peer_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)(s - buf), 0);
- }
- break;
+ 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);
+ if (s + strlen(peer_var[CP_VARLIST].text) + 4 > be)
+ break; /* really long var name */
+
+ snprintf(s, sizeof(buf), "%s=\"",
+ peer_var[CP_VARLIST].text);
+ 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++ = ',';
+ memcpy(s, k->text, i);
+ s += i;
+ }
+ if (s+2 >= be)
+ break;
+
+ *s++ = '"';
+ *s = '\0';
+ ctl_putdata(buf, (unsigned)(s - buf), 0);
+ }
+ break;
#ifdef OPENSSL
- case CP_FLAGS:
+ case CP_FLAGS:
if (peer->crypto)
ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
break;
- case CP_DIGEST:
+ case CP_SIGNATURE:
if (peer->crypto) {
const EVP_MD *dp;
dp = EVP_get_digestbynid(peer->crypto >> 16);
strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(peer_var[CP_DIGEST].text, str,
- strlen(str));
+ ctl_putstr(peer_var[CP_SIGNATURE].text, str,
+ strlen(str));
}
break;
- case CP_HOST:
+ case CP_HOST:
if (peer->subject != NULL)
ctl_putstr(peer_var[CP_HOST].text,
peer->subject, strlen(peer->subject));
break;
- case CP_VALID: /* not used */
- break;
-
- case CP_IDENT:
- if (peer->issuer != NULL)
- ctl_putstr(peer_var[CP_IDENT].text,
- peer->issuer, strlen(peer->issuer));
+ case CP_VALID: /* not used */
break;
- case CP_INITSEQ:
+ case CP_INITSEQ:
if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
break;
+
ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
ctl_putfs(peer_var[CP_INITTSP].text,
- ntohl(peer->recval.tstamp));
+ ntohl(peer->recval.tstamp));
break;
#endif /* OPENSSL */
}
@@ -1749,147 +1898,148 @@ ctl_putclock(
{
switch(varid) {
- case CC_TYPE:
+ case CC_TYPE:
if (mustput || clock_stat->clockdesc == NULL
- || *(clock_stat->clockdesc) == '\0') {
+ || *(clock_stat->clockdesc) == '\0') {
ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
}
break;
- case CC_TIMECODE:
+ case CC_TIMECODE:
ctl_putstr(clock_var[CC_TIMECODE].text,
- clock_stat->p_lastcode,
- (unsigned)clock_stat->lencode);
+ 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:
+ case CC_NOREPLY:
ctl_putuint(clock_var[CC_NOREPLY].text,
- clock_stat->noresponse);
+ clock_stat->noresponse);
break;
- case CC_BADFORMAT:
+ case CC_BADFORMAT:
ctl_putuint(clock_var[CC_BADFORMAT].text,
- clock_stat->badformat);
+ clock_stat->badformat);
break;
- case CC_BADDATA:
+ case CC_BADDATA:
ctl_putuint(clock_var[CC_BADDATA].text,
- clock_stat->baddata);
+ clock_stat->baddata);
break;
- case CC_FUDGETIME1:
+ 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, NULL);
+ clock_stat->fudgeval2, NULL);
else
- ctl_putid(clock_var[CC_FUDGEVAL2].text,
- (char *)&clock_stat->fudgeval2);
+ ctl_putrefid(clock_var[CC_FUDGEVAL2].text,
+ clock_stat->fudgeval2);
}
break;
- case CC_FLAGS:
+ case CC_FLAGS:
if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
- CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
+ CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
ctl_putuint(clock_var[CC_FLAGS].text,
- clock_stat->flags);
+ clock_stat->flags);
break;
- case CC_DEVICE:
+ case CC_DEVICE:
if (clock_stat->clockdesc == NULL ||
*(clock_stat->clockdesc) == '\0') {
if (mustput)
ctl_putstr(clock_var[CC_DEVICE].text,
- "", 0);
+ "", 0);
} else {
ctl_putstr(clock_var[CC_DEVICE].text,
- clock_stat->clockdesc,
- strlen(clock_stat->clockdesc));
+ clock_stat->clockdesc,
+ strlen(clock_stat->clockdesc));
}
break;
- case CC_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf);
- if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
- be)
- break; /* really long var name */
-
- strcpy(s, clock_var[CC_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = clock_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
-
- for (k = clock_stat->kv_list; k && !(k->flags &
- EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- ss = k->text;
- if (!ss)
- continue;
-
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text, (unsigned)i);
- s += i;
- *s = '\0';
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)( s - buf ), 0);
- }
- break;
+ 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 */
+
+ snprintf(s, sizeof(buf), "%s=\"",
+ clock_var[CC_VARLIST].text);
+ s += strlen(s);
+ t = s;
+
+ for (k = clock_var; !(k->flags & EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ i = strlen(k->text);
+ if (s + i + 1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, i);
+ s += i;
+ }
+
+ for (k = clock_stat->kv_list; k && !(k->flags &
+ EOV); k++) {
+ if (k->flags & PADDING)
+ continue;
+
+ ss = k->text;
+ if (!ss)
+ continue;
+
+ while (*ss && *ss != '=')
+ ss++;
+ i = ss - k->text;
+ if (s+i+1 >= be)
+ break;
+
+ if (s != t)
+ *s++ = ',';
+ memcpy(s, k->text, (unsigned)i);
+ s += i;
+ *s = '\0';
+ }
+ if (s+2 >= be)
+ break;
+
+ *s++ = '"';
+ *s = '\0';
+ ctl_putdata(buf, (unsigned)( s - buf ), 0);
+ }
+ break;
}
}
#endif
@@ -1915,7 +2065,7 @@ ctl_getitem(
* Delete leading commas and white space
*/
while (reqpt < reqend && (*reqpt == ',' ||
- isspace((unsigned char)*reqpt)))
+ isspace((unsigned char)*reqpt)))
reqpt++;
if (reqpt >= reqend)
return (0);
@@ -1933,7 +2083,7 @@ ctl_getitem(
if (!(v->flags & PADDING) && *cp == *(v->text)) {
tp = v->text;
while (*tp != '\0' && *tp != '=' && cp <
- reqend && *cp == *tp) {
+ reqend && *cp == *tp) {
cp++;
tp++;
}
@@ -1961,8 +2111,8 @@ ctl_getitem(
#if 0 /* Avoid possible DOS attack */
/* If we get a smarter msyslog we can re-enable this */
msyslog(LOG_WARNING,
- "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
- stoa(rmt_addr), SRCPORT(rmt_addr)
+ "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
+ stoa(rmt_addr), SRCPORT(rmt_addr)
);
#endif
return (0);
@@ -2050,14 +2200,14 @@ read_status(
rpkt.status = htons(ctlsysstatus());
for (i = 0; i < NTP_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)) {
ctl_putdata((char *)ass_stat,
- n * sizeof(u_short), 1);
+ n * sizeof(u_short), 1);
n = 0;
}
}
@@ -2065,7 +2215,7 @@ read_status(
if (n != 0)
ctl_putdata((char *)ass_stat, n *
- sizeof(u_short), 1);
+ sizeof(u_short), 1);
ctl_flushpkt(0);
} else {
peer = findpeerbyassoc(res_associd);
@@ -2104,7 +2254,7 @@ read_variables(
char *valuep;
u_char *wants;
unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
- 1) : (CP_MAXCODE + 1);
+ 1) : (CP_MAXCODE + 1);
if (res_associd == 0) {
/*
* Wants system variables. Figure out which he wants
@@ -2120,14 +2270,14 @@ read_variables(
while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
if (v->flags & EOV) {
if ((v = ctl_getitem(ext_sys_var,
- &valuep)) != 0) {
+ &valuep)) != 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
free((char *)wants);
return;
}
wants[CS_MAXCODE + 1 +
- v->code] = 1;
+ v->code] = 1;
gotvar = 1;
continue;
} else {
@@ -2142,11 +2292,11 @@ read_variables(
if (wants[i])
ctl_putsys(i);
for (i = 0; ext_sys_var &&
- !(ext_sys_var[i].flags & EOV); i++)
+ !(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);
+ strlen(ext_sys_var[i].text),
+ 0);
} else {
register u_char *cs;
register struct ctl_var *kv;
@@ -2154,10 +2304,10 @@ read_variables(
for (cs = def_sys_var; *cs != 0; cs++)
ctl_putsys((int)*cs);
for (kv = ext_sys_var; kv && !(kv->flags & EOV);
- kv++)
+ kv++)
if (kv->flags & DEF)
ctl_putdata(kv->text,
- strlen(kv->text), 0);
+ strlen(kv->text), 0);
}
free((char *)wants);
} else {
@@ -2255,7 +2405,7 @@ write_variables(
return;
}
if (!ext_var && (*valuep == '\0' || !atoint(valuep,
- &val))) {
+ &val))) {
ctl_error(CERR_BADFMT);
return;
}
@@ -2266,7 +2416,7 @@ write_variables(
if (ext_var) {
char *s = (char *)emalloc(strlen(v->text) +
- strlen(valuep) + 2);
+ strlen(valuep) + 2);
const char *t;
char *tt = s;
@@ -2284,8 +2434,8 @@ write_variables(
*/
switch(v->code) {
- case CS_LEAP:
- default:
+ case CS_LEAP:
+ default:
ctl_error(CERR_UNSPEC); /* really */
return;
}
@@ -2297,15 +2447,103 @@ write_variables(
*/
/*
if (leapind != ~0 || leapwarn != ~0) {
- if (!leap_setleap((int)leapind, (int)leapwarn)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
+ if (!leap_setleap((int)leapind, (int)leapwarn)) {
+ ctl_error(CERR_PERMISSION);
+ return;
+ }
}
*/
ctl_flushpkt(0);
}
+/*
+ * configure() processes ntpq :config/config-from-file, allowing
+ * generic runtime reconfiguration.
+ */
+static void configure(
+ struct recvbuf *rbufp,
+ int restrict_mask
+ )
+{
+ size_t data_count;
+ int retval;
+ int replace_nl;
+
+ /* I haven't yet implemented changes to an existing association.
+ * Hence check if the association id is 0
+ */
+ if (res_associd != 0) {
+ ctl_error(CERR_BADVALUE);
+ return;
+ }
+
+ if (restrict_mask & RES_NOMODIFY) {
+ snprintf(remote_config.err_msg,
+ sizeof(remote_config.err_msg),
+ "runtime configuration prohibited by restrict ... nomodify");
+ ctl_putdata(remote_config.err_msg,
+ strlen(remote_config.err_msg), 0);
+ ctl_flushpkt(0);
+ msyslog(LOG_NOTICE,
+ "runtime config from %s rejected due to nomodify restriction",
+ stoa(&rbufp->recv_srcadr));
+ return;
+ }
+
+ /* Initialize the remote config buffer */
+ data_count = reqend - reqpt;
+ memcpy(remote_config.buffer, reqpt, data_count);
+ if (data_count > 0
+ && '\n' != remote_config.buffer[data_count - 1])
+ remote_config.buffer[data_count++] = '\n';
+ remote_config.buffer[data_count] = '\0';
+ remote_config.pos = 0;
+ remote_config.err_pos = 0;
+ remote_config.no_errors = 0;
+
+ /* do not include terminating newline in log */
+ if (data_count > 0
+ && '\n' == remote_config.buffer[data_count - 1]) {
+ remote_config.buffer[data_count - 1] = '\0';
+ replace_nl = 1;
+ } else
+ replace_nl = 0;
+
+ DPRINTF(1, ("Got Remote Configuration Command: %s\n",
+ remote_config.buffer));
+ msyslog(LOG_NOTICE, "%s config: %s",
+ stoa(&rbufp->recv_srcadr),
+ remote_config.buffer);
+
+ if (replace_nl)
+ remote_config.buffer[data_count - 1] = '\n';
+
+ config_remotely(&rbufp->recv_srcadr);
+
+ /*
+ * Check if errors were reported. If not, output 'Config
+ * Succeeded'. Else output the error count. It would be nice
+ * to output any parser error messages.
+ */
+ if (0 == remote_config.no_errors) {
+ retval = snprintf(remote_config.err_msg,
+ sizeof(remote_config.err_msg),
+ "Config Succeeded");
+ if (retval > 0)
+ remote_config.err_pos += retval;
+ }
+
+ ctl_putdata(remote_config.err_msg, remote_config.err_pos, 0);
+ ctl_flushpkt(0);
+
+ DPRINTF(1, ("Reply: %s\n", remote_config.err_msg));
+
+ if (remote_config.no_errors > 0)
+ msyslog(LOG_NOTICE, "%d error in %s config",
+ remote_config.no_errors,
+ stoa(&rbufp->recv_srcadr));
+}
+
/*
* read_clock_status - return clock radio status
@@ -2339,13 +2577,13 @@ read_clock_status(
* for one.
*/
if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
- {
+ {
peer = sys_peer;
} else {
peer = 0;
for (i = 0; peer == 0 && i < NTP_HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
+ peer = peer->ass_next) {
if (peer->flags & FLAG_REFCLOCK)
break;
}
@@ -2369,7 +2607,7 @@ read_clock_status(
*/
clock_stat.kv_list = (struct ctl_var *)0;
refclock_control(&peer->srcadr, (struct refclockstat *)0,
- &clock_stat);
+ &clock_stat);
/*
* Look for variables in the packet.
@@ -2382,7 +2620,7 @@ read_clock_status(
while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
if (v->flags & EOV) {
if ((v = ctl_getitem(clock_stat.kv_list,
- &valuep)) != 0) {
+ &valuep)) != 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
free((char*)wants);
@@ -2403,13 +2641,13 @@ read_clock_status(
if (gotvar) {
for (i = 1; i <= CC_MAXCODE; i++)
if (wants[i])
- ctl_putclock(i, &clock_stat, 1);
+ ctl_putclock(i, &clock_stat, 1);
for (i = 0; clock_stat.kv_list &&
- !(clock_stat.kv_list[i].flags & EOV); i++)
+ !(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);
+ strlen(clock_stat.kv_list[i].text),
+ 0);
} else {
register u_char *cc;
register struct ctl_var *kv;
@@ -2417,10 +2655,10 @@ read_clock_status(
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++)
+ kv++)
if (kv->flags & DEF)
ctl_putdata(kv->text, strlen(kv->text),
- 0);
+ 0);
}
free((char*)wants);
@@ -2480,7 +2718,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);
}
@@ -2521,7 +2759,7 @@ unset_trap(
*/
int
ctlsettrap(
- struct sockaddr_storage *raddr,
+ sockaddr_u *raddr,
struct interface *linter,
int traptype,
int version
@@ -2537,17 +2775,17 @@ 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 */
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 */
tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
@@ -2576,7 +2814,7 @@ ctlsettrap(
} else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
switch (traptype) {
- case TRAP_TYPE_CONFIG:
+ case TRAP_TYPE_CONFIG:
if (tptouse == NULL) {
tptouse = tp;
break;
@@ -2595,18 +2833,18 @@ ctlsettrap(
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))
+ TRAP_INUSE &&
+ tptouse->tr_origtime <
+ tp->tr_origtime))
tptouse = tp;
}
break;
- case TRAP_TYPE_NONPRIO:
+ case TRAP_TYPE_NONPRIO:
break;
}
}
@@ -2642,7 +2880,7 @@ ctlsettrap(
*/
int
ctlclrtrap(
- struct sockaddr_storage *raddr,
+ sockaddr_u *raddr,
struct interface *linter,
int traptype
)
@@ -2653,7 +2891,7 @@ ctlclrtrap(
return (0);
if (tp->tr_flags & TRAP_CONFIGURED
- && traptype != TRAP_TYPE_CONFIG)
+ && traptype != TRAP_TYPE_CONFIG)
return (0);
tp->tr_flags = 0;
@@ -2667,7 +2905,7 @@ ctlclrtrap(
*/
static struct ctl_trap *
ctlfindtrap(
- struct sockaddr_storage *raddr,
+ sockaddr_u *raddr,
struct interface *linter
)
{
@@ -2676,9 +2914,9 @@ ctlfindtrap(
for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
if ((tp->tr_flags & TRAP_INUSE)
&& (NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr))
- && SOCKCMP(raddr, &tp->tr_addr)
+ && SOCK_EQ(raddr, &tp->tr_addr)
&& (linter == tp->tr_localaddr) )
- return (tp);
+ return (tp);
}
return (struct ctl_trap *)NULL;
}
@@ -2689,69 +2927,80 @@ ctlfindtrap(
*/
void
report_event(
- int err,
- struct peer *peer
+ int err, /* error code */
+ struct peer *peer, /* peer structure pointer */
+ const char *str /* protostats string */
)
{
- register int i;
+ char statstr[NTP_MAXSTRLEN];
+ int i;
+ size_t len;
/*
- * Record error code in proper spots, but have mercy on the
- * log file.
+ * Report the error to the protostats file, system log and
+ * trappers.
*/
- if (!(err & (PEER_EVENT | CRPT_EVENT))) {
- if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
- ctl_sys_num_events++;
- if (ctl_sys_last_event != (u_char)err) {
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()), ctlsysstatus());
-#ifdef DEBUG
- if (debug)
- printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()),
- ctlsysstatus());
-#endif
- ctl_sys_last_event = (u_char)err;
+ if (peer == NULL) {
+
+ /*
+ * Discard a system report if the number of reports of
+ * the same type exceeds the maximum.
+ */
+ if (ctl_sys_last_event != (u_char)err)
+ ctl_sys_num_events= 0;
+ if (ctl_sys_num_events >= CTL_SYS_MAXEVENTS)
+ return;
+
+ ctl_sys_last_event = (u_char)err;
+ ctl_sys_num_events++;
+ snprintf(statstr, NTP_MAXSTRLEN,
+ "0.0.0.0 %04x %02x %s",
+ ctlsysstatus(), err, eventstr(err));
+ if (str != NULL) {
+ len = strlen(statstr);
+ snprintf(statstr + len, sizeof(statstr) - len,
+ " %s", str);
}
- } else if (peer != 0) {
- char *src;
+ NLOG(NLOG_SYSEVENT)
+ msyslog(LOG_INFO, statstr);
+ } else {
-#ifdef REFCLOCK
+ /*
+ * Discard a peer report if the number of reports of
+ * the same type exceeds the maximum for that peer.
+ */
+ char *src;
+ u_char errlast;
+
+ errlast = (u_char)err & ~PEER_EVENT;
+ if (peer->last_event == errlast)
+ peer->num_events = 0;
+ if (peer->num_events >= CTL_PEER_MAXEVENTS)
+ return;
+
+ peer->last_event = errlast;
+ peer->num_events++;
if (ISREFCLOCKADR(&peer->srcadr))
src = refnumtoa(&peer->srcadr);
else
-#endif
src = stoa(&peer->srcadr);
- peer->last_event = (u_char)(err & ~PEER_EVENT);
- if (peer->num_events < CTL_PEER_MAXEVENTS)
- peer->num_events++;
+ snprintf(statstr, NTP_MAXSTRLEN,
+ "%s %04x %02x %s", src,
+ ctlpeerstatus(peer), err, eventstr(err));
+ if (str != NULL) {
+ len = strlen(statstr);
+ snprintf(statstr + len, sizeof(statstr) - len,
+ " %s", str);
+ }
NLOG(NLOG_PEEREVENT)
- msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#ifdef DEBUG
- if (debug)
- printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#endif
- } else {
- msyslog(LOG_ERR,
- "report_event: err '%s' (0x%02x), no peer",
- eventstr(err), err);
-#ifdef DEBUG
- printf(
- "report_event: peer event '%s' (0x%02x), no peer\n",
- eventstr(err), err);
-#endif
- return;
+ msyslog(LOG_INFO, statstr);
}
+ record_proto_stats(statstr);
+#if DEBUG
+ if (debug)
+ printf("event at %lu %s\n", current_time, statstr);
+#endif
/*
* If no trappers, return.
@@ -2783,31 +3032,8 @@ report_event(
#endif /* OPENSSL */
ctl_putsys(i);
}
-#ifdef REFCLOCK
- /*
- * for clock exception events: add clock variables to
- * reflect info on exception
- */
- if (err == EVNT_CLOCKEXCPT) {
- struct refclockstat clock_stat;
- struct ctl_var *kv;
-
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
- ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
- for (i = 1; i <= CC_MAXCODE; i++)
- ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- free_varlist(clock_stat.kv_list);
- }
-#endif /* REFCLOCK */
} else {
+ NTP_INSIST(peer != NULL);
rpkt.associd = htons(peer->associd);
rpkt.status = htons(ctlpeerstatus(peer));
@@ -2826,24 +3052,24 @@ report_event(
* for clock exception events: add clock variables to
* reflect info on exception
*/
- if (err == EVNT_PEERCLOCK) {
+ if (err == PEVNT_CLOCK) {
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++)
+ !(kv->flags & EOV); kv++)
if (kv->flags & DEF)
ctl_putdata(kv->text,
- strlen(kv->text), 0);
+ strlen(kv->text), 0);
free_varlist(clock_stat.kv_list);
}
#endif /* REFCLOCK */
@@ -2912,7 +3138,7 @@ add_var(
*kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
if (k) {
memmove((char *)*kv, (char *)k,
- sizeof(struct ctl_var)*c);
+ sizeof(struct ctl_var)*c);
free((char *)k);
}
(*kv)[c].code = (u_short) c;
diff --git a/ntpd/ntp_crypto.c b/ntpd/ntp_crypto.c
index cce95a8e1ea3..38f38a1d3533 100644
--- a/ntpd/ntp_crypto.c
+++ b/ntpd/ntp_crypto.c
@@ -16,7 +16,8 @@
#include "ntp_stdlib.h"
#include "ntp_unixtime.h"
#include "ntp_string.h"
-#include <ntp_random.h>
+#include "ntp_random.h"
+#include "ntp_assert.h"
#include "openssl/asn1_mac.h"
#include "openssl/bn.h"
@@ -40,7 +41,7 @@
* +-------+-------+
* | op | len | <- extension pointer
* +-------+-------+
- * | assocID |
+ * | associd |
* +---------------+
* | timestamp | <- value pointer
* +---------------+
@@ -79,13 +80,28 @@
* creator or signor is synchronized to an authoritative source and
* proventicated to a trusted authority.
*
- * Note there are four conditions required for server trust. First, the
- * public key on the certificate must be verified, which involves a
- * number of format, content and consistency checks. Next, the server
- * identity must be confirmed by one of four schemes: private
- * certificate, IFF scheme, GQ scheme or certificate trail hike to a
- * self signed trusted certificate. Finally, the server signature must
- * be verified.
+ * Note there are several conditions required for server trust. First,
+ * the public key on the server certificate must be verified, which can
+ * involve a hike along the certificate trail to a trusted host. Next,
+ * the server trust must be confirmed by one of several identity
+ * schemes. Valid cryptographic values are signed with attached
+ * timestamp and filestamp. Individual packet trust is confirmed
+ * relative to these values by a message digest with keys generated by a
+ * reverse-order pseudorandom hash.
+ *
+ * State decomposition. These flags are lit in the order given. They are
+ * dim only when the association is demobilized.
+ *
+ * CRYPTO_FLAG_ENAB Lit upon acceptance of a CRYPTO_ASSOC message
+ * CRYPTO_FLAG_CERT Lit when a self-digned trusted certificate is
+ * accepted.
+ * CRYPTO_FLAG_VRFY Lit when identity is confirmed.
+ * CRYPTO_FLAG_PROV Lit when the first signature is verified.
+ * CRYPTO_FLAG_COOK Lit when a valid cookie is accepted.
+ * CRYPTO_FLAG_AUTO Lit when valid autokey values are accepted.
+ * CRYPTO_FLAG_SIGN Lit when the server signed certificate is
+ * accepted.
+ * CRYPTO_FLAG_LEAP Lit when the leapsecond values are accepted.
*/
/*
* Cryptodefines
@@ -99,20 +115,22 @@
* Global cryptodata in host byte order
*/
u_int32 crypto_flags = 0x0; /* status word */
+int crypto_nid = KEY_TYPE_MD5; /* digest nid */
+char *sys_hostname = NULL; /* host name */
+char *sys_groupname = NULL; /* group name */
/*
* Global cryptodata in network byte order
*/
-struct cert_info *cinfo = NULL; /* certificate info/value */
+struct cert_info *cinfo = NULL; /* certificate info/value cache */
+struct cert_info *cert_host = NULL; /* host certificate */
+struct pkey_info *pkinfo = NULL; /* key info/value cache */
struct value hostval; /* host value */
struct value pubkey; /* public key */
-struct value tai_leap; /* leapseconds table */
-EVP_PKEY *iffpar_pkey = NULL; /* IFF parameters */
-EVP_PKEY *gqpar_pkey = NULL; /* GQ parameters */
-EVP_PKEY *mvpar_pkey = NULL; /* MV parameters */
-char *iffpar_file = NULL; /* IFF parameters file */
-char *gqpar_file = NULL; /* GQ parameters file */
-char *mvpar_file = NULL; /* MV parameters file */
+struct value tai_leap; /* leapseconds values */
+struct pkey_info *iffkey_info = NULL; /* IFF keys */
+struct pkey_info *gqkey_info = NULL; /* GQ keys */
+struct pkey_info *mvkey_info = NULL; /* MV keys */
/*
* Private cryptodata in host byte order
@@ -123,43 +141,34 @@ static EVP_PKEY *sign_pkey = NULL; /* sign key */
static const EVP_MD *sign_digest = NULL; /* sign digest */
static u_int sign_siglen; /* sign key length */
static char *rand_file = NULL; /* random seed file */
-static char *host_file = NULL; /* host key file */
-static char *sign_file = NULL; /* sign key file */
-static char *cert_file = NULL; /* certificate file */
-static char *leap_file = NULL; /* leapseconds file */
-static tstamp_t if_fstamp = 0; /* IFF filestamp */
-static tstamp_t gq_fstamp = 0; /* GQ file stamp */
-static tstamp_t mv_fstamp = 0; /* MV filestamp */
-static u_int ident_scheme = 0; /* server identity scheme */
/*
* Cryptotypes
*/
-static int crypto_verify P((struct exten *, struct value *,
- struct peer *));
-static int crypto_encrypt P((struct exten *, struct value *,
- keyid_t *));
-static int crypto_alice P((struct peer *, struct value *));
-static int crypto_alice2 P((struct peer *, struct value *));
-static int crypto_alice3 P((struct peer *, struct value *));
-static int crypto_bob P((struct exten *, struct value *));
-static int crypto_bob2 P((struct exten *, struct value *));
-static int crypto_bob3 P((struct exten *, struct value *));
-static int crypto_iff P((struct exten *, struct peer *));
-static int crypto_gq P((struct exten *, struct peer *));
-static int crypto_mv P((struct exten *, struct peer *));
-static u_int crypto_send P((struct exten *, struct value *));
-static tstamp_t crypto_time P((void));
-static u_long asn2ntp P((ASN1_TIME *));
-static struct cert_info *cert_parse P((u_char *, u_int, tstamp_t));
-static int cert_sign P((struct exten *, struct value *));
-static int cert_valid P((struct cert_info *, EVP_PKEY *));
-static int cert_install P((struct exten *, struct peer *));
-static void cert_free P((struct cert_info *));
-static EVP_PKEY *crypto_key P((char *, tstamp_t *));
-static int bighash P((BIGNUM *, BIGNUM *));
-static struct cert_info *crypto_cert P((char *));
-static void crypto_tai P((char *));
+static int crypto_verify (struct exten *, struct value *,
+ struct peer *);
+static int crypto_encrypt (struct exten *, struct value *,
+ keyid_t *);
+static int crypto_alice (struct peer *, struct value *);
+static int crypto_alice2 (struct peer *, struct value *);
+static int crypto_alice3 (struct peer *, struct value *);
+static int crypto_bob (struct exten *, struct value *);
+static int crypto_bob2 (struct exten *, struct value *);
+static int crypto_bob3 (struct exten *, struct value *);
+static int crypto_iff (struct exten *, struct peer *);
+static int crypto_gq (struct exten *, struct peer *);
+static int crypto_mv (struct exten *, struct peer *);
+static int crypto_send (struct exten *, struct value *, int);
+static tstamp_t crypto_time (void);
+static u_long asn2ntp (ASN1_TIME *);
+static struct cert_info *cert_parse (u_char *, long, tstamp_t);
+static int cert_sign (struct exten *, struct value *);
+static struct cert_info *cert_install (struct exten *, struct peer *);
+static int cert_hike (struct peer *, struct cert_info *);
+static void cert_free (struct cert_info *);
+static struct pkey_info *crypto_key (char *, char *, sockaddr_u *);
+static void bighash (BIGNUM *, BIGNUM *);
+static struct cert_info *crypto_cert (char *);
#ifdef SYS_WINNT
int
@@ -176,12 +185,12 @@ readlink(char * link, char * file, int len) {
* session key is the MD5 hash of these values, while the next key ID is
* the first four octets of the hash.
*
- * Returns the next key ID
+ * Returns the next key ID or 0 if there is no destination address.
*/
keyid_t
session_key(
- struct sockaddr_storage *srcadr, /* source address */
- struct sockaddr_storage *dstadr, /* destination address */
+ sockaddr_u *srcadr, /* source address */
+ sockaddr_u *dstadr, /* destination address */
keyid_t keyno, /* key ID */
keyid_t private, /* private value */
u_long lifetime /* key lifetime */
@@ -201,41 +210,38 @@ session_key(
* greater than zero, install the key and call it trusted.
*/
hdlen = 0;
- switch(srcadr->ss_family) {
+ switch(AF(srcadr)) {
case AF_INET:
- header[0] = ((struct sockaddr_in *)srcadr)->sin_addr.s_addr;
- header[1] = ((struct sockaddr_in *)dstadr)->sin_addr.s_addr;
+ header[0] = NSRCADR(srcadr);
+ header[1] = NSRCADR(dstadr);
header[2] = htonl(keyno);
header[3] = htonl(private);
hdlen = 4 * sizeof(u_int32);
break;
case AF_INET6:
- memcpy(&header[0], &GET_INADDR6(*srcadr),
+ memcpy(&header[0], PSOCK_ADDR6(srcadr),
sizeof(struct in6_addr));
- memcpy(&header[4], &GET_INADDR6(*dstadr),
+ memcpy(&header[4], PSOCK_ADDR6(dstadr),
sizeof(struct in6_addr));
header[8] = htonl(keyno);
header[9] = htonl(private);
hdlen = 10 * sizeof(u_int32);
break;
}
- EVP_DigestInit(&ctx, EVP_md5());
+ EVP_DigestInit(&ctx, EVP_get_digestbynid(crypto_nid));
EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
EVP_DigestFinal(&ctx, dgst, &len);
memcpy(&keyid, dgst, 4);
keyid = ntohl(keyid);
if (lifetime != 0) {
- MD5auth_setkey(keyno, dgst, len);
+ MD5auth_setkey(keyno, crypto_nid, dgst, len);
authtrust(keyno, lifetime);
}
-#ifdef DEBUG
- if (debug > 1)
- printf(
- "session_key: %s > %s %08x %08x hash %08x life %lu\n",
+ DPRINTF(2, ("session_key: %s > %s %08x %08x hash %08x life %lu\n",
stoa(srcadr), stoa(dstadr), keyno,
- private, keyid, lifetime);
-#endif
+ private, keyid, lifetime));
+
return (keyid);
}
@@ -245,7 +251,7 @@ session_key(
*
* Returns
* XEVNT_OK success
- * XEVNT_PER host certificate expired
+ * XEVNT_ERR protocol error
*
* This routine constructs a pseudo-random sequence by repeatedly
* hashing the session key starting from a given source address,
@@ -265,12 +271,12 @@ make_keylist(
struct value *vp; /* value pointer */
keyid_t keyid = 0; /* next key ID */
keyid_t cookie; /* private value */
- u_long lifetime;
+ long lifetime;
u_int len, mpoll;
int i;
if (!dstadr)
- return XEVNT_OK;
+ return XEVNT_ERR;
/*
* Allocate the key list if necessary.
@@ -285,8 +291,10 @@ make_keylist(
* NTP_MAXKEY.
*/
while (1) {
- keyid = (ntp_random() + NTP_MAXKEY + 1) & ((1 <<
- sizeof(keyid_t)) - 1);
+ keyid = ntp_random() & 0xffffffff;
+ if (keyid <= NTP_MAXKEY)
+ continue;
+
if (authhavekey(keyid))
continue;
break;
@@ -300,7 +308,7 @@ make_keylist(
* cookie if client mode or the host cookie if symmetric modes.
*/
mpoll = 1 << min(peer->ppoll, peer->hpoll);
- lifetime = min(sys_automax, NTP_MAXSESSION * mpoll);
+ lifetime = min(1 << sys_automax, NTP_MAXSESSION * mpoll);
if (peer->hmode == MODE_BROADCAST)
cookie = 0;
else
@@ -309,10 +317,10 @@ make_keylist(
peer->keylist[i] = keyid;
peer->keynumber = i;
keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
- cookie, lifetime);
+ cookie, lifetime + mpoll);
lifetime -= mpoll;
if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
- lifetime <= mpoll)
+ lifetime < 0 || tstamp == 0)
break;
}
@@ -333,26 +341,21 @@ make_keylist(
vp->vallen = htonl(sizeof(struct autokey));
vp->siglen = 0;
if (tstamp != 0) {
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
if (vp->sig == NULL)
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)vp, 12);
EVP_SignUpdate(&ctx, vp->ptr, sizeof(struct autokey));
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- else
- msyslog(LOG_ERR, "make_keys %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- peer->flags |= FLAG_ASSOC;
+ if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) {
+ vp->siglen = htonl(sign_siglen);
+ peer->flags |= FLAG_ASSOC;
+ }
}
#ifdef DEBUG
if (debug)
printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
- ntohl(ap->seq), ntohl(ap->key), cookie,
- ntohl(vp->tstamp), ntohl(vp->fstamp), peer->hpoll);
+ peer->keynumber, keyid, cookie, ntohl(vp->tstamp),
+ ntohl(vp->fstamp), peer->hpoll);
#endif
return (XEVNT_OK);
}
@@ -368,6 +371,11 @@ make_keylist(
* valid length and is verified. There are a few cases where some values
* are believed even if the signature fails, but only if the proventic
* bit is not set.
+ *
+ * Returns
+ * XEVNT_OK success
+ * XEVNT_ERR protocol error
+ * XEVNT_LEN bad field format or length
*/
int
crypto_recv(
@@ -379,6 +387,7 @@ crypto_recv(
u_int32 *pkt; /* receive packet pointer */
struct autokey *ap, *bp; /* autokey pointer */
struct exten *ep, *fp; /* extension pointers */
+ struct cert_info *xinfo; /* certificate info pointer */
int has_mac; /* length of MAC field */
int authlen; /* offset of MAC field */
associd_t associd; /* association ID */
@@ -412,12 +421,12 @@ crypto_recv(
ep = (struct exten *)pkt;
code = ntohl(ep->opcode) & 0xffff0000;
len = ntohl(ep->opcode) & 0x0000ffff;
- associd = (associd_t) ntohl(pkt[1]);
+ associd = (associd_t)ntohl(pkt[1]);
rval = XEVNT_OK;
#ifdef DEBUG
if (debug)
printf(
- "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x assocID %d\n",
+ "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n",
peer->crypto, authlen, len, code >> 16,
associd);
#endif
@@ -427,21 +436,10 @@ crypto_recv(
* quietly ignore the packet.
*/
if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8) {
- sys_unknownversion++;
+ sys_badlength++;
code |= CRYPTO_ERROR;
}
- /*
- * Little vulnerability bandage here. If a perp tosses a
- * fake association ID over the fence, we better toss it
- * out. Only the first one counts.
- */
- if (code & CRYPTO_RESP) {
- if (peer->assoc == 0)
- peer->assoc = associd;
- else if (peer->assoc != associd)
- code |= CRYPTO_ERROR;
- }
if (len >= VALUE_LEN) {
tstamp = ntohl(ep->tstamp);
fstamp = ntohl(ep->fstamp);
@@ -462,19 +460,26 @@ crypto_recv(
case CRYPTO_ASSOC:
/*
- * If the machine is running when this message
- * arrives, the other fellow has reset and so
- * must we. Otherwise, pass the extension field
- * to the transmit side.
+ * If our state machine is running when this
+ * message arrives, the other fellow might have
+ * restarted. However, this could be an
+ * intruder, so just clamp the poll interval and
+ * find out for ourselves. Otherwise, pass the
+ * extension field to the transmit side.
*/
- if (peer->crypto) {
+ if (peer->crypto & CRYPTO_FLAG_CERT) {
rval = XEVNT_ERR;
break;
}
+ if (peer->cmmd) {
+ if (peer->assoc != associd) {
+ rval = XEVNT_ERR;
+ break;
+ }
+ }
fp = emalloc(len);
memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
+ fp->associd = htonl(peer->associd);
peer->cmmd = fp;
/* fall through */
@@ -484,67 +489,55 @@ crypto_recv(
* Discard the message if it has already been
* stored or the message has been amputated.
*/
- if (peer->crypto)
+ if (peer->crypto) {
+ if (peer->assoc != associd)
+ rval = XEVNT_ERR;
break;
-
+ }
if (vallen == 0 || vallen > MAXHOSTNAME ||
len < VALUE_LEN + vallen) {
rval = XEVNT_LEN;
break;
}
-
- /*
- * Check the identity schemes are compatible. If
- * the client has PC, the server must have PC,
- * in which case the server public key and
- * identity are presumed valid, so we skip the
- * certificate and identity exchanges and move
- * immediately to the cookie exchange which
- * confirms the server signature.
- */
#ifdef DEBUG
if (debug)
printf(
- "crypto_recv: ident host 0x%x server 0x%x\n",
- crypto_flags, fstamp);
+ "crypto_recv: ident host 0x%x %d server 0x%x %d\n",
+ crypto_flags, peer->associd, fstamp,
+ peer->assoc);
#endif
- temp32 = (crypto_flags | ident_scheme) &
- fstamp & CRYPTO_FLAG_MASK;
+ temp32 = crypto_flags & CRYPTO_FLAG_MASK;
+
+ /*
+ * If the client scheme is PC, the server scheme
+ * must be PC. The public key and identity are
+ * presumed valid, so we skip the certificate
+ * and identity exchanges and move immediately
+ * to the cookie exchange which confirms the
+ * server signature.
+ */
if (crypto_flags & CRYPTO_FLAG_PRIV) {
if (!(fstamp & CRYPTO_FLAG_PRIV)) {
rval = XEVNT_KEY;
break;
-
- } else {
- fstamp |= CRYPTO_FLAG_VALID |
- CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_SIGN;
}
- /*
- * In symmetric modes it is an error if either
- * peer requests identity and the other peer
- * does not support it.
- */
- } else if ((hismode == MODE_ACTIVE || hismode ==
- MODE_PASSIVE) && ((crypto_flags | fstamp) &
- CRYPTO_FLAG_MASK) && !temp32) {
- rval = XEVNT_KEY;
- break;
- /*
- * It is an error if the client requests
- * identity and the server does not support it.
- */
- } else if (hismode == MODE_CLIENT && (fstamp &
- CRYPTO_FLAG_MASK) && !temp32) {
- rval = XEVNT_KEY;
- break;
- }
+ fstamp |= CRYPTO_FLAG_CERT |
+ CRYPTO_FLAG_VRFY | CRYPTO_FLAG_SIGN;
/*
- * Otherwise, the identity scheme(s) are those
- * that both client and server support.
+ * It is an error if either peer supports
+ * identity, but the other does not.
*/
- fstamp = temp32 | (fstamp & ~CRYPTO_FLAG_MASK);
+ } else if (hismode == MODE_ACTIVE || hismode ==
+ MODE_PASSIVE) {
+ if ((temp32 && !(fstamp &
+ CRYPTO_FLAG_MASK)) ||
+ (!temp32 && (fstamp &
+ CRYPTO_FLAG_MASK))) {
+ rval = XEVNT_KEY;
+ break;
+ }
+ }
/*
* Discard the message if the signature digest
@@ -560,19 +553,31 @@ crypto_recv(
/*
* Save status word, host name and message
- * digest/signature type.
+ * digest/signature type. If this is from a
+ * broadcast and the association ID has changed,
+ * request the autokey values.
*/
+ peer->assoc = associd;
+ if (hismode == MODE_SERVER)
+ fstamp |= CRYPTO_FLAG_AUTO;
+ if (!(fstamp & CRYPTO_FLAG_TAI))
+ fstamp |= CRYPTO_FLAG_LEAP;
+ RAND_bytes((u_char *)&peer->hcookie, 4);
peer->crypto = fstamp;
peer->digest = dp;
+ if (peer->subject != NULL)
+ free(peer->subject);
peer->subject = emalloc(vallen + 1);
memcpy(peer->subject, ep->pkt, vallen);
peer->subject[vallen] = '\0';
+ if (peer->issuer != NULL)
+ free(peer->issuer);
peer->issuer = emalloc(vallen + 1);
strcpy(peer->issuer, peer->subject);
- temp32 = (fstamp >> 16) & 0xffff;
snprintf(statstr, NTP_MAXSTRLEN,
- "flags 0x%x host %s signature %s", fstamp,
- peer->subject, OBJ_nid2ln(temp32));
+ "assoc %d %d host %s %s", peer->associd,
+ peer->assoc, peer->subject,
+ OBJ_nid2ln(temp32));
record_crypto_stats(&peer->srcadr, statstr);
#ifdef DEBUG
if (debug)
@@ -590,8 +595,11 @@ crypto_recv(
case CRYPTO_CERT | CRYPTO_RESP:
/*
- * Discard the message if invalid.
+ * Discard the message if empty or invalid.
*/
+ if (len < VALUE_LEN)
+ break;
+
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -599,26 +607,16 @@ crypto_recv(
/*
* Scan the certificate list to delete old
* versions and link the newest version first on
- * the list.
+ * the list. Then, verify the signature. If the
+ * certificate is bad or missing, just ignore
+ * it.
*/
- if ((rval = cert_install(ep, peer)) != XEVNT_OK)
+ if ((xinfo = cert_install(ep, peer)) == NULL) {
+ rval = XEVNT_CRT;
+ break;
+ }
+ if ((rval = cert_hike(peer, xinfo)) != XEVNT_OK)
break;
-
- /*
- * If we snatch the certificate before the
- * server certificate has been signed by its
- * server, it will be self signed. When it is,
- * we chase the certificate issuer, which the
- * server has, and keep going until a self
- * signed trusted certificate is found. Be sure
- * to update the issuer field, since it may
- * change.
- */
- if (peer->issuer != NULL)
- free(peer->issuer);
- peer->issuer = emalloc(strlen(cinfo->issuer) +
- 1);
- strcpy(peer->issuer, cinfo->issuer);
/*
* We plug in the public key and lifetime from
@@ -628,17 +626,17 @@ crypto_recv(
* signature/digest NID.
*/
if (peer->pkey == NULL) {
- ptr = (u_char *)cinfo->cert.ptr;
+ ptr = (u_char *)xinfo->cert.ptr;
cert = d2i_X509(NULL, &ptr,
- ntohl(cinfo->cert.vallen));
+ ntohl(xinfo->cert.vallen));
peer->pkey = X509_get_pubkey(cert);
X509_free(cert);
}
peer->flash &= ~TEST8;
- temp32 = cinfo->nid;
+ temp32 = xinfo->nid;
snprintf(statstr, NTP_MAXSTRLEN,
- "cert %s 0x%x %s (%u) fs %u",
- cinfo->subject, cinfo->flags,
+ "cert %s %s 0x%x %s (%u) fs %u",
+ xinfo->subject, xinfo->issuer, xinfo->flags,
OBJ_nid2ln(temp32), temp32,
ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
@@ -649,45 +647,38 @@ crypto_recv(
break;
/*
- * Schnorr (IFF)identity scheme. This scheme is designed
- * for use with shared secret group keys and where the
- * certificate may be generated by a third party. The
- * client sends a challenge to the server, which
- * performs a calculation and returns the result. A
- * positive result is possible only if both client and
+ * Schnorr (IFF) identity scheme. This scheme is
+ * designed for use with shared secret server group keys
+ * and where the certificate may be generated by a third
+ * party. The client sends a challenge to the server,
+ * which performs a calculation and returns the result.
+ * A positive result is possible only if both client and
* server contain the same secret group key.
*/
case CRYPTO_IFF | CRYPTO_RESP:
/*
- * Discard the message if invalid or certificate
- * trail not trusted.
+ * Discard the message if invalid.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
- rval = XEVNT_ERR;
- break;
- }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
/*
- * If the the challenge matches the response,
- * the certificate public key, as well as the
- * server public key, signatyre and identity are
+ * If the challenge matches the response, the
+ * server public key, signature and identity are
* all verified at the same time. The server is
* declared trusted, so we skip further
- * certificate stages and move immediately to
- * the cookie stage.
+ * certificate exchanges and move immediately to
+ * the cookie exchange.
*/
if ((rval = crypto_iff(ep, peer)) != XEVNT_OK)
break;
- peer->crypto |= CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_PROV;
+ peer->crypto |= CRYPTO_FLAG_VRFY;
peer->flash &= ~TEST8;
- snprintf(statstr, NTP_MAXSTRLEN, "iff fs %u",
- ntohl(ep->fstamp));
+ snprintf(statstr, NTP_MAXSTRLEN, "iff %s fs %u",
+ peer->issuer, ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
#ifdef DEBUG
if (debug)
@@ -708,34 +699,27 @@ crypto_recv(
case CRYPTO_GQ | CRYPTO_RESP:
/*
- * Discard the message if invalid or certificate
- * trail not trusted.
+ * Discard the message if invalid
*/
- if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
- rval = XEVNT_ERR;
- break;
- }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
/*
- * If the the challenge matches the response,
- * the certificate public key, as well as the
- * server public key, signatyre and identity are
+ * If the challenge matches the response, the
+ * server public key, signature and identity are
* all verified at the same time. The server is
* declared trusted, so we skip further
- * certificate stages and move immediately to
- * the cookie stage.
+ * certificate exchanges and move immediately to
+ * the cookie exchange.
*/
if ((rval = crypto_gq(ep, peer)) != XEVNT_OK)
break;
- peer->crypto |= CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_PROV;
+ peer->crypto |= CRYPTO_FLAG_VRFY;
peer->flash &= ~TEST8;
- snprintf(statstr, NTP_MAXSTRLEN, "gq fs %u",
- ntohl(ep->fstamp));
+ snprintf(statstr, NTP_MAXSTRLEN, "gq %s fs %u",
+ peer->issuer, ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
#ifdef DEBUG
if (debug)
@@ -744,39 +728,38 @@ crypto_recv(
break;
/*
- * MV
+ * Mu-Varadharajan (MV) identity scheme. This scheme is
+ * designed for use with three levels of trust, trusted
+ * host, server and client. The trusted host key is
+ * opaque to servers and clients; the server keys are
+ * opaque to clients and each client key is different.
+ * Client keys can be revoked without requiring new key
+ * generations.
*/
case CRYPTO_MV | CRYPTO_RESP:
/*
- * Discard the message if invalid or certificate
- * trail not trusted.
+ * Discard the message if invalid.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
- rval = XEVNT_ERR;
- break;
- }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
/*
- * If the the challenge matches the response,
- * the certificate public key, as well as the
- * server public key, signatyre and identity are
+ * If the challenge matches the response, the
+ * server public key, signature and identity are
* all verified at the same time. The server is
* declared trusted, so we skip further
- * certificate stages and move immediately to
- * the cookie stage.
+ * certificate exchanges and move immediately to
+ * the cookie exchange.
*/
if ((rval = crypto_mv(ep, peer)) != XEVNT_OK)
break;
- peer->crypto |= CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_PROV;
+ peer->crypto |= CRYPTO_FLAG_VRFY;
peer->flash &= ~TEST8;
- snprintf(statstr, NTP_MAXSTRLEN, "mv fs %u",
- ntohl(ep->fstamp));
+ snprintf(statstr, NTP_MAXSTRLEN, "mv %s fs %u",
+ peer->issuer, ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
#ifdef DEBUG
if (debug)
@@ -784,60 +767,6 @@ crypto_recv(
#endif
break;
- /*
- * Cookie request in symmetric modes. Roll a random
- * cookie and install in symmetric mode. Encrypt for the
- * response, which is transmitted later.
- */
- case CRYPTO_COOK:
-
- /*
- * Discard the message if invalid or certificate
- * trail not trusted.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
- rval = XEVNT_ERR;
- break;
- }
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * Pass the extension field to the transmit
- * side. If already agreed, walk away.
- */
- fp = emalloc(len);
- memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
- peer->cmmd = fp;
- if (peer->crypto & CRYPTO_FLAG_AGREE) {
- peer->flash &= ~TEST8;
- break;
- }
-
- /*
- * Install cookie values and light the cookie
- * bit. The transmit side will pick up and
- * encrypt it for the response.
- */
- key_expire(peer);
- peer->cookval.tstamp = ep->tstamp;
- peer->cookval.fstamp = ep->fstamp;
- RAND_bytes((u_char *)&peer->pcookie, 4);
- peer->crypto &= ~CRYPTO_FLAG_AUTO;
- peer->crypto |= CRYPTO_FLAG_AGREE;
- peer->flash &= ~TEST8;
- snprintf(statstr, NTP_MAXSTRLEN, "cook %x ts %u fs %u",
- peer->pcookie, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
/*
* Cookie response in client and symmetric modes. If the
@@ -847,14 +776,10 @@ crypto_recv(
case CRYPTO_COOK | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * not confirmed or signature not verified with
- * respect to the cookie values.
+ * Discard the message if invalid or signature
+ * not verified with respect to the cookie
+ * values.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY)) {
- rval = XEVNT_ERR;
- break;
- }
if ((rval = crypto_verify(ep, &peer->cookval,
peer)) != XEVNT_OK)
break;
@@ -863,13 +788,17 @@ crypto_recv(
* Decrypt the cookie, hunting all the time for
* errors.
*/
- if (vallen == (u_int) EVP_PKEY_size(host_pkey)) {
- RSA_private_decrypt(vallen,
+ if (vallen == (u_int)EVP_PKEY_size(host_pkey)) {
+ if (RSA_private_decrypt(vallen,
(u_char *)ep->pkt,
(u_char *)&temp32,
host_pkey->pkey.rsa,
- RSA_PKCS1_OAEP_PADDING);
- cookie = ntohl(temp32);
+ RSA_PKCS1_OAEP_PADDING) <= 0) {
+ rval = XEVNT_CKY;
+ break;
+ } else {
+ cookie = ntohl(temp32);
+ }
} else {
rval = XEVNT_CKY;
break;
@@ -881,22 +810,16 @@ crypto_recv(
* are done here.
*/
key_expire(peer);
- peer->cookval.tstamp = ep->tstamp;
- peer->cookval.fstamp = ep->fstamp;
- if (peer->crypto & CRYPTO_FLAG_AGREE)
- peer->pcookie ^= cookie;
+ if (hismode == MODE_ACTIVE || hismode ==
+ MODE_PASSIVE)
+ peer->pcookie = peer->hcookie ^ cookie;
else
peer->pcookie = cookie;
- if (peer->hmode == MODE_CLIENT &&
- !(peer->cast_flags & MDF_BCLNT))
- peer->crypto |= CRYPTO_FLAG_AUTO;
- else
- peer->crypto &= ~CRYPTO_FLAG_AUTO;
- peer->crypto |= CRYPTO_FLAG_AGREE;
+ peer->crypto |= CRYPTO_FLAG_COOK;
peer->flash &= ~TEST8;
- snprintf(statstr, NTP_MAXSTRLEN, "cook %x ts %u fs %u",
- peer->pcookie, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
+ snprintf(statstr, NTP_MAXSTRLEN,
+ "cook %x ts %u fs %u", peer->pcookie,
+ ntohl(ep->tstamp), ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
#ifdef DEBUG
if (debug)
@@ -917,22 +840,32 @@ crypto_recv(
case CRYPTO_AUTO | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * not confirmed or signature not verified with
- * respect to the receive autokey values.
+ * Discard the message if invalid or signature
+ * not verified with respect to the receive
+ * autokey values.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY)) {
- rval = XEVNT_ERR;
- break;
- }
if ((rval = crypto_verify(ep, &peer->recval,
- peer)) != XEVNT_OK)
+ peer)) != XEVNT_OK)
+ break;
+
+ /*
+ * Discard the message if a broadcast client and
+ * the association ID does not match. This might
+ * happen if a broacast server restarts the
+ * protocol. A protocol restart will occur at
+ * the next ASSOC message.
+ */
+ if ((peer->cast_flags & MDF_BCLNT) &&
+ peer->assoc != associd)
break;
/*
* Install autokey values and light the
* autokey bit. This is not hard.
*/
+ if (ep->tstamp == 0)
+ break;
+
if (peer->recval.ptr == NULL)
peer->recval.ptr =
emalloc(sizeof(struct autokey));
@@ -945,7 +878,7 @@ crypto_recv(
peer->pkeyid = bp->key;
peer->crypto |= CRYPTO_FLAG_AUTO;
peer->flash &= ~TEST8;
- snprintf(statstr, NTP_MAXSTRLEN,
+ snprintf(statstr, NTP_MAXSTRLEN,
"auto seq %d key %x ts %u fs %u", bp->seq,
bp->key, ntohl(ep->tstamp),
ntohl(ep->fstamp));
@@ -966,13 +899,8 @@ crypto_recv(
case CRYPTO_SIGN | CRYPTO_RESP:
/*
- * Discard the message if invalid or not
- * proventic.
+ * Discard the message if invalid.
*/
- if (!(peer->crypto & CRYPTO_FLAG_PROV)) {
- rval = XEVNT_ERR;
- break;
- }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -982,15 +910,16 @@ crypto_recv(
* versions and link the newest version first on
* the list.
*/
- if ((rval = cert_install(ep, peer)) != XEVNT_OK)
+ if ((xinfo = cert_install(ep, peer)) == NULL) {
+ rval = XEVNT_CRT;
break;
-
+ }
peer->crypto |= CRYPTO_FLAG_SIGN;
peer->flash &= ~TEST8;
- temp32 = cinfo->nid;
+ temp32 = xinfo->nid;
snprintf(statstr, NTP_MAXSTRLEN,
- "sign %s 0x%x %s (%u) fs %u",
- cinfo->issuer, cinfo->flags,
+ "sign %s %s 0x%x %s (%u) fs %u",
+ xinfo->subject, xinfo->issuer, xinfo->flags,
OBJ_nid2ln(temp32), temp32,
ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
@@ -1001,81 +930,50 @@ crypto_recv(
break;
/*
- * Install leapseconds table in symmetric modes. This
- * table is proventicated to the NIST primary servers,
- * either by copying the file containing the table from
- * a NIST server to a trusted server or directly using
- * this protocol. While the entire table is installed at
- * the server, presently only the current TAI offset is
- * provided via the kernel to other applications.
+ * Install leapseconds values. While the leapsecond
+ * values epoch, TAI offset and values expiration epoch
+ * are retained, only the current TAI offset is provided
+ * via the kernel to other applications.
*/
- case CRYPTO_TAI:
+ case CRYPTO_LEAP | CRYPTO_RESP:
/*
- * Discard the message if invalid.
+ * Discard the message if invalid. We can't
+ * compare the value timestamps here, as they
+ * can be updated by different servers.
*/
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
/*
- * Pass the extension field to the transmit
- * side. Continue below if a leapseconds table
- * accompanies the message.
- */
- fp = emalloc(len);
- memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
- peer->cmmd = fp;
- if (len <= VALUE_LEN) {
- peer->flash &= ~TEST8;
- break;
- }
- /* fall through */
-
- case CRYPTO_TAI | CRYPTO_RESP:
-
- /*
- * If this is a response, discard the message if
- * signature not verified with respect to the
- * leapsecond table values.
- */
- if (peer->cmmd == NULL) {
- if ((rval = crypto_verify(ep,
- &peer->tai_leap, peer)) != XEVNT_OK)
- break;
- }
-
- /*
- * Initialize peer variables with latest update.
+ * If the packet leap values are more recent
+ * than the stored ones, install the new leap
+ * values and recompute the signatures.
*/
- peer->tai_leap.tstamp = ep->tstamp;
- peer->tai_leap.fstamp = ep->fstamp;
- peer->tai_leap.vallen = ep->vallen;
+ if (ntohl(ep->pkt[2]) > leap_expire) {
+ char tbuf[80], str1 [20], str2[20];
- /*
- * Install the new table if there is no stored
- * table or the new table is more recent than
- * the stored table. Since a filestamp may have
- * changed, recompute the signatures.
- */
- if (ntohl(peer->tai_leap.fstamp) >
- ntohl(tai_leap.fstamp)) {
+ tai_leap.tstamp = ep->tstamp;
tai_leap.fstamp = ep->fstamp;
tai_leap.vallen = ep->vallen;
- if (tai_leap.ptr != NULL)
- free(tai_leap.ptr);
- tai_leap.ptr = emalloc(vallen);
- memcpy(tai_leap.ptr, ep->pkt, vallen);
+ leap_tai = ntohl(ep->pkt[0]);
+ leap_sec = ntohl(ep->pkt[1]);
+ leap_expire = ntohl(ep->pkt[2]);
crypto_update();
+ strcpy(str1, fstostr(leap_sec));
+ strcpy(str2, fstostr(leap_expire));
+ snprintf(tbuf, sizeof(tbuf),
+ "%d leap %s expire %s", leap_tai, str1,
+ str2);
+ report_event(EVNT_TAI, peer, tbuf);
}
- crypto_flags |= CRYPTO_FLAG_TAI;
peer->crypto |= CRYPTO_FLAG_LEAP;
peer->flash &= ~TEST8;
snprintf(statstr, NTP_MAXSTRLEN,
- "leap %u ts %u fs %u", vallen,
- ntohl(ep->tstamp), ntohl(ep->fstamp));
+ "leap TAI offset %d at %u expire %u fs %u",
+ ntohl(ep->pkt[0]), ntohl(ep->pkt[1]),
+ ntohl(ep->pkt[2]), ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
#ifdef DEBUG
if (debug)
@@ -1087,13 +985,14 @@ crypto_recv(
* We come here in symmetric modes for miscellaneous
* commands that have value fields but are processed on
* the transmit side. All we need do here is check for
- * valid field length. Remaining checks are below and on
- * the transmit side.
+ * valid field length. Note that ASSOC is handled
+ * separately.
*/
case CRYPTO_CERT:
case CRYPTO_IFF:
case CRYPTO_GQ:
case CRYPTO_MV:
+ case CRYPTO_COOK:
case CRYPTO_SIGN:
if (len < VALUE_LEN) {
rval = XEVNT_LEN;
@@ -1102,49 +1001,39 @@ crypto_recv(
/* fall through */
/*
- * We come here for miscellaneous requests and unknown
- * requests and responses. If an unknown response or
- * error, forget it. If a request, save the extension
- * field for later. Unknown requests will be caught on
- * the transmit side.
+ * We come here in symmetric modes for requests
+ * requiring a response (above plus AUTO and LEAP) and
+ * for responses. If a request, save the extension field
+ * for later; invalid requests will be caught on the
+ * transmit side. If an error or invalid response,
+ * declare a protocol error.
*/
default:
if (code & (CRYPTO_RESP | CRYPTO_ERROR)) {
rval = XEVNT_ERR;
- } else if ((rval = crypto_verify(ep, NULL,
- peer)) == XEVNT_OK) {
+ } else if (peer->cmmd == NULL) {
fp = emalloc(len);
memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
peer->cmmd = fp;
}
}
/*
- * We don't log length/format/timestamp errors and
- * duplicates, which are log clogging vulnerabilities.
* The first error found terminates the extension field
- * scan and we return the laundry to the caller. A
- * length/format/timestamp error on transmit is
- * cheerfully ignored, as the message is not sent.
+ * scan and we return the laundry to the caller.
*/
- if (rval > XEVNT_TSP) {
+ if (rval != XEVNT_OK) {
snprintf(statstr, NTP_MAXSTRLEN,
- "error %x opcode %x ts %u fs %u", rval,
- code, tstamp, fstamp);
+ "%04x %d %02x %s", htonl(ep->opcode),
+ associd, rval, eventstr(rval));
record_crypto_stats(&peer->srcadr, statstr);
- report_event(rval, peer);
#ifdef DEBUG
if (debug)
printf("crypto_recv: %s\n", statstr);
#endif
- break;
-
- } else if (rval > XEVNT_OK && (code & CRYPTO_RESP)) {
- rval = XEVNT_OK;
+ return (rval);
}
- authlen += len;
+ authlen += (len + 3) / 4 * 4;
}
return (rval);
}
@@ -1158,30 +1047,38 @@ crypto_recv(
* autokey information, in which case the caller has to provide the
* association ID to match the association.
*
- * Returns length of extension field.
+ * Side effect: update the packet offset.
+ *
+ * Errors
+ * XEVNT_OK success
+ * XEVNT_CRT bad or missing certificate
+ * XEVNT_ERR protocol error
+ * XEVNT_LEN bad field format or length
+ * XEVNT_PER host certificate expired
*/
int
crypto_xmit(
+ struct peer *peer, /* peer structure pointer */
struct pkt *xpkt, /* transmit packet pointer */
- struct sockaddr_storage *srcadr_sin, /* active runway */
+ struct recvbuf *rbufp, /* receive buffer pointer */
int start, /* offset to extension field */
struct exten *ep, /* extension pointer */
keyid_t cookie /* session cookie */
)
{
+ struct exten *fp; /* extension pointers */
+ struct cert_info *cp, *xp, *yp; /* cert info/value pointer */
+ sockaddr_u *srcadr_sin; /* source address */
u_int32 *pkt; /* packet pointer */
- struct peer *peer; /* peer structure pointer */
u_int opcode; /* extension field opcode */
- struct exten *fp; /* extension pointers */
- struct cert_info *cp, *xp; /* certificate info/value pointer */
char certname[MAXHOSTNAME + 1]; /* subject name buffer */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
tstamp_t tstamp;
u_int vallen;
- u_int len;
struct value vtemp;
associd_t associd;
int rval;
+ int len;
keyid_t tcookie;
/*
@@ -1192,9 +1089,17 @@ crypto_xmit(
pkt = (u_int32 *)xpkt + start / 4;
fp = (struct exten *)pkt;
opcode = ntohl(ep->opcode);
+ if (peer != NULL) {
+ srcadr_sin = &peer->srcadr;
+ if (!(opcode & CRYPTO_RESP))
+ peer->opcode = ep->opcode;
+ } else {
+ srcadr_sin = &rbufp->recv_srcadr;
+ }
associd = (associd_t) ntohl(ep->associd);
- fp->associd = htonl(associd);
len = 8;
+ fp->opcode = htonl((opcode & 0xffff0000) | len);
+ fp->associd = ep->associd;
rval = XEVNT_OK;
tstamp = crypto_time();
switch (opcode & 0xffff0000) {
@@ -1204,16 +1109,12 @@ crypto_xmit(
* host name. Note, this message is not signed and the filestamp
* contains only the status word.
*/
+ case CRYPTO_ASSOC:
case CRYPTO_ASSOC | CRYPTO_RESP:
- len += crypto_send(fp, &hostval);
+ len = crypto_send(fp, &hostval, start);
fp->fstamp = htonl(crypto_flags);
break;
- case CRYPTO_ASSOC:
- len += crypto_send(fp, &hostval);
- fp->fstamp = htonl(crypto_flags | ident_scheme);
- break;
-
/*
* Send certificate request. Use the values from the extension
* field.
@@ -1224,21 +1125,36 @@ crypto_xmit(
vtemp.fstamp = ep->fstamp;
vtemp.vallen = ep->vallen;
vtemp.ptr = (u_char *)ep->pkt;
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
break;
/*
- * Send certificate response or sign request. Use the values
- * from the certificate cache. If the request contains no
- * subject name, assume the name of this host. This is for
- * backwards compatibility. Private certificates are never sent.
+ * Send sign request. Use the host certificate, which is self-
+ * signed and may or may not be trusted.
*/
case CRYPTO_SIGN:
+ if (tstamp < cert_host->first || tstamp >
+ cert_host->last)
+ rval = XEVNT_PER;
+ else
+ len = crypto_send(fp, &cert_host->cert, start);
+ break;
+
+ /*
+ * Send certificate response. Use the name in the extension
+ * field to find the certificate in the cache. If the request
+ * contains no subject name, assume the name of this host. This
+ * is for backwards compatibility. Private certificates are
+ * never sent.
+ *
+ * There may be several certificates matching the request. First
+ * choice is a self-signed trusted certificate; second choice is
+ * any certificate signed by another host. There is no third
+ * choice.
+ */
case CRYPTO_CERT | CRYPTO_RESP:
vallen = ntohl(ep->vallen);
- if (vallen == 8) {
- strcpy(certname, sys_hostname);
- } else if (vallen == 0 || vallen > MAXHOSTNAME) {
+ if (vallen == 0 || vallen > MAXHOSTNAME) {
rval = XEVNT_LEN;
break;
@@ -1248,64 +1164,60 @@ crypto_xmit(
}
/*
- * Find all certificates with matching subject. If a
- * self-signed, trusted certificate is found, use that.
- * If not, use the first one with matching subject. A
- * private certificate is never divulged or signed.
+ * Find all public valid certificates with matching
+ * subject. If a self-signed, trusted certificate is
+ * found, use that certificate. If not, use the last non
+ * self-signed certificate.
*/
- xp = NULL;
+ xp = yp = NULL;
for (cp = cinfo; cp != NULL; cp = cp->link) {
- if (cp->flags & CERT_PRIV)
+ if (cp->flags & (CERT_PRIV | CERT_ERROR))
continue;
- if (strcmp(certname, cp->subject) == 0) {
- if (xp == NULL)
- xp = cp;
- if (strcmp(certname, cp->issuer) ==
- 0 && cp->flags & CERT_TRUST) {
- xp = cp;
- break;
- }
- }
+ if (strcmp(certname, cp->subject) != 0)
+ continue;
+
+ if (strcmp(certname, cp->issuer) != 0)
+ yp = cp;
+ else if (cp ->flags & CERT_TRUST)
+ xp = cp;
+ continue;
}
/*
- * Be careful who you trust. If not yet synchronized,
- * give back an empty response. If certificate not found
- * or beyond the lifetime, return an error. This is to
- * avoid a bad dude trying to get an expired certificate
- * re-signed. Otherwise, send it.
+ * Be careful who you trust. If the certificate is not
+ * found, return an empty response. Note that we dont
+ * enforce lifetimes here.
*
- * Note the timestamp and filestamp are taken from the
+ * The timestamp and filestamp are taken from the
* certificate value structure. For all certificates the
* timestamp is the latest signature update time. For
* host and imported certificates the filestamp is the
* creation epoch. For signed certificates the filestamp
* is the creation epoch of the trusted certificate at
- * the base of the certificate trail. In principle, this
+ * the root of the certificate trail. In principle, this
* allows strong checking for signature masquerade.
*/
+ if (xp == NULL)
+ xp = yp;
+ if (xp == NULL)
+ break;
+
if (tstamp == 0)
break;
- if (xp == NULL)
- rval = XEVNT_CRT;
- else if (tstamp < xp->first || tstamp > xp->last)
- rval = XEVNT_SRV;
- else
- len += crypto_send(fp, &xp->cert);
+ len = crypto_send(fp, &xp->cert, start);
break;
/*
* Send challenge in Schnorr (IFF) identity scheme.
*/
case CRYPTO_IFF:
- if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- rval = XEVNT_ERR;
- break;
- }
+ if (peer == NULL)
+ break; /* hack attack */
+
if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK) {
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
value_free(&vtemp);
}
break;
@@ -1315,7 +1227,7 @@ crypto_xmit(
*/
case CRYPTO_IFF | CRYPTO_RESP:
if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK) {
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
value_free(&vtemp);
}
break;
@@ -1324,12 +1236,11 @@ crypto_xmit(
* Send challenge in Guillou-Quisquater (GQ) identity scheme.
*/
case CRYPTO_GQ:
- if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- rval = XEVNT_ERR;
- break;
- }
+ if (peer == NULL)
+ break; /* hack attack */
+
if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK) {
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
value_free(&vtemp);
}
break;
@@ -1339,7 +1250,7 @@ crypto_xmit(
*/
case CRYPTO_GQ | CRYPTO_RESP:
if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK) {
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
value_free(&vtemp);
}
break;
@@ -1348,12 +1259,11 @@ crypto_xmit(
* Send challenge in MV identity scheme.
*/
case CRYPTO_MV:
- if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- rval = XEVNT_ERR;
- break;
- }
+ if (peer == NULL)
+ break; /* hack attack */
+
if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK) {
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
value_free(&vtemp);
}
break;
@@ -1363,7 +1273,7 @@ crypto_xmit(
*/
case CRYPTO_MV | CRYPTO_RESP:
if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK) {
- len += crypto_send(fp, &vtemp);
+ len = crypto_send(fp, &vtemp, start);
value_free(&vtemp);
}
break;
@@ -1377,9 +1287,10 @@ crypto_xmit(
* invalid or contains an unverified signature.
*/
case CRYPTO_SIGN | CRYPTO_RESP:
- if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK) {
+ len = crypto_send(fp, &vtemp, start);
+ value_free(&vtemp);
+ }
break;
/*
@@ -1387,7 +1298,7 @@ crypto_xmit(
* key.
*/
case CRYPTO_COOK:
- len += crypto_send(fp, &pubkey);
+ len = crypto_send(fp, &pubkey, start);
break;
/*
@@ -1399,19 +1310,15 @@ crypto_xmit(
rval = XEVNT_LEN;
break;
}
- if (PKT_MODE(xpkt->li_vn_mode) == MODE_SERVER) {
+ if (peer == NULL)
tcookie = cookie;
- } else {
- if ((peer = findpeerbyassoc(associd)) == NULL) {
- rval = XEVNT_ERR;
- break;
- }
- tcookie = peer->pcookie;
- }
+ else
+ tcookie = peer->hcookie;
if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) ==
- XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ XEVNT_OK) {
+ len = crypto_send(fp, &vtemp, start);
+ value_free(&vtemp);
+ }
break;
/*
@@ -1422,28 +1329,28 @@ crypto_xmit(
* old message, in which case light the error bit.
*/
case CRYPTO_AUTO | CRYPTO_RESP:
- if ((peer = findpeerbyassoc(associd)) == NULL) {
- rval = XEVNT_ERR;
- break;
+ if (peer == NULL) {
+ if ((peer = findpeerbyassoc(associd)) == NULL) {
+ rval = XEVNT_ERR;
+ break;
+ }
}
peer->flags &= ~FLAG_ASSOC;
- len += crypto_send(fp, &peer->sndval);
+ len = crypto_send(fp, &peer->sndval, start);
break;
/*
- * Send leapseconds table and signature. Use the values from the
- * tai structure. If no table has been loaded, just send an
+ * Send leapseconds values and signature. Use the values from
+ * the tai structure. If no table has been loaded, just send an
* empty request.
*/
- case CRYPTO_TAI:
- case CRYPTO_TAI | CRYPTO_RESP:
- if (crypto_flags & CRYPTO_FLAG_TAI)
- len += crypto_send(fp, &tai_leap);
+ case CRYPTO_LEAP | CRYPTO_RESP:
+ len = crypto_send(fp, &tai_leap, start);
break;
/*
- * Default - Fall through for requests; for unknown responses,
- * flag as error.
+ * Default - Send a valid command for unknown requests; send
+ * an error response for unknown resonses.
*/
default:
if (opcode & CRYPTO_RESP)
@@ -1455,11 +1362,15 @@ crypto_xmit(
* puppy; if a response, return so the sender can flame, too.
*/
if (rval != XEVNT_OK) {
- opcode |= CRYPTO_ERROR;
+ u_int32 uint32;
+
+ uint32 = CRYPTO_ERROR;
+ opcode |= uint32;
+ fp->opcode |= htonl(uint32);
snprintf(statstr, NTP_MAXSTRLEN,
- "error %x opcode %x", rval, opcode);
+ "%04x %d %02x %s", opcode, associd, rval,
+ eventstr(rval));
record_crypto_stats(srcadr_sin, statstr);
- report_event(rval, NULL);
#ifdef DEBUG
if (debug)
printf("crypto_xmit: %s\n", statstr);
@@ -1467,17 +1378,10 @@ crypto_xmit(
if (!(opcode & CRYPTO_RESP))
return (0);
}
-
- /*
- * Round up the field length to a multiple of 8 bytes and save
- * the request code and length.
- */
- len = ((len + 7) / 8) * 8;
- fp->opcode = htonl((opcode & 0xffff0000) | len);
#ifdef DEBUG
if (debug)
printf(
- "crypto_xmit: flags 0x%x ext offset %d len %u code 0x%x assocID %d\n",
+ "crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n",
crypto_flags, start, len, opcode >> 16, associd);
#endif
return (len);
@@ -1485,17 +1389,17 @@ crypto_xmit(
/*
- * crypto_verify - parse and verify the extension field and value
+ * crypto_verify - verify the extension field value and signature
*
* Returns
* XEVNT_OK success
- * XEVNT_LEN bad field format or length
- * XEVNT_TSP bad timestamp
+ * XEVNT_ERR protocol error
* XEVNT_FSP bad filestamp
+ * XEVNT_LEN bad field format or length
* XEVNT_PUB bad or missing public key
* XEVNT_SGL bad signature length
* XEVNT_SIG signature not verified
- * XEVNT_ERR protocol error
+ * XEVNT_TSP bad timestamp
*/
static int
crypto_verify(
@@ -1514,38 +1418,46 @@ crypto_verify(
int i;
/*
- * We require valid opcode and field lengths, timestamp,
- * filestamp, public key, digest, signature length and
- * signature, where relevant. Note that preliminary length
- * checks are done in the main loop.
+ * We are extremely parannoyed. We require valid opcode, length,
+ * association ID, timestamp, filestamp, public key, digest,
+ * signature length and signature, where relevant. Note that
+ * preliminary length checks are done in the main loop.
*/
len = ntohl(ep->opcode) & 0x0000ffff;
opcode = ntohl(ep->opcode) & 0xffff0000;
/*
- * Check for valid operation code and protocol. The opcode must
- * not have the error bit set. If a response, it must have a
- * value header. If a request and does not contain a value
- * header, no need for further checking.
+ * Check for valid value header, association ID and extension
+ * field length. Remember, it is not an error to receive an
+ * unsolicited response; however, the response ID must match
+ * the association ID.
*/
if (opcode & CRYPTO_ERROR)
return (XEVNT_ERR);
- if (opcode & CRYPTO_RESP) {
- if (len < VALUE_LEN)
- return (XEVNT_LEN);
+ if (len < VALUE_LEN)
+ return (XEVNT_LEN);
+
+ if (opcode == (CRYPTO_AUTO | CRYPTO_RESP) && (peer->pmode ==
+ MODE_BROADCAST || (peer->cast_flags & MDF_BCLNT))) {
+ if (ntohl(ep->associd) != peer->assoc)
+ return (XEVNT_ERR);
} else {
- if (len < VALUE_LEN)
- return (XEVNT_OK);
+ if (ntohl(ep->associd) != peer->associd)
+ return (XEVNT_ERR);
}
/*
- * We have a value header. Check for valid field lengths. The
- * field length must be long enough to contain the value header,
- * value and signature. Note both the value and signature fields
- * are rounded up to the next word.
+ * We have a valid value header. Check for valid value and
+ * signature field lengths. The extension field length must be
+ * long enough to contain the value header, value and signature.
+ * Note both the value and signature field lengths are rounded
+ * up to the next word (4 octets).
*/
vallen = ntohl(ep->vallen);
+ if (vallen == 0)
+ return (XEVNT_LEN);
+
i = (vallen + 3) / 4;
siglen = ntohl(ep->pkt[i++]);
if (len < VALUE_LEN + ((vallen + 3) / 4) * 4 + ((siglen + 3) /
@@ -1553,32 +1465,16 @@ crypto_verify(
return (XEVNT_LEN);
/*
- * Punt if this is a response with no data. Punt if this is a
- * request and a previous response is pending.
- */
- if (opcode & CRYPTO_RESP) {
- if (vallen == 0)
- return (XEVNT_LEN);
- } else {
- if (peer->cmmd != NULL)
- return (XEVNT_LEN);
- }
-
- /*
* Check for valid timestamp and filestamp. If the timestamp is
* zero, the sender is not synchronized and signatures are
- * disregarded. If not, the timestamp must not precede the
+ * not possible. If nonzero the timestamp must not precede the
* filestamp. The timestamp and filestamp must not precede the
- * corresponding values in the value structure, if present. Once
- * the autokey values have been installed, the timestamp must
- * always be later than the corresponding value in the value
- * structure. Duplicate timestamps are illegal once the cookie
- * has been validated.
- */
+ * corresponding values in the value structure, if present.
+ */
tstamp = ntohl(ep->tstamp);
fstamp = ntohl(ep->fstamp);
if (tstamp == 0)
- return (XEVNT_OK);
+ return (XEVNT_TSP);
if (tstamp < fstamp)
return (XEVNT_TSP);
@@ -1586,15 +1482,24 @@ crypto_verify(
if (vp != NULL) {
tstamp1 = ntohl(vp->tstamp);
fstamp1 = ntohl(vp->fstamp);
- if ((tstamp < tstamp1 || (tstamp == tstamp1 &&
- (peer->crypto & CRYPTO_FLAG_AUTO))))
- return (XEVNT_TSP);
+ if (tstamp1 != 0 && fstamp1 != 0) {
+ if (tstamp < tstamp1)
+ return (XEVNT_TSP);
- if ((tstamp < fstamp1 || fstamp < fstamp1))
- return (XEVNT_FSP);
+ if ((tstamp < fstamp1 || fstamp < fstamp1))
+ return (XEVNT_FSP);
+ }
}
/*
+ * At the time the certificate message is validated, the public
+ * key in the message is not available. Thus, don't try to
+ * verify the signature.
+ */
+ if (opcode == (CRYPTO_CERT | CRYPTO_RESP))
+ return (XEVNT_OK);
+
+ /*
* Check for valid signature length, public key and digest
* algorithm.
*/
@@ -1603,7 +1508,7 @@ crypto_verify(
else
pkey = peer->pkey;
if (siglen == 0 || pkey == NULL || peer->digest == NULL)
- return (XEVNT_OK);
+ return (XEVNT_ERR);
if (siglen != (u_int)EVP_PKEY_size(pkey))
return (XEVNT_SGL);
@@ -1611,19 +1516,16 @@ crypto_verify(
/*
* Darn, I thought we would never get here. Verify the
* signature. If the identity exchange is verified, light the
- * proventic bit. If no client identity scheme is specified,
- * avoid doing the sign exchange.
+ * proventic bit. What a relief.
*/
EVP_VerifyInit(&ctx, peer->digest);
EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen + 12);
- if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen, pkey) <= 0)
+ if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen,
+ pkey) <= 0)
return (XEVNT_SIG);
- if (peer->crypto & CRYPTO_FLAG_VRFY) {
+ if (peer->crypto & CRYPTO_FLAG_VRFY)
peer->crypto |= CRYPTO_FLAG_PROV;
- if (!(crypto_flags & CRYPTO_FLAG_MASK))
- peer->crypto |= CRYPTO_FLAG_SIGN;
- }
return (XEVNT_OK);
}
@@ -1634,9 +1536,8 @@ crypto_verify(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
* XEVNT_CKY bad or missing cookie
- * XEVNT_PER host certificate expired
+ * XEVNT_PUB bad or missing public key
*/
static int
crypto_encrypt(
@@ -1659,7 +1560,7 @@ crypto_encrypt(
ptr = (u_char *)ep->pkt;
pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, len);
if (pkey == NULL) {
- msyslog(LOG_ERR, "crypto_encrypt %s\n",
+ msyslog(LOG_ERR, "crypto_encrypt: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_PUB);
}
@@ -1667,35 +1568,33 @@ crypto_encrypt(
/*
* Encrypt the cookie, encode in ASN.1 and sign.
*/
- tstamp = crypto_time();
memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
vp->tstamp = htonl(tstamp);
vp->fstamp = hostval.tstamp;
len = EVP_PKEY_size(pkey);
vp->vallen = htonl(len);
vp->ptr = emalloc(len);
+ ptr = vp->ptr;
temp32 = htonl(*cookie);
- if (!RSA_public_encrypt(4, (u_char *)&temp32, vp->ptr,
- pkey->pkey.rsa, RSA_PKCS1_OAEP_PADDING)) {
- msyslog(LOG_ERR, "crypto_encrypt %s\n",
+ if (RSA_public_encrypt(4, (u_char *)&temp32, ptr,
+ pkey->pkey.rsa, RSA_PKCS1_OAEP_PADDING) <= 0) {
+ msyslog(LOG_ERR, "crypto_encrypt: %s",
ERR_error_string(ERR_get_error(), NULL));
+ free(vp->ptr);
EVP_PKEY_free(pkey);
return (XEVNT_CKY);
}
EVP_PKEY_free(pkey);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -1705,71 +1604,54 @@ crypto_encrypt(
*
* This routine determines which identity scheme is in use and
* constructs an extension field for that scheme.
+ *
+ * Returns
+ * CRYTPO_IFF IFF scheme
+ * CRYPTO_GQ GQ scheme
+ * CRYPTO_MV MV scheme
+ * CRYPTO_NULL no available scheme
*/
u_int
crypto_ident(
struct peer *peer /* peer structure pointer */
)
{
- char filename[MAXFILENAME + 1];
+ char filename[MAXFILENAME];
/*
- * If the server identity has already been verified, no further
- * action is necessary. Otherwise, try to load the identity file
- * of the certificate issuer. If the issuer file is not found,
- * try the host file. If nothing found, declare a cryptobust.
- * Note we can't get here unless the trusted certificate has
- * been found and the CRYPTO_FLAG_VALID bit is set, so the
- * certificate issuer is valid.
+ * We come here after the group trusted host has been found; its
+ * name defines the group name. Search the key cache for all
+ * keys matching the same group name in order IFF, GQ and MV.
+ * Use the first one available.
*/
- if (peer->ident_pkey != NULL)
- EVP_PKEY_free(peer->ident_pkey);
- if (peer->crypto & CRYPTO_FLAG_GQ) {
- snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
- peer->issuer);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_GQ);
-
- snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
- sys_hostname);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_GQ);
- }
if (peer->crypto & CRYPTO_FLAG_IFF) {
- snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
+ snprintf(filename, MAXFILENAME, "ntpkey_iffpar_%s",
peer->issuer);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
+ peer->ident_pkey = crypto_key(filename, NULL,
+ &peer->srcadr);
if (peer->ident_pkey != NULL)
return (CRYPTO_IFF);
-
- snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
- sys_hostname);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
+ }
+ if (peer->crypto & CRYPTO_FLAG_GQ) {
+ snprintf(filename, MAXFILENAME, "ntpkey_gqpar_%s",
+ peer->issuer);
+ peer->ident_pkey = crypto_key(filename, NULL,
+ &peer->srcadr);
if (peer->ident_pkey != NULL)
- return (CRYPTO_IFF);
+ return (CRYPTO_GQ);
}
if (peer->crypto & CRYPTO_FLAG_MV) {
- snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
+ snprintf(filename, MAXFILENAME, "ntpkey_mvpar_%s",
peer->issuer);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_MV);
-
- snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
- sys_hostname);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
+ peer->ident_pkey = crypto_key(filename, NULL,
+ &peer->srcadr);
if (peer->ident_pkey != NULL)
return (CRYPTO_MV);
}
-
- /*
- * No compatible identity scheme is available. Life is hard.
- */
- msyslog(LOG_INFO,
- "crypto_ident: no compatible identity scheme found");
- return (0);
+ msyslog(LOG_NOTICE,
+ "crypto_ident: no identity parameters found for group %s",
+ peer->issuer);
+ return (CRYPTO_NULL);
}
@@ -1781,12 +1663,13 @@ crypto_ident(
* extension field is created here, but freed after the crypto_xmit()
* call in the protocol module.
*
- * Returns extension field pointer (no errors).
+ * Returns extension field pointer (no errors)
*/
struct exten *
crypto_args(
struct peer *peer, /* peer structure pointer */
u_int opcode, /* operation code */
+ associd_t associd, /* association ID */
char *str /* argument string */
)
{
@@ -1804,23 +1687,13 @@ crypto_args(
return (ep);
ep->opcode = htonl(opcode + len);
-
- /*
- * If a response, send our ID; if a request, send the
- * responder's ID.
- */
- if (opcode & CRYPTO_RESP)
- ep->associd = htonl(peer->associd);
- else
- ep->associd = htonl(peer->assoc);
+ ep->associd = htonl(associd);
ep->tstamp = htonl(tstamp);
ep->fstamp = hostval.tstamp;
ep->vallen = 0;
if (str != NULL) {
ep->vallen = htonl(strlen(str));
memcpy((char *)ep->pkt, str, strlen(str));
- } else {
- ep->pkt[0] = peer->associd;
}
return (ep);
}
@@ -1829,42 +1702,67 @@ crypto_args(
/*
* crypto_send - construct extension field from value components
*
- * Returns extension field length. Note: it is not polite to send a
- * nonempty signature with zero timestamp or a nonzero timestamp with
- * empty signature, but these rules are not enforced here.
+ * The value and signature fields are zero-padded to a word boundary.
+ * Note: it is not polite to send a nonempty signature with zero
+ * timestamp or a nonzero timestamp with an empty signature, but those
+ * rules are not enforced here.
*/
-u_int
+int
crypto_send(
struct exten *ep, /* extension field pointer */
- struct value *vp /* value pointer */
+ struct value *vp, /* value pointer */
+ int start /* buffer offset */
)
{
- u_int len, temp32;
- int i;
+ u_int len, vallen, siglen, opcode;
+ int i, j;
/*
- * Copy data. If the data field is empty or zero length, encode
- * an empty value with length zero.
+ * Calculate extension field length and check for buffer
+ * overflow. Leave room for the MAC.
+ */
+ len = 16;
+ vallen = ntohl(vp->vallen);
+ len += ((vallen + 3) / 4 + 1) * 4;
+ siglen = ntohl(vp->siglen);
+ len += ((siglen + 3) / 4 + 1) * 4;
+ if (start + len > sizeof(struct pkt) - MAX_MAC_LEN)
+ return (0);
+
+ /*
+ * Copy timestamps.
*/
ep->tstamp = vp->tstamp;
ep->fstamp = vp->fstamp;
ep->vallen = vp->vallen;
- len = 12;
- temp32 = ntohl(vp->vallen);
- if (temp32 > 0 && vp->ptr != NULL)
- memcpy(ep->pkt, vp->ptr, temp32);
+
+ /*
+ * Copy value. If the data field is empty or zero length,
+ * encode an empty value with length zero.
+ */
+ i = 0;
+ if (vallen > 0 && vp->ptr != NULL) {
+ j = vallen / 4;
+ if (j * 4 < vallen)
+ ep->pkt[i + j++] = 0;
+ memcpy(&ep->pkt[i], vp->ptr, vallen);
+ i += j;
+ }
/*
* Copy signature. If the signature field is empty or zero
* length, encode an empty signature with length zero.
*/
- i = (temp32 + 3) / 4;
- len += i * 4 + 4;
ep->pkt[i++] = vp->siglen;
- temp32 = ntohl(vp->siglen);
- if (temp32 > 0 && vp->sig != NULL)
- memcpy(&ep->pkt[i], vp->sig, temp32);
- len += temp32;
+ if (siglen > 0 && vp->sig != NULL) {
+ j = vallen / 4;
+ if (j * 4 < siglen)
+ ep->pkt[i + j++] = 0;
+ memcpy(&ep->pkt[i], vp->sig, siglen);
+ i += j;
+ }
+ opcode = ntohl(ep->opcode);
+ ep->opcode = htonl((opcode & 0xffff0000) | len);
return (len);
}
@@ -1879,12 +1777,11 @@ crypto_send(
* hostval host name (not signed)
* pubkey public key
* cinfo certificate info/value list
- * tai_leap leapseconds file
+ * tai_leap leap values
*
- * Filestamps are proventicated data, so this routine is run only when
- * the host has been synchronized to a proventicated source. Thus, the
- * timestamp is proventicated, too, and can be used to deflect
- * clogging attacks and even cook breakfast.
+ * Filestamps are proventic data, so this routine runs only when the
+ * host is synchronized to a proventicated source. Thus, the timestamp
+ * is proventic and can be used to deflect clogging attacks.
*
* Returns void (no errors)
*/
@@ -1892,15 +1789,15 @@ void
crypto_update(void)
{
EVP_MD_CTX ctx; /* message digest context */
- struct cert_info *cp, *cpn; /* certificate info/value */
+ struct cert_info *cp; /* certificate info/value */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- tstamp_t tstamp; /* NTP timestamp */
+ u_int32 *ptr;
u_int len;
- if ((tstamp = crypto_time()) == 0)
+ hostval.tstamp = htonl(crypto_time());
+ if (hostval.tstamp == 0)
return;
- hostval.tstamp = htonl(tstamp);
/*
* Sign public key and timestamps. The filestamp is derived from
@@ -1916,7 +1813,7 @@ crypto_update(void)
EVP_SignUpdate(&ctx, (u_char *)&pubkey, 12);
EVP_SignUpdate(&ctx, pubkey.ptr, ntohl(pubkey.vallen));
if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey))
- pubkey.siglen = htonl(len);
+ pubkey.siglen = htonl(sign_siglen);
}
/*
@@ -1925,8 +1822,7 @@ crypto_update(void)
* was generated. Note we do not throw expired certificates
* away; they may have signed younger ones.
*/
- for (cp = cinfo; cp != NULL; cp = cpn) {
- cpn = cp->link;
+ for (cp = cinfo; cp != NULL; cp = cp->link) {
cp->cert.tstamp = hostval.tstamp;
cp->cert.siglen = 0;
if (cp->cert.sig == NULL)
@@ -1936,28 +1832,34 @@ crypto_update(void)
EVP_SignUpdate(&ctx, cp->cert.ptr,
ntohl(cp->cert.vallen));
if (EVP_SignFinal(&ctx, cp->cert.sig, &len, sign_pkey))
- cp->cert.siglen = htonl(len);
+ cp->cert.siglen = htonl(sign_siglen);
}
/*
- * Sign leapseconds table and timestamps. The filestamp is
- * derived from the leapsecond file extension from wherever the
- * file was generated.
+ * Sign leapseconds values and timestamps. Note it is not an
+ * error to return null values.
*/
- if (tai_leap.vallen != 0) {
- tai_leap.tstamp = hostval.tstamp;
- tai_leap.siglen = 0;
- if (tai_leap.sig == NULL)
- tai_leap.sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
- EVP_SignUpdate(&ctx, tai_leap.ptr,
- ntohl(tai_leap.vallen));
- if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
- tai_leap.siglen = htonl(len);
- }
- snprintf(statstr, NTP_MAXSTRLEN,
- "update ts %u", ntohl(hostval.tstamp));
+ tai_leap.tstamp = hostval.tstamp;
+ tai_leap.fstamp = hostval.fstamp;
+ len = 3 * sizeof(u_int32);
+ if (tai_leap.ptr == NULL)
+ tai_leap.ptr = emalloc(len);
+ tai_leap.vallen = htonl(len);
+ ptr = (u_int32 *)tai_leap.ptr;
+ ptr[0] = htonl(leap_tai);
+ ptr[1] = htonl(leap_sec);
+ ptr[2] = htonl(leap_expire);
+ if (tai_leap.sig == NULL)
+ tai_leap.sig = emalloc(sign_siglen);
+ EVP_SignInit(&ctx, sign_digest);
+ EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
+ EVP_SignUpdate(&ctx, tai_leap.ptr, len);
+ if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
+ tai_leap.siglen = htonl(sign_siglen);
+ if (leap_sec > 0)
+ crypto_flags |= CRYPTO_FLAG_TAI;
+ snprintf(statstr, NTP_MAXSTRLEN, "signature update ts %u",
+ ntohl(hostval.tstamp));
record_crypto_stats(NULL, statstr);
#ifdef DEBUG
if (debug)
@@ -1985,12 +1887,14 @@ value_free(
/*
- * crypto_time - returns current NTP time in seconds.
+ * crypto_time - returns current NTP time.
+ *
+ * Returns NTP seconds if in synch, 0 otherwise
*/
tstamp_t
crypto_time()
{
- l_fp tstamp; /* NTP time */ L_CLR(&tstamp);
+ l_fp tstamp; /* NTP time */
L_CLR(&tstamp);
if (sys_leap != LEAP_NOTINSYNC)
@@ -2000,7 +1904,9 @@ crypto_time()
/*
- * asn2ntp - convert ASN1_TIME time structure to NTP time in seconds.
+ * asn2ntp - convert ASN1_TIME time structure to NTP time.
+ *
+ * Returns NTP seconds (no errors)
*/
u_long
asn2ntp (
@@ -2013,13 +1919,10 @@ asn2ntp (
/*
* Extract time string YYMMDDHHMMSSZ from ASN1 time structure.
* Note that the YY, MM, DD fields start with one, the HH, MM,
- * SS fiels start with zero and the Z character should be 'Z'
- * for UTC. Also note that years less than 50 map to years
- * greater than 100. Dontcha love ASN.1? Better than MIL-188.
+ * SS fiels start with zero and the Z character is ignored.
+ * Also note that years less than 50 map to years greater than
+ * 100. Dontcha love ASN.1? Better than MIL-188.
*/
- if (asn1time->length > 13)
- return ((u_long)(~0)); /* We can't use -1 here. It's invalid */
-
v = (char *)asn1time->data;
tm.tm_year = (v[0] - '0') * 10 + v[1] - '0';
if (tm.tm_year < 50)
@@ -2032,14 +1935,16 @@ asn2ntp (
tm.tm_wday = 0;
tm.tm_yday = 0;
tm.tm_isdst = 0;
- return (timegm(&tm) + JAN_1970);
+ return ((u_long)timegm(&tm) + JAN_1970);
}
/*
* bigdig() - compute a BIGNUM MD5 hash of a BIGNUM number.
+ *
+ * Returns void (no errors)
*/
-static int
+static void
bighash(
BIGNUM *bn, /* BIGNUM * from */
BIGNUM *bk /* BIGNUM * to */
@@ -2057,10 +1962,7 @@ bighash(
EVP_DigestUpdate(&ctx, ptr, len);
EVP_DigestFinal(&ctx, dgst, &len);
BN_bin2bn(dgst, len, bk);
-
- /* XXX MEMLEAK? free ptr? */
-
- return (1);
+ free(ptr);
}
@@ -2072,35 +1974,38 @@ bighash(
***********************************************************************
*
* The Schnorr (IFF) identity scheme is intended for use when
- * the ntp-genkeys program does not generate the certificates used in
- * the protocol and the group key cannot be conveyed in the certificate
- * itself. For this purpose, new generations of IFF values must be
- * securely transmitted to all members of the group before use. The
- * scheme is self contained and independent of new generations of host
- * keys, sign keys and certificates.
- *
- * The IFF identity scheme is based on DSA cryptography and algorithms
- * described in Stinson p. 285. The IFF values hide in a DSA cuckoo
- * structure, but only the primes and generator are used. The p is a
- * 512-bit prime, q a 160-bit prime that divides p - 1 and is a qth root
- * of 1 mod p; that is, g^q = 1 mod p. The TA rolls primvate random
- * group key b disguised as a DSA structure member, then computes public
- * key g^(q - b). These values are shared only among group members and
- * never revealed in messages. Alice challenges Bob to confirm identity
- * using the protocol described below.
+ * certificates are generated by some other trusted certificate
+ * authority and the certificate cannot be used to convey public
+ * parameters. There are two kinds of files: encrypted server files that
+ * contain private and public values and nonencrypted client files that
+ * contain only public values. New generations of server files must be
+ * securely transmitted to all servers of the group; client files can be
+ * distributed by any means. The scheme is self contained and
+ * independent of new generations of host keys, sign keys and
+ * certificates.
+ *
+ * The IFF values hide in a DSA cuckoo structure which uses the same
+ * parameters. The values are used by an identity scheme based on DSA
+ * cryptography and described in Stimson p. 285. The p is a 512-bit
+ * prime, g a generator of Zp* and q a 160-bit prime that divides p - 1
+ * and is a qth root of 1 mod p; that is, g^q = 1 mod p. The TA rolls a
+ * private random group key b (0 < b < q) and public key v = g^b, then
+ * sends (p, q, g, b) to the servers and (p, q, g, v) to the clients.
+ * Alice challenges Bob to confirm identity using the protocol described
+ * below.
*
* How it works
*
* The scheme goes like this. Both Alice and Bob have the public primes
* p, q and generator g. The TA gives private key b to Bob and public
- * key v = g^(q - a) mod p to Alice.
- *
- * Alice rolls new random challenge r and sends to Bob in the IFF
- * request message. Bob rolls new random k, then computes y = k + b r
- * mod q and x = g^k mod p and sends (y, hash(x)) to Alice in the
- * response message. Besides making the response shorter, the hash makes
- * it effectivey impossible for an intruder to solve for b by observing
- * a number of these messages.
+ * key v to Alice.
+ *
+ * Alice rolls new random challenge r (o < r < q) and sends to Bob in
+ * the IFF request message. Bob rolls new random k (0 < k < q), then
+ * computes y = k + b r mod q and x = g^k mod p and sends (y, hash(x))
+ * to Alice in the response message. Besides making the response
+ * shorter, the hash makes it effectivey impossible for an intruder to
+ * solve for b by observing a number of these messages.
*
* Alice receives the response and computes g^y v^r mod p. After a bit
* of algebra, this simplifies to g^k. If the hash of this result
@@ -2112,8 +2017,8 @@ bighash(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
* XEVNT_ID bad or missing group key
+ * XEVNT_PUB bad or missing public key
*/
static int
crypto_alice(
@@ -2133,47 +2038,42 @@ crypto_alice(
if (peer->ident_pkey == NULL)
return (XEVNT_ID);
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_alice: defective key");
+ if ((dsa = peer->ident_pkey->pkey->pkey.dsa) == NULL) {
+ msyslog(LOG_NOTICE, "crypto_alice: defective key");
return (XEVNT_PUB);
}
/*
- * Roll new random r (0 < r < q). The OpenSSL library has a bug
- * omitting BN_rand_range, so we have to do it the hard way.
+ * Roll new random r (0 < r < q).
*/
- bctx = BN_CTX_new();
- len = BN_num_bytes(dsa->q);
if (peer->iffval != NULL)
BN_free(peer->iffval);
peer->iffval = BN_new();
- BN_rand(peer->iffval, len * 8, -1, 1); /* r */
+ len = BN_num_bytes(dsa->q);
+ BN_rand(peer->iffval, len * 8, -1, 1); /* r mod q*/
+ bctx = BN_CTX_new();
BN_mod(peer->iffval, peer->iffval, dsa->q, bctx);
BN_CTX_free(bctx);
/*
* Sign and send to Bob. The filestamp is from the local file.
*/
- tstamp = crypto_time();
memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(peer->fstamp);
+ vp->fstamp = htonl(peer->ident_pkey->fstamp);
vp->vallen = htonl(len);
vp->ptr = emalloc(len);
BN_bn2bin(peer->iffval, vp->ptr);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -2183,9 +2083,8 @@ crypto_alice(
*
* Returns
* XEVNT_OK success
- * XEVNT_ID bad or missing group key
* XEVNT_ERR protocol error
- * XEVNT_PER host expired certificate
+ * XEVNT_ID bad or missing group key
*/
static int
crypto_bob(
@@ -2206,18 +2105,18 @@ crypto_bob(
* If the IFF parameters are not valid, something awful
* happened or we are being tormented.
*/
- if (iffpar_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_bob: scheme unavailable");
+ if (iffkey_info == NULL) {
+ msyslog(LOG_NOTICE, "crypto_bob: scheme unavailable");
return (XEVNT_ID);
}
- dsa = iffpar_pkey->pkey.dsa;
+ dsa = iffkey_info->pkey->pkey.dsa;
/*
* Extract r from the challenge.
*/
len = ntohl(ep->vallen);
if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
- msyslog(LOG_ERR, "crypto_bob %s\n",
+ msyslog(LOG_ERR, "crypto_bob: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_ERR);
}
@@ -2238,39 +2137,40 @@ crypto_bob(
sdsa->s = BN_dup(bk);
BN_CTX_free(bctx);
BN_free(r); BN_free(bn); BN_free(bk);
+#ifdef DEBUG
+ if (debug > 1)
+ DSA_print_fp(stdout, dsa, 0);
+#endif
/*
- * Encode the values in ASN.1 and sign.
+ * Encode the values in ASN.1 and sign. The filestamp is from
+ * the local file.
*/
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(if_fstamp);
len = i2d_DSA_SIG(sdsa, NULL);
- if (len <= 0) {
- msyslog(LOG_ERR, "crypto_bob %s\n",
+ if (len == 0) {
+ msyslog(LOG_ERR, "crypto_bob: %s",
ERR_error_string(ERR_get_error(), NULL));
DSA_SIG_free(sdsa);
return (XEVNT_ERR);
}
+ memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
+ vp->tstamp = htonl(tstamp);
+ vp->fstamp = htonl(iffkey_info->fstamp);
vp->vallen = htonl(len);
ptr = emalloc(len);
vp->ptr = ptr;
i2d_DSA_SIG(sdsa, &ptr);
DSA_SIG_free(sdsa);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -2280,9 +2180,9 @@ crypto_bob(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing group key
* XEVNT_FSP bad filestamp
+ * XEVNT_ID bad or missing group key
+ * XEVNT_PUB bad or missing public key
*/
int
crypto_iff(
@@ -2295,7 +2195,7 @@ crypto_iff(
DSA_SIG *sdsa; /* DSA parameters */
BIGNUM *bn, *bk;
u_int len;
- const u_char *ptr;
+ const u_char *ptr;
int temp;
/*
@@ -2303,20 +2203,20 @@ crypto_iff(
* something awful happened or we are being tormented.
*/
if (peer->ident_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_iff: scheme unavailable");
+ msyslog(LOG_NOTICE, "crypto_iff: scheme unavailable");
return (XEVNT_ID);
}
- if (ntohl(ep->fstamp) != peer->fstamp) {
- msyslog(LOG_INFO, "crypto_iff: invalid filestamp %u",
+ if (ntohl(ep->fstamp) != peer->ident_pkey->fstamp) {
+ msyslog(LOG_NOTICE, "crypto_iff: invalid filestamp %u",
ntohl(ep->fstamp));
return (XEVNT_FSP);
}
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_iff: defective key");
+ if ((dsa = peer->ident_pkey->pkey->pkey.dsa) == NULL) {
+ msyslog(LOG_NOTICE, "crypto_iff: defective key");
return (XEVNT_PUB);
}
if (peer->iffval == NULL) {
- msyslog(LOG_INFO, "crypto_iff: missing challenge");
+ msyslog(LOG_NOTICE, "crypto_iff: missing challenge");
return (XEVNT_ID);
}
@@ -2325,9 +2225,10 @@ crypto_iff(
*/
bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
len = ntohl(ep->vallen);
- ptr = (const u_char *)ep->pkt;
+ ptr = (u_char *)ep->pkt;
if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
- msyslog(LOG_ERR, "crypto_iff %s\n",
+ BN_free(bn); BN_free(bk); BN_CTX_free(bctx);
+ msyslog(LOG_ERR, "crypto_iff: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_ERR);
}
@@ -2351,8 +2252,8 @@ crypto_iff(
if (temp == 0)
return (XEVNT_OK);
- else
- return (XEVNT_ID);
+ msyslog(LOG_NOTICE, "crypto_iff: identity not verified");
+ return (XEVNT_ID);
}
@@ -2365,20 +2266,25 @@ crypto_iff(
***********************************************************************
*
* The Guillou-Quisquater (GQ) identity scheme is intended for use when
- * the ntp-genkeys program generates the certificates used in the
- * protocol and the group key can be conveyed in a certificate extension
- * field. The scheme is self contained and independent of new
- * generations of host keys, sign keys and certificates.
- *
- * The GQ identity scheme is based on RSA cryptography and algorithms
- * described in Stinson p. 300 (with errors). The GQ values hide in a
- * RSA cuckoo structure, but only the modulus is used. The 512-bit
- * public modulus is n = p q, where p and q are secret large primes. The
- * TA rolls random group key b disguised as a RSA structure member.
- * Except for the public key, these values are shared only among group
- * members and never revealed in messages.
- *
- * When rolling new certificates, Bob recomputes the private and
+ * the certificate can be used to convey public parameters. The scheme
+ * uses a X509v3 certificate extension field do convey the public key of
+ * a private key known only to servers. There are two kinds of files:
+ * encrypted server files that contain private and public values and
+ * nonencrypted client files that contain only public values. New
+ * generations of server files must be securely transmitted to all
+ * servers of the group; client files can be distributed by any means.
+ * The scheme is self contained and independent of new generations of
+ * host keys and sign keys. The scheme is self contained and independent
+ * of new generations of host keys and sign keys.
+ *
+ * The GQ parameters hide in a RSA cuckoo structure which uses the same
+ * parameters. The values are used by an identity scheme based on RSA
+ * cryptography and described in Stimson p. 300 (with errors). The 512-
+ * bit public modulus is n = p q, where p and q are secret large primes.
+ * The TA rolls private random group key b as RSA exponent. These values
+ * are known to all group members.
+ *
+ * When rolling new certificates, a server recomputes the private and
* public keys. The private key u is a random roll, while the public key
* is the inverse obscured by the group key v = (u^-1)^b. These values
* replace the private and public keys normally generated by the RSA
@@ -2413,9 +2319,8 @@ crypto_iff(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
* XEVNT_ID bad or missing group key
- * XEVNT_PER host certificate expired
+ * XEVNT_PUB bad or missing public key
*/
static int
crypto_alice2(
@@ -2435,47 +2340,42 @@ crypto_alice2(
if (peer->ident_pkey == NULL)
return (XEVNT_ID);
- if ((rsa = peer->ident_pkey->pkey.rsa) == NULL) {
- msyslog(LOG_INFO, "crypto_alice2: defective key");
+ if ((rsa = peer->ident_pkey->pkey->pkey.rsa) == NULL) {
+ msyslog(LOG_NOTICE, "crypto_alice2: defective key");
return (XEVNT_PUB);
}
/*
- * Roll new random r (0 < r < n). The OpenSSL library has a bug
- * omitting BN_rand_range, so we have to do it the hard way.
+ * Roll new random r (0 < r < n).
*/
- bctx = BN_CTX_new();
- len = BN_num_bytes(rsa->n);
if (peer->iffval != NULL)
BN_free(peer->iffval);
peer->iffval = BN_new();
+ len = BN_num_bytes(rsa->n);
BN_rand(peer->iffval, len * 8, -1, 1); /* r mod n */
+ bctx = BN_CTX_new();
BN_mod(peer->iffval, peer->iffval, rsa->n, bctx);
BN_CTX_free(bctx);
/*
* Sign and send to Bob. The filestamp is from the local file.
*/
- tstamp = crypto_time();
memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(peer->fstamp);
+ vp->fstamp = htonl(peer->ident_pkey->fstamp);
vp->vallen = htonl(len);
vp->ptr = emalloc(len);
BN_bn2bin(peer->iffval, vp->ptr);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -2485,9 +2385,8 @@ crypto_alice2(
*
* Returns
* XEVNT_OK success
- * XEVNT_ID bad or missing group key
* XEVNT_ERR protocol error
- * XEVNT_PER host certificate expired
+ * XEVNT_ID bad or missing group key
*/
static int
crypto_bob2(
@@ -2508,18 +2407,18 @@ crypto_bob2(
* If the GQ parameters are not valid, something awful
* happened or we are being tormented.
*/
- if (gqpar_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_bob2: scheme unavailable");
+ if (gqkey_info == NULL) {
+ msyslog(LOG_NOTICE, "crypto_bob2: scheme unavailable");
return (XEVNT_ID);
}
- rsa = gqpar_pkey->pkey.rsa;
+ rsa = gqkey_info->pkey->pkey.rsa;
/*
* Extract r from the challenge.
*/
len = ntohl(ep->vallen);
if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
- msyslog(LOG_ERR, "crypto_bob2 %s\n",
+ msyslog(LOG_ERR, "crypto_bob2: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_ERR);
}
@@ -2540,39 +2439,40 @@ crypto_bob2(
sdsa->s = BN_dup(g);
BN_CTX_free(bctx);
BN_free(r); BN_free(k); BN_free(g); BN_free(y);
+#ifdef DEBUG
+ if (debug > 1)
+ RSA_print_fp(stdout, rsa, 0);
+#endif
/*
- * Encode the values in ASN.1 and sign.
+ * Encode the values in ASN.1 and sign. The filestamp is from
+ * the local file.
*/
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(gq_fstamp);
len = i2d_DSA_SIG(sdsa, NULL);
if (len <= 0) {
- msyslog(LOG_ERR, "crypto_bob2 %s\n",
+ msyslog(LOG_ERR, "crypto_bob2: %s",
ERR_error_string(ERR_get_error(), NULL));
DSA_SIG_free(sdsa);
return (XEVNT_ERR);
}
+ memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
+ vp->tstamp = htonl(tstamp);
+ vp->fstamp = htonl(gqkey_info->fstamp);
vp->vallen = htonl(len);
ptr = emalloc(len);
vp->ptr = ptr;
i2d_DSA_SIG(sdsa, &ptr);
DSA_SIG_free(sdsa);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -2582,10 +2482,10 @@ crypto_bob2(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing group keys
* XEVNT_ERR protocol error
* XEVNT_FSP bad filestamp
+ * XEVNT_ID bad or missing group keys
+ * XEVNT_PUB bad or missing public key
*/
int
crypto_gq(
@@ -2597,29 +2497,31 @@ crypto_gq(
BN_CTX *bctx; /* BIGNUM context */
DSA_SIG *sdsa; /* RSA signature context fake */
BIGNUM *y, *v;
- const u_char *ptr;
- u_int len;
- int temp;
+ const u_char *ptr;
+ long len;
+ u_int temp;
/*
* If the GQ parameters are not valid or no challenge was sent,
- * something awful happened or we are being tormented.
+ * something awful happened or we are being tormented. Note that
+ * the filestamp on the local key file can be greater than on
+ * the remote parameter file if the keys have been refreshed.
*/
if (peer->ident_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_gq: scheme unavailable");
+ msyslog(LOG_NOTICE, "crypto_gq: scheme unavailable");
return (XEVNT_ID);
}
- if (ntohl(ep->fstamp) != peer->fstamp) {
- msyslog(LOG_INFO, "crypto_gq: invalid filestamp %u",
+ if (ntohl(ep->fstamp) < peer->ident_pkey->fstamp) {
+ msyslog(LOG_NOTICE, "crypto_gq: invalid filestamp %u",
ntohl(ep->fstamp));
return (XEVNT_FSP);
}
- if ((rsa = peer->ident_pkey->pkey.rsa) == NULL) {
- msyslog(LOG_INFO, "crypto_gq: defective key");
+ if ((rsa = peer->ident_pkey->pkey->pkey.rsa) == NULL) {
+ msyslog(LOG_NOTICE, "crypto_gq: defective key");
return (XEVNT_PUB);
}
if (peer->iffval == NULL) {
- msyslog(LOG_INFO, "crypto_gq: missing challenge");
+ msyslog(LOG_NOTICE, "crypto_gq: missing challenge");
return (XEVNT_ID);
}
@@ -2629,9 +2531,10 @@ crypto_gq(
*/
bctx = BN_CTX_new(); y = BN_new(); v = BN_new();
len = ntohl(ep->vallen);
- ptr = (const u_char *)ep->pkt;
+ ptr = (u_char *)ep->pkt;
if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
- msyslog(LOG_ERR, "crypto_gq %s\n",
+ BN_CTX_free(bctx); BN_free(y); BN_free(v);
+ msyslog(LOG_ERR, "crypto_gq: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_ERR);
}
@@ -2639,6 +2542,10 @@ crypto_gq(
/*
* Compute v^r y^b mod n.
*/
+ if (peer->grpkey == NULL) {
+ msyslog(LOG_NOTICE, "crypto_gq: missing group key");
+ return (XEVNT_ID);
+ }
BN_mod_exp(v, peer->grpkey, peer->iffval, rsa->n, bctx);
/* v^r mod n */
BN_mod_exp(y, sdsa->r, rsa->e, rsa->n, bctx); /* y^b mod n */
@@ -2656,8 +2563,8 @@ crypto_gq(
if (temp == 0)
return (XEVNT_OK);
- else
- return (XEVNT_ID);
+ msyslog(LOG_NOTICE, "crypto_gq: identity not verified");
+ return (XEVNT_ID);
}
@@ -2668,8 +2575,7 @@ crypto_gq(
* scheme *
* *
***********************************************************************
- */
-/*
+ *
* The Mu-Varadharajan (MV) cryptosystem was originally intended when
* servers broadcast messages to clients, but clients never send
* messages to servers. There is one encryption key for the server and a
@@ -2686,19 +2592,16 @@ crypto_gq(
* Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001,
* 223-231. The paper has significant errors and serious omissions.
*
- * Let q be the product of n distinct primes s'[j] (j = 1...n), where
- * each s'[j] has m significant bits. Let p be a prime p = 2 * q + 1, so
- * that q and each s'[j] divide p - 1 and p has M = n * m + 1
- * significant bits. The elements x mod q of Zq with the elements 2 and
- * the primes removed form a field Zq* valid for polynomial arithetic.
- * Let g be a generator of Zp; that is, gcd(g, p - 1) = 1 and g^q = 1
- * mod p. We expect M to be in the 500-bit range and n relatively small,
- * like 25, so the likelihood of a randomly generated element of x mod q
- * of Zq colliding with a factor of p - 1 is very small and can be
- * avoided. Associated with each s'[j] is an element s[j] such that s[j]
- * s'[j] = s'[j] mod q. We find s[j] as the quotient (q + s'[j]) /
- * s'[j]. These are the parameters of the scheme and they are expensive
- * to compute.
+ * Let q be the product of n distinct primes s1[j] (j = 1...n), where
+ * each s1[j] has m significant bits. Let p be a prime p = 2 * q + 1, so
+ * that q and each s1[j] divide p - 1 and p has M = n * m + 1
+ * significant bits. Let g be a generator of Zp; that is, gcd(g, p - 1)
+ * = 1 and g^q = 1 mod p. We do modular arithmetic over Zq and then
+ * project into Zp* as exponents of g. Sometimes we have to compute an
+ * inverse b^-1 of random b in Zq, but for that purpose we require
+ * gcd(b, q) = 1. We expect M to be in the 500-bit range and n
+ * relatively small, like 30. These are the parameters of the scheme and
+ * they are expensive to compute.
*
* We set up an instance of the scheme as follows. A set of random
* values x[j] mod q (j = 1...n), are generated as the zeros of a
@@ -2709,39 +2612,41 @@ crypto_gq(
* pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used
* to construct the decryption keys. The devil is in the details.
*
+ * This routine generates a private server encryption file including the
+ * private encryption key E and partial decryption keys gbar and ghat.
+ * It then generates public client decryption files including the public
+ * keys xbar[j] and xhat[j] for each client j. The partial decryption
+ * files are used to compute the inverse of E. These values are suitably
+ * blinded so secrets are not revealed.
+ *
* The distinguishing characteristic of this scheme is the capability to
* revoke keys. Included in the calculation of E, gbar and ghat is the
- * product s = prod(s'[j]) (j = 1...n) above. If the factor s'[j] is
+ * product s = prod(s1[j]) (j = 1...n) above. If the factor s1[j] is
* subsequently removed from the product and E, gbar and ghat
* recomputed, the jth client will no longer be able to compute E^-1 and
- * thus unable to decrypt the block.
+ * thus unable to decrypt the messageblock.
*
* How it works
*
- * The scheme goes like this. Bob has the server values (p, A, q, gbar,
- * ghat) and Alice the client values (p, xbar, xhat).
+ * The scheme goes like this. Bob has the server values (p, E, q, gbar,
+ * ghat) and Alice has the client values (p, xbar, xhat).
*
- * Alice rolls new random challenge r (0 < r < p) and sends to Bob in
- * the MV request message. Bob rolls new random k (0 < k < q), encrypts
- * y = A^k mod p (a permutation) and sends (hash(y), gbar^k, ghat^k) to
- * Alice.
+ * Alice rolls new random nonce r mod p and sends to Bob in the MV
+ * request message. Bob rolls random nonce k mod q, encrypts y = r E^k
+ * mod p and sends (y, gbar^k, ghat^k) to Alice.
*
- * Alice receives the response and computes the decryption key (the
- * inverse permutation) from previously obtained (xbar, xhat) and
- * (gbar^k, ghat^k) in the message. She computes the inverse, which is
- * unique by reasons explained in the ntp-keygen.c program sources. If
- * the hash of this result matches hash(y), Alice knows that Bob has the
- * group key b. The signed response binds this knowledge to Bob's
- * private key and the public key previously received in his
- * certificate.
+ * Alice receives the response and computes the inverse (E^k)^-1 from
+ * the partial decryption keys gbar^k, ghat^k, xbar and xhat. She then
+ * decrypts y and verifies it matches the original r. The signed
+ * response binds this knowledge to Bob's private key and the public key
+ * previously received in his certificate.
*
* crypto_alice3 - construct Alice's challenge in MV scheme
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
* XEVNT_ID bad or missing group key
- * XEVNT_PER host certificate expired
+ * XEVNT_PUB bad or missing public key
*/
static int
crypto_alice3(
@@ -2761,47 +2666,42 @@ crypto_alice3(
if (peer->ident_pkey == NULL)
return (XEVNT_ID);
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_alice3: defective key");
+ if ((dsa = peer->ident_pkey->pkey->pkey.dsa) == NULL) {
+ msyslog(LOG_NOTICE, "crypto_alice3: defective key");
return (XEVNT_PUB);
}
/*
- * Roll new random r (0 < r < q). The OpenSSL library has a bug
- * omitting BN_rand_range, so we have to do it the hard way.
+ * Roll new random r (0 < r < q).
*/
- bctx = BN_CTX_new();
- len = BN_num_bytes(dsa->p);
if (peer->iffval != NULL)
BN_free(peer->iffval);
peer->iffval = BN_new();
- BN_rand(peer->iffval, len * 8, -1, 1); /* r */
+ len = BN_num_bytes(dsa->p);
+ BN_rand(peer->iffval, len * 8, -1, 1); /* r mod p */
+ bctx = BN_CTX_new();
BN_mod(peer->iffval, peer->iffval, dsa->p, bctx);
BN_CTX_free(bctx);
/*
* Sign and send to Bob. The filestamp is from the local file.
*/
- tstamp = crypto_time();
memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(peer->fstamp);
+ vp->fstamp = htonl(peer->ident_pkey->fstamp);
vp->vallen = htonl(len);
vp->ptr = emalloc(len);
BN_bn2bin(peer->iffval, vp->ptr);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -2812,7 +2712,6 @@ crypto_alice3(
* Returns
* XEVNT_OK success
* XEVNT_ERR protocol error
- * XEVNT_PER host certificate expired
*/
static int
crypto_bob3(
@@ -2833,26 +2732,26 @@ crypto_bob3(
* If the MV parameters are not valid, something awful
* happened or we are being tormented.
*/
- if (mvpar_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_bob3: scheme unavailable");
+ if (mvkey_info == NULL) {
+ msyslog(LOG_NOTICE, "crypto_bob3: scheme unavailable");
return (XEVNT_ID);
}
- dsa = mvpar_pkey->pkey.dsa;
+ dsa = mvkey_info->pkey->pkey.dsa;
/*
* Extract r from the challenge.
*/
len = ntohl(ep->vallen);
if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
- msyslog(LOG_ERR, "crypto_bob3 %s\n",
+ msyslog(LOG_ERR, "crypto_bob3: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_ERR);
}
/*
* Bob rolls random k (0 < k < q), making sure it is not a
- * factor of q. He then computes y = A^k r and sends (hash(y),
- * gbar^k, ghat^k) to Alice.
+ * factor of q. He then computes y = r A^k and sends (y, gbar^k,
+ * and ghat^k) to Alice.
*/
bctx = BN_CTX_new(); k = BN_new(); u = BN_new();
sdsa = DSA_new();
@@ -2864,23 +2763,27 @@ crypto_bob3(
if (BN_is_one(u))
break;
}
- BN_mod_exp(u, dsa->g, k, dsa->p, bctx); /* A r */
- BN_mod_mul(u, u, r, dsa->p, bctx);
- bighash(u, sdsa->p);
+ BN_mod_exp(u, dsa->g, k, dsa->p, bctx); /* A^k r */
+ BN_mod_mul(sdsa->p, u, r, dsa->p, bctx);
BN_mod_exp(sdsa->q, dsa->priv_key, k, dsa->p, bctx); /* gbar */
BN_mod_exp(sdsa->g, dsa->pub_key, k, dsa->p, bctx); /* ghat */
BN_CTX_free(bctx); BN_free(k); BN_free(r); BN_free(u);
+#ifdef DEBUG
+ if (debug > 1)
+ DSA_print_fp(stdout, sdsa, 0);
+#endif
/*
- * Encode the values in ASN.1 and sign.
+ * Encode the values in ASN.1 and sign. The filestamp is from
+ * the local file.
*/
- tstamp = crypto_time();
memset(vp, 0, sizeof(struct value));
+ tstamp = crypto_time();
vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(mv_fstamp);
+ vp->fstamp = htonl(mvkey_info->fstamp);
len = i2d_DSAparams(sdsa, NULL);
- if (len <= 0) {
- msyslog(LOG_ERR, "crypto_bob3 %s\n",
+ if (len == 0) {
+ msyslog(LOG_ERR, "crypto_bob3: %s",
ERR_error_string(ERR_get_error(), NULL));
DSA_free(sdsa);
return (XEVNT_ERR);
@@ -2890,19 +2793,15 @@ crypto_bob3(
vp->ptr = ptr;
i2d_DSAparams(sdsa, &ptr);
DSA_free(sdsa);
- vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
EVP_SignUpdate(&ctx, vp->ptr, len);
if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ vp->siglen = htonl(sign_siglen);
return (XEVNT_OK);
}
@@ -2912,10 +2811,10 @@ crypto_bob3(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing group key
* XEVNT_ERR protocol error
* XEVNT_FSP bad filestamp
+ * XEVNT_ID bad or missing group key
+ * XEVNT_PUB bad or missing public key
*/
int
crypto_mv(
@@ -2928,7 +2827,7 @@ crypto_mv(
BN_CTX *bctx; /* BIGNUM context */
BIGNUM *k, *u, *v;
u_int len;
- const u_char *ptr;
+ const u_char *ptr;
int temp;
/*
@@ -2936,49 +2835,47 @@ crypto_mv(
* something awful happened or we are being tormented.
*/
if (peer->ident_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_mv: scheme unavailable");
+ msyslog(LOG_NOTICE, "crypto_mv: scheme unavailable");
return (XEVNT_ID);
}
- if (ntohl(ep->fstamp) != peer->fstamp) {
- msyslog(LOG_INFO, "crypto_mv: invalid filestamp %u",
+ if (ntohl(ep->fstamp) != peer->ident_pkey->fstamp) {
+ msyslog(LOG_NOTICE, "crypto_mv: invalid filestamp %u",
ntohl(ep->fstamp));
return (XEVNT_FSP);
}
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_mv: defective key");
+ if ((dsa = peer->ident_pkey->pkey->pkey.dsa) == NULL) {
+ msyslog(LOG_NOTICE, "crypto_mv: defective key");
return (XEVNT_PUB);
}
if (peer->iffval == NULL) {
- msyslog(LOG_INFO, "crypto_mv: missing challenge");
+ msyslog(LOG_NOTICE, "crypto_mv: missing challenge");
return (XEVNT_ID);
}
/*
- * Extract the (hash(y), gbar, ghat) values from the response.
+ * Extract the y, gbar and ghat values from the response.
*/
bctx = BN_CTX_new(); k = BN_new(); u = BN_new(); v = BN_new();
len = ntohl(ep->vallen);
- ptr = (const u_char *)ep->pkt;
+ ptr = (u_char *)ep->pkt;
if ((sdsa = d2i_DSAparams(NULL, &ptr, len)) == NULL) {
- msyslog(LOG_ERR, "crypto_mv %s\n",
+ msyslog(LOG_ERR, "crypto_mv: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_ERR);
}
/*
- * Compute (gbar^xhat ghat^xbar)^-1 mod p.
+ * Compute (gbar^xhat ghat^xbar) mod p.
*/
BN_mod_exp(u, sdsa->q, dsa->pub_key, dsa->p, bctx);
BN_mod_exp(v, sdsa->g, dsa->priv_key, dsa->p, bctx);
BN_mod_mul(u, u, v, dsa->p, bctx);
- BN_mod_inverse(u, u, dsa->p, bctx);
- BN_mod_mul(v, u, peer->iffval, dsa->p, bctx);
+ BN_mod_mul(u, u, sdsa->p, dsa->p, bctx);
/*
- * The result should match the hash of r mod p.
+ * The result should match r.
*/
- bighash(v, v);
- temp = BN_cmp(v, sdsa->p);
+ temp = BN_cmp(u, peer->iffval);
BN_CTX_free(bctx); BN_free(k); BN_free(u); BN_free(v);
BN_free(peer->iffval);
peer->iffval = NULL;
@@ -2986,8 +2883,8 @@ crypto_mv(
if (temp == 0)
return (XEVNT_OK);
- else
- return (XEVNT_ID);
+ msyslog(LOG_NOTICE, "crypto_mv: identity not verified");
+ return (XEVNT_ID);
}
@@ -2999,187 +2896,6 @@ crypto_mv(
***********************************************************************
*/
/*
- * cert_parse - parse x509 certificate and create info/value structures.
- *
- * The server certificate includes the version number, issuer name,
- * subject name, public key and valid date interval. If the issuer name
- * is the same as the subject name, the certificate is self signed and
- * valid only if the server is configured as trustable. If the names are
- * different, another issuer has signed the server certificate and
- * vouched for it. In this case the server certificate is valid if
- * verified by the issuer public key.
- *
- * Returns certificate info/value pointer if valid, NULL if not.
- */
-struct cert_info * /* certificate information structure */
-cert_parse(
- u_char *asn1cert, /* X509 certificate */
- u_int len, /* certificate length */
- tstamp_t fstamp /* filestamp */
- )
-{
- X509 *cert; /* X509 certificate */
- X509_EXTENSION *ext; /* X509v3 extension */
- struct cert_info *ret; /* certificate info/value */
- BIO *bp;
- X509V3_EXT_METHOD *method;
- char pathbuf[MAXFILENAME];
- u_char *uptr;
- char *ptr;
- int temp, cnt, i;
-
- /*
- * Decode ASN.1 objects and construct certificate structure.
- */
- uptr = asn1cert;
- if ((cert = d2i_X509(NULL, &uptr, len)) == NULL) {
- msyslog(LOG_ERR, "cert_parse %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (NULL);
- }
-
- /*
- * Extract version, subject name and public key.
- */
- ret = emalloc(sizeof(struct cert_info));
- memset(ret, 0, sizeof(struct cert_info));
- if ((ret->pkey = X509_get_pubkey(cert)) == NULL) {
- msyslog(LOG_ERR, "cert_parse %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- ret->version = X509_get_version(cert);
- X509_NAME_oneline(X509_get_subject_name(cert), pathbuf,
- MAXFILENAME - 1);
- ptr = strstr(pathbuf, "CN=");
- if (ptr == NULL) {
- msyslog(LOG_INFO, "cert_parse: invalid subject %s",
- pathbuf);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- ret->subject = emalloc(strlen(ptr) + 1);
- strcpy(ret->subject, ptr + 3);
-
- /*
- * Extract remaining objects. Note that the NTP serial number is
- * the NTP seconds at the time of signing, but this might not be
- * the case for other authority. We don't bother to check the
- * objects at this time, since the real crunch can happen only
- * when the time is valid but not yet certificated.
- */
- ret->nid = OBJ_obj2nid(cert->cert_info->signature->algorithm);
- ret->digest = (const EVP_MD *)EVP_get_digestbynid(ret->nid);
- ret->serial =
- (u_long)ASN1_INTEGER_get(X509_get_serialNumber(cert));
- X509_NAME_oneline(X509_get_issuer_name(cert), pathbuf,
- MAXFILENAME);
- if ((ptr = strstr(pathbuf, "CN=")) == NULL) {
- msyslog(LOG_INFO, "cert_parse: invalid issuer %s",
- pathbuf);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- ret->issuer = emalloc(strlen(ptr) + 1);
- strcpy(ret->issuer, ptr + 3);
- ret->first = asn2ntp(X509_get_notBefore(cert));
- ret->last = asn2ntp(X509_get_notAfter(cert));
-
- /*
- * Extract extension fields. These are ad hoc ripoffs of
- * currently assigned functions and will certainly be changed
- * before prime time.
- */
- cnt = X509_get_ext_count(cert);
- for (i = 0; i < cnt; i++) {
- ext = X509_get_ext(cert, i);
- method = X509V3_EXT_get(ext);
- temp = OBJ_obj2nid(ext->object);
- switch (temp) {
-
- /*
- * If a key_usage field is present, we decode whether
- * this is a trusted or private certificate. This is
- * dorky; all we want is to compare NIDs, but OpenSSL
- * insists on BIO text strings.
- */
- case NID_ext_key_usage:
- bp = BIO_new(BIO_s_mem());
- X509V3_EXT_print(bp, ext, 0, 0);
- BIO_gets(bp, pathbuf, MAXFILENAME);
- BIO_free(bp);
-#if DEBUG
- if (debug)
- printf("cert_parse: %s: %s\n",
- OBJ_nid2ln(temp), pathbuf);
-#endif
- if (strcmp(pathbuf, "Trust Root") == 0)
- ret->flags |= CERT_TRUST;
- else if (strcmp(pathbuf, "Private") == 0)
- ret->flags |= CERT_PRIV;
- break;
-
- /*
- * If a NID_subject_key_identifier field is present, it
- * contains the GQ public key.
- */
- case NID_subject_key_identifier:
- ret->grplen = ext->value->length - 2;
- ret->grpkey = emalloc(ret->grplen);
- memcpy(ret->grpkey, &ext->value->data[2],
- ret->grplen);
- break;
- }
- }
-
- /*
- * If certificate is self signed, verify signature.
- */
- if (strcmp(ret->subject, ret->issuer) == 0) {
- if (!X509_verify(cert, ret->pkey)) {
- msyslog(LOG_INFO,
- "cert_parse: signature not verified %s",
- pathbuf);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- }
-
- /*
- * Verify certificate valid times. Note that certificates cannot
- * be retroactive.
- */
- if (ret->first > ret->last || ret->first < fstamp) {
- msyslog(LOG_INFO,
- "cert_parse: invalid certificate %s first %u last %u fstamp %u",
- ret->subject, ret->first, ret->last, fstamp);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
-
- /*
- * Build the value structure to sign and send later.
- */
- ret->cert.fstamp = htonl(fstamp);
- ret->cert.vallen = htonl(len);
- ret->cert.ptr = emalloc(len);
- memcpy(ret->cert.ptr, asn1cert, len);
-#ifdef DEBUG
- if (debug > 1)
- X509_print_fp(stdout, cert);
-#endif
- X509_free(cert);
- return (ret);
-}
-
-
-/*
* cert_sign - sign x509 certificate equest and update value structure.
*
* The certificate request includes a copy of the host certificate,
@@ -3208,10 +2924,10 @@ cert_parse(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
* XEVNT_CRT bad or missing certificate
- * XEVNT_VFY certificate not verified
* XEVNT_PER host certificate expired
+ * XEVNT_PUB bad or missing public key
+ * XEVNT_VFY certificate not verified
*/
static int
cert_sign(
@@ -3240,12 +2956,9 @@ cert_sign(
if (tstamp == 0)
return (XEVNT_TSP);
- if (tstamp < cinfo->first || tstamp > cinfo->last)
- return (XEVNT_PER);
-
ptr = (u_char *)ep->pkt;
if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
- msyslog(LOG_ERR, "cert_sign %s\n",
+ msyslog(LOG_ERR, "cert_sign: %s",
ERR_error_string(ERR_get_error(), NULL));
return (XEVNT_CRT);
}
@@ -3253,16 +2966,17 @@ cert_sign(
* Extract public key and check for errors.
*/
if ((pkey = X509_get_pubkey(req)) == NULL) {
- msyslog(LOG_ERR, "cert_sign %s\n",
+ msyslog(LOG_ERR, "cert_sign: %s",
ERR_error_string(ERR_get_error(), NULL));
X509_free(req);
return (XEVNT_PUB);
}
/*
- * Generate X509 certificate signed by this server. For this
- * purpose the issuer name is the server name. Also copy any
- * extensions that might be present.
+ * Generate X509 certificate signed by this server. If this is a
+ * trusted host, the issuer name is the group name; otherwise,
+ * it is the host name. Also copy any extensions that might be
+ * present.
*/
cert = X509_new();
X509_set_version(cert, X509_get_version(req));
@@ -3273,7 +2987,7 @@ cert_sign(
X509_gmtime_adj(X509_get_notAfter(cert), YEAR);
subj = X509_get_issuer_name(cert);
X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
- (u_char *)sys_hostname, strlen(sys_hostname), -1, 0);
+ hostval.ptr, strlen(hostval.ptr), -1, 0);
subj = X509_get_subject_name(req);
X509_set_subject_name(cert, subj);
X509_set_pubkey(cert, pkey);
@@ -3286,11 +3000,16 @@ cert_sign(
X509_free(req);
/*
- * Sign and verify the certificate.
+ * Sign and verify the client certificate, but only if the host
+ * certificate has not expired.
*/
+ if (tstamp < cert_host->first || tstamp > cert_host->last) {
+ X509_free(cert);
+ return (XEVNT_PER);
+ }
X509_sign(cert, sign_pkey, sign_digest);
- if (!X509_verify(cert, sign_pkey)) {
- printf("cert_sign\n%s\n",
+ if (X509_verify(cert, sign_pkey) <= 0) {
+ msyslog(LOG_ERR, "cert_sign: %s",
ERR_error_string(ERR_get_error(), NULL));
X509_free(cert);
return (XEVNT_VFY);
@@ -3310,12 +3029,14 @@ cert_sign(
ptr = vp->ptr;
i2d_X509(cert, &ptr);
vp->siglen = 0;
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)vp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
+ if (tstamp != 0) {
+ vp->sig = emalloc(sign_siglen);
+ EVP_SignInit(&ctx, sign_digest);
+ EVP_SignUpdate(&ctx, (u_char *)vp, 12);
+ EVP_SignUpdate(&ctx, vp->ptr, len);
+ if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
+ vp->siglen = htonl(sign_siglen);
+ }
#ifdef DEBUG
if (debug > 1)
X509_print_fp(stdout, cert);
@@ -3326,74 +3047,38 @@ cert_sign(
/*
- * cert_valid - verify certificate with given public key
- *
- * This is pretty ugly, as the certificate has to be verified in the
- * OpenSSL X509 structure, not in the DER format in the info/value
- * structure.
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_VFY certificate not verified
- */
-int
-cert_valid(
- struct cert_info *cinf, /* certificate information structure */
- EVP_PKEY *pkey /* public key */
- )
-{
- X509 *cert; /* X509 certificate */
- u_char *ptr;
-
- if (cinf->flags & CERT_SIGN)
- return (XEVNT_OK);
-
- ptr = (u_char *)cinf->cert.ptr;
- cert = d2i_X509(NULL, &ptr, ntohl(cinf->cert.vallen));
- if (cert == NULL || !X509_verify(cert, pkey))
- return (XEVNT_VFY);
-
- X509_free(cert);
- return (XEVNT_OK);
-}
-
-
-/*
- * cert - install certificate in certificate list
+ * cert_install - install certificate in certificate cache
*
* This routine encodes an extension field into a certificate info/value
* structure. It searches the certificate list for duplicates and
- * expunges whichever is older. It then searches the list for other
- * certificates that might be verified by this latest one. Finally, it
- * inserts this certificate first on the list.
+ * expunges whichever is older. Finally, it inserts this certificate
+ * first on the list.
*
- * Returns
- * XEVNT_OK success
- * XEVNT_FSP bad or missing filestamp
- * XEVNT_CRT bad or missing certificate
+ * Returns certificate info pointer if valid, NULL if not.
*/
-int
+struct cert_info *
cert_install(
struct exten *ep, /* cert info/value */
struct peer *peer /* peer structure */
)
{
- struct cert_info *cp, *xp, *yp, **zp;
+ struct cert_info *cp, *xp, **zp;
/*
* Parse and validate the signed certificate. If valid,
- * construct the info/value structure; otherwise, scamper home.
+ * construct the info/value structure; otherwise, scamper home
+ * empty handed.
*/
- if ((cp = cert_parse((u_char *)ep->pkt, ntohl(ep->vallen),
- ntohl(ep->fstamp))) == NULL)
- return (XEVNT_CRT);
+ if ((cp = cert_parse((u_char *)ep->pkt, (long)ntohl(ep->vallen),
+ (tstamp_t)ntohl(ep->fstamp))) == NULL)
+ return (NULL);
/*
* Scan certificate list looking for another certificate with
* the same subject and issuer. If another is found with the
* same or older filestamp, unlink it and return the goodies to
* the heap. If another is found with a later filestamp, discard
- * the new one and leave the building.
+ * the new one and leave the building with the old one.
*
* Make a note to study this issue again. An earlier certificate
* with a long lifetime might be overtaken by a later
@@ -3401,112 +3086,314 @@ cert_install(
* earlier signature. However, we gotta find a way to leak old
* stuff from the cache, so we do it anyway.
*/
- yp = cp;
zp = &cinfo;
for (xp = cinfo; xp != NULL; xp = xp->link) {
if (strcmp(cp->subject, xp->subject) == 0 &&
strcmp(cp->issuer, xp->issuer) == 0) {
if (ntohl(cp->cert.fstamp) <=
ntohl(xp->cert.fstamp)) {
- *zp = xp->link;;
- cert_free(xp);
- } else {
cert_free(cp);
- return (XEVNT_FSP);
+ cp = xp;
+ } else {
+ *zp = xp->link;
+ cert_free(xp);
+ xp = NULL;
}
break;
}
zp = &xp->link;
}
- yp->link = cinfo;
- cinfo = yp;
+ if (xp == NULL) {
+ cp->link = cinfo;
+ cinfo = cp;
+ }
+ cp->flags |= CERT_VALID;
+ crypto_update();
+ return (cp);
+}
+
+
+/*
+ * cert_hike - verify the signature using the issuer public key
+ *
+ * Returns
+ * XEVNT_OK success
+ * XEVNT_CRT bad or missing certificate
+ * XEVNT_PER host certificate expired
+ * XEVNT_VFY certificate not verified
+ */
+int
+cert_hike(
+ struct peer *peer, /* peer structure pointer */
+ struct cert_info *yp /* issuer certificate */
+ )
+{
+ struct cert_info *xp; /* subject certificate */
+ X509 *cert; /* X509 certificate */
+ u_char *ptr;
/*
- * Scan the certificate list to see if Y is signed by X. This is
- * independent of order.
+ * Save the issuer on the new certificate, but remember the old
+ * one.
*/
- for (yp = cinfo; yp != NULL; yp = yp->link) {
- for (xp = cinfo; xp != NULL; xp = xp->link) {
+ if (peer->issuer != NULL)
+ free(peer->issuer);
+ peer->issuer = emalloc(strlen(yp->issuer) + 1);
+ strcpy(peer->issuer, yp->issuer);
+ xp = peer->xinfo;
+ peer->xinfo = yp;
- /*
- * If the issuer of certificate Y matches the
- * subject of certificate X, verify the
- * signature of Y using the public key of X. If
- * so, X signs Y.
- */
- if (strcmp(yp->issuer, xp->subject) != 0 ||
- xp->flags & CERT_ERROR)
- continue;
+ /*
+ * If subject Y matches issuer Y, then the certificate trail is
+ * complete. If Y is not trusted, the server certificate has yet
+ * been signed, so keep trying. Otherwise, save the group key
+ * and light the valid bit. If the host certificate is trusted,
+ * do not execute a sign exchange. If no identity scheme is in
+ * use, light the identity and proventic bits.
+ */
+ if (strcmp(yp->subject, yp->issuer) == 0) {
+ if (!(yp->flags & CERT_TRUST))
+ return (XEVNT_OK);
- if (cert_valid(yp, xp->pkey) != XEVNT_OK) {
- yp->flags |= CERT_ERROR;
- continue;
- }
+ peer->grpkey = yp->grpkey;
+ peer->crypto |= CRYPTO_FLAG_CERT;
+ if (!(peer->crypto & CRYPTO_FLAG_MASK))
+ peer->crypto |= CRYPTO_FLAG_VRFY |
+ CRYPTO_FLAG_PROV;
- /*
- * The signature Y is valid only if it begins
- * during the lifetime of X; however, it is not
- * necessarily an error, since some other
- * certificate might sign Y.
- */
- if (yp->first < xp->first || yp->first >
- xp->last)
- continue;
+ /*
+ * If the server has an an identity scheme, fetch the
+ * identity credentials. If not, the identity is
+ * verified only by the trusted certificate. The next
+ * signature will set the server proventic.
+ */
+ if (!(peer->crypto & CRYPTO_FLAG_MASK) ||
+ sys_groupname == NULL)
+ peer->crypto |= CRYPTO_FLAG_VRFY;
+ }
- yp->flags |= CERT_SIGN;
+ /*
+ * If X exists, verify signature X using public key Y.
+ */
+ if (xp == NULL)
+ return (XEVNT_OK);
- /*
- * If X is trusted, then Y is trusted. Note that
- * we might stumble over a self-signed
- * certificate that is not trusted, at least
- * temporarily. This can happen when a dude
- * first comes up, but has not synchronized the
- * clock and had its certificate signed by its
- * server. In case of broken certificate trail,
- * this might result in a loop that could
- * persist until timeout.
- */
- if (!(xp->flags & (CERT_TRUST | CERT_VALID)))
- continue;
+ ptr = (u_char *)xp->cert.ptr;
+ cert = d2i_X509(NULL, &ptr, ntohl(xp->cert.vallen));
+ if (cert == NULL) {
+ xp->flags |= CERT_ERROR;
+ return (XEVNT_CRT);
+ }
+ if (X509_verify(cert, yp->pkey) <= 0) {
+ X509_free(cert);
+ xp->flags |= CERT_ERROR;
+ return (XEVNT_VFY);
+ }
+ X509_free(cert);
- yp->flags |= CERT_VALID;
+ /*
+ * Signature X is valid only if it begins during the
+ * lifetime of Y.
+ */
+ if (xp->first < yp->first || xp->first > yp->last) {
+ xp->flags |= CERT_ERROR;
+ return (XEVNT_PER);
+ }
+ xp->flags |= CERT_SIGN;
+ return (XEVNT_OK);
+}
- /*
- * If subject Y matches the server subject name,
- * then Y has completed the certificate trail.
- * Save the group key and light the valid bit.
- */
- if (strcmp(yp->subject, peer->subject) != 0)
- continue;
- if (yp->grpkey != NULL) {
- if (peer->grpkey != NULL)
- BN_free(peer->grpkey);
- peer->grpkey = BN_bin2bn(yp->grpkey,
- yp->grplen, NULL);
- }
- peer->crypto |= CRYPTO_FLAG_VALID;
+/*
+ * cert_parse - parse x509 certificate and create info/value structures.
+ *
+ * The server certificate includes the version number, issuer name,
+ * subject name, public key and valid date interval. If the issuer name
+ * is the same as the subject name, the certificate is self signed and
+ * valid only if the server is configured as trustable. If the names are
+ * different, another issuer has signed the server certificate and
+ * vouched for it. In this case the server certificate is valid if
+ * verified by the issuer public key.
+ *
+ * Returns certificate info/value pointer if valid, NULL if not.
+ */
+struct cert_info * /* certificate information structure */
+cert_parse(
+ u_char *asn1cert, /* X509 certificate */
+ long len, /* certificate length */
+ tstamp_t fstamp /* filestamp */
+ )
+{
+ X509 *cert; /* X509 certificate */
+ X509_EXTENSION *ext; /* X509v3 extension */
+ struct cert_info *ret; /* certificate info/value */
+ BIO *bp;
+ char pathbuf[MAXFILENAME];
+ u_char *ptr;
+ int temp, cnt, i;
- /*
- * If the server has an an identity scheme,
- * fetch the identity credentials. If not, the
- * identity is verified only by the trusted
- * certificate. The next signature will set the
- * server proventic.
- */
- if (peer->crypto & (CRYPTO_FLAG_GQ |
- CRYPTO_FLAG_IFF | CRYPTO_FLAG_MV))
- continue;
+ /*
+ * Decode ASN.1 objects and construct certificate structure.
+ */
+ ptr = asn1cert;
+ if ((cert = d2i_X509(NULL, &ptr, len)) == NULL) {
+ msyslog(LOG_ERR, "cert_parse: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return (NULL);
+ }
+#ifdef DEBUG
+ if (debug > 1)
+ X509_print_fp(stdout, cert);
+#endif
- peer->crypto |= CRYPTO_FLAG_VRFY;
+ /*
+ * Extract version, subject name and public key.
+ */
+ ret = emalloc(sizeof(struct cert_info));
+ memset(ret, 0, sizeof(struct cert_info));
+ if ((ret->pkey = X509_get_pubkey(cert)) == NULL) {
+ msyslog(LOG_ERR, "cert_parse: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
+ }
+ ret->version = X509_get_version(cert);
+ X509_NAME_oneline(X509_get_subject_name(cert), pathbuf,
+ MAXFILENAME);
+ ptr = strstr(pathbuf, "CN=");
+ if (ptr == NULL) {
+ msyslog(LOG_NOTICE, "cert_parse: invalid subject %s",
+ pathbuf);
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
+ }
+ ret->subject = estrdup(ptr + 3);
+
+ /*
+ * Extract remaining objects. Note that the NTP serial number is
+ * the NTP seconds at the time of signing, but this might not be
+ * the case for other authority. We don't bother to check the
+ * objects at this time, since the real crunch can happen only
+ * when the time is valid but not yet certificated.
+ */
+ ret->nid = OBJ_obj2nid(cert->cert_info->signature->algorithm);
+ ret->digest = (const EVP_MD *)EVP_get_digestbynid(ret->nid);
+ ret->serial =
+ (u_long)ASN1_INTEGER_get(X509_get_serialNumber(cert));
+ X509_NAME_oneline(X509_get_issuer_name(cert), pathbuf,
+ MAXFILENAME);
+ if ((ptr = strstr(pathbuf, "CN=")) == NULL) {
+ msyslog(LOG_NOTICE, "cert_parse: invalid issuer %s",
+ pathbuf);
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
+ }
+ ret->issuer = estrdup(ptr + 3);
+ ret->first = asn2ntp(X509_get_notBefore(cert));
+ ret->last = asn2ntp(X509_get_notAfter(cert));
+
+ /*
+ * Extract extension fields. These are ad hoc ripoffs of
+ * currently assigned functions and will certainly be changed
+ * before prime time.
+ */
+ cnt = X509_get_ext_count(cert);
+ for (i = 0; i < cnt; i++) {
+ ext = X509_get_ext(cert, i);
+ temp = OBJ_obj2nid(ext->object);
+ switch (temp) {
+
+ /*
+ * If a key_usage field is present, we decode whether
+ * this is a trusted or private certificate. This is
+ * dorky; all we want is to compare NIDs, but OpenSSL
+ * insists on BIO text strings.
+ */
+ case NID_ext_key_usage:
+ bp = BIO_new(BIO_s_mem());
+ X509V3_EXT_print(bp, ext, 0, 0);
+ BIO_gets(bp, pathbuf, MAXFILENAME);
+ BIO_free(bp);
+ if (strcmp(pathbuf, "Trust Root") == 0)
+ ret->flags |= CERT_TRUST;
+ else if (strcmp(pathbuf, "Private") == 0)
+ ret->flags |= CERT_PRIV;
+#if DEBUG
+ if (debug)
+ printf("cert_parse: %s: %s\n",
+ OBJ_nid2ln(temp), pathbuf);
+#endif
+ break;
+
+ /*
+ * If a NID_subject_key_identifier field is present, it
+ * contains the GQ public key.
+ */
+ case NID_subject_key_identifier:
+ ret->grpkey = BN_bin2bn(&ext->value->data[2],
+ ext->value->length - 2, NULL);
+ /* fall through */
+#if DEBUG
+ default:
+ if (debug)
+ printf("cert_parse: %s\n",
+ OBJ_nid2ln(temp));
+#endif
+ }
+ }
+ if (strcmp(ret->subject, ret->issuer) == 0) {
+
+ /*
+ * If certificate is self signed, verify signature.
+ */
+ if (X509_verify(cert, ret->pkey) <= 0) {
+ msyslog(LOG_NOTICE,
+ "cert_parse: signature not verified %s",
+ ret->subject);
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
+ }
+ } else {
+
+ /*
+ * Check for a certificate loop.
+ */
+ if (strcmp(hostval.ptr, ret->issuer) == 0) {
+ msyslog(LOG_NOTICE,
+ "cert_parse: certificate trail loop %s",
+ ret->subject);
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
}
}
/*
- * That was awesome. Now update the timestamps and signatures.
+ * Verify certificate valid times. Note that certificates cannot
+ * be retroactive.
*/
- crypto_update();
- return (XEVNT_OK);
+ if (ret->first > ret->last || ret->first < fstamp) {
+ msyslog(LOG_NOTICE,
+ "cert_parse: invalid times %s first %u last %u fstamp %u",
+ ret->subject, ret->first, ret->last, fstamp);
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
+ }
+
+ /*
+ * Build the value structure to sign and send later.
+ */
+ ret->cert.fstamp = htonl(fstamp);
+ ret->cert.vallen = htonl(len);
+ ret->cert.ptr = emalloc(len);
+ memcpy(ret->cert.ptr, asn1cert, len);
+ X509_free(cert);
+ return (ret);
}
@@ -3525,42 +3412,47 @@ cert_free(
if (cinf->issuer != NULL)
free(cinf->issuer);
if (cinf->grpkey != NULL)
- free(cinf->grpkey);
+ BN_free(cinf->grpkey);
value_free(&cinf->cert);
free(cinf);
}
/*
- ***********************************************************************
- * *
- * The following routines are used only at initialization time *
- * *
- ***********************************************************************
+ * crypto_key - load cryptographic parameters and keys
+ *
+ * This routine searches the key cache for matching name in the form
+ * ntpkey_<key>_<name>, where <key> is one of host, sign, iff, gq, mv,
+ * and <name> is the host/group name. If not found, it tries to load a
+ * PEM-encoded file of the same name and extracts the filestamp from
+ * the first line of the file name. It returns the key pointer if valid,
+ * NULL if not.
*/
-/*
- * crypto_key - load cryptographic parameters and keys from files
- *
- * This routine loads a PEM-encoded public/private key pair and extracts
- * the filestamp from the file name.
- *
- * Returns public key pointer if valid, NULL if not. Side effect updates
- * the filestamp if valid.
- */
-static EVP_PKEY *
+static struct pkey_info *
crypto_key(
char *cp, /* file name */
- tstamp_t *fstamp /* filestamp */
+ char *passwd1, /* password */
+ sockaddr_u *addr /* IP address */
)
{
FILE *str; /* file handle */
+ struct pkey_info *pkp; /* generic key */
EVP_PKEY *pkey = NULL; /* public/private key */
+ tstamp_t fstamp;
char filename[MAXFILENAME]; /* name of key file */
char linkname[MAXFILENAME]; /* filestamp buffer) */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
char *ptr;
/*
+ * Search the key cache for matching key and name.
+ */
+ for (pkp = pkinfo; pkp != NULL; pkp = pkp->link) {
+ if (strcmp(cp, pkp->name) == 0)
+ return (pkp);
+ }
+
+ /*
* Open the key file. If the first character of the file name is
* not '/', prepend the keys directory string. If something goes
* wrong, abandon ship.
@@ -3577,64 +3469,83 @@ crypto_key(
* Read the filestamp, which is contained in the first line.
*/
if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
- msyslog(LOG_ERR, "crypto_key: no data %s\n",
+ msyslog(LOG_ERR, "crypto_key: empty file %s",
filename);
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
if ((ptr = strrchr(ptr, '.')) == NULL) {
- msyslog(LOG_ERR, "crypto_key: no filestamp %s\n",
+ msyslog(LOG_ERR, "crypto_key: no filestamp %s",
filename);
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
- if (sscanf(++ptr, "%u", fstamp) != 1) {
- msyslog(LOG_ERR, "crypto_key: invalid timestamp %s\n",
+ if (sscanf(++ptr, "%u", &fstamp) != 1) {
+ msyslog(LOG_ERR, "crypto_key: invalid filestamp %s",
filename);
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
/*
- * Read and decrypt PEM-encoded private key.
+ * Read and decrypt PEM-encoded private key. If it fails to
+ * decrypt, game over.
*/
- pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd);
+ pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd1);
fclose(str);
if (pkey == NULL) {
- msyslog(LOG_ERR, "crypto_key %s\n",
+ msyslog(LOG_ERR, "crypto_key: %s",
ERR_error_string(ERR_get_error(), NULL));
- return (NULL);
+ exit (-1);
}
/*
+ * Make a new entry in the key cache.
+ */
+ pkp = emalloc(sizeof(struct pkey_info));
+ pkp->link = pkinfo;
+ pkinfo = pkp;
+ pkp->pkey = pkey;
+ pkp->name = emalloc(strlen(cp) + 1);
+ pkp->fstamp = fstamp;
+ strcpy(pkp->name, cp);
+
+ /*
* Leave tracks in the cryptostats.
*/
if ((ptr = strrchr(linkname, '\n')) != NULL)
*ptr = '\0';
snprintf(statstr, NTP_MAXSTRLEN, "%s mod %d", &linkname[2],
EVP_PKEY_size(pkey) * 8);
- record_crypto_stats(NULL, statstr);
+ record_crypto_stats(addr, statstr);
#ifdef DEBUG
if (debug)
printf("crypto_key: %s\n", statstr);
if (debug > 1) {
if (pkey->type == EVP_PKEY_DSA)
DSA_print_fp(stdout, pkey->pkey.dsa, 0);
- else
+ else if (pkey->type == EVP_PKEY_RSA)
RSA_print_fp(stdout, pkey->pkey.rsa, 0);
}
#endif
- return (pkey);
+ return (pkp);
}
/*
+ ***********************************************************************
+ * *
+ * The following routines are used only at initialization time *
+ * *
+ ***********************************************************************
+ */
+/*
* crypto_cert - load certificate from file
*
- * This routine loads a X.509 RSA or DSA certificate from a file and
+ * This routine loads an X.509 RSA or DSA certificate from a file and
* constructs a info/cert value structure for this machine. The
* structure includes a filestamp extracted from the file name. Later
- * the certificate can be sent to another machine by request.
+ * the certificate can be sent to another machine on request.
*
* Returns certificate info/value pointer if valid, NULL if not.
*/
@@ -3671,21 +3582,21 @@ crypto_cert(
* Read the filestamp, which is contained in the first line.
*/
if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
- msyslog(LOG_ERR, "crypto_cert: no data %s\n",
+ msyslog(LOG_ERR, "crypto_cert: empty file %s",
filename);
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
if ((ptr = strrchr(ptr, '.')) == NULL) {
msyslog(LOG_ERR, "crypto_cert: no filestamp %s\n",
filename);
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
if (sscanf(++ptr, "%u", &fstamp) != 1) {
msyslog(LOG_ERR, "crypto_cert: invalid filestamp %s\n",
filename);
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
@@ -3693,35 +3604,35 @@ crypto_cert(
* Read PEM-encoded certificate and install.
*/
if (!PEM_read(str, &name, &header, &data, &len)) {
- msyslog(LOG_ERR, "crypto_cert %s\n",
+ msyslog(LOG_ERR, "crypto_cert: %s\n",
ERR_error_string(ERR_get_error(), NULL));
- (void)fclose(str);
+ fclose(str);
return (NULL);
}
+ fclose(str);
free(header);
- if (strcmp(name, "CERTIFICATE") !=0) {
- msyslog(LOG_INFO, "crypto_cert: wrong PEM type %s",
+ if (strcmp(name, "CERTIFICATE") != 0) {
+ msyslog(LOG_NOTICE, "crypto_cert: wrong PEM type %s",
name);
free(name);
free(data);
- (void)fclose(str);
return (NULL);
}
free(name);
/*
- * Parse certificate and generate info/value structure.
+ * Parse certificate and generate info/value structure. The
+ * pointer and copy nonsense is due something broken in Solaris.
*/
ret = cert_parse(data, len, fstamp);
free(data);
- (void)fclose(str);
if (ret == NULL)
return (NULL);
if ((ptr = strrchr(linkname, '\n')) != NULL)
*ptr = '\0';
- snprintf(statstr, NTP_MAXSTRLEN,
- "%s 0x%x len %lu", &linkname[2], ret->flags, len);
+ snprintf(statstr, NTP_MAXSTRLEN, "%s 0x%x len %lu",
+ &linkname[2], ret->flags, len);
record_crypto_stats(NULL, statstr);
#ifdef DEBUG
if (debug)
@@ -3732,227 +3643,113 @@ crypto_cert(
/*
- * crypto_tai - load leapseconds table from file
- *
- * This routine loads the ERTS leapsecond file in NIST text format,
- * converts to a value structure and extracts a filestamp from the file
- * name. The data are used to establish the TAI offset from UTC, which
- * is provided to the kernel if supported. Later the data can be sent to
- * another machine on request.
- */
-static void
-crypto_tai(
- char *cp /* file name */
- )
-{
- FILE *str; /* file handle */
- char buf[NTP_MAXSTRLEN]; /* file line buffer */
- u_int32 leapsec[MAX_LEAP]; /* NTP time at leaps */
- int offset; /* offset at leap (s) */
- char filename[MAXFILENAME]; /* name of leapseconds file */
- char linkname[MAXFILENAME]; /* file link (for filestamp) */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- tstamp_t fstamp; /* filestamp */
- u_int len;
- u_int32 *ptr;
- char *dp;
- int rval, i, j;
-
- /*
- * Open the file and discard comment lines. If the first
- * character of the file name is not '/', prepend the keys
- * directory string. If the file is not found, not to worry; it
- * can be retrieved over the net. But, if it is found with
- * errors, we crash and burn.
- */
- if (*cp == '/')
- strcpy(filename, cp);
- else
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- if ((str = fopen(filename, "r")) == NULL)
- return;
-
- /*
- * Extract filestamp if present.
- */
- rval = readlink(filename, linkname, MAXFILENAME - 1);
- if (rval > 0) {
- linkname[rval] = '\0';
- dp = strrchr(linkname, '.');
- } else {
- dp = strrchr(filename, '.');
- }
- if (dp != NULL)
- sscanf(++dp, "%u", &fstamp);
- else
- fstamp = 0;
- tai_leap.fstamp = htonl(fstamp);
-
- /*
- * We are rather paranoid here, since an intruder might cause a
- * coredump by infiltrating naughty values. Empty lines and
- * comments are ignored. Other lines must begin with two
- * integers followed by junk or comments. The first integer is
- * the NTP seconds of leap insertion, the second is the offset
- * of TAI relative to UTC after that insertion. The second word
- * must equal the initial insertion of ten seconds on 1 January
- * 1972 plus one second for each succeeding insertion.
- */
- i = 0;
- while (i < MAX_LEAP) {
- dp = fgets(buf, NTP_MAXSTRLEN - 1, str);
- if (dp == NULL)
- break;
-
- if (strlen(buf) < 1)
- continue;
-
- if (*buf == '#')
- continue;
-
- if (sscanf(buf, "%u %d", &leapsec[i], &offset) != 2)
- continue;
-
- if (i != offset - TAI_1972)
- break;
-
- i++;
- }
- fclose(str);
- if (dp != NULL) {
- msyslog(LOG_INFO,
- "crypto_tai: leapseconds file %s error %d", cp,
- rval);
- exit (-1);
- }
-
- /*
- * The extension field table entries consists of the NTP seconds
- * of leap insertion in network byte order.
- */
- len = i * sizeof(u_int32);
- tai_leap.vallen = htonl(len);
- ptr = emalloc(len);
- tai_leap.ptr = (u_char *)ptr;
- for (j = 0; j < i; j++)
- *ptr++ = htonl(leapsec[j]);
- crypto_flags |= CRYPTO_FLAG_TAI;
- snprintf(statstr, NTP_MAXSTRLEN, "%s fs %u leap %u len %u", cp, fstamp,
- leapsec[--j], len);
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_tai: %s\n", statstr);
-#endif
-}
-
-
-/*
- * crypto_setup - load keys, certificate and leapseconds table
+ * crypto_setup - load keys, certificate and identity parameters
*
* This routine loads the public/private host key and certificate. If
* available, it loads the public/private sign key, which defaults to
- * the host key, and leapseconds table. The host key must be RSA, but
- * the sign key can be either RSA or DSA. In either case, the public key
- * on the certificate must agree with the sign key.
+ * the host key. The host key must be RSA, but the sign key can be
+ * either RSA or DSA. If a trusted certificate, it loads the identity
+ * parameters. In either case, the public key on the certificate must
+ * agree with the sign key.
+ *
+ * Required but missing files and inconsistent data and errors are
+ * fatal. Allowing configuration to continue would be hazardous and
+ * require really messy error checks.
*/
void
crypto_setup(void)
{
- EVP_PKEY *pkey; /* private/public key pair */
+ struct pkey_info *pinfo; /* private/public key */
char filename[MAXFILENAME]; /* file name buffer */
+ char * randfile;
+ char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
l_fp seed; /* crypto PRNG seed as NTP timestamp */
- tstamp_t fstamp; /* filestamp */
- tstamp_t sstamp; /* sign filestamp */
- u_int len, bytes;
+ u_int len;
+ int bytes;
u_char *ptr;
/*
- * Initialize structures.
+ * Check for correct OpenSSL version and avoid initialization in
+ * the case of multiple crypto commands.
*/
- if (!crypto_flags)
+ if (crypto_flags & CRYPTO_FLAG_ENAB) {
+ msyslog(LOG_NOTICE,
+ "crypto_setup: spurious crypto command");
return;
-
- gethostname(filename, MAXFILENAME);
- bytes = strlen(filename) + 1;
- sys_hostname = emalloc(bytes);
- memcpy(sys_hostname, filename, bytes);
- if (passwd == NULL)
- passwd = sys_hostname;
- memset(&hostval, 0, sizeof(hostval));
- memset(&pubkey, 0, sizeof(pubkey));
- memset(&tai_leap, 0, sizeof(tai_leap));
+ }
+ ssl_check_version();
/*
* Load required random seed file and seed the random number
- * generator. Be default, it is found in the user home
+ * generator. Be default, it is found as .rnd in the user home
* directory. The root home directory may be / or /root,
* depending on the system. Wiggle the contents a bit and write
* it back so the sequence does not repeat when we next restart.
*/
- ERR_load_crypto_strings();
- if (rand_file == NULL) {
- if ((RAND_file_name(filename, MAXFILENAME)) != NULL) {
- rand_file = emalloc(strlen(filename) + 1);
- strcpy(rand_file, filename);
+ if (!RAND_status()) {
+ if (rand_file == NULL) {
+ RAND_file_name(filename, sizeof(filename));
+ randfile = filename;
+ } else if (*rand_file != '/') {
+ snprintf(filename, sizeof(filename), "%s/%s",
+ keysdir, rand_file);
+ randfile = filename;
+ } else
+ randfile = rand_file;
+
+ if ((bytes = RAND_load_file(randfile, -1)) == 0) {
+ msyslog(LOG_ERR,
+ "crypto_setup: random seed file %s missing",
+ randfile);
+ exit (-1);
}
- } else if (*rand_file != '/') {
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir,
- rand_file);
- free(rand_file);
- rand_file = emalloc(strlen(filename) + 1);
- strcpy(rand_file, filename);
- }
- if (rand_file == NULL) {
- msyslog(LOG_ERR,
- "crypto_setup: random seed file not specified");
- exit (-1);
- }
- if ((bytes = RAND_load_file(rand_file, -1)) == 0) {
- msyslog(LOG_ERR,
- "crypto_setup: random seed file %s not found\n",
- rand_file);
- exit (-1);
- }
- get_systime(&seed);
- RAND_seed(&seed, sizeof(l_fp));
- RAND_write_file(rand_file);
- OpenSSL_add_all_algorithms();
+ get_systime(&seed);
+ RAND_seed(&seed, sizeof(l_fp));
+ RAND_write_file(randfile);
#ifdef DEBUG
- if (debug)
- printf(
- "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
- SSLeay(), rand_file, bytes);
+ if (debug)
+ printf(
+ "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
+ SSLeay(), randfile, bytes);
#endif
+ }
/*
- * Load required host key from file "ntpkey_host_<hostname>". It
- * also becomes the default sign key.
+ * Initialize structures.
*/
- if (host_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_host_%s",
- sys_hostname);
- host_file = emalloc(strlen(filename) + 1);
- strcpy(host_file, filename);
+ if (sys_hostname == NULL) {
+ gethostname(filename, MAXFILENAME);
+ sys_hostname = emalloc(strlen(filename) + 1);
+ strcpy(sys_hostname, filename);
}
- pkey = crypto_key(host_file, &fstamp);
- if (pkey == NULL) {
+ if (passwd == NULL)
+ passwd = sys_hostname;
+ memset(&hostval, 0, sizeof(hostval));
+ memset(&pubkey, 0, sizeof(pubkey));
+ memset(&tai_leap, 0, sizeof(tai_leap));
+
+ /*
+ * Load required host key from file "ntpkey_host_<hostname>". If
+ * no host key file is not found or has invalid password, life
+ * as we know it ends. The host key also becomes the default
+ * sign key.
+ */
+ snprintf(filename, MAXFILENAME, "ntpkey_host_%s", sys_hostname);
+ pinfo = crypto_key(filename, passwd, NULL);
+ if (pinfo == NULL) {
msyslog(LOG_ERR,
"crypto_setup: host key file %s not found or corrupt",
- host_file);
+ filename);
exit (-1);
}
- host_pkey = pkey;
- sign_pkey = pkey;
- sstamp = fstamp;
- hostval.fstamp = htonl(fstamp);
- if (host_pkey->type != EVP_PKEY_RSA) {
+ if (pinfo->pkey->type != EVP_PKEY_RSA) {
msyslog(LOG_ERR,
"crypto_setup: host key is not RSA key type");
exit (-1);
}
- hostval.vallen = htonl(strlen(sys_hostname));
- hostval.ptr = (u_char *)sys_hostname;
+ host_pkey = pinfo->pkey;
+ sign_pkey = host_pkey;
+ hostval.fstamp = htonl(pinfo->fstamp);
/*
* Construct public key extension field for agreement scheme.
@@ -3961,228 +3758,169 @@ crypto_setup(void)
ptr = emalloc(len);
pubkey.ptr = ptr;
i2d_PublicKey(host_pkey, &ptr);
- pubkey.vallen = htonl(len);
pubkey.fstamp = hostval.fstamp;
+ pubkey.vallen = htonl(len);
/*
* Load optional sign key from file "ntpkey_sign_<hostname>". If
- * loaded, it becomes the sign key.
- */
- if (sign_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_sign_%s",
- sys_hostname);
- sign_file = emalloc(strlen(filename) + 1);
- strcpy(sign_file, filename);
- }
- pkey = crypto_key(sign_file, &fstamp);
- if (pkey != NULL) {
- sign_pkey = pkey;
- sstamp = fstamp;
- }
- sign_siglen = EVP_PKEY_size(sign_pkey);
-
- /*
- * Load optional IFF parameters from file
- * "ntpkey_iff_<hostname>".
- */
- if (iffpar_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
- sys_hostname);
- iffpar_file = emalloc(strlen(filename) + 1);
- strcpy(iffpar_file, filename);
- }
- iffpar_pkey = crypto_key(iffpar_file, &if_fstamp);
- if (iffpar_pkey != NULL)
- crypto_flags |= CRYPTO_FLAG_IFF;
-
- /*
- * Load optional GQ parameters from file "ntpkey_gq_<hostname>".
- */
- if (gqpar_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
- sys_hostname);
- gqpar_file = emalloc(strlen(filename) + 1);
- strcpy(gqpar_file, filename);
- }
- gqpar_pkey = crypto_key(gqpar_file, &gq_fstamp);
- if (gqpar_pkey != NULL)
- crypto_flags |= CRYPTO_FLAG_GQ;
-
- /*
- * Load optional MV parameters from file "ntpkey_mv_<hostname>".
+ * available, it becomes the sign key.
*/
- if (mvpar_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
- sys_hostname);
- mvpar_file = emalloc(strlen(filename) + 1);
- strcpy(mvpar_file, filename);
- }
- mvpar_pkey = crypto_key(mvpar_file, &mv_fstamp);
- if (mvpar_pkey != NULL)
- crypto_flags |= CRYPTO_FLAG_MV;
+ snprintf(filename, MAXFILENAME, "ntpkey_sign_%s", sys_hostname);
+ pinfo = crypto_key(filename, passwd, NULL); if (pinfo != NULL)
+ sign_pkey = pinfo->pkey;
/*
* Load required certificate from file "ntpkey_cert_<hostname>".
*/
- if (cert_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_cert_%s",
- sys_hostname);
- cert_file = emalloc(strlen(filename) + 1);
- strcpy(cert_file, filename);
- }
- if ((cinfo = crypto_cert(cert_file)) == NULL) {
+ snprintf(filename, MAXFILENAME, "ntpkey_cert_%s", sys_hostname);
+ cinfo = crypto_cert(filename);
+ if (cinfo == NULL) {
msyslog(LOG_ERR,
- "certificate file %s not found or corrupt",
- cert_file);
+ "crypto_setup: certificate file %s not found or corrupt",
+ filename);
exit (-1);
}
+ cert_host = cinfo;
+ sign_digest = cinfo->digest;
+ sign_siglen = EVP_PKEY_size(sign_pkey);
+ if (cinfo->flags & CERT_PRIV)
+ crypto_flags |= CRYPTO_FLAG_PRIV;
/*
- * The subject name must be the same as the host name, unless
- * the certificate is private, in which case it may have come
- * from another host.
+ * The certificate must be self-signed.
*/
- if (!(cinfo->flags & CERT_PRIV) && strcmp(cinfo->subject,
- sys_hostname) != 0) {
+ if (strcmp(cinfo->subject, cinfo->issuer) != 0) {
msyslog(LOG_ERR,
- "crypto_setup: certificate %s not for this host",
- cert_file);
- cert_free(cinfo);
+ "crypto_setup: certificate %s is not self-signed",
+ filename);
exit (-1);
}
+ hostval.vallen = htonl(strlen(cinfo->subject));
+ hostval.ptr = cinfo->subject;
/*
- * It the certificate is trusted, the subject must be the same
- * as the issuer, in other words it must be self signed.
+ * If trusted certificate, the subject name must match the group
+ * name.
*/
- if (cinfo->flags & CERT_TRUST && strcmp(cinfo->subject,
- cinfo->issuer) != 0) {
- if (cert_valid(cinfo, sign_pkey) != XEVNT_OK) {
+ if (cinfo->flags & CERT_TRUST) {
+ if (sys_groupname == NULL) {
+ sys_groupname = hostval.ptr;
+ } else if (strcmp(hostval.ptr, sys_groupname) != 0) {
msyslog(LOG_ERR,
- "crypto_setup: certificate %s is trusted, but not self signed.",
- cert_file);
- cert_free(cinfo);
+ "crypto_setup: trusted certificate name %s does not match group name %s",
+ hostval.ptr, sys_groupname);
exit (-1);
}
}
- sign_digest = cinfo->digest;
- if (cinfo->flags & CERT_PRIV)
- crypto_flags |= CRYPTO_FLAG_PRIV;
- crypto_flags |= cinfo->nid << 16;
+ if (sys_groupname != NULL) {
+
+ /*
+ * Load optional IFF parameters from file
+ * "ntpkey_iffkey_<groupname>".
+ */
+ snprintf(filename, MAXFILENAME, "ntpkey_iffkey_%s",
+ sys_groupname);
+ iffkey_info = crypto_key(filename, passwd, NULL);
+ if (iffkey_info != NULL)
+ crypto_flags |= CRYPTO_FLAG_IFF;
+
+ /*
+ * Load optional GQ parameters from file
+ * "ntpkey_gqkey_<groupname>".
+ */
+ snprintf(filename, MAXFILENAME, "ntpkey_gqkey_%s",
+ sys_groupname);
+ gqkey_info = crypto_key(filename, passwd, NULL);
+ if (gqkey_info != NULL)
+ crypto_flags |= CRYPTO_FLAG_GQ;
+
+ /*
+ * Load optional MV parameters from file
+ * "ntpkey_mvkey_<groupname>".
+ */
+ snprintf(filename, MAXFILENAME, "ntpkey_mvkey_%s",
+ sys_groupname);
+ mvkey_info = crypto_key(filename, passwd, NULL);
+ if (mvkey_info != NULL)
+ crypto_flags |= CRYPTO_FLAG_MV;
+ }
/*
- * Load optional leapseconds table from file "ntpkey_leap". If
- * the file is missing or defective, the values can later be
- * retrieved from a server.
+ * We met the enemy and he is us. Now strike up the dance.
*/
- if (leap_file == NULL)
- leap_file = "ntpkey_leap";
- crypto_tai(leap_file);
+ crypto_flags |= CRYPTO_FLAG_ENAB | (cinfo->nid << 16);
+ snprintf(statstr, NTP_MAXSTRLEN,
+ "setup 0x%x host %s %s", crypto_flags, sys_hostname,
+ OBJ_nid2ln(cinfo->nid));
+ record_crypto_stats(NULL, statstr);
#ifdef DEBUG
if (debug)
- printf(
- "crypto_setup: flags 0x%x host %s signature %s\n",
- crypto_flags, sys_hostname, OBJ_nid2ln(cinfo->nid));
+ printf("crypto_setup: %s\n", statstr);
#endif
}
/*
- * crypto_config - configure data from crypto configuration command.
+ * crypto_config - configure data from the crypto command.
*/
void
crypto_config(
int item, /* configuration item */
- char *cp /* file name */
+ char *cp /* item name */
)
{
- switch (item) {
+ int nid;
- /*
- * Set random seed file name.
- */
- case CRYPTO_CONF_RAND:
- rand_file = emalloc(strlen(cp) + 1);
- strcpy(rand_file, cp);
- break;
-
- /*
- * Set private key password.
- */
- case CRYPTO_CONF_PW:
- passwd = emalloc(strlen(cp) + 1);
- strcpy(passwd, cp);
- break;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("crypto_config: item %d %s\n", item, cp);
+#endif
+ switch (item) {
/*
- * Set host file name.
+ * Set host name (host).
*/
case CRYPTO_CONF_PRIV:
- host_file = emalloc(strlen(cp) + 1);
- strcpy(host_file, cp);
- break;
-
- /*
- * Set sign key file name.
- */
- case CRYPTO_CONF_SIGN:
- sign_file = emalloc(strlen(cp) + 1);
- strcpy(sign_file, cp);
+ sys_hostname = emalloc(strlen(cp) + 1);
+ strcpy(sys_hostname, cp);
break;
/*
- * Set iff parameters file name.
+ * Set group name (ident).
*/
- case CRYPTO_CONF_IFFPAR:
- iffpar_file = emalloc(strlen(cp) + 1);
- strcpy(iffpar_file, cp);
- break;
-
- /*
- * Set gq parameters file name.
- */
- case CRYPTO_CONF_GQPAR:
- gqpar_file = emalloc(strlen(cp) + 1);
- strcpy(gqpar_file, cp);
- break;
-
- /*
- * Set mv parameters file name.
- */
- case CRYPTO_CONF_MVPAR:
- mvpar_file = emalloc(strlen(cp) + 1);
- strcpy(mvpar_file, cp);
+ case CRYPTO_CONF_IDENT:
+ sys_groupname = emalloc(strlen(cp) + 1);
+ strcpy(sys_groupname, cp);
break;
/*
- * Set identity scheme.
+ * Set private key password (pw).
*/
- case CRYPTO_CONF_IDENT:
- if (!strcasecmp(cp, "iff"))
- ident_scheme |= CRYPTO_FLAG_IFF;
- else if (!strcasecmp(cp, "gq"))
- ident_scheme |= CRYPTO_FLAG_GQ;
- else if (!strcasecmp(cp, "mv"))
- ident_scheme |= CRYPTO_FLAG_MV;
+ case CRYPTO_CONF_PW:
+ passwd = emalloc(strlen(cp) + 1);
+ strcpy(passwd, cp);
break;
/*
- * Set certificate file name.
+ * Set random seed file name (randfile).
*/
- case CRYPTO_CONF_CERT:
- cert_file = emalloc(strlen(cp) + 1);
- strcpy(cert_file, cp);
+ case CRYPTO_CONF_RAND:
+ rand_file = emalloc(strlen(cp) + 1);
+ strcpy(rand_file, cp);
break;
/*
- * Set leapseconds file name.
+ * Set message digest NID.
*/
- case CRYPTO_CONF_LEAP:
- leap_file = emalloc(strlen(cp) + 1);
- strcpy(leap_file, cp);
+ case CRYPTO_CONF_NID:
+ nid = OBJ_sn2nid(cp);
+ if (nid == 0)
+ msyslog(LOG_ERR,
+ "crypto_config: invalid digest name %s", cp);
+ else
+ crypto_nid = nid;
break;
}
- crypto_flags |= CRYPTO_FLAG_ENAB;
}
# else
int ntp_crypto_bs_pubkey;
diff --git a/ntpd/ntp_data_structures.c b/ntpd/ntp_data_structures.c
new file mode 100644
index 000000000000..fb21529be56b
--- /dev/null
+++ b/ntpd/ntp_data_structures.c
@@ -0,0 +1,199 @@
+/* ntp_data_structures.c
+ *
+ * This file contains the data structures used by the ntp configuration
+ * code and the discrete event simulator.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Copyright (c) 2006
+ */
+
+
+#include <stdlib.h> /* Needed for malloc */
+#include "ntp_data_structures.h"
+#include "ntp_stdlib.h"
+
+/* Priority Queue
+ * --------------
+ * Define a priority queue in which the relative priority of the elements
+ * is determined by a function 'get_order' which is supplied to the
+ * priority_queue
+ */
+
+
+queue *create_priority_queue(int (*get_order)(void *, void *))
+{
+ queue *my_queue = (queue *) emalloc(sizeof(queue));
+ my_queue->get_order = get_order;
+ my_queue->front = NULL;
+ my_queue->no_of_elements = 0;
+ return my_queue;
+}
+
+
+/* Define a function to "destroy" a priority queue, freeing-up
+ * all the allocated resources in the process
+ */
+
+void destroy_queue(queue *my_queue)
+{
+ node *temp = NULL;
+
+ /* Empty out the queue elements if they are not already empty */
+ while (my_queue->front != NULL) {
+ temp = my_queue->front;
+ my_queue->front = my_queue->front->node_next;
+ free(temp);
+ }
+
+ /* Now free the queue */
+ free(my_queue);
+}
+
+
+/* Define a function to allocate memory for one element
+ * of the queue. The allocated memory consists of size
+ * bytes plus the number of bytes needed for bookkeeping
+ */
+
+void *get_node(size_t size)
+{
+ node *new_node = emalloc(sizeof(*new_node) + size);
+ new_node->node_next = NULL;
+ return new_node + 1;
+}
+
+/* Define a function to free the allocated memory for a queue node */
+void free_node(void *my_node)
+{
+ node *old_node = my_node;
+ free(old_node - 1);
+}
+
+
+void *
+next_node(
+ void *pv
+ )
+{
+ node *pn;
+
+ pn = pv;
+ pn--;
+
+ if (pn->node_next == NULL)
+ return NULL;
+
+ return pn->node_next + 1;
+}
+
+
+/* Define a function to check if the queue is empty. */
+int empty(queue *my_queue)
+{
+ return (!my_queue || !my_queue->front);
+}
+
+
+void *
+queue_head(
+ queue *q
+ )
+{
+ if (NULL == q || NULL == q->front)
+ return NULL;
+
+ return q->front + 1;
+}
+
+
+/* Define a function to add an element to the priority queue.
+ * The element is added according to its priority -
+ * relative priority is given by the get_order function
+ */
+queue *enqueue(queue *my_queue, void *my_node)
+{
+ node *new_node = ((node *) my_node) - 1;
+ node *i = NULL;
+ node *j = my_queue->front;
+
+ while (j != NULL && ((*my_queue->get_order)(new_node + 1, j + 1) > 0)) {
+ i = j;
+ j = j->node_next;
+ }
+
+ if (i == NULL) { /* Insert at beginning of the queue */
+ new_node->node_next = my_queue->front;
+ my_queue->front = new_node;
+ }
+ else { /* Insert Elsewhere, including the end */
+ new_node->node_next = i->node_next;
+ i->node_next = new_node;
+ }
+
+ ++my_queue->no_of_elements;
+ return my_queue;
+}
+
+
+/* Define a function to dequeue the first element from the priority
+ * queue and return it
+ */
+
+void *dequeue(queue *my_queue)
+{
+ node *my_node = my_queue->front;
+ if (my_node != NULL) {
+ my_queue->front = my_node->node_next;
+ --my_queue->no_of_elements;
+ return (void *)(my_node + 1);
+ }
+ else
+ return NULL;
+}
+
+/* Define a function that returns the number of elements in the
+ * priority queue
+ */
+int get_no_of_elements(queue *my_queue)
+{
+ return my_queue->no_of_elements;
+}
+
+/* Define a function to append a queue onto another.
+ * Note: there is a faster way (O(1) as opposed to O(n))
+ * to do this for simple (FIFO) queues, but we can't rely on
+ * that for priority queues. (Given the current representation)
+ *
+ * I don't anticipate this to be a problem. If it does turn
+ * out to be a bottleneck, I will consider replacing the
+ * current implementation with a binomial or fibonacci heap.
+ */
+
+void append_queue(queue *q1, queue *q2)
+{
+ while (!empty(q2))
+ enqueue(q1, dequeue(q2));
+ destroy_queue(q2);
+}
+
+/* FIFO Queue
+ * ----------
+ * Use the priority queue to create a traditional FIFO queue.
+ * The only extra function needed is the create_queue
+ */
+
+/* C is not Lisp and does not allow anonymous lambda functions :-(.
+ * So define a get_fifo_order function here
+ */
+
+int get_fifo_order(void *el1, void *el2)
+{ return 1;
+}
+
+/* Define a function to create a FIFO queue */
+
+queue *create_queue()
+{ return create_priority_queue(get_fifo_order);
+}
diff --git a/ntpd/ntp_filegen.c b/ntpd/ntp_filegen.c
index 932d1b6f1231..b7b04bdbab6d 100644
--- a/ntpd/ntp_filegen.c
+++ b/ntpd/ntp_filegen.c
@@ -44,34 +44,46 @@
*/
#define SUFFIX_SEP '.'
+static void filegen_open (FILEGEN *, u_long);
+static int valid_fileref (const char *, const char *);
+static void filegen_init (const char *, const char *, FILEGEN *);
+#ifdef DEBUG
+static void filegen_uninit (FILEGEN *);
+#endif /* DEBUG */
+
+
/*
- * other constants
+ * filegen_init
*/
-#define FGEN_AGE_SECS (24*60*60) /* life time of FILEGEN_AGE in seconds */
-static void filegen_open P((FILEGEN *, u_long));
-static int valid_fileref P((char *, char *));
-#ifdef UNUSED
-static FILEGEN *filegen_unregister P((char *));
-#endif /* UNUSED */
+static void
+filegen_init(
+ const char * prefix,
+ const char * basename,
+ FILEGEN * fgp
+ )
+{
+ fgp->fp = NULL;
+ fgp->prefix = prefix; /* Yes, this is TOTALLY lame! */
+ fgp->basename = estrdup(basename);
+ fgp->id = 0;
+ fgp->type = FILEGEN_DAY;
+ fgp->flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
+}
-static void filegen_init P((char *, const char *, FILEGEN *));
/*
- * filegen_init
+ * filegen_uninit - free memory allocated by filegen_init
*/
-
+#ifdef DEBUG
static void
-filegen_init(char *prefix, const char *basename, FILEGEN *fp)
+filegen_uninit(
+ FILEGEN * fgp
+ )
{
- fp->fp = NULL;
- fp->prefix = prefix; /* Yes, this is TOTALLY lame! */
- fp->basename = (char*)emalloc(strlen(basename) + 1);
- strcpy(fp->basename, basename);
- fp->id = 0;
- fp->type = FILEGEN_DAY;
- fp->flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
+ free(fgp->basename);
}
+#endif
/*
@@ -81,8 +93,8 @@ filegen_init(char *prefix, const char *basename, FILEGEN *fp)
static void
filegen_open(
- FILEGEN *gen,
- u_long newid
+ FILEGEN * gen,
+ u_long newid
)
{
char *filename;
@@ -92,70 +104,83 @@ filegen_open(
struct calendar cal;
len = strlen(gen->prefix) + strlen(gen->basename) + 1;
- basename = (char*)emalloc(len);
- sprintf(basename, "%s%s", gen->prefix, gen->basename);
+ basename = emalloc(len);
+ snprintf(basename, len, "%s%s", gen->prefix, gen->basename);
- switch(gen->type) {
- default:
- msyslog(LOG_ERR, "unsupported file generations type %d for \"%s\" - reverting to FILEGEN_NONE",
+ switch (gen->type) {
+
+ default:
+ msyslog(LOG_ERR,
+ "unsupported file generations type %d for "
+ "\"%s\" - reverting to FILEGEN_NONE",
gen->type, basename);
gen->type = FILEGEN_NONE;
-
- /*FALLTHROUGH*/
- case FILEGEN_NONE:
- filename = (char*)emalloc(len);
- sprintf(filename,"%s", basename);
+ /* fall through to FILEGEN_NONE */
+
+ case FILEGEN_NONE:
+ filename = estrdup(basename);
break;
- case FILEGEN_PID:
- filename = (char*)emalloc(len + 1 + 1 + 10);
- sprintf(filename,"%s%c#%ld", basename, SUFFIX_SEP, newid);
+ case FILEGEN_PID:
+ filename = emalloc(len + 1 + 1 + 10);
+ snprintf(filename, len + 1 + 1 + 10,
+ "%s%c#%ld",
+ basename, SUFFIX_SEP, newid);
break;
-
- case FILEGEN_DAY:
- /* You can argue here in favor of using MJD, but
- * I would assume it to be easier for humans to interpret dates
- * in a format they are used to in everyday life.
+
+ case FILEGEN_DAY:
+ /*
+ * You can argue here in favor of using MJD, but I
+ * would assume it to be easier for humans to interpret
+ * dates in a format they are used to in everyday life.
*/
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4 + 2 + 2);
- sprintf(filename, "%s%c%04d%02d%02d",
- basename, SUFFIX_SEP, cal.year, cal.month, cal.monthday);
+ caljulian(newid, &cal);
+ filename = emalloc(len + 1 + 4 + 2 + 2);
+ snprintf(filename, len + 1 + 4 + 2 + 2,
+ "%s%c%04d%02d%02d",
+ basename, SUFFIX_SEP,
+ cal.year, cal.month, cal.monthday);
break;
-
- case FILEGEN_WEEK:
+
+ case FILEGEN_WEEK:
/*
* This is still a hack
* - the term week is not correlated to week as it is used
* normally - it just refers to a period of 7 days
* starting at Jan 1 - 'weeks' are counted starting from zero
*/
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4 + 1 + 2);
- sprintf(filename, "%s%c%04dw%02d",
- basename, SUFFIX_SEP, cal.year, cal.yearday / 7);
+ caljulian(newid, &cal);
+ filename = emalloc(len + 1 + 4 + 1 + 2);
+ snprintf(filename, len + 1 + 4 + 1 + 2,
+ "%s%c%04dw%02d",
+ basename, SUFFIX_SEP,
+ cal.year, cal.yearday / 7);
break;
- case FILEGEN_MONTH:
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4 + 2);
- sprintf(filename, "%s%c%04d%02d",
- basename, SUFFIX_SEP, cal.year, cal.month);
+ case FILEGEN_MONTH:
+ caljulian(newid, &cal);
+ filename = emalloc(len + 1 + 4 + 2);
+ snprintf(filename, len + 1 + 4 + 2,
+ "%s%c%04d%02d",
+ basename, SUFFIX_SEP, cal.year, cal.month);
break;
- case FILEGEN_YEAR:
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4);
- sprintf(filename, "%s%c%04d", basename, SUFFIX_SEP, cal.year);
+ case FILEGEN_YEAR:
+ caljulian(newid, &cal);
+ filename = emalloc(len + 1 + 4);
+ snprintf(filename, len + 1 + 4,
+ "%s%c%04d",
+ basename, SUFFIX_SEP, cal.year);
break;
- case FILEGEN_AGE:
- filename = (char*)emalloc(len + 1 + 2 + 10);
- sprintf(filename, "%s%ca%08ld", basename, SUFFIX_SEP, newid);
- break;
+ case FILEGEN_AGE:
+ filename = emalloc(len + 1 + 2 + 10);
+ snprintf(filename, len + 1 + 2 + 10,
+ "%s%ca%08ld",
+ basename, SUFFIX_SEP, newid);
}
- if (gen->type != FILEGEN_NONE) {
+ if (FILEGEN_NONE != gen->type) {
/*
* check for existence of a file with name 'basename'
* as we disallow such a file
@@ -177,14 +202,18 @@ filegen_open(
/*
* Oh, it is not linked - try to save it
*/
- char *savename = (char*)emalloc(len + 1 + 1 + 10 + 10);
- sprintf(savename, "%s%c%dC%lu",
- basename,
- SUFFIX_SEP,
- (int) getpid(),
- (u_long)conflicts++);
+ char *savename;
+
+ savename = emalloc(len + 1 + 1 + 10 + 10);
+ snprintf(savename, len + 1 + 1 + 10 + 10,
+ "%s%c%dC%lu",
+ basename, SUFFIX_SEP,
+ (int)getpid(), conflicts++);
+
if (rename(basename, savename) != 0)
- msyslog(LOG_ERR," couldn't save %s: %m", basename);
+ msyslog(LOG_ERR,
+ "couldn't save %s: %m",
+ basename);
free(savename);
} else {
/*
@@ -199,22 +228,28 @@ filegen_open(
delete(basename) != 0
#endif
)
- msyslog(LOG_ERR, "couldn't unlink %s: %m", basename);
+ msyslog(LOG_ERR,
+ "couldn't unlink %s: %m",
+ basename);
}
} else {
/*
* Ehh? Not a regular file ?? strange !!!!
*/
- msyslog(LOG_ERR, "expected regular file for %s (found mode 0%lo)",
- basename, (unsigned long)stats.st_mode);
+ msyslog(LOG_ERR,
+ "expected regular file for %s "
+ "(found mode 0%lo)",
+ basename,
+ (unsigned long)stats.st_mode);
}
} else {
/*
* stat(..) failed, but it is absolutely correct for
* 'basename' not to exist
*/
- if (errno != ENOENT)
- msyslog(LOG_ERR,"stat(%s) failed: %m", basename);
+ if (ENOENT != errno)
+ msyslog(LOG_ERR, "stat(%s) failed: %m",
+ basename);
}
}
@@ -223,13 +258,10 @@ filegen_open(
*/
fp = fopen(filename, "a");
-#ifdef DEBUG
- if (debug > 3)
- printf("opening filegen (type=%d/id=%lu) \"%s\"\n",
- gen->type, (u_long)newid, filename);
-#endif
+ DPRINTF(4, ("opening filegen (type=%d/id=%lu) \"%s\"\n",
+ gen->type, newid, filename));
- if (fp == NULL) {
+ if (NULL == fp) {
/* open failed -- keep previous state
*
* If the file was open before keep the previous generation.
@@ -239,11 +271,12 @@ filegen_open(
* ignore errors due to missing directories
*/
- if (errno != ENOENT)
- msyslog(LOG_ERR, "can't open %s: %m", filename);
+ if (ENOENT != errno)
+ msyslog(LOG_ERR, "can't open %s: %m", filename);
} else {
- if (gen->fp != NULL) {
+ if (NULL != gen->fp) {
fclose(gen->fp);
+ gen->fp = NULL;
}
gen->fp = fp;
gen->id = newid;
@@ -268,8 +301,10 @@ filegen_open(
errno = 0; /* On VMS, don't support FGEN_FLAG_LINK */
#else /* not (VMS) / VXWORKS / WINNT ; DO THE LINK) */
if (link(filename, basename) != 0)
- if (errno != EEXIST)
- msyslog(LOG_ERR, "can't link(%s, %s): %m", filename, basename);
+ if (EEXIST != errno)
+ msyslog(LOG_ERR,
+ "can't link(%s, %s): %m",
+ filename, basename);
#endif /* SYS_WINNT || VXWORKS */
} /* flags & FGEN_FLAG_LINK */
} /* else fp == NULL */
@@ -289,35 +324,39 @@ filegen_open(
void
filegen_setup(
- FILEGEN *gen,
- u_long now
+ FILEGEN * gen,
+ u_long now
)
{
u_long new_gen = ~ (u_long) 0;
struct calendar cal;
if (!(gen->flag & FGEN_FLAG_ENABLED)) {
- if (gen->fp != NULL)
- fclose(gen->fp);
+ if (NULL != gen->fp) {
+ fclose(gen->fp);
+ gen->fp = NULL;
+ }
return;
}
switch (gen->type) {
- case FILEGEN_NONE:
- if (gen->fp != NULL) return; /* file already open */
+
+ case FILEGEN_NONE:
+ if (NULL != gen->fp)
+ return; /* file already open */
break;
-
- case FILEGEN_PID:
+
+ case FILEGEN_PID:
new_gen = getpid();
break;
- case FILEGEN_DAY:
+ case FILEGEN_DAY:
caljulian(now, &cal);
cal.hour = cal.minute = cal.second = 0;
new_gen = caltontp(&cal);
break;
-
- case FILEGEN_WEEK:
+
+ case FILEGEN_WEEK:
/* Would be nice to have a calweekstart() routine */
/* so just use a hack ... */
/* just round time to integral 7 day period for actual year */
@@ -333,33 +372,32 @@ filegen_setup(
cal.hour = cal.minute = cal.second = 0;
new_gen = caltontp(&cal);
break;
-
- case FILEGEN_MONTH:
+
+ case FILEGEN_MONTH:
caljulian(now, &cal);
cal.yearday = (u_short) (cal.yearday - cal.monthday + 1);
cal.monthday = 1;
cal.hour = cal.minute = cal.second = 0;
new_gen = caltontp(&cal);
break;
-
- case FILEGEN_YEAR:
+
+ case FILEGEN_YEAR:
new_gen = calyearstart(now);
break;
- case FILEGEN_AGE:
- new_gen = current_time - (current_time % FGEN_AGE_SECS);
+ case FILEGEN_AGE:
+ new_gen = current_time - (current_time % SECSPERDAY);
break;
}
/*
* try to open file if not yet open
* reopen new file generation file on change of generation id
*/
- if (gen->fp == NULL || gen->id != new_gen) {
-#if DEBUG
- if (debug)
- printf("filegen %0x %lu %lu %lu\n", gen->type, now,
- gen->id, new_gen);
-#endif
+ if (NULL == gen->fp || gen->id != new_gen) {
+
+ DPRINTF(1, ("filegen %0x %lu %lu %lu\n",
+ gen->type, now, gen->id, new_gen));
+
filegen_open(gen, new_gen);
}
}
@@ -370,41 +408,49 @@ filegen_setup(
*/
void
filegen_config(
- FILEGEN *gen,
- char *basename,
- u_int type,
- u_int flag
+ FILEGEN * gen,
+ const char * basename,
+ u_int type,
+ u_int flag
)
{
+ int file_existed = 0;
+
/*
* if nothing would be changed...
*/
- if ((basename == gen->basename || strcmp(basename,gen->basename) == 0) &&
- type == gen->type &&
- flag == gen->flag)
- return;
+ if ((strcmp(basename, gen->basename) == 0) && type == gen->type
+ && flag == gen->flag)
+ return;
/*
* validate parameters
*/
- if (!valid_fileref(gen->prefix,basename))
- return;
+ if (!valid_fileref(gen->prefix, basename))
+ return;
- if (gen->fp != NULL)
- fclose(gen->fp);
+ if (NULL != gen->fp) {
+ fclose(gen->fp);
+ gen->fp = NULL;
+ file_existed = 1;
+ }
-#ifdef DEBUG
- if (debug > 2)
- printf("configuring filegen:\n\tprefix:\t%s\n\tbasename:\t%s -> %s\n\ttype:\t%d -> %d\n\tflag: %x -> %x\n",
- gen->prefix, gen->basename, basename, gen->type, type, gen->flag, flag);
-#endif
- if (gen->basename != basename || strcmp(gen->basename, basename) != 0) {
+ DPRINTF(3, ("configuring filegen:\n"
+ "\tprefix:\t%s\n"
+ "\tbasename:\t%s -> %s\n"
+ "\ttype:\t%d -> %d\n"
+ "\tflag: %x -> %x\n",
+ gen->prefix,
+ gen->basename, basename,
+ gen->type, type,
+ gen->flag, flag));
+
+ if (strcmp(gen->basename, basename) != 0) {
free(gen->basename);
- gen->basename = (char*)emalloc(strlen(basename) + 1);
- strcpy(gen->basename, basename);
+ gen->basename = estrdup(basename);
}
- gen->type = (u_char) type;
- gen->flag = (u_char) flag;
+ gen->type = (u_char)type;
+ gen->flag = (u_char)flag;
/*
* make filegen use the new settings
@@ -412,7 +458,7 @@ filegen_config(
* is currently open
* otherwise the new settings will be used anyway at the next open
*/
- if (gen->fp != NULL) {
+ if (file_existed) {
l_fp now;
get_systime(&now);
@@ -427,8 +473,8 @@ filegen_config(
*/
static int
valid_fileref(
- char *prefix,
- char *basename
+ const char * prefix,
+ const char * basename
)
{
/*
@@ -440,24 +486,25 @@ valid_fileref(
* file system parts 'below' prefix may be
* specified without infringement of security
*
- * restricing prefix to legal values
+ * restricting prefix to legal values
* has to be ensured by other means
* (however, it would be possible to perform some checks here...)
*/
- register char *p = basename;
+ register const char *p = basename;
/*
* Just to catch, dumb errors opening up the world...
*/
- if (prefix == NULL || *prefix == '\0')
- return 0;
+ if (NULL == prefix || '\0' == *prefix)
+ return 0;
- if (basename == NULL)
- return 0;
+ if (NULL == basename)
+ return 0;
- for (p = basename; p; p = strchr(p, '/')) {
- if (*p == '.' && *(p+1) == '.' && (*(p+2) == '\0' || *(p+2) == '/'))
- return 0;
+ for (p = basename; p; p = strchr(p, DIR_SEP)) {
+ if ('.' == p[0] && '.' == p[1]
+ && ('\0' == p[2] || DIR_SEP == p[2]))
+ return 0;
}
return 1;
@@ -469,108 +516,101 @@ valid_fileref(
*/
static struct filegen_entry {
- char *name;
- FILEGEN *filegen;
- struct filegen_entry *next;
+ char * name;
+ FILEGEN * filegen;
+ struct filegen_entry * next;
} *filegen_registry = NULL;
FILEGEN *
filegen_get(
- char *name
+ const char * name
)
{
struct filegen_entry *f = filegen_registry;
- while(f) {
+ while (f) {
if (f->name == name || strcmp(name, f->name) == 0) {
-#ifdef XXX /* this gives the Alpha compiler fits */
- if (debug > 3)
- printf("filegen_get(\"%s\") = %x\n", name,
- (u_int)f->filegen);
-#endif
+ DPRINTF(4, ("filegen_get(%s) = %p\n",
+ name, f->filegen));
return f->filegen;
}
f = f->next;
}
-#ifdef DEBUG
- if (debug > 3)
- printf("filegen_get(\"%s\") = NULL\n", name);
-#endif
+ DPRINTF(4, ("filegen_get(%s) = NULL\n", name));
return NULL;
}
+
void
filegen_register(
- char *prefix,
- const char *name,
- FILEGEN *filegen
+ const char * prefix,
+ const char * name,
+ FILEGEN * filegen
)
{
- struct filegen_entry **f = &filegen_registry;
+ struct filegen_entry **ppfe;
-#ifdef XXX /* this gives the Alpha compiler fits */
- if (debug > 3)
- printf("filegen_register(\"%s\",%x)\n", name, (u_int)filegen);
-#endif
+ DPRINTF(4, ("filegen_register(%s, %p)\n", name, filegen));
filegen_init(prefix, name, filegen);
- while (*f) {
- if ((*f)->name == name || strcmp(name, (*f)->name) == 0) {
-#ifdef XXX /* this gives the Alpha compiler fits */
- if (debug > 4) {
- printf("replacing filegen %x\n", (u_int)(*f)->filegen);
- }
-#endif
- (*f)->filegen = filegen;
+ ppfe = &filegen_registry;
+ while (NULL != *ppfe) {
+ if ((*ppfe)->name == name
+ || !strcmp((*ppfe)->name, name)) {
+
+ DPRINTF(5, ("replacing filegen %p\n",
+ (*ppfe)->filegen));
+
+ (*ppfe)->filegen = filegen;
return;
}
- f = &((*f)->next);
+ ppfe = &((*ppfe)->next);
}
- *f = (struct filegen_entry *) emalloc(sizeof(struct filegen_entry));
- if (*f) {
- (*f)->next = NULL;
- (*f)->name = (char*)emalloc(strlen(name) + 1);
- strcpy((*f)->name, name);
- (*f)->filegen = filegen;
-#ifdef DEBUG
- if (debug > 5) {
- printf("adding new filegen\n");
- }
-#endif
- }
+ *ppfe = emalloc(sizeof **ppfe);
+
+ (*ppfe)->next = NULL;
+ (*ppfe)->name = estrdup(name);
+ (*ppfe)->filegen = filegen;
+
+ DPRINTF(6, ("adding new filegen\n"));
return;
}
-#ifdef UNUSED
-static FILEGEN *
+
+/*
+ * filegen_unregister frees memory allocated by filegen_register for
+ * name.
+ */
+#ifdef DEBUG
+void
filegen_unregister(
char *name
)
{
- struct filegen_entry **f = &filegen_registry;
-
-#ifdef DEBUG
- if (debug > 3)
- printf("filegen_unregister(\"%s\")\n", name);
-#endif
-
- while (*f) {
- if (strcmp((*f)->name,name) == 0) {
- struct filegen_entry *ff = *f;
- FILEGEN *fg;
+ struct filegen_entry ** ppfe;
+ struct filegen_entry * pfe;
+ FILEGEN * fg;
- *f = (*f)->next;
- fg = ff->filegen;
- free(ff->name);
- free(ff);
- return fg;
+ DPRINTF(4, ("filegen_unregister(%s)\n", name));
+
+ ppfe = &filegen_registry;
+
+ while (NULL != *ppfe) {
+ if ((*ppfe)->name == name
+ || !strcmp((*ppfe)->name, name)) {
+ pfe = *ppfe;
+ *ppfe = (*ppfe)->next;
+ fg = pfe->filegen;
+ free(pfe->name);
+ free(pfe);
+ filegen_uninit(fg);
+ break;
}
- f = &((*f)->next);
+ ppfe = &((*ppfe)->next);
}
- return NULL;
}
-#endif /* UNUSED */
+#endif /* DEBUG */
diff --git a/ntpd/ntp_intres.c b/ntpd/ntp_intres.c
index 5facc85693c4..58f54954b7f2 100644
--- a/ntpd/ntp_intres.c
+++ b/ntpd/ntp_intres.c
@@ -20,25 +20,53 @@
# include <config.h>
#endif
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_request.h"
-#include "ntp_stdlib.h"
-#include "ntp_syslog.h"
+#include "ntp_intres.h"
+
+#ifndef NO_INTRES
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
/**/
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
#include <arpa/inet.h>
/**/
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h> /* MAXHOSTNAMELEN (often) */
#endif
+#if !defined(HAVE_RES_INIT) && defined(HAVE___RES_INIT)
+# define HAVE_RES_INIT
+#endif
+
+#if defined(HAVE_RESOLV_H) && defined(HAVE_RES_INIT)
+# ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h> /* DNS HEADER struct */
+# endif
+# ifdef HAVE_NETDB_H
+# include <netdb.h>
+# endif
+# include <resolv.h>
+#endif
+
+#ifdef RES_TIMEOUT
+#undef RES_TIMEOUT /* resolv.h has one, we want ours */
+#endif
+
+#include "ntp_machine.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_request.h"
+#include "ntp_stdlib.h"
+#include "ntp_syslog.h"
+#include "ntp_config.h"
+
#include <isc/net.h>
#include <isc/result.h>
@@ -50,9 +78,12 @@
*/
struct conf_entry {
struct conf_entry *ce_next;
- char *ce_name; /* name we are trying to resolve */
- struct conf_peer ce_config; /* configuration info for peer */
- struct sockaddr_storage peer_store; /* address info for both fams */
+ char *ce_name; /* name to resolve */
+ struct conf_peer ce_config; /* config info for peer */
+ int no_needed; /* number of addresses needed (pool) */
+ /* no_needed isn't used yet: It's needed to fix bug-975 */
+ int type; /* -4 and -6 flags */
+ sockaddr_u peer_store; /* address info for both fams */
};
#define ce_peeraddr ce_config.peeraddr
#define ce_peeraddr6 ce_config.peeraddr6
@@ -95,7 +126,6 @@ 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 */
/*
@@ -111,15 +141,17 @@ static int resolve_value; /* next value of resolve timer */
* is supposed to consist of entries in the following order
*/
#define TOK_HOSTNAME 0
-#define TOK_HMODE 1
-#define TOK_VERSION 2
-#define TOK_MINPOLL 3
-#define TOK_MAXPOLL 4
-#define TOK_FLAGS 5
-#define TOK_TTL 6
-#define TOK_KEYID 7
-#define TOK_KEYSTR 8
-#define NUMTOK 9
+#define TOK_NEEDED 1
+#define TOK_TYPE 2
+#define TOK_HMODE 3
+#define TOK_VERSION 4
+#define TOK_MINPOLL 5
+#define TOK_MAXPOLL 6
+#define TOK_FLAGS 7
+#define TOK_TTL 8
+#define TOK_KEYID 9
+#define TOK_KEYSTR 10
+#define NUMTOK 11
#define MAXLINESIZE 512
@@ -132,21 +164,24 @@ static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */
/* stuff to be filled in by caller */
keyid_t req_keyid; /* request keyid */
+int req_keytype; /* OpenSSL NID such as NID_md5 */
+size_t req_hashlen; /* digest size for req_keytype */
char *req_file; /* name of the file with configuration info */
/* end stuff to be filled in */
-static void checkparent P((void));
-static void removeentry P((struct conf_entry *));
-static void addentry P((char *, int, int, int, int, u_int,
- int, keyid_t, char *));
-static int findhostaddr P((struct conf_entry *));
-static void openntp P((void));
-static int request P((struct conf_peer *));
-static char * nexttoken P((char **));
-static void readconf P((FILE *, char *));
-static void doconfigure P((int));
+static void checkparent (void);
+static struct conf_entry *
+ removeentry (struct conf_entry *);
+static void addentry (char *, int, int, int, int, int, int, u_int,
+ int, keyid_t, char *);
+static int findhostaddr (struct conf_entry *);
+static void openntp (void);
+static int request (struct conf_peer *);
+static char * nexttoken (char **);
+static void readconf (FILE *, char *);
+static void doconfigure (int);
struct ntp_res_t_pkt { /* Tagged packet: */
void *tag; /* For the caller */
@@ -168,7 +203,7 @@ struct ntp_res_c_pkt { /* Control packet: */
};
-static void resolver_exit P((int));
+static void resolver_exit (int);
/*
* Call here instead of just exiting
@@ -179,7 +214,7 @@ static void resolver_exit (int code)
#ifdef SYS_WINNT
CloseHandle(ResolverEventHandle);
ResolverEventHandle = NULL;
- ExitThread(code); /* Just to kill the thread not the process */
+ _endthreadex(code); /* Just to kill the thread not the process */
#else
exit(code); /* kill the forked process */
#endif
@@ -211,12 +246,13 @@ void
ntp_intres(void)
{
FILE *in;
- struct timeval tv;
- fd_set fdset;
#ifdef SYS_WINNT
DWORD rc;
#else
- int rc;
+ int rc;
+ struct timeval tv;
+ fd_set fdset;
+ int time_left;
#endif
#ifdef DEBUG
@@ -248,9 +284,12 @@ ntp_intres(void)
(void) fclose(in);
#ifdef DEBUG
- if (!debug )
+ if (!debug)
#endif
- (void) unlink(req_file);
+ if (unlink(req_file))
+ msyslog(LOG_WARNING,
+ "unable to remove intres request file %s, %m",
+ req_file);
/*
* Set up the timers to do first shot immediately.
@@ -304,20 +343,35 @@ ntp_intres(void)
resolver_exit(1);
#else /* not SYS_WINNT */
- tv.tv_sec = ALARM_TIME;
- tv.tv_usec = 0;
- FD_ZERO(&fdset);
- FD_SET(resolver_pipe_fd[0], &fdset);
- rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
+ /* Bug 1386: fork() in NetBSD leaves timers running. */
+ /* So we need to retry select on EINTR */
+ time_left = ALARM_TIME;
+ while (time_left > 0) {
+ tv.tv_sec = time_left;
+ tv.tv_usec = 0;
+ FD_ZERO(&fdset);
+ FD_SET(resolver_pipe_fd[0], &fdset);
+ rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
+
+ if (rc == 0) /* normal timeout */
+ break;
- if (rc > 0) { /* parent process has written to the pipe */
+ if (rc > 0) { /* parent process has written to the pipe */
read(resolver_pipe_fd[0], (char *)&rc, sizeof(rc)); /* make pipe empty */
resolve_timer = 0; /* retry resolving immediately */
- continue;
- }
+ break;
+ }
- if ( rc < 0 ) /* select() returned error */
+ if ( rc < 0 ) { /* select() returned error */
+ if (errno == EINTR) { /* Timer went off */
+ time_left -= (1<<EVENT_TIMEOUT);
+ continue; /* try again */
+ }
+ msyslog(LOG_ERR, "ntp_intres: Error from select: %s",
+ strerror(errno));
resolver_exit(1);
+ }
+ }
#endif
/* normal timeout, keep on waiting */
@@ -329,6 +383,21 @@ ntp_intres(void)
}
+#ifdef SYS_WINNT
+/*
+ * ntp_intres_thread wraps the slightly different interface of Windows
+ * thread functions and ntp_intres
+ */
+unsigned WINAPI
+ntp_intres_thread(void *UnusedThreadArg)
+{
+ UNUSED_ARG(UnusedThreadArg);
+
+ ntp_intres();
+ return 0;
+}
+#endif /* SYS_WINNT */
+
/*
* checkparent - see if our parent process is still running
@@ -361,26 +430,32 @@ checkparent(void)
/*
* removeentry - we are done with an entry, remove it from the list
*/
-static void
+static struct conf_entry *
removeentry(
struct conf_entry *entry
)
{
register struct conf_entry *ce;
+ struct conf_entry *next_ce;
ce = confentries;
- if (ce == entry) {
+ if (ce == entry)
confentries = ce->ce_next;
- return;
- }
-
- while (ce != NULL) {
- if (ce->ce_next == entry) {
- ce->ce_next = entry->ce_next;
- return;
+ else
+ while (ce != NULL) {
+ if (ce->ce_next == entry) {
+ ce->ce_next = entry->ce_next;
+ break;
+ }
+ ce = ce->ce_next;
}
- ce = ce->ce_next;
- }
+
+ next_ce = entry->ce_next;
+ if (entry->ce_name != NULL)
+ free(entry->ce_name);
+ free(entry);
+
+ return next_ce;
}
@@ -390,6 +465,8 @@ removeentry(
static void
addentry(
char *name,
+ int no_needed,
+ int type,
int mode,
int version,
int minpoll,
@@ -400,36 +477,34 @@ addentry(
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);
+ "intres: <%s> %d %d %d %d %d %d %x %d %x %s",
+ name, no_needed, type, mode, version,
+ minpoll, maxpoll, flags, ttl, keyid, keystr);
#endif
- len = strlen(name) + 1;
- cp = (char *)emalloc(len);
- memmove(cp, name, len);
-
- ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
- ce->ce_name = cp;
+ ce = emalloc(sizeof(*ce));
+ ce->ce_name = estrdup(name);
ce->ce_peeraddr = 0;
#ifdef ISC_PLATFORM_HAVEIPV6
ce->ce_peeraddr6 = in6addr_any;
#endif
- ANYSOCK(&ce->peer_store);
+ ZERO_SOCK(&ce->peer_store);
ce->ce_hmode = (u_char)mode;
ce->ce_version = (u_char)version;
ce->ce_minpoll = (u_char)minpoll;
ce->ce_maxpoll = (u_char)maxpoll;
+ ce->no_needed = no_needed; /* Not used after here. */
+ /* Start of fixing bug-975 */
+ ce->type = type;
ce->ce_flags = (u_char)flags;
ce->ce_ttl = (u_char)ttl;
ce->ce_keyid = keyid;
- strncpy((char *)ce->ce_keystr, keystr, MAXFILENAME);
+ strncpy(ce->ce_keystr, keystr, sizeof(ce->ce_keystr) - 1);
+ ce->ce_keystr[sizeof(ce->ce_keystr) - 1] = 0;
ce->ce_next = NULL;
if (confentries == NULL) {
@@ -466,13 +541,13 @@ findhostaddr(
checkparent(); /* make sure our guy is still running */
- if (entry->ce_name != NULL && !SOCKNUL(&entry->peer_store)) {
+ if (entry->ce_name != NULL && !SOCK_UNSPEC(&entry->peer_store)) {
/* HMS: Squawk? */
msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
return 1;
}
- if (entry->ce_name == NULL && SOCKNUL(&entry->peer_store)) {
+ if (entry->ce_name == NULL && SOCK_UNSPEC(&entry->peer_store)) {
msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
return 0;
}
@@ -482,25 +557,27 @@ findhostaddr(
entry->ce_name));
memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
+ hints.ai_family = entry->type;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
/*
- * If the IPv6 stack is not available look only for IPv4 addresses
+ * If IPv6 is not available look only for v4 addresses
*/
- if (isc_net_probeipv6() != ISC_R_SUCCESS)
+ if (!ipv6_works)
hints.ai_family = AF_INET;
-
error = getaddrinfo(entry->ce_name, NULL, &hints, &addr);
if (error == 0) {
- entry->peer_store = *((struct sockaddr_storage*)(addr->ai_addr));
- if (entry->peer_store.ss_family == AF_INET) {
+ entry->peer_store = *((sockaddr_u *)(addr->ai_addr));
+ if (IS_IPV4(&entry->peer_store)) {
entry->ce_peeraddr =
- GET_INADDR(entry->peer_store);
+ NSRCADR(&entry->peer_store);
entry->ce_config.v6_flag = 0;
} else {
entry->ce_peeraddr6 =
- GET_INADDR6(entry->peer_store);
+ SOCK_ADDR6(&entry->peer_store);
entry->ce_config.v6_flag = 1;
}
+ freeaddrinfo(addr);
}
} else {
DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
@@ -678,15 +755,21 @@ request(
struct conf_peer *conf
)
{
- fd_set fdset;
- struct timeval tvout;
+ struct sock_timeval tvout;
struct req_pkt reqpkt;
- l_fp ts;
+ size_t req_len;
+ size_t total_len; /* req_len plus keyid & digest */
+ fd_set fdset;
+ l_fp ts;
+ char * pch;
+ char * pchEnd;
+ l_fp * pts;
+ keyid_t *pkeyid;
int n;
#ifdef SYS_WINNT
- HANDLE hReadWriteEvent = NULL;
- BOOL ret;
- DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait;
+ HANDLE hReadWriteEvent = NULL;
+ BOOL ret;
+ DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait;
OVERLAPPED overlap;
#endif /* SYS_WINNT */
@@ -709,7 +792,7 @@ request(
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);
+ recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0);
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
}
@@ -717,34 +800,68 @@ request(
/*
* Make up a request packet with the configuration info
*/
- memset((char *)&reqpkt, 0, sizeof(reqpkt));
+ memset(&reqpkt, 0, sizeof(reqpkt));
reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
reqpkt.auth_seq = AUTH_SEQ(1, 0); /* authenticated, no seq */
reqpkt.implementation = IMPL_XNTPD; /* local implementation */
reqpkt.request = REQ_CONFIG; /* configure a new peer */
reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */
- reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));
+ reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(*conf));
/* 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!");
+ if (sizeof(*conf) > sizeof(reqpkt.data)) {
+ msyslog(LOG_ERR,
+ "Bletch: conf_peer is too big for reqpkt.data!");
resolver_exit(1);
}
- memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));
- reqpkt.keyid = htonl(req_keyid);
+ memcpy(reqpkt.data, conf, sizeof(*conf));
+
+ if (sys_authenticate && req_hashlen > 16) {
+ pch = reqpkt.data;
+ /* 32-bit alignment */
+ pch += (sizeof(*conf) + 3) & ~3;
+ pts = (void *)pch;
+ pkeyid = (void *)(pts + 1);
+ pchEnd = (void *)pkeyid;
+ req_len = pchEnd - (char *)&reqpkt;
+ pchEnd = (void *)(pkeyid + 1);
+ pchEnd += req_hashlen;
+ total_len = pchEnd - (char *)&reqpkt;
+ if (total_len > sizeof(reqpkt)) {
+ msyslog(LOG_ERR,
+ "intres total_len %lu limit is %lu (%lu octet digest)\n",
+ (u_long)total_len,
+ (u_long)sizeof(reqpkt),
+ (u_long)req_hashlen);
+ resolver_exit(1);
+ }
+ } else {
+ pts = &reqpkt.tstamp;
+ pkeyid = &reqpkt.keyid;
+ req_len = REQ_LEN_NOMAC;
+ }
+ *pkeyid = 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);
+ HTONL_FP(&ts, pts);
+ if (sys_authenticate) {
+ n = authencrypt(req_keyid, (void *)&reqpkt, req_len);
+ if ((size_t)n != req_hashlen + sizeof(reqpkt.keyid)) {
+ msyslog(LOG_ERR,
+ "intres maclen %d expected %lu\n",
+ n, (u_long)(req_hashlen +
+ sizeof(reqpkt.keyid)));
+ resolver_exit(1);
+ }
+ req_len += n;
+ }
/*
* Done. Send it.
*/
#ifndef SYS_WINNT
- n = send(sockfd, (char *)&reqpkt, (unsigned)(REQ_LEN_NOMAC + n), 0);
+ n = send(sockfd, (char *)&reqpkt, req_len, 0);
if (n < 0) {
msyslog(LOG_ERR, "send to NTP server failed: %m");
return 0; /* maybe should exit */
@@ -762,7 +879,7 @@ request(
*/
overlap.Offset = overlap.OffsetHigh = (DWORD)0;
overlap.hEvent = hReadWriteEvent;
- ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n,
+ ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, req_len,
NULL, (LPOVERLAPPED)&overlap);
if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
msyslog(LOG_ERR, "send to NTP server failed: %m");
@@ -780,7 +897,7 @@ request(
return 0;
}
#endif /* SYS_WINNT */
-
+
/*
* Wait for a response. A weakness of the mode 7 protocol used
@@ -800,23 +917,20 @@ request(
n = select(sockfd + 1, &fdset, (fd_set *)0,
(fd_set *)0, &tvout);
- if (n < 0)
- {
+ if (n < 0) {
if (errno != EINTR)
- msyslog(LOG_ERR, "select() fails: %m");
+ msyslog(LOG_ERR, "select() fails: %m");
return 0;
- }
- else if (n == 0)
- {
+ } else if (n == 0) {
#ifdef DEBUG
if (debug)
- msyslog(LOG_INFO, "select() returned 0.");
+ msyslog(LOG_INFO, "ntp_intres select() returned 0.");
#endif
return 0;
}
#ifndef SYS_WINNT
- n = recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
+ n = recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0);
if (n <= 0) {
if (n < 0) {
msyslog(LOG_ERR, "recv() fails: %m");
@@ -825,7 +939,7 @@ request(
continue;
}
#else /* Overlapped I/O used on non-blocking sockets on Windows NT */
- ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, (DWORD)REQ_LEN_MAC,
+ ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, sizeof(reqpkt),
NULL, (LPOVERLAPPED)&overlap);
if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
msyslog(LOG_ERR, "ReadFile() fails: %m");
@@ -929,34 +1043,36 @@ request(
/* success */
return 1;
+ case INFO_ERR_NODATA:
+ /*
+ * newpeer() refused duplicate association, no
+ * point in retrying so call it success.
+ */
+ return 1;
+
case INFO_ERR_IMPL:
msyslog(LOG_ERR,
- "ntpd reports implementation mismatch!");
+ "ntp_intres.request: implementation mismatch");
return 0;
case INFO_ERR_REQ:
msyslog(LOG_ERR,
- "ntpd says configuration request is unknown!");
+ "ntp_intres.request: request unknown");
return 0;
case INFO_ERR_FMT:
msyslog(LOG_ERR,
- "ntpd indicates a format error occurred!");
+ "ntp_intres.request: format error");
return 0;
- case INFO_ERR_NODATA:
- msyslog(LOG_ERR,
- "ntpd indicates no data available!");
- return 0;
-
case INFO_ERR_AUTH:
msyslog(LOG_ERR,
- "ntpd returns a permission denied error!");
+ "ntp_intres.request: permission denied");
return 0;
default:
msyslog(LOG_ERR,
- "ntpd returns unknown error code %d!", n);
+ "ntp_intres.request: unknown error code %d", n);
return 0;
}
}
@@ -1051,6 +1167,7 @@ readconf(
}
}
+#if 0 /* paranoid checking - these are done in newpeer() */
if (intval[TOK_HMODE] != MODE_ACTIVE &&
intval[TOK_HMODE] != MODE_CLIENT &&
intval[TOK_HMODE] != MODE_BROADCAST) {
@@ -1065,31 +1182,30 @@ readconf(
intval[TOK_VERSION], name);
resolver_exit(1);
}
- if (intval[TOK_MINPOLL] < NTP_MINPOLL ||
+ if (intval[TOK_MINPOLL] < ntp_minpoll ||
intval[TOK_MINPOLL] > NTP_MAXPOLL) {
+
msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",
intval[TOK_MINPOLL], name);
resolver_exit(1);
}
- if (intval[TOK_MAXPOLL] < NTP_MINPOLL ||
+ if (intval[TOK_MAXPOLL] < ntp_minpoll ||
intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",
intval[TOK_MAXPOLL], name);
resolver_exit(1);
}
- if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE | FLAG_PREFER |
- FLAG_NOSELECT | FLAG_BURST | FLAG_IBURST | FLAG_SKEY))
- != 0) {
+ if ((intval[TOK_FLAGS] & ~(FLAG_PREFER | FLAG_NOSELECT |
+ FLAG_BURST | FLAG_IBURST | FLAG_SKEY)) != 0) {
msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
intval[TOK_FLAGS], name);
resolver_exit(1);
}
+#endif /* end paranoid checking */
flags = 0;
- if (intval[TOK_FLAGS] & FLAG_AUTHENABLE)
- flags |= CONF_FLAG_AUTHENABLE;
if (intval[TOK_FLAGS] & FLAG_PREFER)
flags |= CONF_FLAG_PREFER;
if (intval[TOK_FLAGS] & FLAG_NOSELECT)
@@ -1098,15 +1214,20 @@ readconf(
flags |= CONF_FLAG_BURST;
if (intval[TOK_FLAGS] & FLAG_IBURST)
flags |= CONF_FLAG_IBURST;
+
+#ifdef OPENSSL
if (intval[TOK_FLAGS] & FLAG_SKEY)
flags |= CONF_FLAG_SKEY;
+#endif /* OPENSSL */
/*
* This is as good as we can check it. Add it in.
*/
- addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
- (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
- (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
+ addentry(token[TOK_HOSTNAME],
+ (int)intval[TOK_NEEDED], (int)intval[TOK_TYPE],
+ (int)intval[TOK_HMODE], (int)intval[TOK_VERSION],
+ (int)intval[TOK_MINPOLL], (int)intval[TOK_MAXPOLL],
+ flags, (int)intval[TOK_TTL],
intval[TOK_KEYID], token[TOK_KEYSTR]);
}
}
@@ -1121,7 +1242,6 @@ doconfigure(
)
{
register struct conf_entry *ce;
- register struct conf_entry *ceremove;
#ifdef DEBUG
if (debug > 1)
@@ -1129,6 +1249,10 @@ doconfigure(
dores ? "with" : "without" );
#endif
+#if defined(HAVE_RES_INIT)
+ if (dores) /* Reload /etc/resolv.conf - bug 1226 */
+ res_init();
+#endif
ce = confentries;
while (ce != NULL) {
#ifdef DEBUG
@@ -1137,27 +1261,30 @@ doconfigure(
"doconfigure: <%s> has peeraddr %s",
ce->ce_name, stoa(&ce->peer_store));
#endif
- if (dores && SOCKNUL(&(ce->peer_store))) {
+ if (dores && SOCK_UNSPEC(&ce->peer_store)) {
if (!findhostaddr(ce)) {
#ifndef IGNORE_DNS_ERRORS
msyslog(LOG_ERR,
"couldn't resolve `%s', giving up on it",
ce->ce_name);
- ceremove = ce;
- ce = ceremove->ce_next;
- removeentry(ceremove);
+ ce = removeentry(ce);
continue;
#endif
- }
+ } else if (!SOCK_UNSPEC(&ce->peer_store))
+ msyslog(LOG_INFO,
+ "DNS %s -> %s", ce->ce_name,
+ stoa(&ce->peer_store));
}
- if (!SOCKNUL(&ce->peer_store)) {
+ if (!SOCK_UNSPEC(&ce->peer_store)) {
if (request(&ce->ce_config)) {
- ceremove = ce;
- ce = ceremove->ce_next;
- removeentry(ceremove);
+ ce = removeentry(ce);
continue;
}
+ /*
+ * Failed case. Should bump counter and give
+ * up.
+ */
#ifdef DEBUG
if (debug > 1) {
msyslog(LOG_INFO,
@@ -1168,3 +1295,7 @@ doconfigure(
ce = ce->ce_next;
}
}
+
+#else /* NO_INTRES follows */
+int ntp_intres_nonempty_compilation_unit;
+#endif
diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c
index 5cf9f1d858d4..f5584462732f 100644
--- a/ntpd/ntp_io.c
+++ b/ntpd/ntp_io.c
@@ -7,41 +7,54 @@
# include <config.h>
#endif
+#include <stdio.h>
+#include <signal.h>
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
+# include <sys/sockio.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+
#include "ntp_machine.h"
#include "ntpd.h"
#include "ntp_io.h"
#include "iosignal.h"
+#include "ntp_lists.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
#include "ntp_request.h"
#include "ntp.h"
#include "ntp_unixtime.h"
+#include "ntp_assert.h"
+#include "ntpd-opts.h"
/* Don't include ISC's version of IPv6 variables and structures */
#define ISC_IPV6_H 1
+#include <isc/mem.h>
#include <isc/interfaceiter.h>
-#include <isc/list.h>
+#include <isc/netaddr.h>
#include <isc/result.h>
+#include <isc/sockaddr.h>
#ifdef SIM
#include "ntpsim.h"
#endif
-#include <stdio.h>
-#include <signal.h>
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif /* HAVE_SYS_PARAM_H */
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
-# include <sys/sockio.h>
-#endif
-#ifdef HAVE_SYS_UIO_H
-# include <sys/uio.h>
+#ifdef HAS_ROUTING_SOCKET
+# include <net/route.h>
+# ifdef HAVE_RTNETLINK
+# include <linux/rtnetlink.h>
+# endif
#endif
+
/*
* setsockopt does not always have the same arg declaration
* across all platforms. If it's not defined we make it empty
@@ -51,22 +64,28 @@
#define SETSOCKOPT_ARG_CAST
#endif
-/*
- * Set up some macros to look for IPv6 and IPv6 multicast
- */
-
-#if defined(ISC_PLATFORM_HAVEIPV6) && !defined(DISABLE_IPV6)
-
-#define INCLUDE_IPV6_SUPPORT
+extern int listen_to_virtual_ips;
-#if defined(INCLUDE_IPV6_SUPPORT) && defined(IPV6_JOIN_GROUP) && defined(IPV6_LEAVE_GROUP)
-#define INCLUDE_IPV6_MULTICAST_SUPPORT
+/*
+ * NIC rule entry
+ */
+typedef struct nic_rule_tag nic_rule;
+
+struct nic_rule_tag {
+ nic_rule * next;
+ nic_rule_action action;
+ nic_rule_match match_type;
+ char * if_name;
+ sockaddr_u addr;
+ int prefixlen;
+};
-#endif /* IPV6 Multicast Support */
-#endif /* IPv6 Support */
+/*
+ * NIC rule listhead. Entries are added at the head so that the first
+ * match in the list is the last matching rule specified.
+ */
+nic_rule *nic_rule_list;
-extern int listen_to_virtual_ips;
-extern const char *specific_interface;
#if defined(SO_TIMESTAMP) && defined(SCM_TIMESTAMP)
#if defined(CMSG_FIRSTHDR)
@@ -84,17 +103,6 @@ extern const char *specific_interface;
#include <transmitbuff.h>
#include <isc/win32os.h>
/*
- * Define this macro to control the behavior of connection
- * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823
- * for details.
- * NOTE: This requires that Windows 2000 systems install Service Pack 2
- * or later.
- */
-#ifndef SIO_UDP_CONNRESET
-#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
-#endif
-
-/*
* Windows C runtime ioctl() can't deal properly with sockets,
* map to ioctlsocket for this source file.
*/
@@ -124,8 +132,8 @@ extern const char *specific_interface;
volatile u_long packets_dropped; /* total number of packets dropped on reception */
volatile u_long packets_ignored; /* packets received on wild card interface */
volatile u_long packets_received; /* total number of packets received */
-u_long packets_sent; /* total number of packets sent */
-u_long packets_notsent; /* total number of packets which couldn't be sent */
+ u_long packets_sent; /* total number of packets sent */
+ u_long packets_notsent; /* total number of packets which couldn't be sent */
volatile u_long handler_calls; /* number of calls to interrupt handler */
volatile u_long handler_pkts; /* number of pkts received by handler */
@@ -134,13 +142,14 @@ u_long io_timereset; /* time counters were reset */
/*
* Interface stuff
*/
-struct interface *any_interface; /* default ipv4 interface */
-struct interface *any6_interface; /* default ipv6 interface */
-struct interface *loopback_interface; /* loopback ipv4 interface */
+endpt * any_interface; /* wildcard ipv4 interface */
+endpt * any6_interface; /* wildcard ipv6 interface */
+endpt * loopback_interface; /* loopback ipv4 interface */
+isc_boolean_t broadcast_client_enabled; /* is broadcast client enabled */
int ninterfaces; /* Total number of interfaces */
-volatile int disable_dynamic_updates; /* when set to != 0 dynamic updates won't happen */
+int disable_dynamic_updates; /* scan interfaces once only */
#ifdef REFCLOCK
/*
@@ -150,19 +159,14 @@ volatile int disable_dynamic_updates; /* when set to != 0 dynamic updates won'
static struct refclockio *refio;
#endif /* REFCLOCK */
-
-/*
- * Define what the possible "soft" errors can be. These are non-fatal returns
- * of various network related functions, like recv() and so on.
- *
- * For some reason, BSDI (and perhaps others) will sometimes return <0
- * from recv() but will have errno==0. This is broken, but we have to
- * work around it here.
- */
-#define SOFT_ERROR(e) ((e) == EAGAIN || \
- (e) == EWOULDBLOCK || \
- (e) == EINTR || \
- (e) == 0)
+#if defined(HAVE_IPTOS_SUPPORT)
+/* set IP_TOS to minimize packet delay */
+# if defined(IPTOS_PREC_INTERNETCONTROL)
+ unsigned int qos = IPTOS_PREC_INTERNETCONTROL;
+# else
+ unsigned int qos = IPTOS_LOWDELAY;
+# endif
+#endif
/*
* File descriptor masks etc. for call to select
@@ -173,44 +177,53 @@ int maxactivefd;
/*
* bit alternating value to detect verified interfaces during an update cycle
*/
-static u_char sys_interphase = 0;
+static u_short sys_interphase = 0;
-static struct interface *new_interface P((struct interface *));
-static void add_interface P((struct interface *));
-static int update_interfaces P((u_short, interface_receiver_t, void *));
-static void remove_interface P((struct interface *));
-static struct interface *create_interface P((u_short, struct interface *));
+static endpt * new_interface(endpt *);
+static void add_interface(endpt *);
+static int update_interfaces(u_short, interface_receiver_t,
+ void *);
+static void remove_interface(endpt *);
+static endpt * create_interface(u_short, endpt *);
-static int move_fd P((SOCKET));
+static int move_fd (SOCKET);
+static int is_wildcard_addr (const sockaddr_u *);
/*
* Multicast functions
*/
-static isc_boolean_t addr_ismulticast P((struct sockaddr_storage *));
+static isc_boolean_t addr_ismulticast (sockaddr_u *);
+static isc_boolean_t is_anycast (sockaddr_u *,
+ const char *);
+
/*
* Not all platforms support multicast
*/
#ifdef MCAST
-static isc_boolean_t socket_multicast_enable P((struct interface *, int, struct sockaddr_storage *));
-static isc_boolean_t socket_multicast_disable P((struct interface *, struct sockaddr_storage *));
+static isc_boolean_t socket_multicast_enable (endpt *, sockaddr_u *);
+static isc_boolean_t socket_multicast_disable(endpt *, sockaddr_u *);
#endif
#ifdef DEBUG
-static void print_interface P((struct interface *, char *, char *));
-#define DPRINT_INTERFACE(_LVL_, _ARGS_) do { if (debug >= (_LVL_)) { print_interface _ARGS_; } } while (0)
+static void interface_dump (const endpt *);
+static void sockaddr_dump (const sockaddr_u *);
+static void print_interface (const endpt *, char *, char *);
+#define DPRINT_INTERFACE(level, args) do { if (debug >= (level)) { print_interface args; } } while (0)
#else
-#define DPRINT_INTERFACE(_LVL_, _ARGS_) do {} while (0)
+#define DPRINT_INTERFACE(level, args) do {} while (0)
#endif
typedef struct vsock vsock_t;
enum desc_type { FD_TYPE_SOCKET, FD_TYPE_FILE };
struct vsock {
- SOCKET fd;
- enum desc_type type;
- ISC_LINK(vsock_t) link;
+ vsock_t * link;
+ SOCKET fd;
+ enum desc_type type;
};
+vsock_t *fd_list;
+
#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
/*
* async notification processing (e. g. routing sockets)
@@ -220,69 +233,82 @@ struct vsock {
* like e. g. routing sockets
*/
struct asyncio_reader {
- SOCKET fd; /* fd to be read */
- void *data; /* possibly local data */
+ struct asyncio_reader *link; /* the list this is being kept in */
+ SOCKET fd; /* fd to be read */
+ void *data; /* possibly local data */
void (*receiver)(struct asyncio_reader *); /* input handler */
- ISC_LINK(struct asyncio_reader) link; /* the list this is being kept in */
};
-ISC_LIST(struct asyncio_reader) asyncio_reader_list;
+struct asyncio_reader *asyncio_reader_list;
-static void delete_asyncio_reader P((struct asyncio_reader *));
-static struct asyncio_reader *new_asyncio_reader P((void));
-static void add_asyncio_reader P((struct asyncio_reader *, enum desc_type));
-static void remove_asyncio_reader P((struct asyncio_reader *));
+static void delete_asyncio_reader (struct asyncio_reader *);
+static struct asyncio_reader *new_asyncio_reader (void);
+static void add_asyncio_reader (struct asyncio_reader *, enum desc_type);
+static void remove_asyncio_reader (struct asyncio_reader *);
#endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
-static void init_async_notifications P((void));
-
-static int create_sockets P((u_short));
-static SOCKET open_socket P((struct sockaddr_storage *, int, int, struct interface *));
-static char * fdbits P((int, fd_set *));
-static void set_reuseaddr P((int));
-static isc_boolean_t socket_broadcast_enable P((struct interface *, SOCKET, struct sockaddr_storage *));
-static isc_boolean_t socket_broadcast_disable P((struct interface *, struct sockaddr_storage *));
+static void init_async_notifications (void);
-ISC_LIST(vsock_t) fd_list;
+static int addr_eqprefix (const sockaddr_u *, const sockaddr_u *,
+ int);
+static int addr_samesubnet (const sockaddr_u *, const sockaddr_u *,
+ const sockaddr_u *, const sockaddr_u *);
+static int create_sockets (u_short);
+static SOCKET open_socket (sockaddr_u *, int, int, endpt *);
+static char * fdbits (int, fd_set *);
+static void set_reuseaddr (int);
+static isc_boolean_t socket_broadcast_enable (struct interface *, SOCKET, sockaddr_u *);
+static isc_boolean_t socket_broadcast_disable (struct interface *, sockaddr_u *);
typedef struct remaddr remaddr_t;
struct remaddr {
- struct sockaddr_storage addr;
- struct interface *interface;
- ISC_LINK(remaddr_t) link;
+ remaddr_t * link;
+ sockaddr_u addr;
+ endpt * ep;
};
-ISC_LIST(remaddr_t) remoteaddr_list;
-
-ISC_LIST(struct interface) inter_list;
-
-static struct interface *wildipv4 = NULL;
-static struct interface *wildipv6 = NULL;
-
-static void add_fd_to_list P((SOCKET, enum desc_type));
-static void close_and_delete_fd_from_list P((SOCKET));
-static void add_addr_to_list P((struct sockaddr_storage *, struct interface *));
-static void delete_addr_from_list P((struct sockaddr_storage *));
-static struct interface *find_addr_in_list P((struct sockaddr_storage *));
-static struct interface *find_flagged_addr_in_list P((struct sockaddr_storage *, int));
-static void create_wildcards P((u_short));
-static isc_boolean_t address_okay P((struct interface *));
-static void convert_isc_if P((isc_interface_t *, struct interface *, u_short));
-static void delete_interface_from_list P((struct interface *));
-static struct interface *getinterface P((struct sockaddr_storage *, int));
-static struct interface *findlocalinterface P((struct sockaddr_storage *, int));
-static struct interface *findlocalcastinterface P((struct sockaddr_storage *, int));
+remaddr_t * remoteaddr_list;
+endpt * ep_list; /* complete endpt list */
+endpt * mc4_list; /* IPv4 mcast-capable unicast endpts */
+endpt * mc6_list; /* IPv6 mcast-capable unicast endpts */
+
+static endpt * wildipv4;
+static endpt * wildipv6;
+
+static void add_fd_to_list (SOCKET, enum desc_type);
+static endpt * find_addr_in_list (sockaddr_u *);
+static endpt * find_flagged_addr_in_list(sockaddr_u *, u_int32);
+static void delete_addr_from_list (sockaddr_u *);
+static void delete_interface_from_list(endpt *);
+static void close_and_delete_fd_from_list(SOCKET);
+static void add_addr_to_list (sockaddr_u *, endpt *);
+static void create_wildcards (u_short);
+static endpt * getinterface (sockaddr_u *, u_int32);
+static endpt * findlocalinterface (sockaddr_u *, int, int);
+static endpt * findclosestinterface (sockaddr_u *, int);
+#ifdef DEBUG
+static const char * action_text (nic_rule_action);
+#endif
+static nic_rule_action interface_action(char *, sockaddr_u *, u_int32);
+static void convert_isc_if (isc_interface_t *,
+ endpt *, u_short);
+static void calc_addr_distance(sockaddr_u *,
+ const sockaddr_u *,
+ const sockaddr_u *);
+static int cmp_addr_distance(const sockaddr_u *,
+ const sockaddr_u *);
/*
* Routines to read the ntp packets
*/
#if !defined(HAVE_IO_COMPLETION_PORT)
-static inline int read_network_packet P((SOCKET, struct interface *, l_fp));
-static inline int read_refclock_packet P((SOCKET, struct refclockio *, l_fp));
+static inline int read_network_packet (SOCKET, struct interface *, l_fp);
+static inline int read_refclock_packet (SOCKET, struct refclockio *, l_fp);
#endif
+
#ifdef SYS_WINNT
/*
* Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
@@ -296,11 +322,11 @@ static inline int read_refclock_packet P((SOCKET, struct refclockio *, l_fp)
*/
void
connection_reset_fix(
- SOCKET fd,
- struct sockaddr_storage *addr
+ SOCKET fd,
+ sockaddr_u * addr
)
{
- DWORD dwBytesReturned = 0;
+ DWORD dw;
BOOL bNewBehavior = FALSE;
DWORD status;
@@ -311,11 +337,11 @@ connection_reset_fix(
if (isc_win32os_majorversion() >= 5) {
status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
sizeof(bNewBehavior), NULL, 0,
- &dwBytesReturned, NULL, NULL);
+ &dw, NULL, NULL);
if (SOCKET_ERROR == status)
- netsyslog(LOG_ERR, "connection_reset_fix() "
- "failed for address %s: %m",
- stoa(addr));
+ msyslog(LOG_ERR,
+ "connection_reset_fix() failed for address %s: %m",
+ stoa(addr));
}
}
#endif
@@ -323,12 +349,12 @@ connection_reset_fix(
/*
* on Unix systems the stdio library typically
* makes use of file descriptors in the lower
- * integer range. stdio usually will make use
- * of the file descriptor in the range of
+ * integer range. stdio usually will make use
+ * of the file descriptors in the range of
* [0..FOPEN_MAX)
- * in order to keep this range clean for socket
+ * in order to keep this range clean, for socket
* file descriptors we attempt to move them above
- * FOPEM_MAX. This is not as easy as it sounds as
+ * FOPEN_MAX. This is not as easy as it sounds as
* FOPEN_MAX changes from implementation to implementation
* and may exceed to current file decriptor limits.
* We are using following strategy:
@@ -349,7 +375,10 @@ connection_reset_fix(
* allocation is possible or 0 is reached - at this
* point the algrithm will be disabled
*/
-static int move_fd(SOCKET fd)
+static int
+move_fd(
+ SOCKET fd
+ )
{
#if !defined(SYS_WINNT) && defined(F_DUPFD)
#ifndef FD_CHUNK
@@ -382,6 +411,8 @@ static int move_fd(SOCKET fd)
static SOCKET socket_boundary = -1;
SOCKET newfd;
+ NTP_REQUIRE((int)fd >= 0);
+
/*
* check whether boundary has be set up
* already
@@ -390,7 +421,8 @@ static int move_fd(SOCKET fd)
socket_boundary = max(0, min(getdtablesize() - FD_CHUNK,
min(FOPEN_MAX, FD_PREFERRED_SOCKBOUNDARY)));
#ifdef DEBUG
- msyslog(LOG_DEBUG, "ntp_io: estimated max descriptors: %d, initial socket boundary: %d",
+ msyslog(LOG_DEBUG,
+ "ntp_io: estimated max descriptors: %d, initial socket boundary: %d",
getdtablesize(), socket_boundary);
#endif
}
@@ -406,21 +438,24 @@ static int move_fd(SOCKET fd)
if (newfd != -1) {
/* success: drop the old one - return the new one */
- (void)close(fd);
- return (newfd);
+ close(fd);
+ return newfd;
}
} else {
/* outside reserved range: no work - return the original one */
- return (fd);
+ return fd;
}
socket_boundary = max(0, socket_boundary - FD_CHUNK);
#ifdef DEBUG
- msyslog(LOG_DEBUG, "ntp_io: selecting new socket boundary: %d",
+ msyslog(LOG_DEBUG,
+ "ntp_io: selecting new socket boundary: %d",
socket_boundary);
#endif
} while (socket_boundary > 0);
+#else
+ NTP_REQUIRE((int)fd >= 0);
#endif /* !defined(SYS_WINNT) && defined(F_DUPFD) */
- return (fd);
+ return fd;
}
#ifdef DEBUG_TIMING
@@ -434,16 +469,19 @@ static int move_fd(SOCKET fd)
void
collect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts)
{
- char buf[2048];
+ char buf[256];
snprintf(buf, sizeof(buf), "%s %d %s %s",
- (rb != NULL) ?
- ((rb->dstadr) ? stoa(&rb->recv_srcadr) : "-REFCLOCK-") : "-",
+ (rb != NULL)
+ ? ((rb->dstadr != NULL)
+ ? stoa(&rb->recv_srcadr)
+ : "-REFCLOCK-")
+ : "-",
count, lfptoa(dts, 9), tag);
record_timing_stats(buf);
}
#endif
-
+
/*
* About dynamic interfaces, sockets, reception and more...
*
@@ -487,104 +525,64 @@ collect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts)
void
init_io(void)
{
-#ifdef SYS_WINNT
- init_io_completion_port();
-
- if (!Win32InitSockets())
- {
- netsyslog(LOG_ERR, "No useable winsock.dll: %m");
- exit(1);
- }
- init_transmitbuff();
-#endif /* SYS_WINNT */
-
/*
* Init buffer free list and stat counters
*/
init_recvbuff(RECV_INIT);
- packets_dropped = packets_received = 0;
- packets_ignored = 0;
- packets_sent = packets_notsent = 0;
- handler_calls = handler_pkts = 0;
- io_timereset = 0;
- loopback_interface = NULL;
- any_interface = NULL;
- any6_interface = NULL;
-
-#ifdef REFCLOCK
- refio = NULL;
-#endif
+#ifdef SYS_WINNT
+ init_io_completion_port();
+#endif /* SYS_WINNT */
#if defined(HAVE_SIGNALED_IO)
(void) set_signal();
#endif
+}
- ISC_LIST_INIT(fd_list);
-#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
- ISC_LIST_INIT(asyncio_reader_list);
-#endif
+/*
+ * io_open_sockets - call socket creation routine
+ */
+void
+io_open_sockets(void)
+{
+ static int already_opened;
- ISC_LIST_INIT(remoteaddr_list);
+ if (already_opened || HAVE_OPT( SAVECONFIGQUIT ))
+ return;
- ISC_LIST_INIT(inter_list);
+ already_opened = 1;
/*
* Create the sockets
*/
BLOCKIO();
- (void) create_sockets(htons(NTP_PORT));
+ create_sockets(NTP_PORT);
UNBLOCKIO();
init_async_notifications();
- DPRINTF(3, ("init_io: maxactivefd %d\n", maxactivefd));
+ DPRINTF(3, ("io_open_sockets: maxactivefd %d\n", maxactivefd));
}
+
#ifdef DEBUG
/*
* function to dump the contents of the interface structure
* for debugging use only.
*/
void
-interface_dump(struct interface *itf)
+interface_dump(const endpt *itf)
{
- u_char* cp;
- int i;
- /* Limit the size of the sockaddr_storage hex dump */
- int maxsize = min(32, sizeof(struct sockaddr_storage));
-
printf("Dumping interface: %p\n", itf);
printf("fd = %d\n", itf->fd);
printf("bfd = %d\n", itf->bfd);
- printf("sin = %s,\n", stoa(&(itf->sin)));
- cp = (u_char*) &(itf->sin);
- for(i = 0; i < maxsize; i++)
- {
- printf("%02x", *cp++);
- if((i+1)%4 == 0)
- printf(" ");
- }
- printf("\n");
- printf("bcast = %s,\n", stoa(&(itf->bcast)));
- cp = (u_char*) &(itf->bcast);
- for(i = 0; i < maxsize; i++)
- {
- printf("%02x", *cp++);
- if((i+1)%4 == 0)
- printf(" ");
- }
- printf("\n");
- printf("mask = %s,\n", stoa(&(itf->mask)));
- cp = (u_char*) &(itf->mask);
- for(i = 0; i < maxsize; i++)
- {
- printf("%02x", *cp++);
- if((i+1)%4 == 0)
- printf(" ");
- }
- printf("\n");
+ printf("sin = %s,\n", stoa(&itf->sin));
+ sockaddr_dump(&itf->sin);
+ printf("bcast = %s,\n", stoa(&itf->bcast));
+ sockaddr_dump(&itf->bcast);
+ printf("mask = %s,\n", stoa(&itf->mask));
+ sockaddr_dump(&itf->mask);
printf("name = %s\n", itf->name);
printf("flags = 0x%08x\n", itf->flags);
printf("last_ttl = %d\n", itf->last_ttl);
@@ -594,40 +592,59 @@ interface_dump(struct interface *itf)
printf("sent = %ld\n", itf->sent);
printf("notsent = %ld\n", itf->notsent);
printf("ifindex = %u\n", itf->ifindex);
- printf("scopeid = %u\n", itf->scopeid);
printf("peercnt = %u\n", itf->peercnt);
printf("phase = %u\n", itf->phase);
}
/*
+ * sockaddr_dump - hex dump the start of a sockaddr_u
+ */
+static void
+sockaddr_dump(const sockaddr_u *psau)
+{
+ /* Limit the size of the sockaddr_storage hex dump */
+ const int maxsize = min(32, sizeof(psau->sa6));
+ const u_char * cp;
+ int i;
+
+ cp = (const void *)&psau->sa;
+
+ for(i = 0; i < maxsize; i++) {
+ printf("%02x", *cp++);
+ if (!((i + 1) % 4))
+ printf(" ");
+ }
+ printf("\n");
+}
+
+/*
* print_interface - helper to output debug information
*/
static void
-print_interface(struct interface *iface, char *pfx, char *sfx)
+print_interface(const endpt *iface, char *pfx, char *sfx)
{
- printf("%sinterface #%d: fd=%d, bfd=%d, name=%s, flags=0x%x, scope=%d, ifindex=%d",
+ printf("%sinterface #%d: fd=%d, bfd=%d, name=%s, flags=0x%x, ifindex=%u, sin=%s",
pfx,
iface->ifnum,
iface->fd,
iface->bfd,
iface->name,
iface->flags,
- iface->scopeid,
- iface->ifindex);
- /* Leave these as three printf calls. */
- printf(", sin=%s",
- stoa((&iface->sin)));
- if (iface->flags & INT_BROADCAST)
- printf(", bcast=%s,",
- stoa((&iface->bcast)));
- if (iface->family == AF_INET)
- printf(", mask=%s",
- stoa((&iface->mask)));
- printf(", %s:%s", iface->ignore_packets == ISC_FALSE ? "Enabled" : "Disabled", sfx);
+ iface->ifindex,
+ stoa(&iface->sin));
+ if (AF_INET == iface->family) {
+ if (iface->flags & INT_BROADCAST)
+ printf(", bcast=%s", stoa(&iface->bcast));
+ printf(", mask=%s", stoa(&iface->mask));
+ }
+ printf(", %s:%s",
+ (iface->ignore_packets)
+ ? "Disabled"
+ : "Enabled",
+ sfx);
if (debug > 4) /* in-depth debugging only */
interface_dump(iface);
}
-
#endif
#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
@@ -635,14 +652,13 @@ print_interface(struct interface *iface, char *pfx, char *sfx)
* create an asyncio_reader structure
*/
static struct asyncio_reader *
-new_asyncio_reader()
+new_asyncio_reader(void)
{
struct asyncio_reader *reader;
- reader = (struct asyncio_reader *)emalloc(sizeof(struct asyncio_reader));
+ reader = emalloc(sizeof(*reader));
- memset((char *)reader, 0, sizeof(*reader));
- ISC_LINK_INIT(reader, link);
+ memset(reader, 0, sizeof(*reader));
reader->fd = INVALID_SOCKET;
return reader;
}
@@ -651,7 +667,9 @@ new_asyncio_reader()
* delete a reader
*/
static void
-delete_asyncio_reader(struct asyncio_reader *reader)
+delete_asyncio_reader(
+ struct asyncio_reader *reader
+ )
{
free(reader);
}
@@ -660,9 +678,11 @@ delete_asyncio_reader(struct asyncio_reader *reader)
* add asynchio_reader
*/
static void
-add_asyncio_reader(struct asyncio_reader *reader, enum desc_type type)
+add_asyncio_reader(
+ struct asyncio_reader * reader,
+ enum desc_type type)
{
- ISC_LIST_APPEND(asyncio_reader_list, reader, link);
+ LINK_SLIST(asyncio_reader_list, reader, link);
add_fd_to_list(reader->fd, type);
}
@@ -670,9 +690,14 @@ add_asyncio_reader(struct asyncio_reader *reader, enum desc_type type)
* remove asynchio_reader
*/
static void
-remove_asyncio_reader(struct asyncio_reader *reader)
+remove_asyncio_reader(
+ struct asyncio_reader *reader
+ )
{
- ISC_LIST_UNLINK_TYPE(asyncio_reader_list, reader, link, struct asyncio_reader);
+ struct asyncio_reader *unlinked;
+
+ UNLINK_SLIST(unlinked, asyncio_reader_list, reader, link,
+ struct asyncio_reader);
if (reader->fd != INVALID_SOCKET)
close_and_delete_fd_from_list(reader->fd);
@@ -681,366 +706,871 @@ remove_asyncio_reader(struct asyncio_reader *reader)
}
#endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
+
+/* compare two sockaddr prefixes */
+static int
+addr_eqprefix(
+ const sockaddr_u * a,
+ const sockaddr_u * b,
+ int prefixlen
+ )
+{
+ isc_netaddr_t isc_a;
+ isc_netaddr_t isc_b;
+ isc_sockaddr_t isc_sa;
+
+ memset(&isc_sa, 0, sizeof(isc_sa));
+ memcpy(&isc_sa.type.sa, &a->sa,
+ min(sizeof(isc_sa.type), sizeof(*a)));
+ isc_netaddr_fromsockaddr(&isc_a, &isc_sa);
+
+ memset(&isc_sa, 0, sizeof(isc_sa));
+ memcpy(&isc_sa.type.sa, &b->sa,
+ min(sizeof(isc_sa.type), sizeof(*b)));
+ isc_netaddr_fromsockaddr(&isc_b, &isc_sa);
+
+ return (int)isc_netaddr_eqprefix(&isc_a, &isc_b,
+ (u_int)prefixlen);
+}
+
+
+static int
+addr_samesubnet(
+ const sockaddr_u * a,
+ const sockaddr_u * a_mask,
+ const sockaddr_u * b,
+ const sockaddr_u * b_mask
+ )
+{
+ const u_int32 * pa;
+ const u_int32 * pa_limit;
+ const u_int32 * pb;
+ const u_int32 * pm;
+ size_t loops;
+
+ NTP_REQUIRE(AF(a) == AF(a_mask));
+ NTP_REQUIRE(AF(b) == AF(b_mask));
+ /*
+ * With address and mask families verified to match, comparing
+ * the masks also validates the address's families match.
+ */
+ if (!SOCK_EQ(a_mask, b_mask))
+ return FALSE;
+
+ if (IS_IPV6(a)) {
+ loops = sizeof(NSRCADR6(a)) / sizeof(*pa);
+ pa = (const void *)&NSRCADR6(a);
+ pb = (const void *)&NSRCADR6(b);
+ pm = (const void *)&NSRCADR6(a_mask);
+ } else {
+ loops = sizeof(NSRCADR(a)) / sizeof(*pa);
+ pa = (const void *)&NSRCADR(a);
+ pb = (const void *)&NSRCADR(b);
+ pm = (const void *)&NSRCADR(a_mask);
+ }
+ for (pa_limit = pa + loops; pa < pa_limit; pa++, pb++, pm++)
+ if ((*pa & *pm) != (*pb & *pm))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Code to tell if we have an IP address
+ * If we have then return the sockaddr structure
+ * and set the return value
+ * see the bind9/getaddresses.c for details
+ */
+int
+is_ip_address(
+ const char * host,
+ sockaddr_u * addr
+ )
+{
+ struct in_addr in4;
+ struct in6_addr in6;
+ char tmpbuf[128];
+ char *pch;
+
+ NTP_REQUIRE(host != NULL);
+ NTP_REQUIRE(addr != NULL);
+
+ memset(addr, 0, sizeof(*addr));
+
+ /*
+ * Try IPv4, then IPv6. In order to handle the extended format
+ * for IPv6 scoped addresses (address%scope_ID), we'll use a local
+ * working buffer of 128 bytes. The length is an ad-hoc value, but
+ * should be enough for this purpose; the buffer can contain a string
+ * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
+ * addresses (up to 46 bytes), the delimiter character and the
+ * terminating NULL character.
+ */
+ if (inet_pton(AF_INET, host, &in4) == 1) {
+ AF(addr) = AF_INET;
+ SET_ADDR4N(addr, in4.s_addr);
+
+ return TRUE;
+ } else if (sizeof(tmpbuf) > strlen(host)) {
+ if ('[' == host[0]) {
+ strncpy(tmpbuf, &host[1], sizeof(tmpbuf));
+ pch = strchr(tmpbuf, ']');
+ if (pch != NULL)
+ *pch = '\0';
+ } else
+ strncpy(tmpbuf, host, sizeof(tmpbuf));
+ pch = strchr(tmpbuf, '%');
+ if (pch != NULL)
+ *pch = '\0';
+
+ if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
+ AF(addr) = AF_INET6;
+ SET_ADDR6N(addr, in6);
+
+ return TRUE;
+ }
+ }
+ /*
+ * If we got here it was not an IP address
+ */
+ return FALSE;
+}
+
+
/*
* interface list enumerator - visitor pattern
*/
void
-interface_enumerate(interface_receiver_t receiver, void *data)
+interface_enumerate(
+ interface_receiver_t receiver,
+ void * data
+ )
{
interface_info_t ifi;
- struct interface *interf;
ifi.action = IFS_EXISTS;
-
- for (interf = ISC_LIST_HEAD(inter_list);
- interf != NULL;
- interf = ISC_LIST_NEXT(interf, link)) {
- ifi.interface = interf;
- receiver(data, &ifi);
- }
+ for (ifi.ep = ep_list; ifi.ep != NULL; ifi.ep = ifi.ep->elink)
+ (*receiver)(data, &ifi);
}
/*
* do standard initialization of interface structure
*/
static void
-init_interface(struct interface *interface)
+init_interface(
+ endpt *ep
+ )
{
- memset((char *)interface, 0, sizeof(struct interface));
- ISC_LINK_INIT(interface, link);
- ISC_LIST_INIT(interface->peers);
- interface->fd = INVALID_SOCKET;
- interface->bfd = INVALID_SOCKET;
- interface->num_mcast = 0;
- interface->received = 0;
- interface->sent = 0;
- interface->notsent = 0;
- interface->peercnt = 0;
- interface->phase = sys_interphase;
+ memset(ep, 0, sizeof(*ep));
+ ep->fd = INVALID_SOCKET;
+ ep->bfd = INVALID_SOCKET;
+ ep->phase = sys_interphase;
}
+
/*
* create new interface structure initialize from
* template structure or via standard initialization
* function
*/
static struct interface *
-new_interface(struct interface *interface)
+new_interface(
+ struct interface *interface
+ )
{
- static u_int sys_ifnum = 0;
+ static u_int sys_ifnum = 0;
+ struct interface * iface;
- struct interface *iface = (struct interface *)emalloc(sizeof(struct interface));
+ iface = emalloc(sizeof(*iface));
- if (interface != NULL)
- {
- memcpy((char*)iface, (char*)interface, sizeof(*interface));
- }
- else
- {
+ if (NULL == interface)
init_interface(iface);
- }
+ else /* use the template */
+ memcpy(iface, interface, sizeof(*iface));
- iface->ifnum = sys_ifnum++; /* count every new instance of an interface in the system */
+ /* count every new instance of an interface in the system */
+ iface->ifnum = sys_ifnum++;
iface->starttime = current_time;
return iface;
}
+
/*
* return interface storage into free memory pool
*/
-static void
-delete_interface(struct interface *interface)
+static inline void
+delete_interface(
+ endpt *ep
+ )
{
- free(interface);
+ free(ep);
}
+
/*
* link interface into list of known interfaces
*/
static void
-add_interface(struct interface *interface)
+add_interface(
+ endpt * ep
+ )
{
- static struct interface *listhead = NULL;
+ endpt ** pmclisthead;
+ endpt * scan;
+ endpt * scan_next;
+ endpt * unlinked;
+ sockaddr_u * addr;
+ int ep_local;
+ int scan_local;
+ int same_subnet;
+ int ep_univ_iid; /* iface ID from MAC address */
+ int scan_univ_iid; /* see RFC 4291 */
+ int ep_privacy; /* random local iface ID */
+ int scan_privacy; /* see RFC 4941 */
+ int rc;
/*
- * For ntpd, the first few interfaces (wildcard, localhost)
- * will never be removed. This means inter_list.head is
- * unchanging once initialized. Take advantage of that to
- * watch for changes and catch corruption earlier. This
- * helped track down corruption caused by using FD_SET with
- * a descriptor numerically larger than FD_SETSIZE.
+ * Calculate the address hash
*/
- if (NULL == listhead)
- listhead = inter_list.head;
+ ep->addr_refid = addr2refid(&ep->sin);
- if (listhead != inter_list.head) {
- msyslog(LOG_ERR, "add_interface inter_list.head corrupted: was %p now %p",
- listhead, inter_list.head);
- exit(1);
+ LINK_SLIST(ep_list, ep, elink);
+ ninterfaces++;
+#ifdef MCAST
+ /* the rest is for enabled multicast-capable addresses only */
+ if (ep->ignore_packets || !(INT_MULTICAST & ep->flags) ||
+ INT_LOOPBACK & ep->flags)
+ return;
+# ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
+ if (AF_INET6 == ep->family)
+ return;
+# endif
+ pmclisthead = (AF_INET == ep->family)
+ ? &mc4_list
+ : &mc6_list;
+
+ if (AF_INET6 == ep->family) {
+ ep_local =
+ IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&ep->sin)) ||
+ IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(&ep->sin));
+ ep_univ_iid = IS_IID_UNIV(&ep->sin);
+ ep_privacy = !!(INT_PRIVACY & ep->flags);
+ } else {
+ ep_local = FALSE;
+ ep_univ_iid = FALSE;
+ ep_privacy = FALSE;
}
+ DPRINTF(4, ("add_interface mcast-capable %s%s%s%s\n",
+ stoa(&ep->sin),
+ (ep_local) ? " link/scope-local" : "",
+ (ep_univ_iid) ? " univ-IID" : "",
+ (ep_privacy) ? " privacy" : ""));
/*
- * Calculate the address hash
+ * If we have multiple local addresses on the same network
+ * interface, and some are link- or site-local, do not multicast
+ * out from the link-/site-local addresses by default, to avoid
+ * duplicate manycastclient associations between v6 peers using
+ * link-local and global addresses. link-local can still be
+ * chosen using "nic ignore myv6globalprefix::/64".
+ * Similarly, if we have multiple global addresses from the same
+ * prefix on the same network interface, multicast from one,
+ * preferring EUI-64, then static, then least RFC 4941 privacy
+ * addresses.
*/
- interface->addr_refid = addr2refid(&interface->sin);
-
- ISC_LIST_APPEND(inter_list, interface, link);
- ninterfaces++;
+ for (scan = *pmclisthead; scan != NULL; scan = scan_next) {
+ scan_next = scan->mclink;
+ if (ep->family != scan->family)
+ continue;
+ if (strcmp(ep->name, scan->name))
+ continue;
+ same_subnet = addr_samesubnet(&ep->sin, &ep->mask,
+ &scan->sin, &scan->mask);
+ if (AF_INET6 == ep->family) {
+ addr = &scan->sin;
+ scan_local =
+ IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(addr)) ||
+ IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(addr));
+ scan_univ_iid = IS_IID_UNIV(addr);
+ scan_privacy = !!(INT_PRIVACY & scan->flags);
+ } else {
+ scan_local = FALSE;
+ scan_univ_iid = FALSE;
+ scan_privacy = FALSE;
+ }
+ DPRINTF(4, ("add_interface mcast-capable scan %s%s%s%s\n",
+ stoa(&scan->sin),
+ (scan_local) ? " link/scope-local" : "",
+ (scan_univ_iid) ? " univ-IID" : "",
+ (scan_privacy) ? " privacy" : ""));
+ if ((ep_local && !scan_local) || (same_subnet &&
+ ((ep_privacy && !scan_privacy) ||
+ (!ep_univ_iid && scan_univ_iid)))) {
+ DPRINTF(4, ("did not add %s to %s of IPv6 multicast-capable list which already has %s\n",
+ stoa(&ep->sin),
+ (ep_local)
+ ? "tail"
+ : "head",
+ stoa(&scan->sin)));
+ return;
+ }
+ if ((scan_local && !ep_local) || (same_subnet &&
+ ((scan_privacy && !ep_privacy) ||
+ (!scan_univ_iid && ep_univ_iid)))) {
+ UNLINK_SLIST(unlinked, *pmclisthead,
+ scan, mclink, endpt);
+ DPRINTF(4, ("%s %s from IPv6 multicast-capable list to add %s\n",
+ (unlinked != scan)
+ ? "Failed to remove"
+ : "removed",
+ stoa(&scan->sin), stoa(&ep->sin)));
+ }
+ }
+ /*
+ * Add link/site local at the tail of the multicast-
+ * capable unicast interfaces list, so that ntpd will
+ * send from global addresses before link-/site-local
+ * ones.
+ */
+ if (ep_local)
+ LINK_TAIL_SLIST(*pmclisthead, ep, mclink, endpt);
+ else
+ LINK_SLIST(*pmclisthead, ep, mclink);
+ DPRINTF(4, ("added %s to %s of IPv%s multicast-capable unicast local address list\n",
+ stoa(&ep->sin),
+ (ep_local)
+ ? "tail"
+ : "head",
+ (AF_INET == ep->family)
+ ? "4"
+ : "6"));
+
+ /*
+ * select the local address from which to send to multicast.
+ */
+ switch (AF(&ep->sin)) {
+ case AF_INET :
+ rc = setsockopt(ep->fd, IPPROTO_IP,
+ IP_MULTICAST_IF,
+ (void *)&NSRCADR(&ep->sin),
+ sizeof(NSRCADR(&ep->sin)));
+ if (rc)
+ msyslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_IF %s fails: %m",
+ stoa(&ep->sin));
+ break;
+# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ case AF_INET6 :
+ rc = setsockopt(ep->fd, IPPROTO_IPV6,
+ IPV6_MULTICAST_IF,
+ (void *)&ep->ifindex,
+ sizeof(ep->ifindex));
+ if (rc)
+ msyslog(LOG_ERR,
+ "setsockopt IPV6_MULTICAST_IF %u for %s fails: %m",
+ ep->ifindex, stoa(&ep->sin));
+ break;
+# endif
+ }
+#endif /* MCAST */
}
+
/*
* remove interface from known interface list and clean up
* associated resources
*/
static void
-remove_interface(struct interface *interface)
+remove_interface(
+ endpt * ep
+ )
{
- struct sockaddr_storage resmask;
-
- ISC_LIST_UNLINK_TYPE(inter_list, interface, link, struct interface);
-
- delete_interface_from_list(interface);
-
- if (interface->fd != INVALID_SOCKET)
- {
- msyslog(LOG_INFO, "Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs",
- interface->ifnum,
- interface->name,
- stoa((&interface->sin)),
- NTP_PORT, /* XXX should extract port from sin structure */
- interface->received,
- interface->sent,
- interface->notsent,
- current_time - interface->starttime);
-
- close_and_delete_fd_from_list(interface->fd);
+ endpt * unlinked;
+ endpt ** pmclisthead;
+ sockaddr_u resmask;
+
+ UNLINK_SLIST(unlinked, ep_list, ep, elink, endpt);
+ if (!ep->ignore_packets && INT_MULTICAST & ep->flags) {
+ pmclisthead = (AF_INET == ep->family)
+ ? &mc4_list
+ : &mc6_list;
+ UNLINK_SLIST(unlinked, *pmclisthead, ep, mclink, endpt);
+ DPRINTF(4, ("%s %s IPv%s multicast-capable unicast local address list\n",
+ stoa(&ep->sin),
+ (unlinked != NULL)
+ ? "removed from"
+ : "not found on",
+ (AF_INET == ep->family)
+ ? "4"
+ : "6"));
}
+ delete_interface_from_list(ep);
- if (interface->bfd != INVALID_SOCKET)
- {
- msyslog(LOG_INFO, "Deleting interface #%d %s, broadcast address %s#%d",
- interface->ifnum,
- interface->name,
- stoa((&interface->bcast)),
- (u_short) NTP_PORT); /* XXX extract port from sin structure */
- close_and_delete_fd_from_list(interface->bfd);
+ if (ep->fd != INVALID_SOCKET) {
+ msyslog(LOG_INFO,
+ "Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs",
+ ep->ifnum,
+ ep->name,
+ stoa(&ep->sin),
+ SRCPORT(&ep->sin),
+ ep->received,
+ ep->sent,
+ ep->notsent,
+ current_time - ep->starttime);
+ close_and_delete_fd_from_list(ep->fd);
+ }
+
+ if (ep->bfd != INVALID_SOCKET) {
+ msyslog(LOG_INFO,
+ "Deleting broadcast address %s#%d from interface #%d %s",
+ stoa(&ep->bcast), SRCPORT(&ep->bcast),
+ ep->ifnum, ep->name);
+ close_and_delete_fd_from_list(ep->bfd);
}
ninterfaces--;
- ntp_monclearinterface(interface);
+ ntp_monclearinterface(ep);
/* remove restrict interface entry */
-
- /*
- * Blacklist bound interface address
- */
- SET_HOSTMASK(&resmask, interface->sin.ss_family);
- hack_restrict(RESTRICT_REMOVEIF, &interface->sin, &resmask,
- RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
+ SET_HOSTMASK(&resmask, AF(&ep->sin));
+ hack_restrict(RESTRICT_REMOVEIF, &ep->sin, &resmask,
+ RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE);
}
+
static void
-list_if_listening(struct interface *interface, u_short port)
+log_listen_address(
+ endpt * ep
+ )
{
- msyslog(LOG_INFO, "Listening on interface #%d %s, %s#%d %s",
- interface->ifnum,
- interface->name,
- stoa((&interface->sin)),
- ntohs( (u_short) port),
- (interface->ignore_packets == ISC_FALSE) ?
- "Enabled": "Disabled");
+ msyslog(LOG_INFO, "%s on %d %s %s UDP %d",
+ (ep->ignore_packets)
+ ? "Listen and drop"
+ : "Listen normally",
+ ep->ifnum,
+ ep->name,
+ stoa(&ep->sin),
+ SRCPORT(&ep->sin));
}
+
static void
-create_wildcards(u_short port) {
- isc_boolean_t okipv4 = ISC_TRUE;
+create_wildcards(
+ u_short port
+ )
+{
+ int v4wild, v6wild;
+ sockaddr_u wildaddr;
+ nic_rule_action action;
+ struct interface * wildif;
+
+ /*
+ * silence "potentially uninitialized" warnings from VC9
+ * failing to follow the logic. Ideally action could remain
+ * uninitialized, and the memset be the first statement under
+ * the first if (v4wild).
+ */
+ action = ACTION_LISTEN;
+ memset(&wildaddr, 0, sizeof(wildaddr));
+
/*
* create pseudo-interface with wildcard IPv4 address
*/
-#ifdef IPV6_V6ONLY
- if(isc_net_probeipv4() != ISC_R_SUCCESS)
- okipv4 = ISC_FALSE;
-#endif
-
- if(okipv4 == ISC_TRUE) {
- struct interface *interface = new_interface(NULL);
-
- interface->family = AF_INET;
- interface->sin.ss_family = AF_INET;
- ((struct sockaddr_in*)&interface->sin)->sin_addr.s_addr = htonl(INADDR_ANY);
- ((struct sockaddr_in*)&interface->sin)->sin_port = port;
- (void) strncpy(interface->name, "wildcard", sizeof(interface->name));
- interface->mask.ss_family = AF_INET;
- ((struct sockaddr_in*)&interface->mask)->sin_addr.s_addr = htonl(~(u_int32)0);
- interface->flags = INT_BROADCAST | INT_UP | INT_WILDCARD;
- interface->ignore_packets = ISC_TRUE;
+ v4wild = ipv4_works;
+ if (v4wild) {
+ /* set wildaddr to the v4 wildcard address 0.0.0.0 */
+ AF(&wildaddr) = AF_INET;
+ SET_ADDR4(&wildaddr, INADDR_ANY);
+ SET_PORT(&wildaddr, port);
+
+ /* check for interface/nic rules affecting the wildcard */
+ action = interface_action(NULL, &wildaddr, 0);
+ v4wild = (ACTION_IGNORE != action);
+ }
+ if (v4wild) {
+ wildif = new_interface(NULL);
+
+ strncpy(wildif->name, "v4wildcard", sizeof(wildif->name));
+ memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin));
+ wildif->family = AF_INET;
+ AF(&wildif->mask) = AF_INET;
+ SET_ONESMASK(&wildif->mask);
+
+ wildif->flags = INT_BROADCAST | INT_UP | INT_WILDCARD;
+ wildif->ignore_packets = (ACTION_DROP == action);
#if defined(MCAST)
/*
- * enable possible multicast reception on the broadcast socket
+ * enable multicast reception on the broadcast socket
*/
- interface->bcast.ss_family = AF_INET;
- ((struct sockaddr_in*)&interface->bcast)->sin_port = port;
- ((struct sockaddr_in*)&interface->bcast)->sin_addr.s_addr = htonl(INADDR_ANY);
+ AF(&wildif->bcast) = AF_INET;
+ SET_ADDR4(&wildif->bcast, INADDR_ANY);
+ SET_PORT(&wildif->bcast, port);
#endif /* MCAST */
- interface->fd = open_socket(&interface->sin,
- interface->flags, 1, interface);
+ wildif->fd = open_socket(&wildif->sin, 0, 1, wildif);
- if (interface->fd != INVALID_SOCKET) {
- wildipv4 = interface;
- any_interface = interface;
+ if (wildif->fd != INVALID_SOCKET) {
+ wildipv4 = wildif;
+ any_interface = wildif;
- add_addr_to_list(&interface->sin, interface);
- add_interface(interface);
- list_if_listening(interface, port);
+ add_addr_to_list(&wildif->sin, wildif);
+ add_interface(wildif);
+ log_listen_address(wildif);
} else {
- msyslog(LOG_ERR, "unable to bind to wildcard socket address %s - another process may be running - EXITING",
- stoa((&interface->sin)));
+ msyslog(LOG_ERR,
+ "unable to bind to wildcard address %s - another process may be running - EXITING",
+ stoa(&wildif->sin));
exit(1);
}
+ DPRINT_INTERFACE(2, (wildif, "created ", "\n"));
}
#ifdef INCLUDE_IPV6_SUPPORT
/*
* create pseudo-interface with wildcard IPv6 address
*/
- if (isc_net_probeipv6() == ISC_R_SUCCESS) {
- struct interface *interface = new_interface(NULL);
-
- interface->family = AF_INET6;
- interface->sin.ss_family = AF_INET6;
- ((struct sockaddr_in6*)&interface->sin)->sin6_addr = in6addr_any;
- ((struct sockaddr_in6*)&interface->sin)->sin6_port = port;
-# ifdef ISC_PLATFORM_HAVESCOPEID
- ((struct sockaddr_in6*)&interface->sin)->sin6_scope_id = 0;
-# endif
- (void) strncpy(interface->name, "wildcard", sizeof(interface->name));
- interface->mask.ss_family = AF_INET6;
- memset(&((struct sockaddr_in6*)&interface->mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
- interface->flags = INT_UP | INT_WILDCARD;
- interface->ignore_packets = ISC_TRUE;
-
- interface->fd = open_socket(&interface->sin,
- interface->flags, 1, interface);
-
- if (interface->fd != INVALID_SOCKET) {
- wildipv6 = interface;
- any6_interface = interface;
- add_addr_to_list(&interface->sin, interface);
- add_interface(interface);
- list_if_listening(interface, port);
+ v6wild = ipv6_works;
+ if (v6wild) {
+ /* set wildaddr to the v6 wildcard address :: */
+ memset(&wildaddr, 0, sizeof(wildaddr));
+ AF(&wildaddr) = AF_INET6;
+ SET_ADDR6N(&wildaddr, in6addr_any);
+ SET_PORT(&wildaddr, port);
+ SET_SCOPE(&wildaddr, 0);
+
+ /* check for interface/nic rules affecting the wildcard */
+ action = interface_action(NULL, &wildaddr, 0);
+ v6wild = (ACTION_IGNORE != action);
+ }
+ if (v6wild) {
+ wildif = new_interface(NULL);
+
+ strncpy(wildif->name, "v6wildcard", sizeof(wildif->name));
+ memcpy(&wildif->sin, &wildaddr, sizeof(wildif->sin));
+ wildif->family = AF_INET6;
+ AF(&wildif->mask) = AF_INET6;
+ SET_ONESMASK(&wildif->mask);
+
+ wildif->flags = INT_UP | INT_WILDCARD;
+ wildif->ignore_packets = (ACTION_DROP == action);
+
+ wildif->fd = open_socket(&wildif->sin, 0, 1, wildif);
+
+ if (wildif->fd != INVALID_SOCKET) {
+ wildipv6 = wildif;
+ any6_interface = wildif;
+ add_addr_to_list(&wildif->sin, wildif);
+ add_interface(wildif);
+ log_listen_address(wildif);
} else {
- msyslog(LOG_ERR, "unable to bind to wildcard socket address %s - another process may be running - EXITING",
- stoa((&interface->sin)));
+ msyslog(LOG_ERR,
+ "unable to bind to wildcard address %s - another process may be running - EXITING",
+ stoa(&wildif->sin));
exit(1);
}
+ DPRINT_INTERFACE(2, (wildif, "created ", "\n"));
}
#endif
}
-static isc_boolean_t
-address_okay(struct interface *iface) {
+/*
+ * add_nic_rule() -- insert a rule entry at the head of nic_rule_list.
+ */
+void
+add_nic_rule(
+ nic_rule_match match_type,
+ const char * if_name, /* interface name or numeric address */
+ int prefixlen,
+ nic_rule_action action
+ )
+{
+ nic_rule * rule;
+ isc_boolean_t is_ip;
+
+ rule = emalloc(sizeof(*rule));
+ memset(rule, 0, sizeof(*rule));
+ rule->match_type = match_type;
+ rule->prefixlen = prefixlen;
+ rule->action = action;
+
+ if (MATCH_IFNAME == match_type) {
+ NTP_REQUIRE(NULL != if_name);
+ rule->if_name = estrdup(if_name);
+ } else if (MATCH_IFADDR == match_type) {
+ NTP_REQUIRE(NULL != if_name);
+ /* set rule->addr */
+ is_ip = is_ip_address(if_name, &rule->addr);
+ NTP_REQUIRE(is_ip);
+ } else
+ NTP_REQUIRE(NULL == if_name);
+
+ LINK_SLIST(nic_rule_list, rule, next);
+}
+
+
+#ifdef DEBUG
+static const char *
+action_text(
+ nic_rule_action action
+ )
+{
+ const char *t;
+
+ switch (action) {
+
+ default:
+ t = "ERROR"; /* quiet uninit warning */
+ DPRINTF(1, ("fatal: unknown nic_rule_action %d\n",
+ action));
+ NTP_ENSURE(0);
+ break;
- DPRINTF(4, ("address_okay: listen Virtual: %d, IF name: %s\n",
- listen_to_virtual_ips, iface->name));
+ case ACTION_LISTEN:
+ t = "listen";
+ break;
+
+ case ACTION_IGNORE:
+ t = "ignore";
+ break;
+
+ case ACTION_DROP:
+ t = "drop";
+ break;
+ }
+
+ return t;
+}
+#endif /* DEBUG */
+
+
+static nic_rule_action
+interface_action(
+ char * if_name,
+ sockaddr_u * if_addr,
+ u_int32 if_flags
+ )
+{
+ nic_rule * rule;
+ int isloopback;
+ int iswildcard;
+
+ DPRINTF(4, ("interface_action: %s %s ",
+ (if_name != NULL)
+ ? if_name
+ : "wildcard",
+ stoa(if_addr)));
+
+ iswildcard = is_wildcard_addr(if_addr);
/*
- * Always allow the loopback
+ * Always listen on 127.0.0.1 - required by ntp_intres
*/
- if((iface->flags & INT_LOOPBACK) != 0) {
- DPRINTF(4, ("address_okay: loopback - OK\n"));
- return (ISC_TRUE);
+ if (INT_LOOPBACK & if_flags) {
+ isloopback = TRUE;
+ if (IS_IPV4(if_addr)) {
+ DPRINTF(4, ("IPv4 loopback - listen\n"));
+ return ACTION_LISTEN;
+ }
+ } else {
+ isloopback = FALSE;
}
/*
- * Check if the interface is specified
+ * Find any matching NIC rule from --interface / -I or ntp.conf
+ * interface/nic rules.
*/
- if (specific_interface != NULL) {
- if (strcasecmp(iface->name, specific_interface) == 0) {
- DPRINTF(4, ("address_okay: specific interface name matched - OK\n"));
- return (ISC_TRUE);
- } else {
- DPRINTF(4, ("address_okay: specific interface name NOT matched - FAIL\n"));
- return (ISC_FALSE);
+ for (rule = nic_rule_list; rule != NULL; rule = rule->next) {
+
+ switch (rule->match_type) {
+
+ case MATCH_ALL:
+ /* loopback and wildcard excluded from "all" */
+ if (isloopback || iswildcard)
+ break;
+ DPRINTF(4, ("nic all %s\n",
+ action_text(rule->action)));
+ return rule->action;
+
+ case MATCH_IPV4:
+ if (IS_IPV4(if_addr)) {
+ DPRINTF(4, ("nic ipv4 %s\n",
+ action_text(rule->action)));
+ return rule->action;
+ }
+ break;
+
+ case MATCH_IPV6:
+ if (IS_IPV6(if_addr)) {
+ DPRINTF(4, ("nic ipv6 %s\n",
+ action_text(rule->action)));
+ return rule->action;
+ }
+ break;
+
+ case MATCH_WILDCARD:
+ if (iswildcard) {
+ DPRINTF(4, ("nic wildcard %s\n",
+ action_text(rule->action)));
+ return rule->action;
+ }
+ break;
+
+ case MATCH_IFADDR:
+ if (rule->prefixlen != -1) {
+ if (addr_eqprefix(if_addr, &rule->addr,
+ rule->prefixlen)) {
+
+ DPRINTF(4, ("subnet address match - %s\n",
+ action_text(rule->action)));
+ return rule->action;
+ }
+ } else
+ if (SOCK_EQ(if_addr, &rule->addr)) {
+
+ DPRINTF(4, ("address match - %s\n",
+ action_text(rule->action)));
+ return rule->action;
+ }
+ break;
+
+ case MATCH_IFNAME:
+ if (if_name != NULL
+ && !strcasecmp(if_name, rule->if_name)) {
+
+ DPRINTF(4, ("interface name match - %s\n",
+ action_text(rule->action)));
+ return rule->action;
+ }
+ break;
}
}
- else {
- if (listen_to_virtual_ips == 0 &&
- (strchr(iface->name, (int)':') != NULL)) {
- DPRINTF(4, ("address_okay: virtual ip/alias - FAIL\n"));
- return (ISC_FALSE);
- }
+
+ /*
+ * Unless explicitly disabled such as with "nic ignore ::1"
+ * listen on loopback addresses. Since ntpq and ntpdc query
+ * "localhost" by default, which typically resolves to ::1 and
+ * 127.0.0.1, it's useful to default to listening on both.
+ */
+ if (isloopback) {
+ DPRINTF(4, ("default loopback listen\n"));
+ return ACTION_LISTEN;
+ }
+
+ /*
+ * Treat wildcard addresses specially. If there is no explicit
+ * "nic ... wildcard" or "nic ... 0.0.0.0" or "nic ... ::" rule
+ * default to drop.
+ */
+ if (iswildcard) {
+ DPRINTF(4, ("default wildcard drop\n"));
+ return ACTION_DROP;
+ }
+
+ /*
+ * Check for "virtual IP" (colon in the interface name) after
+ * the rules so that "ntpd --interface eth0:1 -novirtualips"
+ * does indeed listen on eth0:1's addresses.
+ */
+ if (!listen_to_virtual_ips && if_name != NULL
+ && (strchr(if_name, ':') != NULL)) {
+
+ DPRINTF(4, ("virtual ip - ignore\n"));
+ return ACTION_IGNORE;
+ }
+
+ /*
+ * If there are no --interface/-I command-line options and no
+ * interface/nic rules in ntp.conf, the default action is to
+ * listen. In the presence of rules from either, the default
+ * is to ignore. This implements ntpd's traditional listen-
+ * every default with no interface listen configuration, and
+ * ensures a single -I eth0 or "nic listen eth0" means do not
+ * listen on any other addresses.
+ */
+ if (NULL == nic_rule_list) {
+ DPRINTF(4, ("default listen\n"));
+ return ACTION_LISTEN;
}
- DPRINTF(4, ("address_okay: OK\n"));
- return (ISC_TRUE);
+ DPRINTF(4, ("implicit ignore\n"));
+ return ACTION_IGNORE;
}
+
static void
-convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port)
+convert_isc_if(
+ isc_interface_t *isc_if,
+ endpt *itf,
+ u_short port
+ )
{
- itf->scopeid = 0;
- itf->family = (short) isc_if->af;
- strcpy(itf->name, isc_if->name);
-
- if(isc_if->af == AF_INET) {
- itf->sin.ss_family = (u_short) isc_if->af;
- memcpy(&(((struct sockaddr_in*)&itf->sin)->sin_addr),
- &(isc_if->address.type.in),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&itf->sin)->sin_port = port;
-
- if((isc_if->flags & INTERFACE_F_BROADCAST) != 0) {
+ const u_char v6loop[16] = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1};
+
+ strncpy(itf->name, isc_if->name, sizeof(itf->name));
+ itf->name[sizeof(itf->name) - 1] = 0; /* strncpy may not */
+ itf->ifindex = isc_if->ifindex;
+ itf->family = (u_short)isc_if->af;
+ AF(&itf->sin) = itf->family;
+ AF(&itf->mask) = itf->family;
+ AF(&itf->bcast) = itf->family;
+ SET_PORT(&itf->sin, port);
+ SET_PORT(&itf->mask, port);
+ SET_PORT(&itf->bcast, port);
+
+ if (IS_IPV4(&itf->sin)) {
+ NSRCADR(&itf->sin) = isc_if->address.type.in.s_addr;
+ NSRCADR(&itf->mask) = isc_if->netmask.type.in.s_addr;
+
+ if (isc_if->flags & INTERFACE_F_BROADCAST) {
itf->flags |= INT_BROADCAST;
- itf->bcast.ss_family = itf->sin.ss_family;
- memcpy(&(((struct sockaddr_in*)&itf->bcast)->sin_addr),
- &(isc_if->broadcast.type.in),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&itf->bcast)->sin_port = port;
+ NSRCADR(&itf->bcast) =
+ isc_if->broadcast.type.in.s_addr;
}
-
- itf->mask.ss_family = itf->sin.ss_family;
- memcpy(&(((struct sockaddr_in*)&itf->mask)->sin_addr),
- &(isc_if->netmask.type.in),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&itf->mask)->sin_port = port;
}
#ifdef INCLUDE_IPV6_SUPPORT
- else if (isc_if->af == AF_INET6) {
- itf->sin.ss_family = (u_short) isc_if->af;
- memcpy(&(((struct sockaddr_in6 *)&itf->sin)->sin6_addr),
- &(isc_if->address.type.in6),
- sizeof(((struct sockaddr_in6 *)&itf->sin)->sin6_addr));
- ((struct sockaddr_in6 *)&itf->sin)->sin6_port = port;
-
-#ifdef ISC_PLATFORM_HAVESCOPEID
- ((struct sockaddr_in6 *)&itf->sin)->sin6_scope_id = isc_netaddr_getzone(&isc_if->address);
- itf->scopeid = isc_netaddr_getzone(&isc_if->address);
-#endif
- itf->mask.ss_family = itf->sin.ss_family;
- memcpy(&(((struct sockaddr_in6 *)&itf->mask)->sin6_addr),
- &(isc_if->netmask.type.in6),
- sizeof(struct in6_addr));
- ((struct sockaddr_in6 *)&itf->mask)->sin6_port = port;
- /* Copy the interface index */
- itf->ifindex = isc_if->ifindex;
+ else if (IS_IPV6(&itf->sin)) {
+ SET_ADDR6N(&itf->sin, isc_if->address.type.in6);
+ SET_ADDR6N(&itf->mask, isc_if->netmask.type.in6);
+
+ SET_SCOPE(&itf->sin, isc_if->address.zone);
}
#endif /* INCLUDE_IPV6_SUPPORT */
/* Process the rest of the flags */
- if((isc_if->flags & INTERFACE_F_UP) != 0)
- itf->flags |= INT_UP;
- if((isc_if->flags & INTERFACE_F_LOOPBACK) != 0)
- itf->flags |= INT_LOOPBACK;
- if((isc_if->flags & INTERFACE_F_POINTTOPOINT) != 0)
- itf->flags |= INT_PPP;
- if((isc_if->flags & INTERFACE_F_MULTICAST) != 0)
- itf->flags |= INT_MULTICAST;
+ itf->flags |=
+ ((INTERFACE_F_UP & isc_if->flags)
+ ? INT_UP : 0)
+ | ((INTERFACE_F_LOOPBACK & isc_if->flags)
+ ? INT_LOOPBACK : 0)
+ | ((INTERFACE_F_POINTTOPOINT & isc_if->flags)
+ ? INT_PPP : 0)
+ | ((INTERFACE_F_MULTICAST & isc_if->flags)
+ ? INT_MULTICAST : 0)
+ | ((INTERFACE_F_PRIVACY & isc_if->flags)
+ ? INT_PRIVACY : 0)
+ ;
+ /*
+ * Clear the loopback flag if the address is not localhost.
+ * http://bugs.ntp.org/1683
+ */
+ if (INT_LOOPBACK & itf->flags) {
+ if (AF_INET == itf->family) {
+ if (127 != (SRCADR(&itf->sin) >> 24))
+ itf->flags &= ~INT_LOOPBACK;
+ } else {
+ if (memcmp(v6loop, NSRCADR6(&itf->sin),
+ sizeof(NSRCADR6(&itf->sin))))
+ itf->flags &= ~INT_LOOPBACK;
+ }
+ }
}
+
/*
* refresh_interface
*
@@ -1051,27 +1581,25 @@ convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port)
* the socket.
*/
static int
-refresh_interface(struct interface * interface)
+refresh_interface(
+ struct interface * interface
+ )
{
#ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES
- if (interface->fd != INVALID_SOCKET)
- {
+ if (interface->fd != INVALID_SOCKET) {
close_and_delete_fd_from_list(interface->fd);
interface->fd = open_socket(&interface->sin,
- interface->flags, 0, interface);
+ 0, 0, interface);
/*
* reset TTL indication so TTL is is set again
* next time around
*/
interface->last_ttl = 0;
- return interface->fd != INVALID_SOCKET;
- }
- else
- {
+ return (interface->fd != INVALID_SOCKET);
+ } else
return 0; /* invalid sockets are not refreshable */
- }
#else /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
- return interface->fd != INVALID_SOCKET;
+ return (interface->fd != INVALID_SOCKET);
#endif /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
}
@@ -1079,94 +1607,143 @@ refresh_interface(struct interface * interface)
* interface_update - externally callable update function
*/
void
-interface_update(interface_receiver_t receiver, void *data)
+interface_update(
+ interface_receiver_t receiver,
+ void * data)
{
- if (!disable_dynamic_updates) {
- int new_interface_found;
+ int new_interface_found;
- BLOCKIO();
- new_interface_found = update_interfaces(htons(NTP_PORT), receiver, data);
- UNBLOCKIO();
+ if (disable_dynamic_updates)
+ return;
+
+ BLOCKIO();
+ new_interface_found = update_interfaces(NTP_PORT, receiver, data);
+ UNBLOCKIO();
+
+ if (!new_interface_found)
+ return;
- if (new_interface_found) {
#ifdef DEBUG
- msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
+ msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
#endif
#ifdef SYS_WINNT
- /* wake up the resolver thread */
- if (ResolverEventHandle != NULL)
- SetEvent(ResolverEventHandle);
+ /* wake up the resolver thread */
+ if (ResolverEventHandle != NULL)
+ SetEvent(ResolverEventHandle);
#else
- /* write any single byte to the pipe to wake up the resolver process */
- write( resolver_pipe_fd[1], &new_interface_found, 1 );
+ /* write any single byte to the pipe to wake up the resolver process */
+ write( resolver_pipe_fd[1], &new_interface_found, 1 );
#endif
- }
- }
}
+
/*
- * find out if a given interface structure contains
- * a wildcard address
+ * sau_from_netaddr() - convert network address on-wire formats.
+ * Convert from libisc's isc_netaddr_t to NTP's sockaddr_u
*/
+void
+sau_from_netaddr(
+ sockaddr_u *psau,
+ const isc_netaddr_t *pna
+ )
+{
+ memset(psau, 0, sizeof(*psau));
+ AF(psau) = (u_short)pna->family;
+ switch (pna->family) {
+
+ case AF_INET:
+ memcpy(&psau->sa4.sin_addr, &pna->type.in,
+ sizeof(psau->sa4.sin_addr));
+ break;
+
+ case AF_INET6:
+ memcpy(&psau->sa6.sin6_addr, &pna->type.in6,
+ sizeof(psau->sa6.sin6_addr));
+ break;
+ }
+}
+
+
static int
-is_wildcard_addr(struct sockaddr_storage *sas)
+is_wildcard_addr(
+ const sockaddr_u *psau
+ )
{
- if (sas->ss_family == AF_INET &&
- ((struct sockaddr_in*)sas)->sin_addr.s_addr == htonl(INADDR_ANY))
+ if (IS_IPV4(psau) && !NSRCADR(psau))
return 1;
#ifdef INCLUDE_IPV6_SUPPORT
- if (sas->ss_family == AF_INET6 &&
- memcmp(&((struct sockaddr_in6*)sas)->sin6_addr, &in6addr_any,
- sizeof(in6addr_any) == 0))
+ if (IS_IPV6(psau) && S_ADDR6_EQ(psau, &in6addr_any))
return 1;
#endif
return 0;
}
+
#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
/*
* enable/disable re-use of wildcard address socket
*/
static void
-set_wildcard_reuse(int family, int on)
+set_wildcard_reuse(
+ u_short family,
+ int on
+ )
{
- int onvalue = 1;
- int offvalue = 0;
- int *onoff;
+ struct interface *any;
SOCKET fd = INVALID_SOCKET;
- onoff = on ? &onvalue : &offvalue;
+ any = ANY_INTERFACE_BYFAM(family);
+ if (any != NULL)
+ fd = any->fd;
- switch (family) {
- case AF_INET:
- if (any_interface) {
- fd = any_interface->fd;
- }
- break;
+ if (fd != INVALID_SOCKET) {
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&on, sizeof(on)))
+ msyslog(LOG_ERR,
+ "set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m",
+ on ? "on" : "off");
-#ifdef INCLUDE_IPV6_SUPPORT
- case AF_INET6:
- if (any6_interface) {
- fd = any6_interface->fd;
- }
- break;
-#endif /* !INCLUDE_IPV6_SUPPORT */
+ DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n",
+ on ? "on" : "off",
+ stoa(&any->sin)));
}
+}
+#endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */
- if (fd != INVALID_SOCKET) {
- if (setsockopt(fd, SOL_SOCKET,
- SO_REUSEADDR, (char *)onoff,
- sizeof(*onoff))) {
- netsyslog(LOG_ERR, "set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m", *onoff ? "on" : "off");
- }
- DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n", *onoff ? "ON" : "OFF",
- stoa((family == AF_INET) ?
- &any_interface->sin : &any6_interface->sin)));
+
+static isc_boolean_t
+is_anycast(
+ sockaddr_u *psau,
+ const char *name
+ )
+{
+#if defined(INCLUDE_IPV6_SUPPORT) && defined(SIOCGIFAFLAG_IN6) && \
+ defined(IN6_IFF_ANYCAST)
+ struct in6_ifreq ifr6;
+ int fd;
+ u_int32 flags6;
+
+ if (psau->sa.sa_family != AF_INET6)
+ return ISC_FALSE;
+ if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ return ISC_FALSE;
+ memset(&ifr6, 0, sizeof(ifr6));
+ memcpy(&ifr6.ifr_addr, &psau->sa6, sizeof(ifr6.ifr_addr));
+ strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
+ if (ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
+ close(fd);
+ return ISC_FALSE;
}
+ close(fd);
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ if ((flags6 & IN6_IFF_ANYCAST) != 0)
+ return ISC_TRUE;
+#endif /* INCLUDE_IPV6_SUPPORT && SIOCGIFAFLAG_IN6 && IN6_IFF_ANYCAST */
+ return ISC_FALSE;
}
-#endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */
+
/*
* update_interface strategy
@@ -1176,17 +1753,17 @@ set_wildcard_reuse(int family, int on)
* Phase 1:
* forall currently existing interfaces
* if address is known:
- * drop socket - rebind again
+ * drop socket - rebind again
*
* if address is NOT known:
- * attempt to create a new interface entry
+ * attempt to create a new interface entry
*
* Phase 2:
* forall currently known non MCAST and WILDCARD interfaces
* if interface does not match configuration phase (not seen in phase 1):
- * remove interface from known interface list
- * forall peers associated with this interface
- * disconnect peer from this interface
+ * remove interface from known interface list
+ * forall peers associated with this interface
+ * disconnect peer from this interface
*
* Phase 3:
* attempt to re-assign interfaces to peers
@@ -1195,67 +1772,49 @@ set_wildcard_reuse(int family, int on)
static int
update_interfaces(
- u_short port,
- interface_receiver_t receiver,
- void *data
+ u_short port,
+ interface_receiver_t receiver,
+ void * data
)
{
- interface_info_t ifi;
- isc_mem_t *mctx = NULL;
- isc_interfaceiter_t *iter = NULL;
- isc_boolean_t scan_ipv4 = ISC_FALSE;
- isc_boolean_t scan_ipv6 = ISC_FALSE;
- isc_result_t result;
- int new_interface_found = 0;
+ isc_mem_t * mctx = (void *)-1;
+ interface_info_t ifi;
+ isc_interfaceiter_t * iter;
+ isc_result_t result;
+ isc_interface_t isc_if;
+ int new_interface_found;
+ int refresh_peers;
+ unsigned int family;
+ endpt enumep;
+ endpt * ep;
+ endpt * next_ep;
+
+ DPRINTF(3, ("update_interfaces(%d)\n", port));
- DPRINTF(3, ("update_interfaces(%d)\n", ntohs( (u_short) port)));
-
-#ifdef INCLUDE_IPV6_SUPPORT
- if (isc_net_probeipv6() == ISC_R_SUCCESS)
- scan_ipv6 = ISC_TRUE;
-#if defined(DEBUG)
- else
- if (debug)
- netsyslog(LOG_ERR, "no IPv6 interfaces found");
-#endif
-#endif
- if (isc_net_probeipv6() == ISC_R_SUCCESS)
- scan_ipv6 = ISC_TRUE;
-#if defined(ISC_PLATFORM_HAVEIPV6) && defined(DEBUG)
- else
- if (debug)
- netsyslog(LOG_ERR, "no IPv6 interfaces found");
-#endif
-
- if (isc_net_probeipv4() == ISC_R_SUCCESS)
- scan_ipv4 = ISC_TRUE;
-#ifdef DEBUG
- else
- if(debug)
- netsyslog(LOG_ERR, "no IPv4 interfaces found");
-#endif
/*
* phase one - scan interfaces
* - create those that are not found
* - update those that are found
*/
+ new_interface_found = FALSE;
+ refresh_peers = FALSE;
+ iter = NULL;
result = isc_interfaceiter_create(mctx, &iter);
if (result != ISC_R_SUCCESS)
return 0;
- sys_interphase ^= 0x1; /* toggle system phase for finding untouched (to be deleted) interfaces */
+ /*
+ * Toggle system interface scan phase to find untouched
+ * interfaces to be deleted.
+ */
+ sys_interphase ^= 0x1;
for (result = isc_interfaceiter_first(iter);
- result == ISC_R_SUCCESS;
- result = isc_interfaceiter_next(iter))
- {
- isc_interface_t isc_if;
- unsigned int family;
- struct interface interface;
- struct interface *iface;
-
+ ISC_R_SUCCESS == result;
+ result = isc_interfaceiter_next(iter)) {
+
result = isc_interfaceiter_current(iter, &isc_if);
if (result != ISC_R_SUCCESS)
@@ -1263,39 +1822,42 @@ update_interfaces(
/* See if we have a valid family to use */
family = isc_if.address.family;
- if (family != AF_INET && family != AF_INET6)
+ if (AF_INET != family && AF_INET6 != family)
continue;
- if (scan_ipv4 == ISC_FALSE && family == AF_INET)
+ if (AF_INET == family && !ipv4_works)
continue;
- if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
+ if (AF_INET6 == family && !ipv6_works)
continue;
- /*
- * create prototype
- */
- init_interface(&interface);
+ /* create prototype */
+ init_interface(&enumep);
- convert_isc_if(&isc_if, &interface, port);
+ convert_isc_if(&isc_if, &enumep, port);
/*
- * Check to see if we are going to use the interface
- * If we don't use it we mark it to drop any packet
- * received but we still must create the socket and
- * bind to it. This prevents other apps binding to it
- * and potentially causing problems with more than one
- * process fiddling with the clock
+ * Check if and how we are going to use the interface.
*/
- if (address_okay(&interface) == ISC_TRUE) {
- interface.ignore_packets = ISC_FALSE;
- }
- else {
- interface.ignore_packets = ISC_TRUE;
+ switch (interface_action(enumep.name, &enumep.sin,
+ enumep.flags)) {
+
+ case ACTION_IGNORE:
+ continue;
+
+ case ACTION_LISTEN:
+ enumep.ignore_packets = ISC_FALSE;
+ break;
+
+ case ACTION_DROP:
+ enumep.ignore_packets = ISC_TRUE;
+ break;
}
- DPRINT_INTERFACE(4, (&interface, "examining ", "\n"));
+ DPRINT_INTERFACE(4, (&enumep, "examining ", "\n"));
- if (!(interface.flags & INT_UP)) { /* interfaces must be UP to be usable */
- DPRINTF(4, ("skipping interface %s (%s) - DOWN\n", interface.name, stoa(&interface.sin)));
+ /* interfaces must be UP to be usable */
+ if (!(enumep.flags & INT_UP)) {
+ DPRINTF(4, ("skipping interface %s (%s) - DOWN\n",
+ enumep.name, stoa(&enumep.sin)));
continue;
}
@@ -1304,57 +1866,123 @@ update_interfaces(
* address - some dhcp clients produce that in the
* wild
*/
- if (is_wildcard_addr(&interface.sin))
+ if (is_wildcard_addr(&enumep.sin))
+ continue;
+
+ if (is_anycast(&enumep.sin, isc_if.name))
continue;
/*
- * map to local *address* in order
- * to map all duplicate interfaces to an interface structure
- * with the appropriate socket (our name space is
- * (ip-address) - NOT (interface name, ip-address))
+ * map to local *address* in order to map all duplicate
+ * interfaces to an endpt structure with the appropriate
+ * socket. Our name space is (ip-address), NOT
+ * (interface name, ip-address).
*/
- iface = getinterface(&interface.sin, INT_WILDCARD);
+ ep = getinterface(&enumep.sin, INT_WILDCARD);
- if (iface && refresh_interface(iface))
- {
+ if (ep != NULL && refresh_interface(ep)) {
/*
- * found existing and up to date interface - mark present
+ * found existing and up to date interface -
+ * mark present.
*/
+ if (ep->phase != sys_interphase) {
+ /*
+ * On a new round we reset the name so
+ * the interface name shows up again if
+ * this address is no longer shared.
+ * We reset ignore_packets from the
+ * new prototype to respect any runtime
+ * changes to the nic rules.
+ */
+ strncpy(ep->name, enumep.name,
+ sizeof(ep->name));
+ if (ep->ignore_packets !=
+ enumep.ignore_packets) {
+ ep->ignore_packets =
+ enumep.ignore_packets;
+ refresh_peers = TRUE;
+ DPRINTF(4, ("refreshing peers due to %s ignore_packets change to %d\n",
+ stoa(&ep->sin),
+ ep->ignore_packets));
+ }
+ } else {
+ /* name collision - rename interface */
+ strncpy(ep->name, "*multiple*",
+ sizeof(ep->name));
+ }
+
+ DPRINT_INTERFACE(4, (ep, "updating ",
+ " present\n"));
+
+ if (ep->ignore_packets !=
+ enumep.ignore_packets) {
+ /*
+ * We have conflicting configurations
+ * for the interface address. This is
+ * caused by using -I <interfacename>
+ * for an interface that shares its
+ * address with other interfaces. We
+ * can not disambiguate incoming
+ * packets delivered to this socket
+ * without extra syscalls/features.
+ * These are not (commonly) available.
+ * Note this is a more unusual
+ * configuration where several
+ * interfaces share an address but
+ * filtering via interface name is
+ * attempted. We resolve the
+ * configuration conflict by disabling
+ * the processing of received packets.
+ * This leads to no service on the
+ * interface address where the conflict
+ * occurs.
+ */
+ msyslog(LOG_ERR,
+ "WARNING: conflicting enable configuration for interfaces %s and %s for address %s - unsupported configuration - address DISABLED",
+ enumep.name, ep->name,
+ stoa(&enumep.sin));
+
+ ep->ignore_packets = ISC_TRUE;
+ }
+
+ ep->phase = sys_interphase;
- iface->phase = sys_interphase;
- DPRINT_INTERFACE(4, (iface, "updating ", " present\n"));
ifi.action = IFS_EXISTS;
- ifi.interface = iface;
- if (receiver)
- receiver(data, &ifi);
- }
- else
- {
+ ifi.ep = ep;
+ if (receiver != NULL)
+ (*receiver)(data, &ifi);
+ } else {
/*
- * this is new or refreshing failed - add to our interface list
- * if refreshing failed we will delete the interface structure in
- * phase 2 as the interface was not marked current. We can bind to
- * the address as the refresh code already closed the offending socket
+ * This is new or refreshing failed - add to
+ * our interface list. If refreshing failed we
+ * will delete the interface structure in phase
+ * 2 as the interface was not marked current.
+ * We can bind to the address as the refresh
+ * code already closed the offending socket
*/
-
- iface = create_interface(port, &interface);
+ ep = create_interface(port, &enumep);
- if (iface)
- {
+ if (ep != NULL) {
ifi.action = IFS_CREATED;
- ifi.interface = iface;
- if (receiver)
- receiver(data, &ifi);
-
- new_interface_found = 1;
-
- DPRINT_INTERFACE(3, (iface, "updating ", " new - created\n"));
- }
- else
- {
- DPRINT_INTERFACE(3, (&interface, "updating ", " new - creation FAILED"));
+ ifi.ep = ep;
+ if (receiver != NULL)
+ (*receiver)(data, &ifi);
+
+ new_interface_found = TRUE;
+ refresh_peers = TRUE;
+ DPRINTF(4, ("refreshing peers due to new addr %s\n",
+ stoa(&ep->sin)));
+ DPRINT_INTERFACE(3,
+ (ep, "updating ",
+ " new - created\n"));
+ } else {
+ DPRINT_INTERFACE(3,
+ (&enumep, "updating ",
+ " new - creation FAILED"));
- msyslog(LOG_INFO, "failed to initialize interface for address %s", stoa(&interface.sin));
+ msyslog(LOG_INFO,
+ "failed to init interface for address %s",
+ stoa(&enumep.sin));
continue;
}
}
@@ -1363,64 +1991,57 @@ update_interfaces(
isc_interfaceiter_destroy(&iter);
/*
- * phase 2 - delete gone interfaces - reassigning peers to other interfaces
+ * phase 2 - delete gone interfaces - reassigning peers to
+ * other interfaces
*/
- {
- struct interface *interf = ISC_LIST_HEAD(inter_list);
+ for (ep = ep_list; ep != NULL; ep = next_ep) {
+ next_ep = ep->elink;
+
+ /*
+ * if phase does not match sys_phase this interface was
+ * not enumerated during the last interface scan - so it
+ * is gone and will be deleted here unless it did not
+ * originate from interface enumeration (INT_WILDCARD,
+ * INT_MCASTIF).
+ */
+ if (((INT_WILDCARD | INT_MCASTIF) & ep->flags) ||
+ ep->phase == sys_interphase)
+ continue;
- while (interf != NULL)
- {
- struct interface *next = ISC_LIST_NEXT(interf, link);
-
- if (!(interf->flags & (INT_WILDCARD|INT_MCASTIF))) {
- /*
- * if phase does not match sys_phase this interface was not
- * enumerated during interface scan - so it is gone and
- * will be deleted here unless it is solely an MCAST/WILDCARD interface
- */
- if (interf->phase != sys_interphase) {
- struct peer *peer;
- DPRINT_INTERFACE(3, (interf, "updating ", "GONE - deleting\n"));
- remove_interface(interf);
-
- ifi.action = IFS_DELETED;
- ifi.interface = interf;
- if (receiver)
- receiver(data, &ifi);
-
- peer = ISC_LIST_HEAD(interf->peers);
- /*
- * disconnect peer from deleted interface
- */
- while (peer != NULL) {
- struct peer *npeer = ISC_LIST_NEXT(peer, ilink);
-
- /*
- * this one just lost it's interface
- */
- set_peerdstadr(peer, NULL);
-
- peer = npeer;
- }
+ DPRINT_INTERFACE(3, (ep, "updating ",
+ "GONE - deleting\n"));
+ remove_interface(ep);
+ refresh_peers = TRUE;
+ DPRINTF(4, ("refreshing peers due to deleted addr %s",
+ stoa(&ep->sin)));
- /*
- * update globals in case we lose
- * a loopback interface
- */
- if (interf == loopback_interface)
- loopback_interface = NULL;
+ ifi.action = IFS_DELETED;
+ ifi.ep = ep;
+ if (receiver != NULL)
+ (*receiver)(data, &ifi);
- delete_interface(interf);
- }
- }
- interf = next;
- }
+ /* disconnect peers from deleted endpt. */
+ while (ep->peers != NULL)
+ set_peerdstadr(ep->peers, NULL);
+
+ /*
+ * update globals in case we lose
+ * a loopback interface
+ */
+ if (ep == loopback_interface)
+ loopback_interface = NULL;
+
+ delete_interface(ep);
}
/*
* phase 3 - re-configure as the world has changed if necessary
*/
- refresh_all_peerinterfaces();
+ if (refresh_peers) {
+ refresh_all_peerinterfaces();
+ msyslog(LOG_INFO, "peers refreshed");
+ }
+
return new_interface_found;
}
@@ -1442,7 +2063,7 @@ create_sockets(
FD_ZERO(&activefds);
#endif
- DPRINTF(2, ("create_sockets(%d)\n", ntohs( (u_short) port)));
+ DPRINTF(2, ("create_sockets(%d)\n", port));
create_wildcards(port);
@@ -1465,87 +2086,137 @@ create_sockets(
*/
static struct interface *
create_interface(
- u_short port,
- struct interface *iface
- )
+ u_short port,
+ struct interface * protot
+ )
{
- struct sockaddr_storage resmask;
- struct interface *interface;
-
- DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&iface->sin), ntohs( (u_short) port)));
+ sockaddr_u resmask;
+ endpt * iface;
+#if defined(MCAST) && defined(MULTICAST_NONEWSOCKET)
+ remaddr_t * entry;
+ remaddr_t * next_entry;
+#endif
+ DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&protot->sin),
+ port));
/* build an interface */
- interface = new_interface(iface);
+ iface = new_interface(protot);
/*
* create socket
*/
- interface->fd = open_socket(&interface->sin,
- interface->flags, 0, interface);
+ iface->fd = open_socket(&iface->sin, 0, 0, iface);
- if (interface->fd != INVALID_SOCKET)
- list_if_listening(interface, port);
+ if (iface->fd != INVALID_SOCKET)
+ log_listen_address(iface);
- if ((interface->flags & INT_BROADCAST) &&
- interface->bfd != INVALID_SOCKET)
- msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
- stoa((&interface->bcast)),
- ntohs( (u_short) port));
+ if ((INT_BROADCAST & iface->flags)
+ && iface->bfd != INVALID_SOCKET)
+ msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
+ stoa((&iface->bcast)), port);
- if (interface->fd == INVALID_SOCKET &&
- interface->bfd == INVALID_SOCKET) {
+ if (INVALID_SOCKET == iface->fd
+ && INVALID_SOCKET == iface->bfd) {
msyslog(LOG_ERR, "unable to create socket on %s (%d) for %s#%d",
- interface->name,
- interface->ifnum,
- stoa((&interface->sin)),
- ntohs( (u_short) port));
- delete_interface(interface);
+ iface->name,
+ iface->ifnum,
+ stoa((&iface->sin)),
+ port);
+ delete_interface(iface);
return NULL;
}
- /*
- * Blacklist bound interface address
+ /*
+ * Blacklist our own addresses, no use talking to ourself
*/
-
- SET_HOSTMASK(&resmask, interface->sin.ss_family);
- hack_restrict(RESTRICT_FLAGS, &interface->sin, &resmask,
- RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
+ SET_HOSTMASK(&resmask, AF(&iface->sin));
+ hack_restrict(RESTRICT_FLAGS, &iface->sin, &resmask,
+ RESM_NTPONLY | RESM_INTERFACE, RES_IGNORE);
/*
* set globals with the first found
* loopback interface of the appropriate class
*/
- if ((loopback_interface == NULL) &&
- (interface->family == AF_INET) &&
- ((interface->flags & INT_LOOPBACK) != 0))
- {
- loopback_interface = interface;
- }
+ if (NULL == loopback_interface && AF_INET == iface->family
+ && (INT_LOOPBACK & iface->flags))
+ loopback_interface = iface;
/*
* put into our interface list
*/
- add_addr_to_list(&interface->sin, interface);
- add_interface(interface);
+ add_addr_to_list(&iface->sin, iface);
+ add_interface(iface);
- DPRINT_INTERFACE(2, (interface, "created ", "\n"));
- return interface;
+#if defined(MCAST) && defined(MULTICAST_NONEWSOCKET)
+ /*
+ * Join any previously-configured compatible multicast groups.
+ */
+ if (INT_MULTICAST & iface->flags &&
+ !((INT_LOOPBACK | INT_WILDCARD) & iface->flags) &&
+ !iface->ignore_packets) {
+ for (entry = remoteaddr_list;
+ entry != NULL;
+ entry = next_entry) {
+ next_entry = entry->link;
+ if (AF(&iface->sin) != AF(&entry->addr) ||
+ !IS_MCAST(&entry->addr))
+ continue;
+ if (socket_multicast_enable(iface,
+ &entry->addr))
+ msyslog(LOG_INFO,
+ "Joined %s socket to multicast group %s",
+ stoa(&iface->sin),
+ stoa(&entry->addr));
+ else
+ msyslog(LOG_ERR,
+ "Failed to join %s socket to multicast group %s",
+ stoa(&iface->sin),
+ stoa(&entry->addr));
+ }
+ }
+#endif /* MCAST && MCAST_NONEWSOCKET */
+
+ DPRINT_INTERFACE(2, (iface, "created ", "\n"));
+ return iface;
}
#ifdef SO_EXCLUSIVEADDRUSE
static void
-set_excladdruse(int fd)
+set_excladdruse(
+ SOCKET fd
+ )
{
int one = 1;
int failed;
+#ifdef SYS_WINNT
+ DWORD err;
+#endif
failed = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
(char *)&one, sizeof(one));
- if (failed)
- netsyslog(LOG_ERR,
- "setsockopt(%d, SO_EXCLUSIVEADDRUSE, on): %m", fd);
+ if (!failed)
+ return;
+
+#ifdef SYS_WINNT
+ /*
+ * Prior to Windows XP setting SO_EXCLUSIVEADDRUSE can fail with
+ * error WSAINVAL depending on service pack level and whether
+ * the user account is in the Administrators group. Do not
+ * complain if it fails that way on versions prior to XP (5.1).
+ */
+ err = GetLastError();
+
+ if (isc_win32os_versioncheck(5, 1, 0, 0) < 0 /* < 5.1/XP */
+ && WSAEINVAL == err)
+ return;
+
+ SetLastError(err);
+#endif
+ msyslog(LOG_ERR,
+ "setsockopt(%d, SO_EXCLUSIVEADDRUSE, on): %m",
+ (int)fd);
}
#endif /* SO_EXCLUSIVEADDRUSE */
@@ -1556,29 +2227,30 @@ set_excladdruse(int fd)
* fd's also?
*/
static void
-set_reuseaddr(int flag) {
- struct interface *interf;
-
+set_reuseaddr(
+ int flag
+ )
+{
#ifndef SO_EXCLUSIVEADDRUSE
+ endpt *ep;
- for (interf = ISC_LIST_HEAD(inter_list);
- interf != NULL;
- interf = ISC_LIST_NEXT(interf, link)) {
-
- if (interf->flags & INT_WILDCARD)
+ for (ep = ep_list; ep != NULL; ep = ep->elink) {
+ if (ep->flags & INT_WILDCARD)
continue;
/*
- * if interf->fd is INVALID_SOCKET, we might have a adapter
+ * if ep->fd is INVALID_SOCKET, we might have a adapter
* configured but not present
*/
- DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n", interf->name, stoa(&interf->sin), flag ? "on" : "off"));
+ DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n",
+ ep->name, stoa(&ep->sin),
+ flag ? "on" : "off"));
- if (interf->fd != INVALID_SOCKET) {
- if (setsockopt(interf->fd, SOL_SOCKET,
- SO_REUSEADDR, (char *)&flag,
- sizeof(flag))) {
- netsyslog(LOG_ERR, "set_reuseaddr: setsockopt(SO_REUSEADDR, %s) failed: %m", flag ? "on" : "off");
+ if (ep->fd != INVALID_SOCKET) {
+ if (setsockopt(ep->fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&flag, sizeof(flag))) {
+ msyslog(LOG_ERR, "set_reuseaddr: setsockopt(%s, SO_REUSEADDR, %s) failed: %m",
+ stoa(&ep->sin), flag ? "on" : "off");
}
}
}
@@ -1590,9 +2262,12 @@ set_reuseaddr(int flag) {
* make other changes as necessary later on
*/
void
-enable_broadcast(struct interface *iface, struct sockaddr_storage *baddr)
+enable_broadcast(
+ struct interface * iface,
+ sockaddr_u * baddr
+ )
{
-#ifdef SO_BROADCAST
+#ifdef OPEN_BCAST_SOCKET
socket_broadcast_enable(iface, iface->fd, baddr);
#endif
}
@@ -1604,28 +2279,28 @@ enable_broadcast(struct interface *iface, struct sockaddr_storage *baddr)
* broadcasting. It is not this function's job to select the socket
*/
static isc_boolean_t
-socket_broadcast_enable(struct interface *iface, SOCKET fd, struct sockaddr_storage *maddr)
+socket_broadcast_enable(
+ struct interface * iface,
+ SOCKET fd,
+ sockaddr_u * baddr
+ )
{
#ifdef SO_BROADCAST
int on = 1;
- if (maddr->ss_family == AF_INET)
- {
+ if (IS_IPV4(baddr)) {
/* if this interface can support broadcast, set SO_BROADCAST */
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
(char *)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) enable failure on address %s: %m",
- stoa(maddr));
- }
-#ifdef DEBUG
- else if (debug > 1) {
- printf("Broadcast enabled on socket %d for address %s\n",
- fd, stoa(maddr));
- }
-#endif
+ msyslog(LOG_ERR,
+ "setsockopt(SO_BROADCAST) enable failure on address %s: %m",
+ stoa(baddr));
+ else
+ DPRINTF(2, ("Broadcast enabled on socket %d for address %s\n",
+ fd, stoa(baddr)));
}
iface->flags |= INT_BCASTOPEN;
+ broadcast_client_enabled = ISC_TRUE;
return ISC_TRUE;
#else
return ISC_FALSE;
@@ -1638,21 +2313,22 @@ socket_broadcast_enable(struct interface *iface, SOCKET fd, struct sockaddr_stor
* broadcasting. It is not this function's job to select the socket
*/
static isc_boolean_t
-socket_broadcast_disable(struct interface *iface, struct sockaddr_storage *maddr)
+socket_broadcast_disable(
+ struct interface * iface,
+ sockaddr_u * baddr
+ )
{
#ifdef SO_BROADCAST
int off = 0; /* This seems to be OK as an int */
- if (maddr->ss_family == AF_INET)
- {
- if (setsockopt(iface->fd, SOL_SOCKET, SO_BROADCAST,
- (char *)&off, sizeof(off)))
- {
- netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) disable failure on address %s: %m",
- stoa(maddr));
- }
- }
+ if (IS_IPV4(baddr) && setsockopt(iface->fd, SOL_SOCKET,
+ SO_BROADCAST, (char *)&off, sizeof(off)))
+ msyslog(LOG_ERR,
+ "setsockopt(SO_BROADCAST) disable failure on address %s: %m",
+ stoa(baddr));
+
iface->flags &= ~INT_BCASTOPEN;
+ broadcast_client_enabled = ISC_FALSE;
return ISC_TRUE;
#else
return ISC_FALSE;
@@ -1660,47 +2336,40 @@ socket_broadcast_disable(struct interface *iface, struct sockaddr_storage *maddr
}
#endif /* OPEN_BCAST_SOCKET */
+
+/*
+ * return the broadcast client flag value
+ */
+isc_boolean_t
+get_broadcastclient_flag(void)
+{
+ return (broadcast_client_enabled);
+}
/*
* Check to see if the address is a multicast address
*/
static isc_boolean_t
-addr_ismulticast(struct sockaddr_storage *maddr)
+addr_ismulticast(
+ sockaddr_u *maddr
+ )
{
- switch (maddr->ss_family)
- {
- case AF_INET :
- if (!IN_CLASSD(ntohl(((struct sockaddr_in*)maddr)->sin_addr.s_addr))) {
- DPRINTF(4, ("multicast address %s not class D\n", stoa(maddr)));
- return (ISC_FALSE);
- }
- else
- {
- return (ISC_TRUE);
- }
-
- case AF_INET6 :
-#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- if (!IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)maddr)->sin6_addr)) {
- DPRINTF(4, ("address %s not IPv6 multicast address\n", stoa(maddr)));
- return (ISC_FALSE);
- }
- else
- {
- return (ISC_TRUE);
- }
+ isc_boolean_t result;
-/*
- * If we don't have IPV6 support any IPV6 address is not multicast
- */
-#else
- return (ISC_FALSE);
-#endif
+#ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
/*
- * Never valid
+ * If we don't have IPV6 support any IPV6 addr is not multicast
*/
- default:
- return (ISC_FALSE);
- }
+ if (IS_IPV6(maddr))
+ result = ISC_FALSE;
+ else
+#endif
+ result = IS_MCAST(maddr);
+
+ if (!result)
+ DPRINTF(4, ("address %s is not multicast\n",
+ stoa(maddr)));
+
+ return result;
}
/*
@@ -1709,62 +2378,52 @@ addr_ismulticast(struct sockaddr_storage *maddr)
* send the multicast packet.
*/
void
-enable_multicast_if(struct interface *iface, struct sockaddr_storage *maddr)
+enable_multicast_if(
+ struct interface * iface,
+ sockaddr_u * maddr
+ )
{
#ifdef MCAST
- /*u_char*/ TYPEOF_IP_MULTICAST_LOOP off = 0;
+ TYPEOF_IP_MULTICAST_LOOP off = 0;
+
+ NTP_REQUIRE(AF(maddr) == AF(&iface->sin));
+
+ switch (AF(&iface->sin)) {
- switch (maddr->ss_family)
- {
case AF_INET:
- if (setsockopt(iface->fd, IPPROTO_IP, IP_MULTICAST_IF,
- (char *)&(((struct sockaddr_in*)&iface->sin)->sin_addr.s_addr),
- sizeof(struct in_addr)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IP_MULTICAST_IF failure: %m on socket %d, addr %s for multicast address %s",
- iface->fd, stoa(&iface->sin), stoa(maddr));
- return;
- }
#ifdef IP_MULTICAST_LOOP
/*
- * Don't send back to itself, but allow it to fail to set it
+ * Don't send back to itself, but allow failure to set
*/
- if (setsockopt(iface->fd, IPPROTO_IP, IP_MULTICAST_LOOP,
- SETSOCKOPT_ARG_CAST &off, sizeof(off)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IP_MULTICAST_LOOP failure: %m on socket %d, addr %s for multicast address %s",
- iface->fd, stoa(&iface->sin), stoa(maddr));
+ if (setsockopt(iface->fd, IPPROTO_IP,
+ IP_MULTICAST_LOOP,
+ SETSOCKOPT_ARG_CAST &off,
+ sizeof(off))) {
+
+ msyslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s",
+ iface->fd, stoa(&iface->sin),
+ stoa(maddr));
}
#endif
- DPRINTF(4, ("Added IPv4 multicast interface on socket %d, addr %s for multicast address %s\n",
- iface->fd, stoa(&iface->sin),
- stoa(maddr)));
break;
case AF_INET6:
#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
- (char *) &iface->scopeid, sizeof(iface->scopeid)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IPV6_MULTICAST_IF failure: %m on socket %d, addr %s, scope %d for multicast address %s",
- iface->fd, stoa(&iface->sin), iface->scopeid,
- stoa(maddr));
- return;
- }
#ifdef IPV6_MULTICAST_LOOP
/*
- * Don't send back to itself, but allow it to fail to set it
+ * Don't send back to itself, but allow failure to set
*/
- if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
- (char *) &off, sizeof(off)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IP_MULTICAST_LOOP failure: %m on socket %d, addr %s for multicast address %s",
- iface->fd, stoa(&iface->sin), stoa(maddr));
+ if (setsockopt(iface->fd, IPPROTO_IPV6,
+ IPV6_MULTICAST_LOOP,
+ (char *) &off, sizeof(off))) {
+
+ msyslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_LOOP failed: %m on socket %d, addr %s for multicast address %s",
+ iface->fd, stoa(&iface->sin),
+ stoa(maddr));
}
#endif
- DPRINTF(4, ("Added IPv6 multicast interface on socket %d, addr %s, scope %d for multicast address %s\n",
- iface->fd, stoa(&iface->sin), iface->scopeid,
- stoa(maddr)));
break;
#else
return;
@@ -1779,34 +2438,34 @@ enable_multicast_if(struct interface *iface, struct sockaddr_storage *maddr)
* The socket is in the inter_list all we need to do is enable
* multicasting. It is not this function's job to select the socket
*/
+#if defined(MCAST)
static isc_boolean_t
-socket_multicast_enable(struct interface *iface, int lscope, struct sockaddr_storage *maddr)
+socket_multicast_enable(
+ endpt * iface,
+ sockaddr_u * maddr
+ )
{
+ struct ip_mreq mreq;
#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- struct ipv6_mreq mreq6;
- struct in6_addr iaddr6;
-#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
-
- struct ip_mreq mreq;
-
- if (find_addr_in_list(maddr)) {
- DPRINTF(4, ("socket_multicast_enable(%s): already enabled\n", stoa(maddr)));
- return ISC_TRUE;
- }
+ struct ipv6_mreq mreq6;
+#endif
+ switch (AF(maddr)) {
- switch (maddr->ss_family)
- {
case AF_INET:
- memset((char *)&mreq, 0, sizeof(mreq));
- mreq.imr_multiaddr = (((struct sockaddr_in*)maddr)->sin_addr);
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.imr_multiaddr = SOCK_ADDR4(maddr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(iface->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *)&mreq, sizeof(mreq)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IP_ADD_MEMBERSHIP failure: %m on socket %d, addr %s for %x / %x (%s)",
- iface->fd, stoa(&iface->sin),
- mreq.imr_multiaddr.s_addr,
- mreq.imr_interface.s_addr, stoa(maddr));
+ if (setsockopt(iface->fd,
+ IPPROTO_IP,
+ IP_ADD_MEMBERSHIP,
+ (char *)&mreq,
+ sizeof(mreq))) {
+ msyslog(LOG_ERR,
+ "setsockopt IP_ADD_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)",
+ iface->fd, stoa(&iface->sin),
+ mreq.imr_multiaddr.s_addr,
+ mreq.imr_interface.s_addr,
+ stoa(maddr));
return ISC_FALSE;
}
DPRINTF(4, ("Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n",
@@ -1818,71 +2477,79 @@ socket_multicast_enable(struct interface *iface, int lscope, struct sockaddr_sto
case AF_INET6:
#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
/*
- * Enable reception of multicast packets
- * If the address is link-local we can get the interface index
- * from the scope id. Don't do this for other types of multicast
- * addresses. For now let the kernel figure it out.
+ * Enable reception of multicast packets.
+ * If the address is link-local we can get the
+ * interface index from the scope id. Don't do this
+ * for other types of multicast addresses. For now let
+ * the kernel figure it out.
*/
- memset((char *)&mreq6, 0, sizeof(mreq6));
- iaddr6 = ((struct sockaddr_in6*)maddr)->sin6_addr;
- mreq6.ipv6mr_multiaddr = iaddr6;
- mreq6.ipv6mr_interface = lscope;
-
- if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- (char *)&mreq6, sizeof(mreq6)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IPV6_JOIN_GROUP failure: %m on socket %d, addr %s for interface %d(%s)",
- iface->fd, stoa(&iface->sin),
- mreq6.ipv6mr_interface, stoa(maddr));
+ memset(&mreq6, 0, sizeof(mreq6));
+ mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
+ mreq6.ipv6mr_interface = iface->ifindex;
+
+ if (setsockopt(iface->fd, IPPROTO_IPV6,
+ IPV6_JOIN_GROUP, (char *)&mreq6,
+ sizeof(mreq6))) {
+ msyslog(LOG_ERR,
+ "setsockopt IPV6_JOIN_GROUP failed: %m on socket %d, addr %s for interface %u (%s)",
+ iface->fd, stoa(&iface->sin),
+ mreq6.ipv6mr_interface, stoa(maddr));
return ISC_FALSE;
}
- DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %d(%s)\n",
+ DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %u (%s)\n",
iface->fd, stoa(&iface->sin),
mreq6.ipv6mr_interface, stoa(maddr)));
- break;
#else
return ISC_FALSE;
#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
}
iface->flags |= INT_MCASTOPEN;
iface->num_mcast++;
- add_addr_to_list(maddr, iface);
+
return ISC_TRUE;
}
+#endif /* MCAST */
+
/*
* Remove a multicast address from a given socket
* The socket is in the inter_list all we need to do is disable
* multicasting. It is not this function's job to select the socket
*/
+#ifdef MCAST
static isc_boolean_t
-socket_multicast_disable(struct interface *iface, struct sockaddr_storage *maddr)
+socket_multicast_disable(
+ struct interface * iface,
+ sockaddr_u * maddr
+ )
{
#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
struct ipv6_mreq mreq6;
- struct in6_addr iaddr6;
-#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
-
+#endif
struct ip_mreq mreq;
- memset((char *)&mreq, 0, sizeof(mreq));
+
+ memset(&mreq, 0, sizeof(mreq));
if (find_addr_in_list(maddr) == NULL) {
- DPRINTF(4, ("socket_multicast_disable(%s): not enabled\n", stoa(maddr)));
+ DPRINTF(4, ("socket_multicast_disable(%s): not found\n",
+ stoa(maddr)));
return ISC_TRUE;
}
- switch (maddr->ss_family)
- {
+ switch (AF(maddr)) {
+
case AF_INET:
- mreq.imr_multiaddr = (((struct sockaddr_in*)&maddr)->sin_addr);
- mreq.imr_interface.s_addr = ((struct sockaddr_in*)&iface->sin)->sin_addr.s_addr;
- if (setsockopt(iface->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char *)&mreq, sizeof(mreq)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IP_DROP_MEMBERSHIP failure: %m on socket %d, addr %s for %x / %x (%s)",
- iface->fd, stoa(&iface->sin),
- mreq.imr_multiaddr.s_addr,
- mreq.imr_interface.s_addr, stoa(maddr));
+ mreq.imr_multiaddr = SOCK_ADDR4(maddr);
+ mreq.imr_interface = SOCK_ADDR4(&iface->sin);
+ if (setsockopt(iface->fd, IPPROTO_IP,
+ IP_DROP_MEMBERSHIP, (char *)&mreq,
+ sizeof(mreq))) {
+
+ msyslog(LOG_ERR,
+ "setsockopt IP_DROP_MEMBERSHIP failed: %m on socket %d, addr %s for %x / %x (%s)",
+ iface->fd, stoa(&iface->sin),
+ SRCADR(maddr), SRCADR(&iface->sin),
+ stoa(maddr));
return ISC_FALSE;
}
break;
@@ -1890,35 +2557,37 @@ socket_multicast_disable(struct interface *iface, struct sockaddr_storage *maddr
#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
/*
* Disable reception of multicast packets
- * If the address is link-local we can get the interface index
- * from the scope id. Don't do this for other types of multicast
- * addresses. For now let the kernel figure it out.
+ * If the address is link-local we can get the
+ * interface index from the scope id. Don't do this
+ * for other types of multicast addresses. For now let
+ * the kernel figure it out.
*/
- iaddr6 = ((struct sockaddr_in6*)&maddr)->sin6_addr;
- mreq6.ipv6mr_multiaddr = iaddr6;
- mreq6.ipv6mr_interface = iface->scopeid;
-
- if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- (char *)&mreq6, sizeof(mreq6)) == -1) {
- netsyslog(LOG_ERR,
- "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d(%s)",
- iface->fd, stoa(&iface->sin),
- mreq6.ipv6mr_interface, stoa(maddr));
+ mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
+ mreq6.ipv6mr_interface = iface->ifindex;
+
+ if (setsockopt(iface->fd, IPPROTO_IPV6,
+ IPV6_LEAVE_GROUP, (char *)&mreq6,
+ sizeof(mreq6))) {
+
+ msyslog(LOG_ERR,
+ "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d (%s)",
+ iface->fd, stoa(&iface->sin),
+ iface->ifindex, stoa(maddr));
return ISC_FALSE;
}
break;
#else
return ISC_FALSE;
#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
-
}
+
iface->num_mcast--;
- if (iface->num_mcast <= 0) {
- iface->num_mcast = 0;
+ if (!iface->num_mcast)
iface->flags &= ~INT_MCASTOPEN;
- }
+
return ISC_TRUE;
}
+#endif /* MCAST */
/*
* io_setbclient - open the broadcast client sockets
@@ -1927,37 +2596,39 @@ void
io_setbclient(void)
{
#ifdef OPEN_BCAST_SOCKET
- struct interface *interf;
- int nif = 0;
- isc_boolean_t jstatus;
- SOCKET fd;
+ struct interface * interf;
+ int nif;
+ isc_boolean_t jstatus;
+ SOCKET fd;
+ nif = 0;
set_reuseaddr(1);
- for (interf = ISC_LIST_HEAD(inter_list);
+ for (interf = ep_list;
interf != NULL;
- interf = ISC_LIST_NEXT(interf, link)) {
- if (interf->flags & INT_WILDCARD)
- continue;
+ interf = interf->elink) {
+
+ if (interf->flags & (INT_WILDCARD | INT_LOOPBACK))
+ continue;
/* use only allowed addresses */
- if (interf->ignore_packets == ISC_TRUE)
- continue;
- /* Only IPv4 addresses are valid for broadcast */
- if (interf->sin.ss_family != AF_INET)
+ if (interf->ignore_packets)
continue;
- /* Is this a broadcast address? */
+
+ /* Need a broadcast-capable interface */
if (!(interf->flags & INT_BROADCAST))
continue;
- /* Skip the loopback addresses */
- if (interf->flags & INT_LOOPBACK)
- continue;
+ /* Only IPv4 addresses are valid for broadcast */
+ NTP_REQUIRE(IS_IPV4(&interf->sin));
/* Do we already have the broadcast address open? */
if (interf->flags & INT_BCASTOPEN) {
- /* account for already open interfaces to aviod misleading warning below */
+ /*
+ * account for already open interfaces to avoid
+ * misleading warning below
+ */
nif++;
continue;
}
@@ -1966,41 +2637,40 @@ io_setbclient(void)
* Try to open the broadcast address
*/
interf->family = AF_INET;
- interf->bfd = open_socket(&interf->bcast,
- INT_BROADCAST, 0, interf);
+ interf->bfd = open_socket(&interf->bcast, 1, 0, interf);
- /*
- * If we succeeded then we use it otherwise
- * enable the underlying address
+ /*
+ * If we succeeded then we use it otherwise enable
+ * broadcast on the interface address
*/
- if (interf->bfd == INVALID_SOCKET) {
- fd = interf->fd;
- }
- else {
+ if (interf->bfd != INVALID_SOCKET) {
fd = interf->bfd;
+ jstatus = ISC_TRUE;
+ } else {
+ fd = interf->fd;
+ jstatus = socket_broadcast_enable(interf, fd,
+ &interf->sin);
}
/* Enable Broadcast on socket */
- jstatus = socket_broadcast_enable(interf, fd, &interf->sin);
- if (jstatus == ISC_TRUE)
- {
+ if (jstatus) {
nif++;
- netsyslog(LOG_INFO,"io_setbclient: Opened broadcast client on interface #%d %s, socket: %d",
- interf->ifnum, interf->name, fd);
+ msyslog(LOG_INFO,
+ "io_setbclient: Opened broadcast client on interface #%d %s",
+ interf->ifnum, interf->name);
interf->addr_refid = addr2refid(&interf->sin);
}
}
set_reuseaddr(0);
-#ifdef DEBUG
- if (debug)
- if (nif > 0)
- printf("io_setbclient: Opened broadcast clients\n");
-#endif
- if (nif == 0)
- netsyslog(LOG_ERR, "Unable to listen for broadcasts, no broadcast interfaces available");
+ if (nif > 0)
+ DPRINTF(1, ("io_setbclient: Opened broadcast clients\n"));
+ else if (!nif)
+ msyslog(LOG_ERR,
+ "Unable to listen for broadcasts, no broadcast interfaces available");
#else
- netsyslog(LOG_ERR, "io_setbclient: Broadcast Client disabled by build");
-#endif
+ msyslog(LOG_ERR,
+ "io_setbclient: Broadcast Client disabled by build");
+#endif /* OPEN_BCAST_SOCKET */
}
/*
@@ -2009,19 +2679,14 @@ io_setbclient(void)
void
io_unsetbclient(void)
{
- struct interface *interf;
- isc_boolean_t lstatus;
+ endpt *ep;
- for (interf = ISC_LIST_HEAD(inter_list);
- interf != NULL;
- interf = ISC_LIST_NEXT(interf, link))
- {
- if (interf->flags & INT_WILDCARD)
- continue;
-
- if (!(interf->flags & INT_BCASTOPEN))
- continue;
- lstatus = socket_broadcast_disable(interf, &interf->sin);
+ for (ep = ep_list; ep != NULL; ep = ep->elink) {
+ if (INT_WILDCARD & ep->flags)
+ continue;
+ if (!(INT_BCASTOPEN & ep->flags))
+ continue;
+ socket_broadcast_disable(ep, &ep->sin);
}
}
@@ -2030,218 +2695,158 @@ io_unsetbclient(void)
*/
void
io_multicast_add(
- struct sockaddr_storage addr
+ sockaddr_u *addr
)
{
#ifdef MCAST
- struct interface *interface;
-#ifndef MULTICAST_NONEWSOCKET
- struct interface *iface;
-#endif
- int lscope = 0;
-
+ endpt * ep;
+ endpt * one_ep;
+
/*
* Check to see if this is a multicast address
*/
- if (addr_ismulticast(&addr) == ISC_FALSE)
+ if (!addr_ismulticast(addr))
return;
/* If we already have it we can just return */
- if (find_flagged_addr_in_list(&addr, INT_MCASTOPEN|INT_MCASTIF) != NULL)
- {
- netsyslog(LOG_INFO, "Duplicate request found for multicast address %s",
- stoa(&addr));
+ if (NULL != find_flagged_addr_in_list(addr, INT_MCASTOPEN)) {
+ msyslog(LOG_INFO,
+ "Duplicate request found for multicast address %s",
+ stoa(addr));
return;
}
#ifndef MULTICAST_NONEWSOCKET
- interface = new_interface(NULL);
+ ep = new_interface(NULL);
/*
* Open a new socket for the multicast address
*/
- interface->sin.ss_family = addr.ss_family;
- interface->family = addr.ss_family;
+ ep->sin = *addr;
+ SET_PORT(&ep->sin, NTP_PORT);
+ ep->family = AF(&ep->sin);
+ AF(&ep->mask) = ep->family;
+ SET_ONESMASK(&ep->mask);
- switch(addr.ss_family) {
- case AF_INET:
- memcpy(&(((struct sockaddr_in *)&interface->sin)->sin_addr),
- &(((struct sockaddr_in*)&addr)->sin_addr),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&interface->sin)->sin_port = htons(NTP_PORT);
- memset(&((struct sockaddr_in*)&interface->mask)->sin_addr.s_addr, 0xff, sizeof(struct in_addr));
- break;
- case AF_INET6:
-#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- memcpy(&(((struct sockaddr_in6 *)&interface->sin)->sin6_addr),
- &((struct sockaddr_in6*)&addr)->sin6_addr,
- sizeof(struct in6_addr));
- ((struct sockaddr_in6*)&interface->sin)->sin6_port = htons(NTP_PORT);
-#ifdef ISC_PLATFORM_HAVESCOPEID
- ((struct sockaddr_in6*)&interface->sin)->sin6_scope_id = ((struct sockaddr_in6*)&addr)->sin6_scope_id;
-#endif
- memset(&((struct sockaddr_in6*)&interface->mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
-#endif
- iface = findlocalcastinterface(&addr, INT_MULTICAST);
- if (iface) {
-# ifdef ISC_PLATFORM_HAVESCOPEID
- lscope = ((struct sockaddr_in6*)&iface->sin)->sin6_scope_id;
-# endif
- DPRINTF(4, ("Found interface #%d %s, scope: %d for address %s\n", iface->ifnum, iface->name, lscope, stoa(&addr)));
- }
- break;
- }
-
set_reuseaddr(1);
- interface->bfd = INVALID_SOCKET;
- interface->fd = open_socket(&interface->sin,
- INT_MULTICAST, 0, interface);
-
- if (interface->fd != INVALID_SOCKET)
- {
- interface->bfd = INVALID_SOCKET;
- interface->ignore_packets = ISC_FALSE;
- interface->flags |= INT_MCASTIF;
+ ep->bfd = INVALID_SOCKET;
+ ep->fd = open_socket(&ep->sin, 0, 0, ep);
+ if (ep->fd != INVALID_SOCKET) {
+ ep->ignore_packets = ISC_FALSE;
+ ep->flags |= INT_MCASTIF;
- (void) strncpy(interface->name, "multicast",
- sizeof(interface->name));
- ((struct sockaddr_in*)&interface->mask)->sin_addr.s_addr =
- htonl(~(u_int32)0);
- DPRINT_INTERFACE(2, (interface, "multicast add ", "\n"));
- /* socket_multicast_enable() will add this address to the addresslist */
- add_interface(interface);
- list_if_listening(interface, htons(NTP_PORT));
- }
- else
- {
- delete_interface(interface); /* re-use existing interface */
- interface = NULL;
- if (addr.ss_family == AF_INET)
- interface = wildipv4;
- else if (addr.ss_family == AF_INET6)
- interface = wildipv6;
-
- if (interface != NULL) {
+ strncpy(ep->name, "multicast", sizeof(ep->name));
+ DPRINT_INTERFACE(2, (ep, "multicast add ", "\n"));
+ add_interface(ep);
+ log_listen_address(ep);
+ } else {
+ /* bind failed, re-use wildcard interface */
+ delete_interface(ep);
+
+ if (IS_IPV4(addr))
+ ep = wildipv4;
+ else if (IS_IPV6(addr))
+ ep = wildipv6;
+ else
+ ep = NULL;
+
+ if (ep != NULL) {
/* HACK ! -- stuff in an address */
- interface->bcast = addr;
- netsyslog(LOG_ERR,
- "...multicast address %s using wildcard interface #%d %s",
- stoa(&addr), interface->ifnum, interface->name);
+ /* because we don't bind addr? DH */
+ ep->bcast = *addr;
+ msyslog(LOG_ERR,
+ "multicast address %s using wildcard interface #%d %s",
+ stoa(addr), ep->ifnum, ep->name);
} else {
- netsyslog(LOG_ERR,
- "No multicast socket available to use for address %s",
- stoa(&addr));
+ msyslog(LOG_ERR,
+ "No multicast socket available to use for address %s",
+ stoa(addr));
return;
}
}
-#else
- /*
- * For the case where we can't use a separate socket
- */
- interface = findlocalcastinterface(&addr, INT_MULTICAST);
+ { /* in place of the { following for in #else clause */
+ one_ep = ep;
+#else /* MULTICAST_NONEWSOCKET follows */
/*
- * If we don't have a valid socket, just return
+ * For the case where we can't use a separate socket (Windows)
+ * join each applicable endpoint socket to the group address.
*/
- if (!interface)
- {
- netsyslog(LOG_ERR,
- "Cannot add multicast address %s: Cannot find slot",
- stoa(&addr));
- return;
+ if (IS_IPV4(addr))
+ one_ep = wildipv4;
+ else
+ one_ep = wildipv6;
+ for (ep = ep_list; ep != NULL; ep = ep->elink) {
+ if (ep->ignore_packets || AF(&ep->sin) != AF(addr) ||
+ !(INT_MULTICAST & ep->flags) ||
+ (INT_LOOPBACK | INT_WILDCARD) & ep->flags)
+ continue;
+ one_ep = ep;
+#endif /* MULTICAST_NONEWSOCKET */
+ if (socket_multicast_enable(ep, addr))
+ msyslog(LOG_INFO,
+ "Joined %s socket to multicast group %s",
+ stoa(&ep->sin),
+ stoa(addr));
+ else
+ msyslog(LOG_ERR,
+ "Failed to join %s socket to multicast group %s",
+ stoa(&ep->sin),
+ stoa(addr));
}
+ add_addr_to_list(addr, one_ep);
+#else /* !MCAST follows*/
+ msyslog(LOG_ERR,
+ "Can not add multicast address %s: no multicast support",
+ stoa(addr));
#endif
- {
- isc_boolean_t jstatus;
- jstatus = socket_multicast_enable(interface, lscope, &addr);
-
- if (jstatus == ISC_TRUE)
- netsyslog(LOG_INFO, "Added Multicast Listener %s on interface #%d %s\n", stoa(&addr), interface->ifnum, interface->name);
- else
- netsyslog(LOG_ERR, "Failed to add Multicast Listener %s\n", stoa(&addr));
- }
-#else /* MCAST */
- netsyslog(LOG_ERR,
- "Cannot add multicast address %s: no Multicast support",
- stoa(&addr));
-#endif /* MCAST */
return;
}
+
/*
* io_multicast_del() - delete multicast group address
*/
void
io_multicast_del(
- struct sockaddr_storage addr
+ sockaddr_u * addr
)
{
#ifdef MCAST
- struct interface *interface;
- isc_boolean_t lstatus;
+ endpt *iface;
/*
* Check to see if this is a multicast address
*/
- if (addr_ismulticast(&addr) == ISC_FALSE)
- {
- netsyslog(LOG_ERR,
- "invalid multicast address %s", stoa(&addr));
+ if (!addr_ismulticast(addr)) {
+ msyslog(LOG_ERR, "invalid multicast address %s",
+ stoa(addr));
return;
}
- switch (addr.ss_family)
- {
- case AF_INET :
- /*
- * Disable reception of multicast packets
- */
- interface = find_flagged_addr_in_list(&addr, INT_MCASTOPEN);
- while ( interface != NULL) {
- lstatus = socket_multicast_disable(interface, &addr);
- interface = find_flagged_addr_in_list(&addr, INT_MCASTOPEN);
- }
- break;
-
-#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- case AF_INET6 :
- /*
- * Disable reception of multicast packets
- */
- for (interface = ISC_LIST_HEAD(inter_list);
- interface != NULL;
- interface = ISC_LIST_NEXT(interface, link))
- {
- if (interface->flags & INT_WILDCARD)
- continue;
-
- /* Be sure it's the correct family */
- if (interface->sin.ss_family != AF_INET6)
- continue;
- if (!(interface->flags & INT_MCASTOPEN))
- continue;
- if (!(interface->fd < 0))
- continue;
- if (!SOCKCMP(&addr, &interface->sin))
- continue;
- lstatus = socket_multicast_disable(interface, &addr);
- }
- break;
-#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
-
- }/* switch */
+ /*
+ * Disable reception of multicast packets
+ */
+ while ((iface = find_flagged_addr_in_list(addr, INT_MCASTOPEN))
+ != NULL)
+ socket_multicast_disable(iface, addr);
- delete_addr_from_list(&addr);
+ delete_addr_from_list(addr);
#else /* not MCAST */
- netsyslog(LOG_ERR, "this function requires multicast kernel");
+ msyslog(LOG_ERR,
+ "Can not delete multicast address %s: no multicast support",
+ stoa(addr));
#endif /* not MCAST */
}
+
/*
* init_nonblocking_io() - set up descriptor to be non blocking
*/
-static void init_nonblocking_io(SOCKET fd)
+static void init_nonblocking_io(
+ SOCKET fd
+ )
{
/*
* set non-blocking,
@@ -2257,47 +2862,39 @@ static void init_nonblocking_io(SOCKET fd)
#endif
#if defined(O_NONBLOCK) /* POSIX */
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails on fd #%d: %m",
- fd);
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ msyslog(LOG_ERR,
+ "fcntl(O_NONBLOCK) fails on fd #%d: %m", fd);
exit(1);
- /*NOTREACHED*/
}
#elif defined(FNDELAY)
- if (fcntl(fd, F_SETFL, FNDELAY) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(FNDELAY) fails on fd #%d: %m",
+ if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
+ msyslog(LOG_ERR, "fcntl(FNDELAY) fails on fd #%d: %m",
fd);
exit(1);
- /*NOTREACHED*/
}
#elif defined(O_NDELAY) /* generally the same as FNDELAY */
- if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on fd #%d: %m",
+ if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
+ msyslog(LOG_ERR, "fcntl(O_NDELAY) fails on fd #%d: %m",
fd);
exit(1);
- /*NOTREACHED*/
}
#elif defined(FIONBIO)
{
int on = 1;
- if (ioctl(fd,FIONBIO,&on) < 0)
- {
- netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on fd #%d: %m",
+
+ if (ioctl(fd, FIONBIO, &on) < 0) {
+ msyslog(LOG_ERR,
+ "ioctl(FIONBIO) fails on fd #%d: %m",
fd);
exit(1);
- /*NOTREACHED*/
}
}
#elif defined(FIOSNBIO)
- if (ioctl(fd,FIOSNBIO,&on) < 0)
- {
- netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on fd #%d: %m",
- fd);
+ if (ioctl(fd, FIOSNBIO, &on) < 0) {
+ msyslog(LOG_ERR,
+ "ioctl(FIOSNBIO) fails on fd #%d: %m", fd);
exit(1);
- /*NOTREACHED*/
}
#else
# include "Bletch: Need non-blocking I/O!"
@@ -2310,48 +2907,43 @@ static void init_nonblocking_io(SOCKET fd)
static SOCKET
open_socket(
- struct sockaddr_storage *addr,
- int flags,
- int turn_off_reuse,
- struct interface *interf
+ sockaddr_u * addr,
+ int bcast,
+ int turn_off_reuse,
+ endpt * interf
)
{
- int errval;
- SOCKET fd;
+ SOCKET fd;
+ int errval;
+ char scopetext[16];
/*
* int is OK for REUSEADR per
* http://www.kohala.com/start/mcast.api.txt
*/
- int on = 1;
- int off = 0;
+ int on = 1;
+ int off = 0;
-#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
- int tos;
-#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
-
- if ((addr->ss_family == AF_INET6) && (isc_net_probeipv6() != ISC_R_SUCCESS))
- return (INVALID_SOCKET);
+ if (IS_IPV6(addr) && !ipv6_works)
+ return INVALID_SOCKET;
/* create a datagram (UDP) socket */
- fd = socket(addr->ss_family, SOCK_DGRAM, 0);
+ fd = socket(AF(addr), SOCK_DGRAM, 0);
if (INVALID_SOCKET == fd) {
-#ifndef SYS_WINNT
- errval = errno;
-#else
- errval = WSAGetLastError();
-#endif
- netsyslog(LOG_ERR,
- "socket(AF_INET%s, SOCK_DGRAM, 0) failed on address %s: %m",
- (addr->ss_family == AF_INET6) ? "6" : "",
- stoa(addr));
+ errval = socket_errno();
+ msyslog(LOG_ERR,
+ "socket(AF_INET%s, SOCK_DGRAM, 0) failed on address %s: %m",
+ IS_IPV6(addr) ? "6" : "", stoa(addr));
if (errval == EPROTONOSUPPORT ||
errval == EAFNOSUPPORT ||
errval == EPFNOSUPPORT)
return (INVALID_SOCKET);
- msyslog(LOG_ERR, "unexpected error code %d (not PROTONOSUPPORT|AFNOSUPPORT|FPNOSUPPORT) - exiting", errval);
+
+ errno = errval;
+ msyslog(LOG_ERR,
+ "unexpected socket() error %m code %d (not EPROTONOSUPPORT nor EAFNOSUPPORT nor EPFNOSUPPORT) - exiting",
+ errno);
exit(1);
- /*NOTREACHED*/
}
#ifdef SYS_WINNT
@@ -2373,17 +2965,17 @@ open_socket(
if (isc_win32os_versioncheck(5, 1, 0, 0) < 0) /* before 5.1 */
#endif
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)(turn_off_reuse
- ? &off
- : &on),
+ (char *)((turn_off_reuse)
+ ? &off
+ : &on),
sizeof(on))) {
- netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR %s"
- " fails for address %s: %m",
- turn_off_reuse
- ? "off"
- : "on",
- stoa(addr));
+ msyslog(LOG_ERR,
+ "setsockopt SO_REUSEADDR %s fails for address %s: %m",
+ (turn_off_reuse)
+ ? "off"
+ : "on",
+ stoa(addr));
closesocket(fd);
return INVALID_SOCKET;
}
@@ -2399,39 +2991,37 @@ open_socket(
/*
* IPv4 specific options go here
*/
- if (addr->ss_family == AF_INET) {
-#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
- /* set IP_TOS to minimize packet delay */
- tos = IPTOS_LOWDELAY;
- if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0)
- {
- netsyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails on address %s: %m",
- stoa(addr));
- }
-#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
+ if (IS_IPV4(addr)) {
+#if defined(HAVE_IPTOS_SUPPORT)
+ if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&qos,
+ sizeof(qos)))
+ msyslog(LOG_ERR,
+ "setsockopt IP_TOS (%02x) fails on address %s: %m",
+ qos, stoa(addr));
+#endif /* HAVE_IPTOS_SUPPORT */
+ if (bcast)
+ socket_broadcast_enable(interf, fd, addr);
}
/*
* IPv6 specific options go here
*/
- if (addr->ss_family == AF_INET6) {
-#if defined(IPV6_V6ONLY)
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
- (char*)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR, "setsockopt IPV6_V6ONLY on fails on address %s: %m",
+ if (IS_IPV6(addr)) {
+#ifdef IPV6_V6ONLY
+ if (isc_net_probe_ipv6only() == ISC_R_SUCCESS
+ && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char*)&on, sizeof(on)))
+ msyslog(LOG_ERR,
+ "setsockopt IPV6_V6ONLY on fails on address %s: %m",
stoa(addr));
- }
-#endif /* IPV6_V6ONLY */
-#if defined(IPV6_BINDV6ONLY)
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
- (char*)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR,
- "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m",
- stoa(addr));
- }
-#endif /* IPV6_BINDV6ONLY */
+#endif
+#ifdef IPV6_BINDV6ONLY
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
+ (char*)&on, sizeof(on)))
+ msyslog(LOG_ERR,
+ "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m",
+ stoa(addr));
+#endif
}
#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
@@ -2440,25 +3030,18 @@ open_socket(
* addresses if a wildcard address already bound
* to the port and SO_REUSEADDR is not set
*/
- if (!is_wildcard_addr(addr)) {
- set_wildcard_reuse(addr->ss_family, 1);
- }
+ if (!is_wildcard_addr(addr))
+ set_wildcard_reuse(AF(addr), 1);
#endif
/*
* bind the local address.
*/
- errval = bind(fd, (struct sockaddr *)addr, SOCKLEN(addr));
+ errval = bind(fd, &addr->sa, SOCKLEN(addr));
#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
- /*
- * some OSes don't allow binding to more specific
- * addresses if a wildcard address already bound
- * to the port and REUSE_ADDR is not set
- */
- if (!is_wildcard_addr(addr)) {
- set_wildcard_reuse(addr->ss_family, 0);
- }
+ if (!is_wildcard_addr(addr))
+ set_wildcard_reuse(AF(addr), 0);
#endif
if (errval < 0) {
@@ -2469,28 +3052,19 @@ open_socket(
#ifdef DEBUG
|| debug > 1
#endif
- ) {
- if (addr->ss_family == AF_INET)
- netsyslog(LOG_ERR,
- "bind() fd %d, family AF_INET, port %d, addr %s, in_classd=%d flags=0x%x fails: %m",
- fd, (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
- stoa(addr),
- IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)),
- flags);
-#ifdef INCLUDE_IPV6_SUPPORT
- else if (addr->ss_family == AF_INET6)
- netsyslog(LOG_ERR,
- "bind() fd %d, family AF_INET6, port %d, scope %d, addr %s, mcast=%d flags=0x%x fails: %m",
- fd, (int)ntohs(((struct sockaddr_in6*)addr)->sin6_port),
-# ifdef ISC_PLATFORM_HAVESCOPEID
- ((struct sockaddr_in6*)addr)->sin6_scope_id
-# else
- -1
-# endif
- , stoa(addr),
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr),
- flags);
-#endif
+ ) {
+ if (SCOPE(addr))
+ snprintf(scopetext, sizeof(scopetext),
+ "%%%d", SCOPE(addr));
+ else
+ scopetext[0] = 0;
+
+ msyslog(LOG_ERR,
+ "bind(%d) AF_INET%s %s%s#%d%s flags 0x%x failed: %m",
+ fd, IS_IPV6(addr) ? "6" : "",
+ stoa(addr), scopetext, SRCPORT(addr),
+ IS_MCAST(addr) ? " (multicast)" : "",
+ interf->flags);
}
closesocket(fd);
@@ -2502,25 +3076,17 @@ open_socket(
{
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP,
(char*)&on, sizeof(on)))
- {
- netsyslog(LOG_DEBUG,
- "setsockopt SO_TIMESTAMP on fails on address %s: %m",
- stoa(addr));
- }
-#ifdef DEBUG
+ msyslog(LOG_DEBUG,
+ "setsockopt SO_TIMESTAMP on fails on address %s: %m",
+ stoa(addr));
else
- {
- DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n", fd, stoa(addr)));
- }
-#endif
+ DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n",
+ fd, stoa(addr)));
}
#endif
- DPRINTF(4, ("bind() fd %d, family %d, port %d, addr %s, flags=0x%x\n",
- fd,
- addr->ss_family,
- (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
- stoa(addr),
- interf->flags));
+ DPRINTF(4, ("bind(%d) AF_INET%s, addr %s%%%d#%d, flags 0x%x\n",
+ fd, IS_IPV6(addr) ? "6" : "", stoa(addr),
+ SCOPE(addr), SRCPORT(addr), interf->flags));
init_nonblocking_io(fd);
@@ -2539,8 +3105,7 @@ open_socket(
/*
* Add the socket to the completion port
*/
- if (io_completion_port_add_socket(fd, interf))
- {
+ if (io_completion_port_add_socket(fd, interf)) {
msyslog(LOG_ERR, "unable to set up io completion port - EXITING");
exit(1);
}
@@ -2548,6 +3113,12 @@ open_socket(
return fd;
}
+
+#ifdef SYS_WINNT
+#define sendto(fd, buf, len, flags, dest, destsz) \
+ io_completion_port_sendto(fd, buf, len, (sockaddr_u *)(dest))
+#endif
+
/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
/*
* sendpkt - send a packet to the specified destination. Maintain a
@@ -2556,216 +3127,101 @@ open_socket(
*/
void
sendpkt(
- struct sockaddr_storage *dest,
- struct interface *inter,
- int ttl,
- struct pkt *pkt,
- int len
+ sockaddr_u * dest,
+ struct interface * ep,
+ int ttl,
+ struct pkt * pkt,
+ int len
)
{
- int cc, slot;
-
- /*
- * Send error caches. Empty slots have port == 0
- * Set ERRORCACHESIZE to 0 to disable
- */
- struct cache {
- u_short port;
- struct in_addr addr;
- };
-
-#ifdef INCLUDE_IPV6_SUPPORT
- struct cache6 {
- u_short port;
- struct in6_addr addr;
- };
-#endif /* INCLUDE_IPV6_SUPPORT */
-
-
-#ifndef ERRORCACHESIZE
-#define ERRORCACHESIZE 8
-#endif
-#if ERRORCACHESIZE > 0
- static struct cache badaddrs[ERRORCACHESIZE];
-#ifdef INCLUDE_IPV6_SUPPORT
- static struct cache6 badaddrs6[ERRORCACHESIZE];
-#endif /* INCLUDE_IPV6_SUPPORT */
-#else
-#define badaddrs ((struct cache *)0) /* Only used in empty loops! */
-#ifdef INCLUDE_IPV6_SUPPORT
-#define badaddrs6 ((struct cache6 *)0) /* Only used in empty loops! */
-#endif /* INCLUDE_IPV6_SUPPORT */
-#endif
-#ifdef DEBUG
- if (debug > 1)
- {
- if (inter != NULL)
- {
- printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n",
- (ttl > 0) ? "\tMCAST\t***** " : "",
- inter->fd, stoa(dest),
- stoa(&inter->sin), ttl, len);
- }
- else
- {
- printf("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n",
- (ttl > 0) ? "\tMCAST\t***** " : "",
- stoa(dest),
- ttl, len);
- }
- }
-#endif
-
- if (inter == NULL) /* unbound peer - drop request and wait for better network conditions */
- return;
+ endpt * src;
+ int ismcast;
+ int cc;
+ int rc;
+ u_char cttl;
+
+ ismcast = IS_MCAST(dest);
+ if (!ismcast)
+ src = ep;
+ else
+ src = (IS_IPV4(dest))
+ ? mc4_list
+ : mc6_list;
-#ifdef MCAST
-
- /*
- * for the moment we use the bcast option to set multicast ttl
- */
- if (ttl > 0 && ttl != inter->last_ttl) {
-
+ if (NULL == src) {
/*
- * set the multicast ttl for outgoing packets
+ * unbound peer - drop request and wait for better
+ * network conditions
*/
- int rtc;
-
- switch (inter->sin.ss_family) {
-
- case AF_INET :
- {
- u_char mttl = (u_char) ttl;
-
- rtc = setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
- (const void *) &mttl, sizeof(mttl));
- break;
- }
-
-#ifdef INCLUDE_IPV6_SUPPORT
- case AF_INET6 :
- {
- u_int ittl = (u_char) ttl;
-
- rtc = setsockopt(inter->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- (const void *) &ittl, sizeof(ittl));
- break;
- }
-
-#endif /* INCLUDE_IPV6_SUPPORT */
- default: /* just NOP if not supported */
- rtc = 0;
- break;
- }
-
- if (rtc != 0) {
- netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m",
- stoa(&inter->sin));
- }
- else
- inter->last_ttl = ttl;
+ DPRINTF(2, ("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n",
+ ismcast ? "\tMCAST\t***** " : "",
+ stoa(dest), ttl, len));
+ return;
}
-#endif /* MCAST */
-
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if(dest->ss_family == AF_INET) {
- if (badaddrs[slot].port == ((struct sockaddr_in*)dest)->sin_port &&
- badaddrs[slot].addr.s_addr == ((struct sockaddr_in*)dest)->sin_addr.s_addr)
- break;
- }
-#ifdef INCLUDE_IPV6_SUPPORT
- else if (dest->ss_family == AF_INET6) {
- if (badaddrs6[slot].port == ((struct sockaddr_in6*)dest)->sin6_port &&
- badaddrs6[slot].addr.s6_addr == ((struct sockaddr_in6*)dest)->sin6_addr.s6_addr)
- break;
- }
-#endif /* INCLUDE_IPV6_SUPPORT */
-
-#if defined(HAVE_IO_COMPLETION_PORT)
- cc = io_completion_port_sendto(inter, pkt, len, dest);
- if (cc != ERROR_SUCCESS)
-#else
-#ifdef SIM
- cc = srvr_rply(&ntp_node, dest, inter, pkt);
-#else /* SIM */
- cc = sendto(inter->fd, (char *)pkt, (unsigned int)len, 0, (struct sockaddr *)dest,
- SOCKLEN(dest));
-#endif /* SIM */
- if (cc == -1)
-#endif
- {
- inter->notsent++;
- packets_notsent++;
-
-#if defined(HAVE_IO_COMPLETION_PORT)
- if (cc != WSAEWOULDBLOCK && cc != WSAENOBUFS && slot < 0)
-#else
- if (errno != EWOULDBLOCK && errno != ENOBUFS && slot < 0)
-#endif
- {
+ do {
+ DPRINTF(2, ("%ssendpkt(%d, dst=%s, src=%s, ttl=%d, len=%d)\n",
+ ismcast ? "\tMCAST\t***** " : "", src->fd,
+ stoa(dest), stoa(&src->sin), ttl, len));
+#ifdef MCAST
+ /*
+ * for the moment we use the bcast option to set multicast ttl
+ */
+ if (ismcast && ttl > 0 && ttl != src->last_ttl) {
/*
- * Remember this, if there's an empty slot
+ * set the multicast ttl for outgoing packets
*/
- switch (dest->ss_family) {
-
+ switch (AF(&src->sin)) {
+
case AF_INET :
-
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs[slot].port == 0)
- {
- badaddrs[slot].port = SRCPORT(dest);
- badaddrs[slot].addr = ((struct sockaddr_in*)dest)->sin_addr;
- break;
- }
+ cttl = (u_char)ttl;
+ rc = setsockopt(src->fd, IPPROTO_IP,
+ IP_MULTICAST_TTL,
+ (void *)&cttl,
+ sizeof(cttl));
break;
-
-#ifdef INCLUDE_IPV6_SUPPORT
+
+# ifdef INCLUDE_IPV6_SUPPORT
case AF_INET6 :
-
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs6[slot].port == 0)
- {
- badaddrs6[slot].port = SRCPORT(dest);
- badaddrs6[slot].addr = ((struct sockaddr_in6*)dest)->sin6_addr;
- break;
- }
+ rc = setsockopt(src->fd, IPPROTO_IPV6,
+ IPV6_MULTICAST_HOPS,
+ (void *)&ttl,
+ sizeof(ttl));
break;
-#endif /* INCLUDE_IPV6_SUPPORT */
- default: /* don't care if not supported */
- break;
- }
+# endif /* INCLUDE_IPV6_SUPPORT */
- netsyslog(LOG_ERR, "sendto(%s) (fd=%d): %m",
- stoa(dest), inter->fd);
- }
- }
- else
- {
- inter->sent++;
- packets_sent++;
- /*
- * He's not bad any more
- */
- if (slot >= 0)
- {
- netsyslog(LOG_INFO, "Connection re-established to %s", stoa(dest));
- switch (dest->ss_family) {
- case AF_INET :
- badaddrs[slot].port = 0;
- break;
-#ifdef INCLUDE_IPV6_SUPPORT
- case AF_INET6 :
- badaddrs6[slot].port = 0;
- break;
-#endif /* INCLUDE_IPV6_SUPPORT */
- default: /* don't care if not supported */
- break;
+ default:
+ rc = 0;
}
+
+ if (!rc)
+ src->last_ttl = ttl;
+ else
+ msyslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m",
+ stoa(&src->sin));
}
- }
+#endif /* MCAST */
+
+#ifdef SIM
+ cc = simulate_server(dest, src, pkt);
+#else
+ cc = sendto(src->fd, (char *)pkt, (u_int)len, 0,
+ &dest->sa, SOCKLEN(dest));
+#endif
+ if (cc == -1) {
+ src->notsent++;
+ packets_notsent++;
+ } else {
+ src->sent++;
+ packets_sent++;
+ }
+ if (ismcast)
+ src = src->mclink;
+ } while (ismcast && src != NULL);
}
+
#if !defined(HAVE_IO_COMPLETION_PORT)
/*
* fdbits - generate ascii representation of fd_set (FAU debug support)
@@ -2780,10 +3236,9 @@ fdbits(
static char buffer[256];
char * buf = buffer;
- count = (count < 256) ? count : 255;
+ count = min(count, 255);
- while (count >= 0)
- {
+ while (count >= 0) {
*buf++ = FD_ISSET(count, set) ? '#' : '-';
count--;
}
@@ -2806,8 +3261,7 @@ read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
rb = get_free_recv_buffer();
- if (rb == NULL)
- {
+ if (NULL == rb) {
/*
* No buffer space available - just drop the packet
*/
@@ -2819,15 +3273,14 @@ read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
}
i = (rp->datalen == 0
- || rp->datalen > sizeof(rb->recv_space))
- ? sizeof(rb->recv_space) : rp->datalen;
+ || rp->datalen > sizeof(rb->recv_space))
+ ? sizeof(rb->recv_space)
+ : rp->datalen;
buflen = read(fd, (char *)&rb->recv_space, (unsigned)i);
- if (buflen < 0)
- {
- if (errno != EINTR && errno != EAGAIN) {
- netsyslog(LOG_ERR, "clock read fd %d: %m", fd);
- }
+ if (buflen < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ msyslog(LOG_ERR, "clock read fd %d: %m", fd);
freerecvbuf(rb);
return (buflen);
}
@@ -2843,13 +3296,11 @@ read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
rb->recv_time = ts;
rb->receiver = rp->clock_recv;
- if (rp->io_input)
- {
+ if (rp->io_input) {
/*
* have direct input routine for refclocks
*/
- if (rp->io_input(rb) == 0)
- {
+ if (rp->io_input(rb) == 0) {
/*
* data was consumed - nothing to pass up
* into block input machine
@@ -2866,12 +3317,17 @@ read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
return (buflen);
}
+
#ifdef HAVE_TIMESTAMP
/*
* extract timestamps from control message buffer
*/
static l_fp
- fetch_timestamp(struct recvbuf *rb, struct msghdr *msghdr, l_fp ts)
+fetch_timestamp(
+ struct recvbuf * rb,
+ struct msghdr * msghdr,
+ l_fp ts
+ )
{
#ifdef USE_TIMESTAMP_CMSG
struct cmsghdr *cmsghdr;
@@ -2882,33 +3338,36 @@ static l_fp
{
case SCM_TIMESTAMP:
{
- struct timeval *tvp = (struct timeval *)CMSG_DATA(cmsghdr);
+ struct timeval *tvp;
double dtemp;
l_fp nts;
- DPRINTF(4, ("fetch_timestamp: system network time stamp: %ld.%06ld\n", tvp->tv_sec, tvp->tv_usec));
- nts.l_i = tvp->tv_sec + JAN_1970;
- dtemp = tvp->tv_usec / 1e6;
- /* fuzz lower bits not covered by precision */
- if (sys_precision != 0)
- dtemp += (ntp_random() / FRAC - .5) / (1 <<
- -sys_precision);
-
- nts.l_uf = (u_int32)(dtemp*FRAC);
+ tvp = (struct timeval *)CMSG_DATA(cmsghdr);
+ DPRINTF(4, ("fetch_timestamp: system network time stamp: %ld.%06ld\n",
+ tvp->tv_sec, tvp->tv_usec));
+ nts.l_i = tvp->tv_sec + JAN_1970;
+ dtemp = (tvp->tv_usec
+ + (ntp_random() * 2. / FRAC)) / 1e6;
+ nts.l_uf = (u_int32)(dtemp * FRAC);
#ifdef DEBUG_TIMING
{
- l_fp dts = ts;
+ l_fp dts;
+
+ dts = ts;
L_SUB(&dts, &nts);
- collect_timing(rb, "input processing delay", 1, &dts);
- DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. prec fuzz)\n", lfptoa(&dts, 9)));
+ collect_timing(rb,
+ "input processing delay",
+ 1, &dts);
+ DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. prec fuzz)\n",
+ lfptoa(&dts, 9)));
}
#endif
ts = nts; /* network time stamp */
break;
}
default:
- DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n", cmsghdr->cmsg_type));
- break;
+ DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n",
+ cmsghdr->cmsg_type));
}
cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr);
}
@@ -2917,13 +3376,18 @@ static l_fp
}
#endif
+
/*
* Routine to read the network NTP packets for a specific interface
* Return the number of bytes read. That way we know if we should
* read it again or go on to the next one if no bytes returned
*/
static inline int
-read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
+read_network_packet(
+ SOCKET fd,
+ struct interface * itf,
+ l_fp ts
+ )
{
GETSOCKNAME_SOCKLEN_TYPE fromlen;
int buflen;
@@ -2931,7 +3395,7 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
#ifdef HAVE_TIMESTAMP
struct msghdr msghdr;
struct iovec iovec;
- char control[TIMESTAMP_CTLMSGBUF_SIZE]; /* pick up control messages */
+ char control[TIMESTAMP_CTLMSGBUF_SIZE];
#endif
/*
@@ -2942,41 +3406,39 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
*/
rb = get_free_recv_buffer();
-
- if (rb == NULL || itf->ignore_packets == ISC_TRUE)
- {
+ if (NULL == rb || itf->ignore_packets) {
char buf[RX_BUFF_SIZE];
- struct sockaddr_storage from;
+ sockaddr_u from;
+
if (rb != NULL)
freerecvbuf(rb);
fromlen = sizeof(from);
buflen = recvfrom(fd, buf, sizeof(buf), 0,
- (struct sockaddr*)&from, &fromlen);
+ &from.sa, &fromlen);
DPRINTF(4, ("%s on (%lu) fd=%d from %s\n",
- (itf->ignore_packets == ISC_TRUE) ? "ignore" : "drop",
- free_recvbuffs(), fd,
- stoa(&from)));
- if (itf->ignore_packets == ISC_TRUE)
+ (itf->ignore_packets)
+ ? "ignore"
+ : "drop",
+ free_recvbuffs(), fd, stoa(&from)));
+ if (itf->ignore_packets)
packets_ignored++;
else
packets_dropped++;
return (buflen);
}
- fromlen = sizeof(struct sockaddr_storage);
+ fromlen = sizeof(rb->recv_srcadr);
#ifndef HAVE_TIMESTAMP
- rb->recv_length = recvfrom(fd,
- (char *)&rb->recv_space,
- sizeof(rb->recv_space), 0,
- (struct sockaddr *)&rb->recv_srcadr,
- &fromlen);
+ rb->recv_length = recvfrom(fd, (char *)&rb->recv_space,
+ sizeof(rb->recv_space), 0,
+ &rb->recv_srcadr.sa, &fromlen);
#else
- iovec.iov_base = (void *)&rb->recv_space;
+ iovec.iov_base = &rb->recv_space;
iovec.iov_len = sizeof(rb->recv_space);
- msghdr.msg_name = (void *)&rb->recv_srcadr;
- msghdr.msg_namelen = sizeof(rb->recv_srcadr);
+ msghdr.msg_name = &rb->recv_srcadr;
+ msghdr.msg_namelen = fromlen;
msghdr.msg_iov = &iovec;
msghdr.msg_iovlen = 1;
msghdr.msg_control = (void *)&control;
@@ -2988,37 +3450,24 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
buflen = rb->recv_length;
if (buflen == 0 || (buflen == -1 &&
- (errno==EWOULDBLOCK
+ (EWOULDBLOCK == errno
#ifdef EAGAIN
- || errno==EAGAIN
+ || EAGAIN == errno
#endif
- ))) {
+ ))) {
freerecvbuf(rb);
return (buflen);
- }
- else if (buflen < 0)
- {
- netsyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
- stoa(&rb->recv_srcadr), fd);
- DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n", fd));
+ } else if (buflen < 0) {
+ msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
+ stoa(&rb->recv_srcadr), fd);
+ DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n",
+ fd));
freerecvbuf(rb);
return (buflen);
}
-#ifdef DEBUG
- if (debug > 2) {
- if(rb->recv_srcadr.ss_family == AF_INET)
- printf("read_network_packet: fd=%d length %d from %08lx %s\n",
- fd, buflen,
- (u_long)ntohl(((struct sockaddr_in*)&rb->recv_srcadr)->sin_addr.s_addr) &
- 0x00000000ffffffff,
- stoa(&rb->recv_srcadr));
- else
- printf("read_network_packet: fd=%d length %d from %s\n",
- fd, buflen,
- stoa(&rb->recv_srcadr));
- }
-#endif
+ DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n",
+ fd, buflen, stoa(&rb->recv_srcadr)));
/*
* Got one. Mark how and when it got here,
@@ -3027,7 +3476,8 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
rb->dstadr = itf;
rb->fd = fd;
#ifdef HAVE_TIMESTAMP
- ts = fetch_timestamp(rb, &msghdr, ts); /* pick up a network time stamp if possible */
+ /* pick up a network time stamp if possible */
+ ts = fetch_timestamp(rb, &msghdr, ts);
#endif
rb->recv_time = ts;
rb->receiver = receive;
@@ -3039,6 +3489,7 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
return (buflen);
}
+
/*
* input_handler - receive packets asynchronously
*/
@@ -3047,19 +3498,18 @@ input_handler(
l_fp *cts
)
{
-
int buflen;
int n;
int doing;
SOCKET fd;
struct timeval tvzero;
- l_fp ts; /* Timestamp at BOselect() gob */
+ l_fp ts; /* Timestamp at BOselect() gob */
#ifdef DEBUG_TIMING
- l_fp ts_e; /* Timestamp at EOselect() gob */
+ l_fp ts_e; /* Timestamp at EOselect() gob */
#endif
fd_set fds;
int select_count = 0;
- struct interface *interface;
+ endpt *ep;
#if defined(HAS_ROUTING_SOCKET)
struct asyncio_reader *asyncio_reader;
#endif
@@ -3068,7 +3518,7 @@ input_handler(
/*
* If we have something to do, freeze a timestamp.
- * See below for the other cases (nothing (left) to do or error)
+ * See below for the other cases (nothing left to do or error)
*/
ts = *cts;
@@ -3079,28 +3529,31 @@ input_handler(
fds = activefds;
tvzero.tv_sec = tvzero.tv_usec = 0;
- n = select(maxactivefd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
+ n = select(maxactivefd + 1, &fds, (fd_set *)0, (fd_set *)0,
+ &tvzero);
/*
* If there are no packets waiting just return
*/
- if (n < 0)
- {
+ if (n < 0) {
int err = errno;
/*
* extended FAU debugging output
*/
if (err != EINTR)
- netsyslog(LOG_ERR,
- "select(%d, %s, 0L, 0L, &0.0) error: %m",
- maxactivefd+1,
- fdbits(maxactivefd, &activefds));
+ msyslog(LOG_ERR,
+ "select(%d, %s, 0L, 0L, &0.0) error: %m",
+ maxactivefd + 1,
+ fdbits(maxactivefd, &activefds));
if (err == EBADF) {
int j, b;
fds = activefds;
for (j = 0; j <= maxactivefd; j++)
- if ((FD_ISSET(j, &fds) && (read(j, &b, 0) == -1)))
- netsyslog(LOG_ERR, "Bad file descriptor %d", j);
+ if ((FD_ISSET(j, &fds)
+ && (read(j, &b, 0) == -1)))
+ msyslog(LOG_ERR,
+ "Bad file descriptor %d",
+ j);
}
return;
}
@@ -3114,55 +3567,43 @@ input_handler(
* Check out the reference clocks first, if any
*/
- if (refio != NULL)
- {
+ if (refio != NULL) {
register struct refclockio *rp;
- for (rp = refio; rp != NULL; rp = rp->next)
- {
+ for (rp = refio; rp != NULL; rp = rp->next) {
fd = rp->fd;
if (FD_ISSET(fd, &fds))
- {
do {
++select_count;
- buflen = read_refclock_packet(fd, rp, ts);
+ buflen = read_refclock_packet(
+ fd, rp, ts);
} while (buflen > 0);
-
- } /* End if (FD_ISSET(fd, &fds)) */
- } /* End for (rp = refio; rp != 0 && n > 0; rp = rp->next) */
- } /* End if (refio != 0) */
-
+ }
+ }
#endif /* REFCLOCK */
/*
* Loop through the interfaces looking for data to read.
*/
- for (interface = ISC_LIST_TAIL(inter_list);
- interface != NULL;
- interface = ISC_LIST_PREV(interface, link))
- {
- for (doing = 0; (doing < 2); doing++)
- {
- if (doing == 0)
- {
- fd = interface->fd;
- }
- else
- {
- if (!(interface->flags & INT_BCASTOPEN))
- break;
- fd = interface->bfd;
+ for (ep = ep_list; ep != NULL; ep = ep->elink) {
+ for (doing = 0; doing < 2; doing++) {
+ if (!doing) {
+ fd = ep->fd;
+ } else {
+ if (!(ep->flags & INT_BCASTOPEN))
+ break;
+ fd = ep->bfd;
}
- if (fd < 0) continue;
+ if (fd < 0)
+ continue;
if (FD_ISSET(fd, &fds))
- {
do {
++select_count;
- buflen = read_network_packet(fd, interface, ts);
+ buflen = read_network_packet(
+ fd, ep, ts);
} while (buflen > 0);
- }
- /* Check more interfaces */
+ /* Check more interfaces */
}
}
@@ -3170,16 +3611,14 @@ input_handler(
/*
* scan list of asyncio readers - currently only used for routing sockets
*/
- asyncio_reader = ISC_LIST_TAIL(asyncio_reader_list);
+ asyncio_reader = asyncio_reader_list;
- while (asyncio_reader != NULL)
- {
- struct asyncio_reader *next = ISC_LIST_PREV(asyncio_reader, link);
+ while (asyncio_reader != NULL) {
if (FD_ISSET(asyncio_reader->fd, &fds)) {
++select_count;
- asyncio_reader->receiver(asyncio_reader);
+ (asyncio_reader->receiver)(asyncio_reader);
}
- asyncio_reader = next;
+ asyncio_reader = asyncio_reader->link;
}
#endif /* HAS_ROUTING_SOCKET */
@@ -3191,15 +3630,14 @@ input_handler(
* If nothing to do, just return.
* If an error occurred, complain and return.
*/
- if (select_count == 0) /* We really had nothing to do */
- {
+ if (select_count == 0) { /* We really had nothing to do */
#ifdef DEBUG
if (debug)
- netsyslog(LOG_DEBUG, "input_handler: select() returned 0");
+ msyslog(LOG_DEBUG, "input_handler: select() returned 0");
#endif
return;
}
- /* We've done our work */
+ /* We've done our work */
#ifdef DEBUG_TIMING
get_systime(&ts_e);
/*
@@ -3210,44 +3648,43 @@ input_handler(
L_SUB(&ts_e, &ts);
collect_timing(NULL, "input handler", 1, &ts_e);
if (debug > 3)
- netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
+ msyslog(LOG_DEBUG,
+ "input_handler: Processed a gob of fd's in %s msec",
+ lfptoms(&ts_e, 6));
#endif
/* just bail. */
return;
}
-
#endif
/*
* findinterface - find local interface corresponding to address
*/
-struct interface *
+endpt *
findinterface(
- struct sockaddr_storage *addr
+ sockaddr_u *addr
)
{
- struct interface *interface;
+ endpt *iface;
- interface = findlocalinterface(addr, INT_WILDCARD);
+ iface = findlocalinterface(addr, INT_WILDCARD, 0);
- if (interface == NULL)
- {
+ if (NULL == iface) {
DPRINTF(4, ("Found no interface for address %s - returning wildcard\n",
stoa(addr)));
- return (ANY_INTERFACE_CHOOSE(addr));
- }
- else
- {
+ iface = ANY_INTERFACE_CHOOSE(addr);
+ } else
DPRINTF(4, ("Found interface #%d %s for address %s\n",
- interface->ifnum, interface->name, stoa(addr)));
+ iface->ifnum, iface->name, stoa(addr)));
- return (interface);
- }
+ return iface;
}
/*
- * findlocalinterface - find local interface index corresponding to address
+ * findlocalinterface - find local interface corresponding to addr,
+ * which does not have any of flags set. If bast is nonzero, addr is
+ * a broadcast address.
*
* This code attempts to find the local sending address for an outgoing
* address by connecting a new socket to destinationaddress:NTP_PORT
@@ -3259,246 +3696,301 @@ findinterface(
* logic in ntpd which would be a silly and really unportable thing to do.
*
*/
-static struct interface *
+static endpt *
findlocalinterface(
- struct sockaddr_storage *addr,
- int flags
+ sockaddr_u * addr,
+ int flags,
+ int bcast
)
{
- SOCKET s;
- int rtn;
- struct sockaddr_storage saddr;
- GETSOCKNAME_SOCKLEN_TYPE saddrlen = SOCKLEN(addr);
- struct interface *iface;
+ GETSOCKNAME_SOCKLEN_TYPE sockaddrlen;
+ endpt * iface;
+ sockaddr_u saddr;
+ SOCKET s;
+ int rtn;
+ int on;
DPRINTF(4, ("Finding interface for addr %s in list of addresses\n",
stoa(addr)));
-
- memset(&saddr, 0, sizeof(saddr));
- saddr.ss_family = addr->ss_family;
- if(addr->ss_family == AF_INET) {
- memcpy(&((struct sockaddr_in*)&saddr)->sin_addr, &((struct sockaddr_in*)addr)->sin_addr, sizeof(struct in_addr));
- ((struct sockaddr_in*)&saddr)->sin_port = htons(NTP_PORT);
- }
-#ifdef INCLUDE_IPV6_SUPPORT
- else if(addr->ss_family == AF_INET6) {
- memcpy(&((struct sockaddr_in6*)&saddr)->sin6_addr, &((struct sockaddr_in6*)addr)->sin6_addr, sizeof(struct in6_addr));
- ((struct sockaddr_in6*)&saddr)->sin6_port = htons(NTP_PORT);
-# ifdef ISC_PLATFORM_HAVESCOPEID
- ((struct sockaddr_in6*)&saddr)->sin6_scope_id = ((struct sockaddr_in6*)addr)->sin6_scope_id;
-# endif
- }
-#endif
- s = socket(addr->ss_family, SOCK_DGRAM, 0);
- if (s == INVALID_SOCKET)
+ s = socket(AF(addr), SOCK_DGRAM, 0);
+ if (INVALID_SOCKET == s)
return NULL;
- rtn = connect(s, (struct sockaddr *)&saddr, SOCKLEN(&saddr));
-#ifndef SYS_WINNT
- if (rtn < 0)
-#else
- if (rtn == SOCKET_ERROR)
-#endif
- {
+ /*
+ * If we are looking for broadcast interface we need to set this
+ * socket to allow broadcast
+ */
+ if (bcast) {
+ on = 1;
+ setsockopt(s, SOL_SOCKET, SO_BROADCAST,
+ (char *)&on, sizeof(on));
+ }
+
+ rtn = connect(s, &addr->sa, SOCKLEN(addr));
+ if (SOCKET_ERROR == rtn) {
closesocket(s);
return NULL;
}
- rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen);
+ sockaddrlen = sizeof(saddr);
+ rtn = getsockname(s, &saddr.sa, &sockaddrlen);
closesocket(s);
-#ifndef SYS_WINNT
- if (rtn < 0)
-#else
- if (rtn == SOCKET_ERROR)
-#endif
+ if (SOCKET_ERROR == rtn)
return NULL;
- DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n", stoa(addr), stoa(&saddr)));
+ DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n",
+ stoa(addr), stoa(&saddr)));
iface = getinterface(&saddr, flags);
- /* Don't both with ignore interfaces */
- if (iface != NULL && iface->ignore_packets == ISC_TRUE)
- {
- return NULL;
- }
- else
- {
- return iface;
- }
+ /*
+ * if we didn't find an exact match on saddr, find the closest
+ * available local address. This handles the case of the
+ * address suggested by the kernel being excluded by nic rules
+ * or the user's -I and -L options to ntpd.
+ * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683
+ * for more background.
+ */
+ if (NULL == iface || iface->ignore_packets)
+ iface = findclosestinterface(&saddr,
+ flags | INT_LOOPBACK);
+
+ /* Don't use an interface which will ignore replies */
+ if (iface != NULL && iface->ignore_packets)
+ iface = NULL;
+
+ return iface;
}
+
/*
- * fetch an interface structure the matches the
- * address is has the given flags not set
+ * findclosestinterface
+ *
+ * If there are -I/--interface or -L/novirtualips command-line options,
+ * or "nic" or "interface" rules in ntp.conf, findlocalinterface() may
+ * find the kernel's preferred local address for a given peer address is
+ * administratively unavailable to ntpd, and punt to this routine's more
+ * expensive search.
+ *
+ * Find the numerically closest local address to the one connect()
+ * suggested. This matches an address on the same subnet first, as
+ * needed by Bug 1184, and provides a consistent choice if there are
+ * multiple feasible local addresses, regardless of the order ntpd
+ * enumerated them.
*/
-static struct interface *
-getinterface(struct sockaddr_storage *addr, int flags)
+static endpt *
+findclosestinterface(
+ sockaddr_u * addr,
+ int flags
+ )
{
- struct interface *interface = find_addr_in_list(addr);
+ endpt * ep;
+ endpt * winner;
+ sockaddr_u addr_dist;
+ sockaddr_u min_dist;
- if (interface != NULL && interface->flags & flags)
- {
- return NULL;
+ winner = NULL;
+
+ for (ep = ep_list; ep != NULL; ep = ep->elink) {
+ if (ep->ignore_packets ||
+ AF(addr) != ep->family ||
+ flags & ep->flags)
+ continue;
+
+ calc_addr_distance(&addr_dist, addr, &ep->sin);
+ if (NULL == winner ||
+ -1 == cmp_addr_distance(&addr_dist, &min_dist)) {
+ min_dist = addr_dist;
+ winner = ep;
+ }
}
+ if (NULL == winner)
+ DPRINTF(4, ("findclosestinterface(%s) failed\n",
+ stoa(addr)));
else
- {
- return interface;
- }
+ DPRINTF(4, ("findclosestinterface(%s) -> %s\n",
+ stoa(addr), stoa(&winner->sin)));
+
+ return winner;
}
+
/*
- * findlocalcastinterface - find local *cast interface index corresponding to address
- * depending on the flags passed
+ * calc_addr_distance - calculate the distance between two addresses,
+ * the absolute value of the difference between
+ * the addresses numerically, stored as an address.
*/
-static struct interface *
-findlocalcastinterface(
- struct sockaddr_storage *addr, int flags
+static void
+calc_addr_distance(
+ sockaddr_u * dist,
+ const sockaddr_u * a1,
+ const sockaddr_u * a2
)
{
- struct interface *interface;
- struct interface *nif = NULL;
-#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- isc_boolean_t want_linklocal;
-#endif
+ u_int32 a1val;
+ u_int32 a2val;
+ u_int32 v4dist;
+ int found_greater;
+ int a1_greater;
+ int i;
+
+ NTP_REQUIRE(AF(a1) == AF(a2));
+
+ memset(dist, 0, sizeof(*dist));
+ AF(dist) = AF(a1);
+
+ /* v4 can be done a bit simpler */
+ if (IS_IPV4(a1)) {
+ a1val = SRCADR(a1);
+ a2val = SRCADR(a2);
+ v4dist = (a1val > a2val)
+ ? a1val - a2val
+ : a2val - a1val;
+ SET_ADDR4(dist, v4dist);
- /*
- * see how kernel maps the mcast address
- */
- nif = findlocalinterface(addr, 0);
-
- if (nif) {
- DPRINTF(2, ("findlocalcastinterface: kernel recommends interface #%d %s\n", nif->ifnum, nif->name));
- return nif;
+ return;
}
-#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- want_linklocal = ISC_FALSE;
- if (addr_ismulticast(addr) && flags == INT_MULTICAST)
- {
- if (IN6_IS_ADDR_MC_LINKLOCAL(&((struct sockaddr_in6*)addr)->sin6_addr))
- {
- want_linklocal = ISC_TRUE;
+ found_greater = FALSE;
+ a1_greater = FALSE; /* suppress pot. uninit. warning */
+ for (i = 0; i < sizeof(NSRCADR6(a1)); i++) {
+ if (!found_greater &&
+ NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) {
+ found_greater = TRUE;
+ a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]);
}
- else if (IN6_IS_ADDR_MC_SITELOCAL(&((struct sockaddr_in6*)addr)->sin6_addr))
- {
- want_linklocal = ISC_TRUE;
+ if (!found_greater) {
+ NSRCADR6(dist)[i] = 0;
+ } else {
+ if (a1_greater)
+ NSRCADR6(dist)[i] = NSRCADR6(a1)[i] -
+ NSRCADR6(a2)[i];
+ else
+ NSRCADR6(dist)[i] = NSRCADR6(a2)[i] -
+ NSRCADR6(a1)[i];
}
}
-#endif
-
- for (interface = ISC_LIST_HEAD(inter_list);
- interface != NULL;
- interface = ISC_LIST_NEXT(interface, link))
- {
- /* use only allowed addresses */
- if (interface->ignore_packets == ISC_TRUE)
- continue;
+}
- /* Skip the loopback and wildcard addresses */
- if (interface->flags & (INT_LOOPBACK|INT_WILDCARD))
- continue;
- /* Skip if different family */
- if(interface->sin.ss_family != addr->ss_family)
- continue;
+/*
+ * cmp_addr_distance - compare two address distances, returning -1, 0,
+ * 1 to indicate their relationship.
+ */
+static int
+cmp_addr_distance(
+ const sockaddr_u * d1,
+ const sockaddr_u * d2
+ )
+{
+ int i;
- /* Is this it one of these based on flags? */
- if (!(interface->flags & flags))
- continue;
+ NTP_REQUIRE(AF(d1) == AF(d2));
- /* for IPv6 multicast check the address for linklocal */
-#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
- if (flags == INT_MULTICAST && interface->sin.ss_family == AF_INET6 &&
- (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&interface->sin)->sin6_addr))
- && want_linklocal == ISC_TRUE)
- {
- nif = interface;
- break;
- }
- /* If we want a linklocal address and this isn't it, skip */\
- if (want_linklocal == ISC_TRUE)
- continue;
-#endif
- /* Otherwise just look for the flag */
- if((interface->flags & flags))
- {
- nif = interface;
- break;
- }
- }
-#ifdef DEBUG
- if (debug > 2)
- {
- if (nif)
- printf("findlocalcastinterface: found interface #%d %s\n", nif->ifnum, nif->name);
+ if (IS_IPV4(d1)) {
+ if (SRCADR(d1) < SRCADR(d2))
+ return -1;
+ else if (SRCADR(d1) == SRCADR(d2))
+ return 0;
else
- printf("findlocalcastinterface: no interface found for %s flags 0x%x\n", stoa(addr), flags);
+ return 1;
}
-#endif
- return (nif);
+
+ for (i = 0; i < sizeof(NSRCADR6(d1)); i++) {
+ if (NSRCADR6(d1)[i] < NSRCADR6(d2)[i])
+ return -1;
+ else if (NSRCADR6(d1)[i] > NSRCADR6(d2)[i])
+ return 1;
+ }
+
+ return 0;
}
+
+
+/*
+ * fetch an interface structure the matches the
+ * address and has the given flags NOT set
+ */
+static endpt *
+getinterface(
+ sockaddr_u * addr,
+ u_int32 flags
+ )
+{
+ endpt *iface;
+
+ iface = find_addr_in_list(addr);
+
+ if (iface != NULL && (iface->flags & flags))
+ iface = NULL;
+
+ return iface;
+}
+
+
/*
* findbcastinter - find broadcast interface corresponding to address
*/
-struct interface *
+endpt *
findbcastinter(
- struct sockaddr_storage *addr
+ sockaddr_u *addr
)
{
#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
- struct interface *interface;
+ struct interface *iface;
DPRINTF(4, ("Finding broadcast/multicast interface for addr %s in list of addresses\n",
stoa(addr)));
- interface = findlocalinterface(addr, INT_LOOPBACK|INT_WILDCARD);
-
- if (interface != NULL)
- {
- DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n", interface->ifnum, interface->name));
- return interface;
+ iface = findlocalinterface(addr, INT_LOOPBACK | INT_WILDCARD,
+ 1);
+ if (iface != NULL) {
+ DPRINTF(4, ("Easily found bcast-/mcast- interface index #%d %s\n",
+ iface->ifnum, iface->name));
+ return iface;
}
- /* plan B - try to find something reasonable in our lists in case kernel lookup doesn't help */
-
- for (interface = ISC_LIST_HEAD(inter_list);
- interface != NULL;
- interface = ISC_LIST_NEXT(interface, link))
- {
- if (interface->flags & INT_WILDCARD)
- continue;
+ /*
+ * plan B - try to find something reasonable in our lists in
+ * case kernel lookup doesn't help
+ */
+ for (iface = ep_list; iface != NULL; iface = iface->elink) {
+ if (iface->flags & INT_WILDCARD)
+ continue;
/* Don't bother with ignored interfaces */
- if (interface->ignore_packets == ISC_TRUE)
+ if (iface->ignore_packets)
continue;
/*
* First look if this is the correct family
*/
- if(interface->sin.ss_family != addr->ss_family)
- continue;
+ if(AF(&iface->sin) != AF(addr))
+ continue;
/* Skip the loopback addresses */
- if (interface->flags & INT_LOOPBACK)
+ if (iface->flags & INT_LOOPBACK)
continue;
/*
- * If we are looking to match a multicast address grab it.
+ * If we are looking to match a multicast address and
+ * this interface is one...
*/
- if (addr_ismulticast(addr) == ISC_TRUE && interface->flags & INT_MULTICAST)
- {
+ if (addr_ismulticast(addr)
+ && (iface->flags & INT_MULTICAST)) {
#ifdef INCLUDE_IPV6_SUPPORT
- if(addr->ss_family == AF_INET6) {
- /* Only use link-local address for link-scope mcast */
- if(IN6_IS_ADDR_MC_LINKLOCAL(&((struct sockaddr_in6*)addr)->sin6_addr) &&
- !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&interface->sin)->sin6_addr)) {
- continue;
- }
- }
+ /*
+ * ...it is the winner unless we're looking for
+ * an interface to use for link-local multicast
+ * and its address is not link-local.
+ */
+ if (IS_IPV6(addr)
+ && IN6_IS_ADDR_MC_LINKLOCAL(PSOCK_ADDR6(addr))
+ && !IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&iface->sin)))
+ continue;
#endif
break;
}
@@ -3509,34 +4001,33 @@ findbcastinter(
* address or the network portion of the IP address.
* Sloppy.
*/
- if(addr->ss_family == AF_INET) {
- if (SOCKCMP(&interface->bcast, addr)) {
+ if (IS_IPV4(addr)) {
+ if (SOCK_EQ(&iface->bcast, addr))
break;
- }
- if ((NSRCADR(&interface->sin) &
- NSRCADR(&interface->mask)) == (NSRCADR(addr) &
- NSRCADR(&interface->mask)))
+
+ if ((NSRCADR(&iface->sin) & NSRCADR(&iface->mask))
+ == (NSRCADR(addr) & NSRCADR(&iface->mask)))
break;
}
#ifdef INCLUDE_IPV6_SUPPORT
- else if(addr->ss_family == AF_INET6) {
- if (SOCKCMP(&interface->bcast, addr)) {
+ else if (IS_IPV6(addr)) {
+ if (SOCK_EQ(&iface->bcast, addr))
break;
- }
- if (SOCKCMP(netof(&interface->sin), netof(addr))) {
+
+ if (SOCK_EQ(netof(&iface->sin), netof(addr)))
break;
- }
}
#endif
}
#endif /* SIOCGIFCONF */
- if (interface == NULL) {
- DPRINTF(4, ("No bcast interface found for %s\n", stoa(addr)));
- return ANY_INTERFACE_CHOOSE(addr);
- } else {
- DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n", interface->ifnum, interface->name));
- return interface;
- }
+ if (NULL == iface) {
+ DPRINTF(4, ("No bcast interface found for %s\n",
+ stoa(addr)));
+ iface = ANY_INTERFACE_CHOOSE(addr);
+ } else
+ DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n",
+ iface->ifnum, iface->name));
+ return iface;
}
@@ -3569,21 +4060,20 @@ io_addclock(
)
{
BLOCKIO();
+
/*
* Stuff the I/O structure in the list and mark the descriptor
- * in use. There is a harmless (I hope) race condition here.
+ * in use. There is a harmless (I hope) race condition here.
*/
rio->next = refio;
# ifdef HAVE_SIGNALED_IO
- if (init_clock_sig(rio))
- {
+ if (init_clock_sig(rio)) {
UNBLOCKIO();
return 0;
}
# elif defined(HAVE_IO_COMPLETION_PORT)
- if (io_completion_port_add_clock_io(rio))
- {
+ if (io_completion_port_add_clock_io(rio)) {
UNBLOCKIO();
return 0;
}
@@ -3594,7 +4084,7 @@ io_addclock(
*/
refio = rio;
- /*
+ /*
* register fd
*/
add_fd_to_list(rio->fd, FD_TYPE_FILE);
@@ -3611,26 +4101,23 @@ io_closeclock(
struct refclockio *rio
)
{
+ register struct refclockio *rp;
+
BLOCKIO();
+
/*
* Remove structure from the list
*/
if (refio == rio)
- {
refio = rio->next;
- }
- else
- {
- register struct refclockio *rp;
-
+ else {
for (rp = refio; rp != NULL; rp = rp->next)
- if (rp->next == rio)
- {
- rp->next = rio->next;
- break;
- }
+ if (rp->next == rio) {
+ rp->next = rio->next;
+ break;
+ }
- if (rp == NULL) {
+ if (NULL == rp) {
UNBLOCKIO();
return;
}
@@ -3648,230 +4135,268 @@ io_closeclock(
* On NT a SOCKET is an unsigned int so we cannot possibly keep it in
* an array. So we use one of the ISC_LIST functions to hold the
* socket value and use that when we want to enumerate it.
+ *
+ * This routine is called by the forked intres child process to close
+ * all open sockets. On Windows there's no need as intres runs in
+ * the same process as a thread.
*/
+#ifndef SYS_WINNT
void
kill_asyncio(int startfd)
{
- vsock_t *lsock;
- vsock_t *next;
-
BLOCKIO();
- lsock = ISC_LIST_HEAD(fd_list);
- while (lsock != NULL) {
- /*
- * careful here - list is being dismantled while
- * we scan it - setting next here insures that
- * we are able to correctly scan the list
- */
- next = ISC_LIST_NEXT(lsock, link);
- /*
- * will remove socket from list
- */
- close_and_delete_fd_from_list(lsock->fd);
- lsock = next;
- }
+ /*
+ * In the child process we do not maintain activefds and
+ * maxactivefd. Zeroing maxactivefd disables code which
+ * maintains it in close_and_delete_fd_from_list().
+ */
+ maxactivefd = 0;
+
+ while (fd_list != NULL)
+ close_and_delete_fd_from_list(fd_list->fd);
UNBLOCKIO();
}
+#endif /* !SYS_WINNT */
/*
* Add and delete functions for the list of open sockets
*/
static void
-add_fd_to_list(SOCKET fd, enum desc_type type) {
- vsock_t *lsock = (vsock_t *)emalloc(sizeof(vsock_t));
+add_fd_to_list(
+ SOCKET fd,
+ enum desc_type type
+ )
+{
+ vsock_t *lsock = emalloc(sizeof(*lsock));
+
lsock->fd = fd;
lsock->type = type;
- ISC_LIST_APPEND(fd_list, lsock, link);
+ LINK_SLIST(fd_list, lsock, link);
/*
* I/O Completion Ports don't care about the select and FD_SET
*/
#ifndef HAVE_IO_COMPLETION_PORT
if (fd < 0 || fd >= FD_SETSIZE) {
- msyslog(LOG_ERR, "Too many sockets in use, FD_SETSIZE %d exceeded",
+ msyslog(LOG_ERR,
+ "Too many sockets in use, FD_SETSIZE %d exceeded",
FD_SETSIZE);
exit(1);
}
/*
* keep activefds in sync
*/
- if (fd > maxactivefd)
- maxactivefd = fd;
- FD_SET( (u_int)fd, &activefds);
+ maxactivefd = max(fd, maxactivefd);
+
+ FD_SET(fd, &activefds);
#endif
}
static void
-close_and_delete_fd_from_list(SOCKET fd) {
+close_and_delete_fd_from_list(
+ SOCKET fd
+ )
+{
+ vsock_t *lsock;
+
+ UNLINK_EXPR_SLIST(lsock, fd_list, fd ==
+ UNLINK_EXPR_SLIST_CURRENT()->fd, link, vsock_t);
- vsock_t *next;
- vsock_t *lsock = ISC_LIST_HEAD(fd_list);
+ if (lsock != NULL) {
+ switch (lsock->type) {
+ case FD_TYPE_SOCKET:
+ closesocket(lsock->fd);
+ break;
- while(lsock != NULL) {
- next = ISC_LIST_NEXT(lsock, link);
- if(lsock->fd == fd) {
- ISC_LIST_DEQUEUE_TYPE(fd_list, lsock, link, vsock_t);
+ case FD_TYPE_FILE:
+ close(lsock->fd);
+ break;
- switch (lsock->type) {
- case FD_TYPE_SOCKET:
-#ifdef SYS_WINNT
- closesocket(lsock->fd);
- break;
-#endif
- case FD_TYPE_FILE:
- (void) close(lsock->fd);
- break;
- default:
- msyslog(LOG_ERR, "internal error - illegal descriptor type %d - EXITING", (int)lsock->type);
- exit(1);
- }
+ default:
+ msyslog(LOG_ERR,
+ "internal error - illegal descriptor type %d - EXITING",
+ (int)lsock->type);
+ exit(1);
+ }
- free(lsock);
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
+ free(lsock);
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
#ifndef HAVE_IO_COMPLETION_PORT
- /*
- * remove from activefds
- */
- FD_CLR( (u_int) fd, &activefds);
-
- if (fd == maxactivefd) {
- int i, newmax = 0;
- for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
- maxactivefd = newmax;
- }
-#endif
- break;
+ /*
+ * remove from activefds
+ */
+ FD_CLR(fd, &activefds);
+
+ if (fd == maxactivefd && maxactivefd) {
+ int i;
+ NTP_INSIST(maxactivefd - 1 < FD_SETSIZE);
+ for (i = maxactivefd - 1; i >= 0; i--)
+ if (FD_ISSET(i, &activefds)) {
+ maxactivefd = i;
+ break;
+ }
+ NTP_INSIST(fd != maxactivefd);
}
- lsock = next;
+#endif
}
}
static void
-add_addr_to_list(struct sockaddr_storage *addr, struct interface *interface){
+add_addr_to_list(
+ sockaddr_u * addr,
+ endpt * ep
+ )
+{
+ remaddr_t *laddr;
+
#ifdef DEBUG
if (find_addr_in_list(addr) == NULL) {
#endif
/* not there yet - add to list */
- remaddr_t *laddr = (remaddr_t *)emalloc(sizeof(remaddr_t));
- memcpy(&laddr->addr, addr, sizeof(struct sockaddr_storage));
- laddr->interface = interface;
+ laddr = emalloc(sizeof(*laddr));
+ laddr->addr = *addr;
+ laddr->ep = ep;
- ISC_LIST_APPEND(remoteaddr_list, laddr, link);
+ LINK_SLIST(remoteaddr_list, laddr, link);
DPRINTF(4, ("Added addr %s to list of addresses\n",
stoa(addr)));
#ifdef DEBUG
- } else {
+ } else
DPRINTF(4, ("WARNING: Attempt to add duplicate addr %s to address list\n",
stoa(addr)));
- }
#endif
}
+
static void
-delete_addr_from_list(struct sockaddr_storage *addr) {
-
- remaddr_t *next;
- remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
-
- while(laddr != NULL) {
- next = ISC_LIST_NEXT(laddr, link);
- if(SOCKCMP(&laddr->addr, addr)) {
- ISC_LIST_DEQUEUE_TYPE(remoteaddr_list, laddr, link, remaddr_t);
- DPRINTF(4, ("Deleted addr %s from list of addresses\n",
- stoa(addr)));
- free(laddr);
- break;
- }
- laddr = next;
+delete_addr_from_list(
+ sockaddr_u *addr
+ )
+{
+ remaddr_t *unlinked;
+
+ UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, SOCK_EQ(addr,
+ &(UNLINK_EXPR_SLIST_CURRENT()->addr)), link, remaddr_t);
+
+ if (unlinked != NULL) {
+ DPRINTF(4, ("Deleted addr %s from list of addresses\n",
+ stoa(addr)));
+ free(unlinked);
}
}
+
static void
-delete_interface_from_list(struct interface *iface) {
- remaddr_t *next;
- remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
-
- while(laddr != NULL) {
- next = ISC_LIST_NEXT(laddr, link);
- if (laddr->interface == iface) {
- ISC_LIST_DEQUEUE_TYPE(remoteaddr_list, laddr, link, remaddr_t);
+delete_interface_from_list(
+ endpt *iface
+ )
+{
+ remaddr_t *unlinked;
+
+ do {
+ UNLINK_EXPR_SLIST(unlinked, remoteaddr_list, iface ==
+ UNLINK_EXPR_SLIST_CURRENT()->ep, link,
+ remaddr_t);
+
+ if (unlinked != NULL) {
DPRINTF(4, ("Deleted addr %s for interface #%d %s from list of addresses\n",
- stoa(&laddr->addr), iface->ifnum, iface->name));
- free(laddr);
+ stoa(&unlinked->addr), iface->ifnum,
+ iface->name));
+ free(unlinked);
}
- laddr = next;
- }
+ } while (unlinked != NULL);
}
-static struct interface *
-find_addr_in_list(struct sockaddr_storage *addr) {
- remaddr_t *next;
- remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
+static struct interface *
+find_addr_in_list(
+ sockaddr_u *addr
+ )
+{
+ remaddr_t *entry;
+
DPRINTF(4, ("Searching for addr %s in list of addresses - ",
stoa(addr)));
- while(laddr != NULL) {
- next = ISC_LIST_NEXT(laddr, link);
- if(SOCKCMP(&laddr->addr, addr)) {
+ for (entry = remoteaddr_list;
+ entry != NULL;
+ entry = entry->link)
+ if (SOCK_EQ(&entry->addr, addr)) {
DPRINTF(4, ("FOUND\n"));
- return laddr->interface;
+ return entry->ep;
}
- else
- laddr = next;
- }
+
DPRINTF(4, ("NOT FOUND\n"));
- return NULL; /* Not found */
+ return NULL;
}
+
/*
- * Find the given address with the associated flag in the list
+ * Find the given address with the all given flags set in the list
*/
-static struct interface *
-find_flagged_addr_in_list(struct sockaddr_storage *addr, int flag) {
+static endpt *
+find_flagged_addr_in_list(
+ sockaddr_u * addr,
+ u_int32 flags
+ )
+{
+ remaddr_t *entry;
+
+ DPRINTF(4, ("Finding addr %s with flags %d in list: ",
+ stoa(addr), flags));
- remaddr_t *next;
- remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
- DPRINTF(4, ("Finding addr %s in list of addresses\n",
- stoa(addr)));
+ for (entry = remoteaddr_list;
+ entry != NULL;
+ entry = entry->link)
- while(laddr != NULL) {
- next = ISC_LIST_NEXT(laddr, link);
- if(SOCKCMP(&laddr->addr, addr) && (laddr->interface->flags & flag)) {
- return laddr->interface;
- break;
+ if (SOCK_EQ(&entry->addr, addr)
+ && (entry->ep->flags & flags) == flags) {
+
+ DPRINTF(4, ("FOUND\n"));
+ return entry->ep;
}
- else
- laddr = next;
- }
- return NULL; /* Not found */
+
+ DPRINTF(4, ("NOT FOUND\n"));
+ return NULL;
}
-#ifdef HAS_ROUTING_SOCKET
-#include <net/route.h>
-#ifndef UPDATE_GRACE
-#define UPDATE_GRACE 2 /* wait UPDATE_GRACE seconds before scanning */
-#endif
+const char *
+localaddrtoa(
+ endpt *la
+ )
+{
+ return (NULL == la)
+ ? "<null>"
+ : stoa(&la->sin);
+}
+
+
+#ifdef HAS_ROUTING_SOCKET
+# ifndef UPDATE_GRACE
+# define UPDATE_GRACE 2 /* wait UPDATE_GRACE seconds before scanning */
+# endif
static void
process_routing_msgs(struct asyncio_reader *reader)
{
char buffer[5120];
- char *p = buffer;
-
- int cnt;
+ int cnt, msg_type;
+#ifdef HAVE_RTNETLINK
+ struct nlmsghdr *nh;
+#else
+ struct rt_msghdr *rtm;
+ char *p;
+#endif
if (disable_dynamic_updates) {
/*
- * discard ourselves if we are not need any more
+ * discard ourselves if we are not needed any more
* usually happens when running unprivileged
*/
remove_asyncio_reader(reader);
@@ -3882,7 +4407,8 @@ process_routing_msgs(struct asyncio_reader *reader)
cnt = read(reader->fd, buffer, sizeof(buffer));
if (cnt < 0) {
- msyslog(LOG_ERR, "i/o error on routing socket %m - disabling");
+ msyslog(LOG_ERR,
+ "i/o error on routing socket %m - disabling");
remove_asyncio_reader(reader);
delete_asyncio_reader(reader);
return;
@@ -3891,19 +4417,28 @@ process_routing_msgs(struct asyncio_reader *reader)
/*
* process routing message
*/
- while ((p + sizeof(struct rt_msghdr)) <= (buffer + cnt))
- {
- struct rt_msghdr *rtm;
-
+#ifdef HAVE_RTNETLINK
+ for (nh = (struct nlmsghdr *)buffer;
+ NLMSG_OK(nh, cnt);
+ nh = NLMSG_NEXT(nh, cnt)) {
+ msg_type = nh->nlmsg_type;
+#else
+ for (p = buffer;
+ (p + sizeof(struct rt_msghdr)) <= (buffer + cnt);
+ p += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)p;
if (rtm->rtm_version != RTM_VERSION) {
- msyslog(LOG_ERR, "version mismatch on routing socket %m - disabling");
+ msyslog(LOG_ERR,
+ "version mismatch (got %d - expected %d) on routing socket - disabling",
+ rtm->rtm_version, RTM_VERSION);
+
remove_asyncio_reader(reader);
delete_asyncio_reader(reader);
return;
}
-
- switch (rtm->rtm_type) {
+ msg_type = rtm->rtm_type;
+#endif
+ switch (msg_type) {
#ifdef RTM_NEWADDR
case RTM_NEWADDR:
#endif
@@ -3931,20 +4466,40 @@ process_routing_msgs(struct asyncio_reader *reader)
#ifdef RTM_IFANNOUNCE
case RTM_IFANNOUNCE:
#endif
+#ifdef RTM_NEWLINK
+ case RTM_NEWLINK:
+#endif
+#ifdef RTM_DELLINK
+ case RTM_DELLINK:
+#endif
+#ifdef RTM_NEWROUTE
+ case RTM_NEWROUTE:
+#endif
+#ifdef RTM_DELROUTE
+ case RTM_DELROUTE:
+#endif
/*
- * we are keen on new and deleted addresses and if an interface goes up and down or routing changes
+ * we are keen on new and deleted addresses and
+ * if an interface goes up and down or routing
+ * changes
*/
- DPRINTF(3, ("routing message op = %d: scheduling interface update\n", rtm->rtm_type));
+ DPRINTF(3, ("routing message op = %d: scheduling interface update\n",
+ msg_type));
timer_interfacetimeout(current_time + UPDATE_GRACE);
break;
+#ifdef HAVE_RTNETLINK
+ case NLMSG_DONE:
+ /* end of multipart message */
+ return;
+#endif
default:
/*
* the rest doesn't bother us.
*/
- DPRINTF(4, ("routing message op = %d: ignored\n", rtm->rtm_type));
+ DPRINTF(4, ("routing message op = %d: ignored\n",
+ msg_type));
break;
}
- p += rtm->rtm_msglen;
}
}
@@ -3955,29 +4510,51 @@ static void
init_async_notifications()
{
struct asyncio_reader *reader;
+#ifdef HAVE_RTNETLINK
+ int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ struct sockaddr_nl sa;
+#else
int fd = socket(PF_ROUTE, SOCK_RAW, 0);
-
- if (fd >= 0) {
- fd = move_fd(fd);
- init_nonblocking_io(fd);
+#endif
+ if (fd < 0) {
+ msyslog(LOG_ERR,
+ "unable to open routing socket (%m) - using polled interface update");
+ return;
+ }
+
+ fd = move_fd(fd);
+#ifdef HAVE_RTNETLINK
+ memset(&sa, 0, sizeof(sa));
+ sa.nl_family = PF_NETLINK;
+ sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR
+ | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_ROUTE
+ | RTMGRP_IPV4_MROUTE | RTMGRP_IPV6_ROUTE
+ | RTMGRP_IPV6_MROUTE;
+ if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+ msyslog(LOG_ERR,
+ "bind failed on routing socket (%m) - using polled interface update");
+ return;
+ }
+#endif
+ init_nonblocking_io(fd);
#if defined(HAVE_SIGNALED_IO)
- init_socket_sig(fd);
+ init_socket_sig(fd);
#endif /* HAVE_SIGNALED_IO */
-
- reader = new_asyncio_reader();
+
+ reader = new_asyncio_reader();
- reader->fd = fd;
- reader->receiver = process_routing_msgs;
-
- add_asyncio_reader(reader, FD_TYPE_SOCKET);
- msyslog(LOG_INFO, "Listening on routing socket on fd #%d for interface updates", fd);
- } else {
- msyslog(LOG_ERR, "unable to open routing socket (%m) - using polled interface update");
- }
+ reader->fd = fd;
+ reader->receiver = process_routing_msgs;
+
+ add_asyncio_reader(reader, FD_TYPE_SOCKET);
+ msyslog(LOG_INFO,
+ "Listening on routing socket on fd #%d for interface updates",
+ fd);
}
#else
+/* HAS_ROUTING_SOCKET not defined */
static void
-init_async_notifications()
+init_async_notifications(void)
{
}
#endif
diff --git a/ntpd/ntp_keyword.h b/ntpd/ntp_keyword.h
new file mode 100644
index 000000000000..14ecefae6000
--- /dev/null
+++ b/ntpd/ntp_keyword.h
@@ -0,0 +1,929 @@
+/*
+ * ntp_keyword.h
+ *
+ * NOTE: edit this file with caution, it is generated by keyword-gen.c
+ * Generated 2010-04-06 04:38:11 UTC diff_ignore_line
+ *
+ */
+#include "ntp_scanner.h"
+#include "ntp_parser.h"
+
+#define LOWEST_KEYWORD_ID 258
+
+const char * const keyword_text[163] = {
+ /* 0 258 T_Age */ "age",
+ /* 1 259 T_All */ "all",
+ /* 2 260 T_Allan */ "allan",
+ /* 3 261 T_Auth */ "auth",
+ /* 4 262 T_Autokey */ "autokey",
+ /* 5 263 T_Automax */ "automax",
+ /* 6 264 T_Average */ "average",
+ /* 7 265 T_Bclient */ "bclient",
+ /* 8 266 T_Beacon */ "beacon",
+ /* 9 267 T_Bias */ "bias",
+ /* 10 268 T_Broadcast */ "broadcast",
+ /* 11 269 T_Broadcastclient */ "broadcastclient",
+ /* 12 270 T_Broadcastdelay */ "broadcastdelay",
+ /* 13 271 T_Burst */ "burst",
+ /* 14 272 T_Calibrate */ "calibrate",
+ /* 15 273 T_Calldelay */ "calldelay",
+ /* 16 274 T_Ceiling */ "ceiling",
+ /* 17 275 T_Clockstats */ "clockstats",
+ /* 18 276 T_Cohort */ "cohort",
+ /* 19 277 T_ControlKey */ "controlkey",
+ /* 20 278 T_Crypto */ "crypto",
+ /* 21 279 T_Cryptostats */ "cryptostats",
+ /* 22 280 T_Day */ "day",
+ /* 23 281 T_Default */ "default",
+ /* 24 282 T_Digest */ "digest",
+ /* 25 283 T_Disable */ "disable",
+ /* 26 284 T_Discard */ "discard",
+ /* 27 285 T_Dispersion */ "dispersion",
+ /* 28 286 T_Double */ NULL,
+ /* 29 287 T_Driftfile */ "driftfile",
+ /* 30 288 T_Drop */ "drop",
+ /* 31 289 T_Ellipsis */ "...",
+ /* 32 290 T_Enable */ "enable",
+ /* 33 291 T_End */ "end",
+ /* 34 292 T_False */ NULL,
+ /* 35 293 T_File */ "file",
+ /* 36 294 T_Filegen */ "filegen",
+ /* 37 295 T_Flag1 */ "flag1",
+ /* 38 296 T_Flag2 */ "flag2",
+ /* 39 297 T_Flag3 */ "flag3",
+ /* 40 298 T_Flag4 */ "flag4",
+ /* 41 299 T_Flake */ "flake",
+ /* 42 300 T_Floor */ "floor",
+ /* 43 301 T_Freq */ "freq",
+ /* 44 302 T_Fudge */ "fudge",
+ /* 45 303 T_Host */ "host",
+ /* 46 304 T_Huffpuff */ "huffpuff",
+ /* 47 305 T_Iburst */ "iburst",
+ /* 48 306 T_Ident */ "ident",
+ /* 49 307 T_Ignore */ "ignore",
+ /* 50 308 T_Includefile */ "includefile",
+ /* 51 309 T_Integer */ NULL,
+ /* 52 310 T_Interface */ "interface",
+ /* 53 311 T_Ipv4 */ "ipv4",
+ /* 54 312 T_Ipv4_flag */ "-4",
+ /* 55 313 T_Ipv6 */ "ipv6",
+ /* 56 314 T_Ipv6_flag */ "-6",
+ /* 57 315 T_Kernel */ "kernel",
+ /* 58 316 T_Key */ "key",
+ /* 59 317 T_Keys */ "keys",
+ /* 60 318 T_Keysdir */ "keysdir",
+ /* 61 319 T_Kod */ "kod",
+ /* 62 320 T_Mssntp */ "mssntp",
+ /* 63 321 T_Leapfile */ "leapfile",
+ /* 64 322 T_Limited */ "limited",
+ /* 65 323 T_Link */ "link",
+ /* 66 324 T_Listen */ "listen",
+ /* 67 325 T_Logconfig */ "logconfig",
+ /* 68 326 T_Logfile */ "logfile",
+ /* 69 327 T_Loopstats */ "loopstats",
+ /* 70 328 T_Lowpriotrap */ "lowpriotrap",
+ /* 71 329 T_Manycastclient */ "manycastclient",
+ /* 72 330 T_Manycastserver */ "manycastserver",
+ /* 73 331 T_Mask */ "mask",
+ /* 74 332 T_Maxclock */ "maxclock",
+ /* 75 333 T_Maxdist */ "maxdist",
+ /* 76 334 T_Maxpoll */ "maxpoll",
+ /* 77 335 T_Minclock */ "minclock",
+ /* 78 336 T_Mindist */ "mindist",
+ /* 79 337 T_Minimum */ "minimum",
+ /* 80 338 T_Minpoll */ "minpoll",
+ /* 81 339 T_Minsane */ "minsane",
+ /* 82 340 T_Mode */ "mode",
+ /* 83 341 T_Monitor */ "monitor",
+ /* 84 342 T_Month */ "month",
+ /* 85 343 T_Multicastclient */ "multicastclient",
+ /* 86 344 T_Nic */ "nic",
+ /* 87 345 T_Nolink */ "nolink",
+ /* 88 346 T_Nomodify */ "nomodify",
+ /* 89 347 T_None */ "none",
+ /* 90 348 T_Nopeer */ "nopeer",
+ /* 91 349 T_Noquery */ "noquery",
+ /* 92 350 T_Noselect */ "noselect",
+ /* 93 351 T_Noserve */ "noserve",
+ /* 94 352 T_Notrap */ "notrap",
+ /* 95 353 T_Notrust */ "notrust",
+ /* 96 354 T_Ntp */ "ntp",
+ /* 97 355 T_Ntpport */ "ntpport",
+ /* 98 356 T_NtpSignDsocket */ "ntpsigndsocket",
+ /* 99 357 T_Orphan */ "orphan",
+ /* 100 358 T_Panic */ "panic",
+ /* 101 359 T_Peer */ "peer",
+ /* 102 360 T_Peerstats */ "peerstats",
+ /* 103 361 T_Phone */ "phone",
+ /* 104 362 T_Pid */ "pid",
+ /* 105 363 T_Pidfile */ "pidfile",
+ /* 106 364 T_Pool */ "pool",
+ /* 107 365 T_Port */ "port",
+ /* 108 366 T_Preempt */ "preempt",
+ /* 109 367 T_Prefer */ "prefer",
+ /* 110 368 T_Protostats */ "protostats",
+ /* 111 369 T_Pw */ "pw",
+ /* 112 370 T_Qos */ "qos",
+ /* 113 371 T_Randfile */ "randfile",
+ /* 114 372 T_Rawstats */ "rawstats",
+ /* 115 373 T_Refid */ "refid",
+ /* 116 374 T_Requestkey */ "requestkey",
+ /* 117 375 T_Restrict */ "restrict",
+ /* 118 376 T_Revoke */ "revoke",
+ /* 119 377 T_Saveconfigdir */ "saveconfigdir",
+ /* 120 378 T_Server */ "server",
+ /* 121 379 T_Setvar */ "setvar",
+ /* 122 380 T_Sign */ "sign",
+ /* 123 381 T_Statistics */ "statistics",
+ /* 124 382 T_Stats */ "stats",
+ /* 125 383 T_Statsdir */ "statsdir",
+ /* 126 384 T_Step */ "step",
+ /* 127 385 T_Stepout */ "stepout",
+ /* 128 386 T_Stratum */ "stratum",
+ /* 129 387 T_String */ NULL,
+ /* 130 388 T_Sysstats */ "sysstats",
+ /* 131 389 T_Tick */ "tick",
+ /* 132 390 T_Time1 */ "time1",
+ /* 133 391 T_Time2 */ "time2",
+ /* 134 392 T_Timingstats */ "timingstats",
+ /* 135 393 T_Tinker */ "tinker",
+ /* 136 394 T_Tos */ "tos",
+ /* 137 395 T_Trap */ "trap",
+ /* 138 396 T_True */ "true",
+ /* 139 397 T_Trustedkey */ "trustedkey",
+ /* 140 398 T_Ttl */ "ttl",
+ /* 141 399 T_Type */ "type",
+ /* 142 400 T_Unconfig */ "unconfig",
+ /* 143 401 T_Unpeer */ "unpeer",
+ /* 144 402 T_Version */ "version",
+ /* 145 403 T_WanderThreshold */ NULL,
+ /* 146 404 T_Week */ "week",
+ /* 147 405 T_Wildcard */ "wildcard",
+ /* 148 406 T_Xleave */ "xleave",
+ /* 149 407 T_Year */ "year",
+ /* 150 408 T_Flag */ NULL,
+ /* 151 409 T_Void */ NULL,
+ /* 152 410 T_EOC */ NULL,
+ /* 153 411 T_Simulate */ "simulate",
+ /* 154 412 T_Beep_Delay */ "beep_delay",
+ /* 155 413 T_Sim_Duration */ "simulation_duration",
+ /* 156 414 T_Server_Offset */ "server_offset",
+ /* 157 415 T_Duration */ "duration",
+ /* 158 416 T_Freq_Offset */ "freq_offset",
+ /* 159 417 T_Wander */ "wander",
+ /* 160 418 T_Jitter */ "jitter",
+ /* 161 419 T_Prop_Delay */ "prop_delay",
+ /* 162 420 T_Proc_Delay */ "proc_delay"
+};
+
+#define SCANNER_INIT_S 742
+
+const scan_state sst[745] = {
+/*SS_T( ch, f-by, match, other ), */
+ 0, /* 0 */
+ S_ST( '-', 3, 314, 0 ), /* 1 */
+ S_ST( '.', 3, 3, 1 ), /* 2 */
+ S_ST( '.', 3, 289, 0 ), /* 3 */
+ S_ST( 'a', 3, 15, 2 ), /* 4 */
+ S_ST( 'g', 3, 258, 0 ), /* 5 */
+ S_ST( 'l', 3, 259, 5 ), /* 6 */
+ S_ST( 'a', 3, 260, 0 ), /* 7 */
+ S_ST( 'u', 3, 9, 6 ), /* 8 */
+ S_ST( 't', 3, 10, 0 ), /* 9 */
+ S_ST( 'o', 3, 13, 261 ), /* 10 */
+ S_ST( 'k', 3, 12, 0 ), /* 11 */
+ S_ST( 'e', 3, 262, 0 ), /* 12 */
+ S_ST( 'm', 3, 14, 11 ), /* 13 */
+ S_ST( 'a', 3, 263, 0 ), /* 14 */
+ S_ST( 'v', 3, 16, 8 ), /* 15 */
+ S_ST( 'e', 3, 17, 0 ), /* 16 */
+ S_ST( 'r', 3, 18, 0 ), /* 17 */
+ S_ST( 'a', 3, 19, 0 ), /* 18 */
+ S_ST( 'g', 3, 264, 0 ), /* 19 */
+ S_ST( 'b', 3, 55, 4 ), /* 20 */
+ S_ST( 'c', 3, 22, 0 ), /* 21 */
+ S_ST( 'l', 3, 23, 0 ), /* 22 */
+ S_ST( 'i', 3, 24, 0 ), /* 23 */
+ S_ST( 'e', 3, 25, 0 ), /* 24 */
+ S_ST( 'n', 3, 265, 0 ), /* 25 */
+ S_ST( 'e', 3, 30, 21 ), /* 26 */
+ S_ST( 'a', 3, 28, 0 ), /* 27 */
+ S_ST( 'c', 3, 29, 0 ), /* 28 */
+ S_ST( 'o', 3, 266, 0 ), /* 29 */
+ S_ST( 'e', 3, 31, 27 ), /* 30 */
+ S_ST( 'p', 3, 32, 0 ), /* 31 */
+ S_ST( '_', 3, 33, 0 ), /* 32 */
+ S_ST( 'd', 3, 34, 0 ), /* 33 */
+ S_ST( 'e', 3, 35, 0 ), /* 34 */
+ S_ST( 'l', 3, 36, 0 ), /* 35 */
+ S_ST( 'a', 3, 412, 0 ), /* 36 */
+ S_ST( 'i', 3, 38, 26 ), /* 37 */
+ S_ST( 'a', 3, 267, 0 ), /* 38 */
+ S_ST( 'r', 3, 40, 37 ), /* 39 */
+ S_ST( 'o', 3, 41, 0 ), /* 40 */
+ S_ST( 'a', 3, 42, 0 ), /* 41 */
+ S_ST( 'd', 3, 43, 0 ), /* 42 */
+ S_ST( 'c', 3, 44, 0 ), /* 43 */
+ S_ST( 'a', 3, 45, 0 ), /* 44 */
+ S_ST( 's', 3, 268, 0 ), /* 45 */
+ S_ST( 'c', 3, 47, 0 ), /* 46 */
+ S_ST( 'l', 3, 48, 0 ), /* 47 */
+ S_ST( 'i', 3, 49, 0 ), /* 48 */
+ S_ST( 'e', 3, 50, 0 ), /* 49 */
+ S_ST( 'n', 3, 269, 0 ), /* 50 */
+ S_ST( 'd', 3, 52, 46 ), /* 51 */
+ S_ST( 'e', 3, 53, 0 ), /* 52 */
+ S_ST( 'l', 3, 54, 0 ), /* 53 */
+ S_ST( 'a', 3, 270, 0 ), /* 54 */
+ S_ST( 'u', 3, 56, 39 ), /* 55 */
+ S_ST( 'r', 3, 57, 0 ), /* 56 */
+ S_ST( 's', 3, 271, 0 ), /* 57 */
+ S_ST( 'c', 3, 95, 20 ), /* 58 */
+ S_ST( 'a', 3, 60, 0 ), /* 59 */
+ S_ST( 'l', 3, 66, 0 ), /* 60 */
+ S_ST( 'i', 3, 62, 0 ), /* 61 */
+ S_ST( 'b', 3, 63, 0 ), /* 62 */
+ S_ST( 'r', 3, 64, 0 ), /* 63 */
+ S_ST( 'a', 3, 65, 0 ), /* 64 */
+ S_ST( 't', 3, 272, 0 ), /* 65 */
+ S_ST( 'l', 3, 67, 61 ), /* 66 */
+ S_ST( 'd', 3, 68, 0 ), /* 67 */
+ S_ST( 'e', 3, 69, 0 ), /* 68 */
+ S_ST( 'l', 3, 70, 0 ), /* 69 */
+ S_ST( 'a', 3, 273, 0 ), /* 70 */
+ S_ST( 'e', 3, 72, 59 ), /* 71 */
+ S_ST( 'i', 3, 73, 0 ), /* 72 */
+ S_ST( 'l', 3, 74, 0 ), /* 73 */
+ S_ST( 'i', 3, 75, 0 ), /* 74 */
+ S_ST( 'n', 3, 274, 0 ), /* 75 */
+ S_ST( 'l', 3, 77, 71 ), /* 76 */
+ S_ST( 'o', 3, 78, 0 ), /* 77 */
+ S_ST( 'c', 3, 79, 0 ), /* 78 */
+ S_ST( 'k', 3, 80, 0 ), /* 79 */
+ S_ST( 's', 3, 81, 0 ), /* 80 */
+ S_ST( 't', 3, 82, 0 ), /* 81 */
+ S_ST( 'a', 3, 83, 0 ), /* 82 */
+ S_ST( 't', 3, 275, 0 ), /* 83 */
+ S_ST( 'o', 3, 88, 76 ), /* 84 */
+ S_ST( 'h', 3, 86, 0 ), /* 85 */
+ S_ST( 'o', 3, 87, 0 ), /* 86 */
+ S_ST( 'r', 3, 276, 0 ), /* 87 */
+ S_ST( 'n', 3, 89, 85 ), /* 88 */
+ S_ST( 't', 3, 90, 0 ), /* 89 */
+ S_ST( 'r', 3, 91, 0 ), /* 90 */
+ S_ST( 'o', 3, 92, 0 ), /* 91 */
+ S_ST( 'l', 3, 93, 0 ), /* 92 */
+ S_ST( 'k', 3, 94, 0 ), /* 93 */
+ S_ST( 'e', 3, 277, 0 ), /* 94 */
+ S_ST( 'r', 3, 96, 84 ), /* 95 */
+ S_ST( 'y', 3, 97, 0 ), /* 96 */
+ S_ST( 'p', 3, 98, 0 ), /* 97 */
+ S_ST( 't', 3, 278, 0 ), /* 98 */
+ S_ST( 's', 3, 100, 0 ), /* 99 */
+ S_ST( 't', 3, 101, 0 ), /* 100 */
+ S_ST( 'a', 3, 102, 0 ), /* 101 */
+ S_ST( 't', 3, 279, 0 ), /* 102 */
+ S_ST( 'd', 3, 135, 58 ), /* 103 */
+ S_ST( 'a', 3, 280, 0 ), /* 104 */
+ S_ST( 'e', 3, 106, 104 ), /* 105 */
+ S_ST( 'f', 3, 107, 0 ), /* 106 */
+ S_ST( 'a', 3, 108, 0 ), /* 107 */
+ S_ST( 'u', 3, 109, 0 ), /* 108 */
+ S_ST( 'l', 3, 281, 0 ), /* 109 */
+ S_ST( 'i', 3, 114, 105 ), /* 110 */
+ S_ST( 'g', 3, 112, 0 ), /* 111 */
+ S_ST( 'e', 3, 113, 0 ), /* 112 */
+ S_ST( 's', 3, 282, 0 ), /* 113 */
+ S_ST( 's', 3, 121, 111 ), /* 114 */
+ S_ST( 'a', 3, 116, 0 ), /* 115 */
+ S_ST( 'b', 3, 117, 0 ), /* 116 */
+ S_ST( 'l', 3, 283, 0 ), /* 117 */
+ S_ST( 'c', 3, 119, 115 ), /* 118 */
+ S_ST( 'a', 3, 120, 0 ), /* 119 */
+ S_ST( 'r', 3, 284, 0 ), /* 120 */
+ S_ST( 'p', 3, 122, 118 ), /* 121 */
+ S_ST( 'e', 3, 123, 0 ), /* 122 */
+ S_ST( 'r', 3, 124, 0 ), /* 123 */
+ S_ST( 's', 3, 125, 0 ), /* 124 */
+ S_ST( 'i', 3, 126, 0 ), /* 125 */
+ S_ST( 'o', 3, 285, 0 ), /* 126 */
+ S_ST( 'r', 3, 134, 110 ), /* 127 */
+ S_ST( 'i', 3, 129, 0 ), /* 128 */
+ S_ST( 'f', 3, 130, 0 ), /* 129 */
+ S_ST( 't', 3, 131, 0 ), /* 130 */
+ S_ST( 'f', 3, 132, 0 ), /* 131 */
+ S_ST( 'i', 3, 133, 0 ), /* 132 */
+ S_ST( 'l', 3, 287, 0 ), /* 133 */
+ S_ST( 'o', 3, 288, 128 ), /* 134 */
+ S_ST( 'u', 3, 136, 127 ), /* 135 */
+ S_ST( 'r', 3, 137, 0 ), /* 136 */
+ S_ST( 'a', 3, 138, 0 ), /* 137 */
+ S_ST( 't', 3, 139, 0 ), /* 138 */
+ S_ST( 'i', 3, 140, 0 ), /* 139 */
+ S_ST( 'o', 3, 415, 0 ), /* 140 */
+ S_ST( 'e', 3, 142, 103 ), /* 141 */
+ S_ST( 'n', 3, 291, 0 ), /* 142 */
+ S_ST( 'a', 3, 144, 0 ), /* 143 */
+ S_ST( 'b', 3, 145, 0 ), /* 144 */
+ S_ST( 'l', 3, 290, 0 ), /* 145 */
+ S_ST( 'f', 3, 165, 141 ), /* 146 */
+ S_ST( 'i', 3, 148, 0 ), /* 147 */
+ S_ST( 'l', 3, 293, 0 ), /* 148 */
+ S_ST( 'g', 3, 150, 0 ), /* 149 */
+ S_ST( 'e', 3, 294, 0 ), /* 150 */
+ S_ST( 'l', 3, 155, 147 ), /* 151 */
+ S_ST( 'a', 3, 154, 0 ), /* 152 */
+ S_ST( 'g', 3, 298, 0 ), /* 153 */
+ S_ST( 'k', 3, 299, 153 ), /* 154 */
+ S_ST( 'o', 3, 156, 152 ), /* 155 */
+ S_ST( 'o', 3, 300, 0 ), /* 156 */
+ S_ST( 'r', 3, 158, 151 ), /* 157 */
+ S_ST( 'e', 3, 301, 0 ), /* 158 */
+ S_ST( '_', 3, 160, 0 ), /* 159 */
+ S_ST( 'o', 3, 161, 0 ), /* 160 */
+ S_ST( 'f', 3, 162, 0 ), /* 161 */
+ S_ST( 'f', 3, 163, 0 ), /* 162 */
+ S_ST( 's', 3, 164, 0 ), /* 163 */
+ S_ST( 'e', 3, 416, 0 ), /* 164 */
+ S_ST( 'u', 3, 166, 157 ), /* 165 */
+ S_ST( 'd', 3, 167, 0 ), /* 166 */
+ S_ST( 'g', 3, 302, 0 ), /* 167 */
+ S_ST( 'h', 3, 171, 146 ), /* 168 */
+ S_ST( 'o', 3, 170, 0 ), /* 169 */
+ S_ST( 's', 3, 303, 0 ), /* 170 */
+ S_ST( 'u', 3, 172, 169 ), /* 171 */
+ S_ST( 'f', 3, 173, 0 ), /* 172 */
+ S_ST( 'f', 3, 174, 0 ), /* 173 */
+ S_ST( 'p', 3, 175, 0 ), /* 174 */
+ S_ST( 'u', 3, 176, 0 ), /* 175 */
+ S_ST( 'f', 3, 304, 0 ), /* 176 */
+ S_ST( 'i', 3, 204, 168 ), /* 177 */
+ S_ST( 'b', 3, 179, 0 ), /* 178 */
+ S_ST( 'u', 3, 180, 0 ), /* 179 */
+ S_ST( 'r', 3, 181, 0 ), /* 180 */
+ S_ST( 's', 3, 305, 0 ), /* 181 */
+ S_ST( 'd', 3, 183, 178 ), /* 182 */
+ S_ST( 'e', 3, 184, 0 ), /* 183 */
+ S_ST( 'n', 3, 306, 0 ), /* 184 */
+ S_ST( 'g', 3, 186, 182 ), /* 185 */
+ S_ST( 'n', 3, 187, 0 ), /* 186 */
+ S_ST( 'o', 3, 188, 0 ), /* 187 */
+ S_ST( 'r', 3, 307, 0 ), /* 188 */
+ S_ST( 'n', 3, 198, 185 ), /* 189 */
+ S_ST( 'c', 3, 191, 0 ), /* 190 */
+ S_ST( 'l', 3, 192, 0 ), /* 191 */
+ S_ST( 'u', 3, 193, 0 ), /* 192 */
+ S_ST( 'd', 3, 194, 0 ), /* 193 */
+ S_ST( 'e', 3, 195, 0 ), /* 194 */
+ S_ST( 'f', 3, 196, 0 ), /* 195 */
+ S_ST( 'i', 3, 197, 0 ), /* 196 */
+ S_ST( 'l', 3, 308, 0 ), /* 197 */
+ S_ST( 't', 3, 199, 190 ), /* 198 */
+ S_ST( 'e', 3, 200, 0 ), /* 199 */
+ S_ST( 'r', 3, 201, 0 ), /* 200 */
+ S_ST( 'f', 3, 202, 0 ), /* 201 */
+ S_ST( 'a', 3, 203, 0 ), /* 202 */
+ S_ST( 'c', 3, 310, 0 ), /* 203 */
+ S_ST( 'p', 3, 205, 189 ), /* 204 */
+ S_ST( 'v', 3, 313, 0 ), /* 205 */
+ S_ST( 'j', 3, 207, 177 ), /* 206 */
+ S_ST( 'i', 3, 208, 0 ), /* 207 */
+ S_ST( 't', 3, 209, 0 ), /* 208 */
+ S_ST( 't', 3, 210, 0 ), /* 209 */
+ S_ST( 'e', 3, 418, 0 ), /* 210 */
+ S_ST( 'k', 3, 218, 206 ), /* 211 */
+ S_ST( 'e', 3, 316, 0 ), /* 212 */
+ S_ST( 'r', 3, 214, 0 ), /* 213 */
+ S_ST( 'n', 3, 215, 0 ), /* 214 */
+ S_ST( 'e', 3, 315, 0 ), /* 215 */
+ S_ST( 'd', 3, 217, 0 ), /* 216 */
+ S_ST( 'i', 3, 318, 0 ), /* 217 */
+ S_ST( 'o', 3, 319, 212 ), /* 218 */
+ S_ST( 'l', 3, 235, 211 ), /* 219 */
+ S_ST( 'e', 3, 221, 0 ), /* 220 */
+ S_ST( 'a', 3, 222, 0 ), /* 221 */
+ S_ST( 'p', 3, 223, 0 ), /* 222 */
+ S_ST( 'f', 3, 224, 0 ), /* 223 */
+ S_ST( 'i', 3, 225, 0 ), /* 224 */
+ S_ST( 'l', 3, 321, 0 ), /* 225 */
+ S_ST( 'i', 3, 232, 220 ), /* 226 */
+ S_ST( 'm', 3, 228, 0 ), /* 227 */
+ S_ST( 'i', 3, 229, 0 ), /* 228 */
+ S_ST( 't', 3, 230, 0 ), /* 229 */
+ S_ST( 'e', 3, 322, 0 ), /* 230 */
+ S_ST( 'n', 3, 323, 227 ), /* 231 */
+ S_ST( 's', 3, 233, 231 ), /* 232 */
+ S_ST( 't', 3, 234, 0 ), /* 233 */
+ S_ST( 'e', 3, 324, 0 ), /* 234 */
+ S_ST( 'o', 3, 251, 226 ), /* 235 */
+ S_ST( 'g', 3, 242, 0 ), /* 236 */
+ S_ST( 'c', 3, 238, 0 ), /* 237 */
+ S_ST( 'o', 3, 239, 0 ), /* 238 */
+ S_ST( 'n', 3, 240, 0 ), /* 239 */
+ S_ST( 'f', 3, 241, 0 ), /* 240 */
+ S_ST( 'i', 3, 325, 0 ), /* 241 */
+ S_ST( 'f', 3, 243, 237 ), /* 242 */
+ S_ST( 'i', 3, 244, 0 ), /* 243 */
+ S_ST( 'l', 3, 326, 0 ), /* 244 */
+ S_ST( 'o', 3, 246, 236 ), /* 245 */
+ S_ST( 'p', 3, 247, 0 ), /* 246 */
+ S_ST( 's', 3, 248, 0 ), /* 247 */
+ S_ST( 't', 3, 249, 0 ), /* 248 */
+ S_ST( 'a', 3, 250, 0 ), /* 249 */
+ S_ST( 't', 3, 327, 0 ), /* 250 */
+ S_ST( 'w', 3, 252, 245 ), /* 251 */
+ S_ST( 'p', 3, 253, 0 ), /* 252 */
+ S_ST( 'r', 3, 254, 0 ), /* 253 */
+ S_ST( 'i', 3, 255, 0 ), /* 254 */
+ S_ST( 'o', 3, 256, 0 ), /* 255 */
+ S_ST( 't', 3, 257, 0 ), /* 256 */
+ S_ST( 'r', 3, 286, 0 ), /* 257 */
+ S_ST( 'e', 0, 0, 0 ), /* 258 T_Age */
+ S_ST( 'l', 0, 7, 0 ), /* 259 T_All */
+ S_ST( 'n', 0, 0, 0 ), /* 260 T_Allan */
+ S_ST( 'h', 0, 0, 0 ), /* 261 T_Auth */
+ S_ST( 'y', 0, 0, 0 ), /* 262 T_Autokey */
+ S_ST( 'x', 0, 0, 0 ), /* 263 T_Automax */
+ S_ST( 'e', 0, 0, 0 ), /* 264 T_Average */
+ S_ST( 't', 0, 0, 0 ), /* 265 T_Bclient */
+ S_ST( 'n', 0, 0, 0 ), /* 266 T_Beacon */
+ S_ST( 's', 0, 0, 0 ), /* 267 T_Bias */
+ S_ST( 't', 1, 51, 0 ), /* 268 T_Broadcast */
+ S_ST( 't', 0, 0, 0 ), /* 269 T_Broadcastclient */
+ S_ST( 'y', 0, 0, 0 ), /* 270 T_Broadcastdelay */
+ S_ST( 't', 0, 0, 0 ), /* 271 T_Burst */
+ S_ST( 'e', 0, 0, 0 ), /* 272 T_Calibrate */
+ S_ST( 'y', 0, 0, 0 ), /* 273 T_Calldelay */
+ S_ST( 'g', 0, 0, 0 ), /* 274 T_Ceiling */
+ S_ST( 's', 0, 0, 0 ), /* 275 T_Clockstats */
+ S_ST( 't', 0, 0, 0 ), /* 276 T_Cohort */
+ S_ST( 'y', 0, 0, 0 ), /* 277 T_ControlKey */
+ S_ST( 'o', 0, 99, 0 ), /* 278 T_Crypto */
+ S_ST( 's', 0, 0, 0 ), /* 279 T_Cryptostats */
+ S_ST( 'y', 0, 0, 0 ), /* 280 T_Day */
+ S_ST( 't', 0, 0, 0 ), /* 281 T_Default */
+ S_ST( 't', 1, 0, 0 ), /* 282 T_Digest */
+ S_ST( 'e', 0, 0, 0 ), /* 283 T_Disable */
+ S_ST( 'd', 0, 0, 0 ), /* 284 T_Discard */
+ S_ST( 'n', 0, 0, 0 ), /* 285 T_Dispersion */
+ S_ST( 'a', 3, 328, 0 ), /* 286 */
+ S_ST( 'e', 1, 0, 0 ), /* 287 T_Driftfile */
+ S_ST( 'p', 0, 0, 0 ), /* 288 T_Drop */
+ S_ST( '.', 0, 0, 0 ), /* 289 T_Ellipsis */
+ S_ST( 'e', 0, 0, 0 ), /* 290 T_Enable */
+ S_ST( 'd', 0, 0, 143 ), /* 291 T_End */
+ S_ST( 'm', 3, 473, 219 ), /* 292 */
+ S_ST( 'e', 1, 149, 0 ), /* 293 T_File */
+ S_ST( 'n', 0, 0, 0 ), /* 294 T_Filegen */
+ S_ST( '1', 0, 0, 0 ), /* 295 T_Flag1 */
+ S_ST( '2', 0, 0, 295 ), /* 296 T_Flag2 */
+ S_ST( '3', 0, 0, 296 ), /* 297 T_Flag3 */
+ S_ST( '4', 0, 0, 297 ), /* 298 T_Flag4 */
+ S_ST( 'e', 0, 0, 0 ), /* 299 T_Flake */
+ S_ST( 'r', 0, 0, 0 ), /* 300 T_Floor */
+ S_ST( 'q', 0, 159, 0 ), /* 301 T_Freq */
+ S_ST( 'e', 1, 0, 0 ), /* 302 T_Fudge */
+ S_ST( 't', 1, 0, 0 ), /* 303 T_Host */
+ S_ST( 'f', 0, 0, 0 ), /* 304 T_Huffpuff */
+ S_ST( 't', 0, 0, 0 ), /* 305 T_Iburst */
+ S_ST( 't', 1, 0, 0 ), /* 306 T_Ident */
+ S_ST( 'e', 0, 0, 0 ), /* 307 T_Ignore */
+ S_ST( 'e', 1, 0, 0 ), /* 308 T_Includefile */
+ S_ST( 'a', 3, 433, 0 ), /* 309 */
+ S_ST( 'e', 0, 0, 0 ), /* 310 T_Interface */
+ S_ST( '4', 0, 0, 0 ), /* 311 T_Ipv4 */
+ S_ST( '4', 0, 0, 0 ), /* 312 T_Ipv4_flag */
+ S_ST( '6', 0, 0, 311 ), /* 313 T_Ipv6 */
+ S_ST( '6', 0, 0, 312 ), /* 314 T_Ipv6_flag */
+ S_ST( 'l', 0, 0, 0 ), /* 315 T_Kernel */
+ S_ST( 'y', 0, 317, 213 ), /* 316 T_Key */
+ S_ST( 's', 1, 216, 0 ), /* 317 T_Keys */
+ S_ST( 'r', 1, 0, 0 ), /* 318 T_Keysdir */
+ S_ST( 'd', 0, 0, 0 ), /* 319 T_Kod */
+ S_ST( 'p', 0, 0, 0 ), /* 320 T_Mssntp */
+ S_ST( 'e', 1, 0, 0 ), /* 321 T_Leapfile */
+ S_ST( 'd', 0, 0, 0 ), /* 322 T_Limited */
+ S_ST( 'k', 0, 0, 0 ), /* 323 T_Link */
+ S_ST( 'n', 0, 0, 0 ), /* 324 T_Listen */
+ S_ST( 'g', 2, 0, 0 ), /* 325 T_Logconfig */
+ S_ST( 'e', 1, 0, 0 ), /* 326 T_Logfile */
+ S_ST( 's', 0, 0, 0 ), /* 327 T_Loopstats */
+ S_ST( 'p', 0, 0, 0 ), /* 328 T_Lowpriotrap */
+ S_ST( 't', 1, 0, 0 ), /* 329 T_Manycastclient */
+ S_ST( 'r', 2, 0, 0 ), /* 330 T_Manycastserver */
+ S_ST( 'k', 0, 0, 0 ), /* 331 T_Mask */
+ S_ST( 'k', 0, 0, 0 ), /* 332 T_Maxclock */
+ S_ST( 't', 0, 0, 0 ), /* 333 T_Maxdist */
+ S_ST( 'l', 0, 0, 0 ), /* 334 T_Maxpoll */
+ S_ST( 'k', 0, 0, 0 ), /* 335 T_Minclock */
+ S_ST( 't', 0, 0, 0 ), /* 336 T_Mindist */
+ S_ST( 'm', 0, 0, 0 ), /* 337 T_Minimum */
+ S_ST( 'l', 0, 0, 0 ), /* 338 T_Minpoll */
+ S_ST( 'e', 0, 0, 0 ), /* 339 T_Minsane */
+ S_ST( 'e', 0, 0, 0 ), /* 340 T_Mode */
+ S_ST( 'r', 0, 0, 0 ), /* 341 T_Monitor */
+ S_ST( 'h', 0, 0, 0 ), /* 342 T_Month */
+ S_ST( 't', 2, 0, 0 ), /* 343 T_Multicastclient */
+ S_ST( 'c', 0, 0, 0 ), /* 344 T_Nic */
+ S_ST( 'k', 0, 0, 0 ), /* 345 T_Nolink */
+ S_ST( 'y', 0, 0, 0 ), /* 346 T_Nomodify */
+ S_ST( 'e', 0, 0, 0 ), /* 347 T_None */
+ S_ST( 'r', 0, 0, 0 ), /* 348 T_Nopeer */
+ S_ST( 'y', 0, 0, 0 ), /* 349 T_Noquery */
+ S_ST( 't', 0, 0, 0 ), /* 350 T_Noselect */
+ S_ST( 'e', 0, 0, 0 ), /* 351 T_Noserve */
+ S_ST( 'p', 0, 0, 0 ), /* 352 T_Notrap */
+ S_ST( 't', 0, 0, 0 ), /* 353 T_Notrust */
+ S_ST( 'p', 0, 521, 0 ), /* 354 T_Ntp */
+ S_ST( 't', 0, 0, 0 ), /* 355 T_Ntpport */
+ S_ST( 't', 1, 0, 0 ), /* 356 T_NtpSignDsocket */
+ S_ST( 'n', 0, 0, 0 ), /* 357 T_Orphan */
+ S_ST( 'c', 0, 0, 0 ), /* 358 T_Panic */
+ S_ST( 'r', 1, 542, 0 ), /* 359 T_Peer */
+ S_ST( 's', 0, 0, 0 ), /* 360 T_Peerstats */
+ S_ST( 'e', 2, 0, 0 ), /* 361 T_Phone */
+ S_ST( 'd', 0, 550, 0 ), /* 362 T_Pid */
+ S_ST( 'e', 1, 0, 0 ), /* 363 T_Pidfile */
+ S_ST( 'l', 1, 0, 0 ), /* 364 T_Pool */
+ S_ST( 't', 0, 0, 0 ), /* 365 T_Port */
+ S_ST( 't', 0, 0, 0 ), /* 366 T_Preempt */
+ S_ST( 'r', 0, 0, 0 ), /* 367 T_Prefer */
+ S_ST( 's', 0, 0, 0 ), /* 368 T_Protostats */
+ S_ST( 'w', 1, 0, 556 ), /* 369 T_Pw */
+ S_ST( 's', 0, 0, 0 ), /* 370 T_Qos */
+ S_ST( 'e', 1, 0, 0 ), /* 371 T_Randfile */
+ S_ST( 's', 0, 0, 0 ), /* 372 T_Rawstats */
+ S_ST( 'd', 1, 0, 0 ), /* 373 T_Refid */
+ S_ST( 'y', 0, 0, 0 ), /* 374 T_Requestkey */
+ S_ST( 't', 0, 0, 0 ), /* 375 T_Restrict */
+ S_ST( 'e', 0, 0, 0 ), /* 376 T_Revoke */
+ S_ST( 'r', 1, 0, 0 ), /* 377 T_Saveconfigdir */
+ S_ST( 'r', 1, 630, 0 ), /* 378 T_Server */
+ S_ST( 'r', 1, 0, 0 ), /* 379 T_Setvar */
+ S_ST( 'n', 1, 0, 0 ), /* 380 T_Sign */
+ S_ST( 's', 0, 0, 0 ), /* 381 T_Statistics */
+ S_ST( 's', 0, 665, 660 ), /* 382 T_Stats */
+ S_ST( 'r', 1, 0, 0 ), /* 383 T_Statsdir */
+ S_ST( 'p', 0, 668, 0 ), /* 384 T_Step */
+ S_ST( 't', 0, 0, 0 ), /* 385 T_Stepout */
+ S_ST( 'm', 0, 0, 0 ), /* 386 T_Stratum */
+ S_ST( 'n', 3, 403, 0 ), /* 387 */
+ S_ST( 's', 0, 0, 0 ), /* 388 T_Sysstats */
+ S_ST( 'k', 0, 0, 0 ), /* 389 T_Tick */
+ S_ST( '1', 0, 0, 0 ), /* 390 T_Time1 */
+ S_ST( '2', 0, 0, 390 ), /* 391 T_Time2 */
+ S_ST( 's', 0, 0, 0 ), /* 392 T_Timingstats */
+ S_ST( 'r', 0, 0, 0 ), /* 393 T_Tinker */
+ S_ST( 's', 0, 0, 0 ), /* 394 T_Tos */
+ S_ST( 'p', 1, 0, 0 ), /* 395 T_Trap */
+ S_ST( 'e', 0, 0, 0 ), /* 396 T_True */
+ S_ST( 'y', 0, 0, 0 ), /* 397 T_Trustedkey */
+ S_ST( 'l', 0, 0, 0 ), /* 398 T_Ttl */
+ S_ST( 'e', 0, 0, 0 ), /* 399 T_Type */
+ S_ST( 'g', 1, 0, 0 ), /* 400 T_Unconfig */
+ S_ST( 'r', 1, 0, 0 ), /* 401 T_Unpeer */
+ S_ST( 'n', 0, 0, 0 ), /* 402 T_Version */
+ S_ST( 'y', 3, 408, 0 ), /* 403 */
+ S_ST( 'k', 0, 0, 0 ), /* 404 T_Week */
+ S_ST( 'd', 0, 0, 0 ), /* 405 T_Wildcard */
+ S_ST( 'e', 0, 0, 0 ), /* 406 T_Xleave */
+ S_ST( 'r', 0, 0, 0 ), /* 407 T_Year */
+ S_ST( 'c', 3, 409, 0 ), /* 408 */
+ S_ST( 'a', 3, 410, 0 ), /* 409 */
+ S_ST( 's', 3, 421, 0 ), /* 410 */
+ S_ST( 'e', 0, 0, 0 ), /* 411 T_Simulate */
+ S_ST( 'y', 0, 0, 0 ), /* 412 T_Beep_Delay */
+ S_ST( 'n', 0, 0, 0 ), /* 413 T_Sim_Duration */
+ S_ST( 't', 0, 0, 0 ), /* 414 T_Server_Offset */
+ S_ST( 'n', 0, 0, 0 ), /* 415 T_Duration */
+ S_ST( 't', 0, 0, 0 ), /* 416 T_Freq_Offset */
+ S_ST( 'r', 0, 0, 0 ), /* 417 T_Wander */
+ S_ST( 'r', 0, 0, 0 ), /* 418 T_Jitter */
+ S_ST( 'y', 0, 0, 0 ), /* 419 T_Prop_Delay */
+ S_ST( 'y', 0, 0, 0 ), /* 420 T_Proc_Delay */
+ S_ST( 't', 3, 427, 0 ), /* 421 */
+ S_ST( 'c', 3, 423, 0 ), /* 422 */
+ S_ST( 'l', 3, 424, 0 ), /* 423 */
+ S_ST( 'i', 3, 425, 0 ), /* 424 */
+ S_ST( 'e', 3, 426, 0 ), /* 425 */
+ S_ST( 'n', 3, 329, 0 ), /* 426 */
+ S_ST( 's', 3, 428, 422 ), /* 427 */
+ S_ST( 'e', 3, 429, 0 ), /* 428 */
+ S_ST( 'r', 3, 430, 0 ), /* 429 */
+ S_ST( 'v', 3, 431, 0 ), /* 430 */
+ S_ST( 'e', 3, 330, 0 ), /* 431 */
+ S_ST( 's', 3, 331, 387 ), /* 432 */
+ S_ST( 'x', 3, 441, 432 ), /* 433 */
+ S_ST( 'c', 3, 435, 0 ), /* 434 */
+ S_ST( 'l', 3, 436, 0 ), /* 435 */
+ S_ST( 'o', 3, 437, 0 ), /* 436 */
+ S_ST( 'c', 3, 332, 0 ), /* 437 */
+ S_ST( 'd', 3, 439, 434 ), /* 438 */
+ S_ST( 'i', 3, 440, 0 ), /* 439 */
+ S_ST( 's', 3, 333, 0 ), /* 440 */
+ S_ST( 'p', 3, 442, 438 ), /* 441 */
+ S_ST( 'o', 3, 443, 0 ), /* 442 */
+ S_ST( 'l', 3, 334, 0 ), /* 443 */
+ S_ST( 'i', 3, 445, 309 ), /* 444 */
+ S_ST( 'n', 3, 459, 0 ), /* 445 */
+ S_ST( 'c', 3, 447, 0 ), /* 446 */
+ S_ST( 'l', 3, 448, 0 ), /* 447 */
+ S_ST( 'o', 3, 449, 0 ), /* 448 */
+ S_ST( 'c', 3, 335, 0 ), /* 449 */
+ S_ST( 'd', 3, 451, 446 ), /* 450 */
+ S_ST( 'i', 3, 452, 0 ), /* 451 */
+ S_ST( 's', 3, 336, 0 ), /* 452 */
+ S_ST( 'i', 3, 454, 450 ), /* 453 */
+ S_ST( 'm', 3, 455, 0 ), /* 454 */
+ S_ST( 'u', 3, 337, 0 ), /* 455 */
+ S_ST( 'p', 3, 457, 453 ), /* 456 */
+ S_ST( 'o', 3, 458, 0 ), /* 457 */
+ S_ST( 'l', 3, 338, 0 ), /* 458 */
+ S_ST( 's', 3, 460, 456 ), /* 459 */
+ S_ST( 'a', 3, 461, 0 ), /* 460 */
+ S_ST( 'n', 3, 339, 0 ), /* 461 */
+ S_ST( 'o', 3, 464, 444 ), /* 462 */
+ S_ST( 'd', 3, 340, 0 ), /* 463 */
+ S_ST( 'n', 3, 468, 463 ), /* 464 */
+ S_ST( 'i', 3, 466, 0 ), /* 465 */
+ S_ST( 't', 3, 467, 0 ), /* 466 */
+ S_ST( 'o', 3, 341, 0 ), /* 467 */
+ S_ST( 't', 3, 342, 465 ), /* 468 */
+ S_ST( 's', 3, 470, 462 ), /* 469 */
+ S_ST( 's', 3, 471, 0 ), /* 470 */
+ S_ST( 'n', 3, 472, 0 ), /* 471 */
+ S_ST( 't', 3, 320, 0 ), /* 472 */
+ S_ST( 'u', 3, 474, 469 ), /* 473 */
+ S_ST( 'l', 3, 475, 0 ), /* 474 */
+ S_ST( 't', 3, 476, 0 ), /* 475 */
+ S_ST( 'i', 3, 477, 0 ), /* 476 */
+ S_ST( 'c', 3, 478, 0 ), /* 477 */
+ S_ST( 'a', 3, 479, 0 ), /* 478 */
+ S_ST( 's', 3, 480, 0 ), /* 479 */
+ S_ST( 't', 3, 481, 0 ), /* 480 */
+ S_ST( 'c', 3, 482, 0 ), /* 481 */
+ S_ST( 'l', 3, 483, 0 ), /* 482 */
+ S_ST( 'i', 3, 484, 0 ), /* 483 */
+ S_ST( 'e', 3, 485, 0 ), /* 484 */
+ S_ST( 'n', 3, 343, 0 ), /* 485 */
+ S_ST( 'n', 3, 517, 292 ), /* 486 */
+ S_ST( 'i', 3, 344, 0 ), /* 487 */
+ S_ST( 'o', 3, 512, 487 ), /* 488 */
+ S_ST( 'l', 3, 490, 0 ), /* 489 */
+ S_ST( 'i', 3, 491, 0 ), /* 490 */
+ S_ST( 'n', 3, 345, 0 ), /* 491 */
+ S_ST( 'm', 3, 493, 489 ), /* 492 */
+ S_ST( 'o', 3, 494, 0 ), /* 493 */
+ S_ST( 'd', 3, 495, 0 ), /* 494 */
+ S_ST( 'i', 3, 496, 0 ), /* 495 */
+ S_ST( 'f', 3, 346, 0 ), /* 496 */
+ S_ST( 'n', 3, 347, 492 ), /* 497 */
+ S_ST( 'p', 3, 499, 497 ), /* 498 */
+ S_ST( 'e', 3, 500, 0 ), /* 499 */
+ S_ST( 'e', 3, 348, 0 ), /* 500 */
+ S_ST( 'q', 3, 502, 498 ), /* 501 */
+ S_ST( 'u', 3, 503, 0 ), /* 502 */
+ S_ST( 'e', 3, 504, 0 ), /* 503 */
+ S_ST( 'r', 3, 349, 0 ), /* 504 */
+ S_ST( 's', 3, 506, 501 ), /* 505 */
+ S_ST( 'e', 3, 510, 0 ), /* 506 */
+ S_ST( 'l', 3, 508, 0 ), /* 507 */
+ S_ST( 'e', 3, 509, 0 ), /* 508 */
+ S_ST( 'c', 3, 350, 0 ), /* 509 */
+ S_ST( 'r', 3, 511, 507 ), /* 510 */
+ S_ST( 'v', 3, 351, 0 ), /* 511 */
+ S_ST( 't', 3, 513, 505 ), /* 512 */
+ S_ST( 'r', 3, 515, 0 ), /* 513 */
+ S_ST( 'a', 3, 352, 0 ), /* 514 */
+ S_ST( 'u', 3, 516, 514 ), /* 515 */
+ S_ST( 's', 3, 353, 0 ), /* 516 */
+ S_ST( 't', 3, 354, 488 ), /* 517 */
+ S_ST( 'p', 3, 519, 0 ), /* 518 */
+ S_ST( 'o', 3, 520, 0 ), /* 519 */
+ S_ST( 'r', 3, 355, 0 ), /* 520 */
+ S_ST( 's', 3, 522, 518 ), /* 521 */
+ S_ST( 'i', 3, 523, 0 ), /* 522 */
+ S_ST( 'g', 3, 524, 0 ), /* 523 */
+ S_ST( 'n', 3, 525, 0 ), /* 524 */
+ S_ST( 'd', 3, 526, 0 ), /* 525 */
+ S_ST( 's', 3, 527, 0 ), /* 526 */
+ S_ST( 'o', 3, 528, 0 ), /* 527 */
+ S_ST( 'c', 3, 529, 0 ), /* 528 */
+ S_ST( 'k', 3, 530, 0 ), /* 529 */
+ S_ST( 'e', 3, 356, 0 ), /* 530 */
+ S_ST( 'o', 3, 532, 486 ), /* 531 */
+ S_ST( 'r', 3, 533, 0 ), /* 532 */
+ S_ST( 'p', 3, 534, 0 ), /* 533 */
+ S_ST( 'h', 3, 535, 0 ), /* 534 */
+ S_ST( 'a', 3, 357, 0 ), /* 535 */
+ S_ST( 'p', 3, 369, 531 ), /* 536 */
+ S_ST( 'a', 3, 538, 0 ), /* 537 */
+ S_ST( 'n', 3, 539, 0 ), /* 538 */
+ S_ST( 'i', 3, 358, 0 ), /* 539 */
+ S_ST( 'e', 3, 541, 537 ), /* 540 */
+ S_ST( 'e', 3, 359, 0 ), /* 541 */
+ S_ST( 's', 3, 543, 0 ), /* 542 */
+ S_ST( 't', 3, 544, 0 ), /* 543 */
+ S_ST( 'a', 3, 545, 0 ), /* 544 */
+ S_ST( 't', 3, 360, 0 ), /* 545 */
+ S_ST( 'h', 3, 547, 540 ), /* 546 */
+ S_ST( 'o', 3, 548, 0 ), /* 547 */
+ S_ST( 'n', 3, 361, 0 ), /* 548 */
+ S_ST( 'i', 3, 362, 546 ), /* 549 */
+ S_ST( 'f', 3, 551, 0 ), /* 550 */
+ S_ST( 'i', 3, 552, 0 ), /* 551 */
+ S_ST( 'l', 3, 363, 0 ), /* 552 */
+ S_ST( 'o', 3, 555, 549 ), /* 553 */
+ S_ST( 'o', 3, 364, 0 ), /* 554 */
+ S_ST( 'r', 3, 365, 554 ), /* 555 */
+ S_ST( 'r', 3, 563, 553 ), /* 556 */
+ S_ST( 'e', 3, 561, 0 ), /* 557 */
+ S_ST( 'e', 3, 559, 0 ), /* 558 */
+ S_ST( 'm', 3, 560, 0 ), /* 559 */
+ S_ST( 'p', 3, 366, 0 ), /* 560 */
+ S_ST( 'f', 3, 562, 558 ), /* 561 */
+ S_ST( 'e', 3, 367, 0 ), /* 562 */
+ S_ST( 'o', 3, 576, 557 ), /* 563 */
+ S_ST( 'c', 3, 565, 0 ), /* 564 */
+ S_ST( '_', 3, 566, 0 ), /* 565 */
+ S_ST( 'd', 3, 567, 0 ), /* 566 */
+ S_ST( 'e', 3, 568, 0 ), /* 567 */
+ S_ST( 'l', 3, 569, 0 ), /* 568 */
+ S_ST( 'a', 3, 420, 0 ), /* 569 */
+ S_ST( 'p', 3, 571, 564 ), /* 570 */
+ S_ST( '_', 3, 572, 0 ), /* 571 */
+ S_ST( 'd', 3, 573, 0 ), /* 572 */
+ S_ST( 'e', 3, 574, 0 ), /* 573 */
+ S_ST( 'l', 3, 575, 0 ), /* 574 */
+ S_ST( 'a', 3, 419, 0 ), /* 575 */
+ S_ST( 't', 3, 577, 570 ), /* 576 */
+ S_ST( 'o', 3, 578, 0 ), /* 577 */
+ S_ST( 's', 3, 579, 0 ), /* 578 */
+ S_ST( 't', 3, 580, 0 ), /* 579 */
+ S_ST( 'a', 3, 581, 0 ), /* 580 */
+ S_ST( 't', 3, 368, 0 ), /* 581 */
+ S_ST( 'q', 3, 583, 536 ), /* 582 */
+ S_ST( 'o', 3, 370, 0 ), /* 583 */
+ S_ST( 'r', 3, 596, 582 ), /* 584 */
+ S_ST( 'a', 3, 591, 0 ), /* 585 */
+ S_ST( 'n', 3, 587, 0 ), /* 586 */
+ S_ST( 'd', 3, 588, 0 ), /* 587 */
+ S_ST( 'f', 3, 589, 0 ), /* 588 */
+ S_ST( 'i', 3, 590, 0 ), /* 589 */
+ S_ST( 'l', 3, 371, 0 ), /* 590 */
+ S_ST( 'w', 3, 592, 586 ), /* 591 */
+ S_ST( 's', 3, 593, 0 ), /* 592 */
+ S_ST( 't', 3, 594, 0 ), /* 593 */
+ S_ST( 'a', 3, 595, 0 ), /* 594 */
+ S_ST( 't', 3, 372, 0 ), /* 595 */
+ S_ST( 'e', 3, 611, 585 ), /* 596 */
+ S_ST( 'f', 3, 598, 0 ), /* 597 */
+ S_ST( 'i', 3, 373, 0 ), /* 598 */
+ S_ST( 'q', 3, 600, 597 ), /* 599 */
+ S_ST( 'u', 3, 601, 0 ), /* 600 */
+ S_ST( 'e', 3, 602, 0 ), /* 601 */
+ S_ST( 's', 3, 603, 0 ), /* 602 */
+ S_ST( 't', 3, 604, 0 ), /* 603 */
+ S_ST( 'k', 3, 605, 0 ), /* 604 */
+ S_ST( 'e', 3, 374, 0 ), /* 605 */
+ S_ST( 's', 3, 607, 599 ), /* 606 */
+ S_ST( 't', 3, 608, 0 ), /* 607 */
+ S_ST( 'r', 3, 609, 0 ), /* 608 */
+ S_ST( 'i', 3, 610, 0 ), /* 609 */
+ S_ST( 'c', 3, 375, 0 ), /* 610 */
+ S_ST( 'v', 3, 612, 606 ), /* 611 */
+ S_ST( 'o', 3, 613, 0 ), /* 612 */
+ S_ST( 'k', 3, 376, 0 ), /* 613 */
+ S_ST( 's', 3, 674, 584 ), /* 614 */
+ S_ST( 'a', 3, 616, 0 ), /* 615 */
+ S_ST( 'v', 3, 617, 0 ), /* 616 */
+ S_ST( 'e', 3, 618, 0 ), /* 617 */
+ S_ST( 'c', 3, 619, 0 ), /* 618 */
+ S_ST( 'o', 3, 620, 0 ), /* 619 */
+ S_ST( 'n', 3, 621, 0 ), /* 620 */
+ S_ST( 'f', 3, 622, 0 ), /* 621 */
+ S_ST( 'i', 3, 623, 0 ), /* 622 */
+ S_ST( 'g', 3, 624, 0 ), /* 623 */
+ S_ST( 'd', 3, 625, 0 ), /* 624 */
+ S_ST( 'i', 3, 377, 0 ), /* 625 */
+ S_ST( 'e', 3, 636, 615 ), /* 626 */
+ S_ST( 'r', 3, 628, 0 ), /* 627 */
+ S_ST( 'v', 3, 629, 0 ), /* 628 */
+ S_ST( 'e', 3, 378, 0 ), /* 629 */
+ S_ST( '_', 3, 631, 0 ), /* 630 */
+ S_ST( 'o', 3, 632, 0 ), /* 631 */
+ S_ST( 'f', 3, 633, 0 ), /* 632 */
+ S_ST( 'f', 3, 634, 0 ), /* 633 */
+ S_ST( 's', 3, 635, 0 ), /* 634 */
+ S_ST( 'e', 3, 414, 0 ), /* 635 */
+ S_ST( 't', 3, 637, 627 ), /* 636 */
+ S_ST( 'v', 3, 638, 0 ), /* 637 */
+ S_ST( 'a', 3, 379, 0 ), /* 638 */
+ S_ST( 'i', 3, 641, 626 ), /* 639 */
+ S_ST( 'g', 3, 380, 0 ), /* 640 */
+ S_ST( 'm', 3, 642, 640 ), /* 641 */
+ S_ST( 'u', 3, 643, 0 ), /* 642 */
+ S_ST( 'l', 3, 644, 0 ), /* 643 */
+ S_ST( 'a', 3, 645, 0 ), /* 644 */
+ S_ST( 't', 3, 646, 0 ), /* 645 */
+ S_ST( 'i', 3, 647, 411 ), /* 646 */
+ S_ST( 'o', 3, 648, 0 ), /* 647 */
+ S_ST( 'n', 3, 649, 0 ), /* 648 */
+ S_ST( '_', 3, 650, 0 ), /* 649 */
+ S_ST( 'd', 3, 651, 0 ), /* 650 */
+ S_ST( 'u', 3, 652, 0 ), /* 651 */
+ S_ST( 'r', 3, 653, 0 ), /* 652 */
+ S_ST( 'a', 3, 654, 0 ), /* 653 */
+ S_ST( 't', 3, 655, 0 ), /* 654 */
+ S_ST( 'i', 3, 656, 0 ), /* 655 */
+ S_ST( 'o', 3, 413, 0 ), /* 656 */
+ S_ST( 't', 3, 670, 639 ), /* 657 */
+ S_ST( 'a', 3, 659, 0 ), /* 658 */
+ S_ST( 't', 3, 382, 0 ), /* 659 */
+ S_ST( 'i', 3, 661, 0 ), /* 660 */
+ S_ST( 's', 3, 662, 0 ), /* 661 */
+ S_ST( 't', 3, 663, 0 ), /* 662 */
+ S_ST( 'i', 3, 664, 0 ), /* 663 */
+ S_ST( 'c', 3, 381, 0 ), /* 664 */
+ S_ST( 'd', 3, 666, 0 ), /* 665 */
+ S_ST( 'i', 3, 383, 0 ), /* 666 */
+ S_ST( 'e', 3, 384, 658 ), /* 667 */
+ S_ST( 'o', 3, 669, 0 ), /* 668 */
+ S_ST( 'u', 3, 385, 0 ), /* 669 */
+ S_ST( 'r', 3, 671, 667 ), /* 670 */
+ S_ST( 'a', 3, 672, 0 ), /* 671 */
+ S_ST( 't', 3, 673, 0 ), /* 672 */
+ S_ST( 'u', 3, 386, 0 ), /* 673 */
+ S_ST( 'y', 3, 675, 657 ), /* 674 */
+ S_ST( 's', 3, 676, 0 ), /* 675 */
+ S_ST( 's', 3, 677, 0 ), /* 676 */
+ S_ST( 't', 3, 678, 0 ), /* 677 */
+ S_ST( 'a', 3, 679, 0 ), /* 678 */
+ S_ST( 't', 3, 388, 0 ), /* 679 */
+ S_ST( 't', 3, 706, 614 ), /* 680 */
+ S_ST( 'i', 3, 692, 0 ), /* 681 */
+ S_ST( 'c', 3, 389, 0 ), /* 682 */
+ S_ST( 'm', 3, 685, 682 ), /* 683 */
+ S_ST( 'e', 3, 391, 0 ), /* 684 */
+ S_ST( 'i', 3, 686, 684 ), /* 685 */
+ S_ST( 'n', 3, 687, 0 ), /* 686 */
+ S_ST( 'g', 3, 688, 0 ), /* 687 */
+ S_ST( 's', 3, 689, 0 ), /* 688 */
+ S_ST( 't', 3, 690, 0 ), /* 689 */
+ S_ST( 'a', 3, 691, 0 ), /* 690 */
+ S_ST( 't', 3, 392, 0 ), /* 691 */
+ S_ST( 'n', 3, 693, 683 ), /* 692 */
+ S_ST( 'k', 3, 694, 0 ), /* 693 */
+ S_ST( 'e', 3, 393, 0 ), /* 694 */
+ S_ST( 'o', 3, 394, 681 ), /* 695 */
+ S_ST( 'r', 3, 698, 695 ), /* 696 */
+ S_ST( 'a', 3, 395, 0 ), /* 697 */
+ S_ST( 'u', 3, 699, 697 ), /* 698 */
+ S_ST( 's', 3, 700, 396 ), /* 699 */
+ S_ST( 't', 3, 701, 0 ), /* 700 */
+ S_ST( 'e', 3, 702, 0 ), /* 701 */
+ S_ST( 'd', 3, 703, 0 ), /* 702 */
+ S_ST( 'k', 3, 704, 0 ), /* 703 */
+ S_ST( 'e', 3, 397, 0 ), /* 704 */
+ S_ST( 't', 3, 398, 696 ), /* 705 */
+ S_ST( 'y', 3, 707, 705 ), /* 706 */
+ S_ST( 'p', 3, 399, 0 ), /* 707 */
+ S_ST( 'u', 3, 709, 680 ), /* 708 */
+ S_ST( 'n', 3, 715, 0 ), /* 709 */
+ S_ST( 'c', 3, 711, 0 ), /* 710 */
+ S_ST( 'o', 3, 712, 0 ), /* 711 */
+ S_ST( 'n', 3, 713, 0 ), /* 712 */
+ S_ST( 'f', 3, 714, 0 ), /* 713 */
+ S_ST( 'i', 3, 400, 0 ), /* 714 */
+ S_ST( 'p', 3, 716, 710 ), /* 715 */
+ S_ST( 'e', 3, 717, 0 ), /* 716 */
+ S_ST( 'e', 3, 401, 0 ), /* 717 */
+ S_ST( 'v', 3, 719, 708 ), /* 718 */
+ S_ST( 'e', 3, 720, 0 ), /* 719 */
+ S_ST( 'r', 3, 721, 0 ), /* 720 */
+ S_ST( 's', 3, 722, 0 ), /* 721 */
+ S_ST( 'i', 3, 723, 0 ), /* 722 */
+ S_ST( 'o', 3, 402, 0 ), /* 723 */
+ S_ST( 'w', 3, 731, 718 ), /* 724 */
+ S_ST( 'a', 3, 726, 0 ), /* 725 */
+ S_ST( 'n', 3, 727, 0 ), /* 726 */
+ S_ST( 'd', 3, 728, 0 ), /* 727 */
+ S_ST( 'e', 3, 417, 0 ), /* 728 */
+ S_ST( 'e', 3, 730, 725 ), /* 729 */
+ S_ST( 'e', 3, 404, 0 ), /* 730 */
+ S_ST( 'i', 3, 732, 729 ), /* 731 */
+ S_ST( 'l', 3, 733, 0 ), /* 732 */
+ S_ST( 'd', 3, 734, 0 ), /* 733 */
+ S_ST( 'c', 3, 735, 0 ), /* 734 */
+ S_ST( 'a', 3, 736, 0 ), /* 735 */
+ S_ST( 'r', 3, 405, 0 ), /* 736 */
+ S_ST( 'x', 3, 738, 724 ), /* 737 */
+ S_ST( 'l', 3, 739, 0 ), /* 738 */
+ S_ST( 'e', 3, 740, 0 ), /* 739 */
+ S_ST( 'a', 3, 741, 0 ), /* 740 */
+ S_ST( 'v', 3, 406, 0 ), /* 741 */
+ S_ST( 'y', 3, 743, 737 ), /* 742 initial state */
+ S_ST( 'e', 3, 744, 0 ), /* 743 */
+ S_ST( 'a', 3, 407, 0 ) /* 744 */
+};
+
diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c
index d0fa466c9eb3..3eb09e10060a 100644
--- a/ntpd/ntp_loopfilter.c
+++ b/ntpd/ntp_loopfilter.c
@@ -40,13 +40,15 @@
#define CLOCK_PHI 15e-6 /* max frequency error (s/s) */
#define CLOCK_PLL 16. /* PLL loop gain (log2) */
#define CLOCK_AVG 8. /* parameter averaging constant */
-#define CLOCK_FLL (NTP_MAXPOLL + CLOCK_AVG) /* FLL loop gain */
-#define CLOCK_ALLAN 1500. /* compromise Allan intercept (s) */
+#define CLOCK_FLL .25 /* FLL loop gain */
+#define CLOCK_ALLAN 11 /* Allan intercept (log2 s) */
#define CLOCK_DAY 86400. /* one day in seconds (s) */
#define CLOCK_JUNE (CLOCK_DAY * 30) /* June in seconds (s) */
#define CLOCK_LIMIT 30 /* poll-adjust threshold */
#define CLOCK_PGATE 4. /* poll-adjust gate */
#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
+#define FREQTOD(x) ((x) / 65536e6) /* NTP to double */
+#define DTOFREQ(x) ((int32)((x) * 65536e6)) /* double to NTP */
/*
* Clock discipline state machine. This is used to control the
@@ -54,32 +56,25 @@
* timewarp.
*
* State < step > step Comments
- * ====================================================
- * NSET FREQ step, FREQ no ntp.drift
+ * ========================================================
+ * NSET FREQ step, FREQ freq not set
*
- * FSET SYNC step, SYNC ntp.drift
+ * FSET SYNC step, SYNC freq set
*
- * FREQ if (mu < 900) if (mu < 900) set freq
+ * FREQ if (mu < 900) if (mu < 900) set freq direct
* ignore ignore
* else else
* freq, SYNC freq, step, SYNC
*
- * SYNC SYNC if (mu < 900) adjust phase/freq
- * ignore
- * else
- * SPIK
+ * SYNC SYNC SPIK, ignore adjust phase/freq
*
- * SPIK SYNC step, SYNC set phase
+ * SPIK SYNC if (mu < 900) adjust phase/freq
+ * ignore
+ * step, SYNC
*/
-#define S_NSET 0 /* clock never set */
-#define S_FSET 1 /* frequency set from the drift file */
-#define S_SPIK 2 /* spike detected */
-#define S_FREQ 3 /* frequency mode */
-#define S_SYNC 4 /* clock synchronized */
-
/*
* Kernel PLL/PPS state machine. This is used with the kernel PLL
- * modifications described in the README.kernel file.
+ * modifications described in the documentation.
*
* If kernel support for the ntp_adjtime() system call is available, the
* ntp_control flag is set. The ntp_enable and kern_enable flags can be
@@ -97,54 +92,55 @@
* includes TAI offset and is identified by the symbol NTP_API with
* value 4.
*
- * Each update to a prefer peer sets pps_stratum if it survives the
- * intersection algorithm and its time is within range. The PPS time
- * discipline is enabled (STA_PPSTIME bit set in the status word) when
- * pps_stratum is true and the PPS frequency discipline is enabled. If
- * the PPS time discipline is enabled and the kernel reports a PPS
- * signal is present, the pps_control variable is set to the current
- * time. If the current time is later than pps_control by PPS_MAXAGE
- * (120 s), this variable is set to zero.
+ * Each PPS time/frequency discipline can be enabled by the atom driver
+ * or another driver. If enabled, the STA_PPSTIME and STA_FREQ bits are
+ * set in the kernel status word; otherwise, these bits are cleared.
+ * These bits are also cleard if the kernel reports an error.
*
* If an external clock is present, the clock driver sets STA_CLK in the
* status word. When the local clock driver sees this bit, it updates
* via this routine, which then calls ntp_adjtime() with the STA_PLL bit
* set to zero, in which case the system clock is not adjusted. This is
* also a signal for the external clock driver to discipline the system
- * clock.
+ * clock. Unless specified otherwise, all times are in seconds.
*/
/*
* Program variables that can be tinkered.
*/
-double clock_max = CLOCK_MAX; /* step threshold (s) */
-double clock_minstep = CLOCK_MINSTEP; /* stepout threshold (s) */
-double clock_panic = CLOCK_PANIC; /* panic threshold (s) */
+double clock_max = CLOCK_MAX; /* step threshold */
+double clock_minstep = CLOCK_MINSTEP; /* stepout threshold */
+double clock_panic = CLOCK_PANIC; /* panic threshold */
double clock_phi = CLOCK_PHI; /* dispersion rate (s/s) */
-double allan_xpt = CLOCK_ALLAN; /* Allan intercept (s) */
+u_char allan_xpt = CLOCK_ALLAN; /* Allan intercept (log2 s) */
/*
* Program variables
*/
-static double clock_offset; /* offset (s) */
-double clock_jitter; /* offset jitter (s) */
+static double clock_offset; /* offset */
+double clock_jitter; /* offset jitter */
double drift_comp; /* frequency (s/s) */
double clock_stability; /* frequency stability (wander) (s/s) */
-u_long sys_clocktime; /* last system clock update */
-u_long pps_control; /* last pps update */
-u_long sys_tai; /* UTC offset from TAI (s) */
-static void rstclock P((int, u_long, double)); /* transition function */
+double clock_codec; /* audio codec frequency (samples/s) */
+static u_long clock_epoch; /* last update */
+u_int sys_tai; /* TAI offset from UTC */
+static void rstclock (int, double); /* transition function */
+static double direct_freq(double); /* direct set frequency */
+static void set_freq(double); /* set frequency */
#ifdef KERNEL_PLL
-struct timex ntv; /* kernel API parameters */
-int pll_status; /* status bits for kernel pll */
+static struct timex ntv; /* ntp_adjtime() parameters */
+int pll_status; /* last kernel status bits */
+#if defined(STA_NANO) && NTP_API == 4
+static u_int loop_tai; /* last TAI offset */
+#endif /* STA_NANO */
#endif /* KERNEL_PLL */
/*
* Clock state machine control flags
*/
-int ntp_enable; /* clock discipline enabled */
+int ntp_enable = 1; /* clock discipline enabled */
int pll_control; /* kernel support available */
-int kern_enable; /* kernel support enabled */
+int kern_enable = 1; /* kernel support enabled */
int pps_enable; /* kernel PPS discipline enabled */
int ext_enable; /* external clock enabled */
int pps_stratum; /* pps stratum */
@@ -155,9 +151,10 @@ int mode_ntpdate = FALSE; /* exit on first clock set */
* Clock state machine variables
*/
int state; /* clock discipline state */
-u_char sys_poll = NTP_MINDPOLL; /* time constant/poll (log2 s) */
+u_char sys_poll; /* time constant/poll (log2 s) */
int tc_counter; /* jiggle counter */
double last_offset; /* last offset (s) */
+static u_long last_step; /* last clock step */
/*
* Huff-n'-puff filter variables
@@ -172,7 +169,7 @@ static double sys_mindly; /* huff-n'-puff filter min delay */
#define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
MOD_STATUS | MOD_TIMECONST)
#ifdef SIGSYS
-static void pll_trap P((int)); /* configuration trap */
+static void pll_trap (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() */
@@ -186,11 +183,9 @@ void
init_loopfilter(void)
{
/*
- * Initialize state variables. Initially, we expect no drift
- * file, so set the state to S_NSET. If a drift file is present,
- * it will be detected later and the state set to S_FSET.
+ * Initialize state variables.
*/
- rstclock(S_NSET, 0, 0);
+ sys_poll = ntp_minpoll;
clock_jitter = LOGTOD(sys_precision);
}
@@ -204,7 +199,7 @@ init_loopfilter(void)
* 2 clock was stepped
*
* LOCKCLOCK: The only thing this routine does is set the
- * sys_rootdispersion variable equal to the peer dispersion.
+ * sys_rootdisp variable equal to the peer dispersion.
*/
int
local_clock(
@@ -213,29 +208,17 @@ local_clock(
)
{
int rval; /* return code */
- u_long mu; /* interval since last update (s) */
- double flladj; /* FLL frequency adjustment (ppm) */
- double plladj; /* PLL frequency adjustment (ppm) */
- double clock_frequency; /* clock frequency adjustment (ppm) */
+ int osys_poll; /* old system poll */
+ double mu; /* interval since last update */
+ double clock_frequency; /* clock frequency */
double dtemp, etemp; /* double temps */
-#ifdef OPENSSL
- u_int32 *tpt;
- int i;
- u_int len;
- long togo;
-#endif /* OPENSSL */
+ char tbuf[80]; /* report buffer */
/*
* If the loop is opened or the NIST LOCKCLOCK is in use,
* monitor and record the offsets anyway in order to determine
* the open-loop response and then go home.
*/
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: assocID %d offset %.9f freq %.3f state %d\n",
- peer->associd, fp_offset, drift_comp * 1e6, state);
-#endif
#ifdef LOCKCLOCK
return (0);
@@ -257,33 +240,31 @@ local_clock(
*/
if (fabs(fp_offset) > clock_panic && clock_panic > 0 &&
!allow_panic) {
- msyslog(LOG_ERR,
- "time correction of %.0f seconds exceeds sanity limit (%.0f); set clock manually to the correct UTC time.",
+ snprintf(tbuf, sizeof(tbuf),
+ "%+.0f s; set clock manually within %.0f s.",
fp_offset, clock_panic);
+ report_event(EVNT_SYSFAULT, NULL, tbuf);
return (-1);
}
/*
- * If simulating ntpdate, set the clock directly, rather than
- * using the discipline. The clock_max defines the step
- * threshold, above which the clock will be stepped instead of
- * slewed. The value defaults to 128 ms, but can be set to even
- * unreasonable values. If set to zero, the clock will never be
- * stepped. Note that a slew will persist beyond the life of
- * this program.
- *
- * Note that if ntpdate is active, the terminal does not detach,
- * so the termination comments print directly to the console.
+ * This section simulates ntpdate. If the offset exceeds the
+ * step threshold (128 ms), step the clock to that time and
+ * exit. Othewise, slew the clock to that time and exit. Note
+ * that the slew will persist and eventually complete beyond the
+ * life of this program. Note that while ntpdate is active, the
+ * terminal does not detach, so the termination message prints
+ * directly to the terminal.
*/
if (mode_ntpdate) {
if (fabs(fp_offset) > clock_max && clock_max > 0) {
step_systime(fp_offset);
- msyslog(LOG_NOTICE, "time reset %+.6f s",
+ msyslog(LOG_NOTICE, "ntpd: time set %+.6f s",
fp_offset);
printf("ntpd: time set %+.6fs\n", fp_offset);
} else {
adj_systime(fp_offset);
- msyslog(LOG_NOTICE, "time slew %+.6f s",
+ msyslog(LOG_NOTICE, "ntpd: time slew %+.6f s",
fp_offset);
printf("ntpd: time slew %+.6fs\n", fp_offset);
}
@@ -299,12 +280,8 @@ local_clock(
* is most effective if the delays are highly assymetric and
* clockhopping is avoided and the clock frequency wander is
* relatively small.
- *
- * Note either there is no prefer peer or this update is from
- * the prefer peer.
*/
- if (sys_huffpuff != NULL && (sys_prefer == NULL || sys_prefer ==
- peer)) {
+ if (sys_huffpuff != NULL) {
if (peer->delay < sys_huffpuff[sys_huffptr])
sys_huffpuff[sys_huffptr] = peer->delay;
if (peer->delay < sys_mindly)
@@ -323,100 +300,104 @@ local_clock(
}
/*
- * Clock state machine transition function. This is where the
- * action is and defines how the system reacts to large phase
- * and frequency errors. There are two main regimes: when the
- * offset exceeds the step threshold and when it does not.
- * However, if the step threshold is set to zero, a step will
- * never occur. See the instruction manual for the details how
- * these actions interact with the command line options.
+ * Clock state machine transition function which defines how the
+ * system reacts to large phase and frequency excursion. There
+ * are two main regimes: when the offset exceeds the step
+ * threshold (128 ms) and when it does not. Under certain
+ * conditions updates are suspended until the stepout theshold
+ * (900 s) is exceeded. See the documentation on how these
+ * thresholds interact with commands and command line options.
*
- * Note the system poll is set to minpoll only if the clock is
- * stepped. Note also the kernel is disabled if step is
- * disabled or greater than 0.5 s.
+ * Note the kernel is disabled if step is disabled or greater
+ * than 0.5 s or in ntpdate mode.
*/
- clock_frequency = flladj = plladj = 0;
- mu = peer->epoch - sys_clocktime;
- if (clock_max == 0 || clock_max > 0.5)
- kern_enable = 0;
+ osys_poll = sys_poll;
+ if (sys_poll < peer->minpoll)
+ sys_poll = peer->minpoll;
+ if (sys_poll > peer->maxpoll)
+ sys_poll = peer->maxpoll;
+ mu = current_time - clock_epoch;
+ clock_frequency = drift_comp;
rval = 1;
if (fabs(fp_offset) > clock_max && clock_max > 0) {
switch (state) {
/*
- * In S_SYNC state we ignore the first outlyer amd
- * switch to S_SPIK state.
+ * In SYNC state we ignore the first outlyer and switch
+ * to SPIK state.
*/
- case S_SYNC:
- state = S_SPIK;
+ case EVNT_SYNC:
+ snprintf(tbuf, sizeof(tbuf), "%+.6f s",
+ fp_offset);
+ report_event(EVNT_SPIK, NULL, tbuf);
+ state = EVNT_SPIK;
return (0);
/*
- * In S_FREQ state we ignore outlyers and inlyers. At
- * the first outlyer after the stepout threshold,
- * compute the apparent frequency correction and step
- * the phase.
+ * In FREQ state we ignore outlyers and inlyers. At the
+ * first outlyer after the stepout threshold, compute
+ * the apparent frequency correction and step the phase.
*/
- case S_FREQ:
+ case EVNT_FREQ:
if (mu < clock_minstep)
return (0);
- clock_frequency = (fp_offset - clock_offset) /
- mu;
+ clock_frequency = direct_freq(fp_offset);
/* fall through to S_SPIK */
/*
- * In S_SPIK state we ignore succeeding outlyers until
+ * In SPIK state we ignore succeeding outlyers until
* either an inlyer is found or the stepout threshold is
* exceeded.
*/
- case S_SPIK:
+ case EVNT_SPIK:
if (mu < clock_minstep)
return (0);
/* fall through to default */
/*
- * We get here by default in S_NSET and S_FSET states
- * and from above in S_FREQ or S_SPIK states.
+ * We get here by default in NSET and FSET states and
+ * from above in FREQ or SPIK states.
*
- * In S_NSET state an initial frequency correction is
- * not available, usually because the frequency file has
- * not yet been written. Since the time is outside the
- * step threshold, the clock is stepped. The frequency
- * will be set directly following the stepout interval.
+ * In NSET state an initial frequency correction is not
+ * available, usually because the frequency file has not
+ * yet been written. Since the time is outside the step
+ * threshold, the clock is stepped. The frequency will
+ * be set directly following the stepout interval.
*
- * In S_FSET state the initial frequency has been set
- * from the frequency file. Since the time is outside
- * the step threshold, the clock is stepped immediately,
+ * In FSET state the initial frequency has been set from
+ * the frequency file. Since the time is outside the
+ * step threshold, the clock is stepped immediately,
* rather than after the stepout interval. Guys get
- * nervous if it takes 17 minutes to set the clock for
+ * nervous if it takes 15 minutes to set the clock for
* the first time.
*
- * In S_FREQ and S_SPIK states the stepout threshold has
+ * In FREQ and SPIK states the stepout threshold has
* expired and the phase is still above the step
* threshold. Note that a single spike greater than the
- * step threshold is always suppressed, even at the
- * longer poll intervals.
+ * step threshold is always suppressed, even with a
+ * long time constant.
*/
default:
- step_systime(fp_offset);
- msyslog(LOG_NOTICE, "time reset %+.6f s",
+ snprintf(tbuf, sizeof(tbuf), "%+.6f s",
fp_offset);
+ report_event(EVNT_CLOCKRESET, NULL, tbuf);
+ step_systime(fp_offset);
reinit_timer();
tc_counter = 0;
- sys_poll = NTP_MINPOLL;
- sys_tai = 0;
clock_jitter = LOGTOD(sys_precision);
rval = 2;
- if (state == S_NSET) {
- rstclock(S_FREQ, peer->epoch, 0);
+ if (state == EVNT_NSET || (current_time -
+ last_step) < clock_minstep * 2) {
+ rstclock(EVNT_FREQ, 0);
return (rval);
}
+ last_step = current_time;
break;
}
- rstclock(S_SYNC, peer->epoch, 0);
+ rstclock(EVNT_SYNC, 0);
} else {
/*
@@ -432,105 +413,76 @@ local_clock(
switch (state) {
/*
- * In S_NSET state this is the first update received and
+ * In NSET state this is the first update received and
* the frequency has not been initialized. Adjust the
* phase, but do not adjust the frequency until after
* the stepout threshold.
*/
- case S_NSET:
- rstclock(S_FREQ, peer->epoch, fp_offset);
+ case EVNT_NSET:
+ rstclock(EVNT_FREQ, fp_offset);
break;
/*
- * In S_FSET state this is the first update received and
+ * In FSET state this is the first update received and
* the frequency has been initialized. Adjust the phase,
* but do not adjust the frequency until the next
* update.
*/
- case S_FSET:
- rstclock(S_SYNC, peer->epoch, fp_offset);
+ case EVNT_FSET:
+ rstclock(EVNT_SYNC, fp_offset);
break;
/*
- * In S_FREQ state ignore updates until the stepout
- * threshold. After that, correct the phase and
- * frequency and switch to S_SYNC state.
+ * In FREQ state ignore updates until the stepout
+ * threshold. After that, compute the new frequency, but
+ * do not adjust the phase or frequency until the next
+ * update.
*/
- case S_FREQ:
+ case EVNT_FREQ:
if (mu < clock_minstep)
return (0);
- clock_frequency = (fp_offset - clock_offset) /
- mu;
- rstclock(S_SYNC, peer->epoch, fp_offset);
+ clock_frequency = direct_freq(fp_offset);
+ rstclock(EVNT_SYNC, 0);
break;
+
/*
- * We get here by default in S_SYNC and S_SPIK states.
- * Here we compute the frequency update due to PLL and
- * FLL contributions.
+ * We get here by default in SYNC and SPIK states. Here
+ * we compute the frequency update due to PLL and FLL
+ * contributions.
*/
default:
allow_panic = FALSE;
/*
* The FLL and PLL frequency gain constants
- * depend on the poll interval and Allan
+ * depend on the time constant and Allan
* intercept. The PLL is always used, but
- * becomes ineffective above the Allan
- * intercept. The FLL is not used below one-half
- * the Allan intercept. Above that the loop gain
- * increases in steps to 1 / CLOCK_AVG.
+ * becomes ineffective above the Allan intercept
+ * where the FLL becomes effective.
*/
- if (ULOGTOD(sys_poll) > allan_xpt / 2) {
- dtemp = CLOCK_FLL - sys_poll;
- flladj = (fp_offset - clock_offset) /
- (max(mu, allan_xpt) * dtemp);
- }
+ if (sys_poll >= allan_xpt)
+ clock_frequency += (fp_offset -
+ clock_offset) /
+ max(ULOGTOD(sys_poll), mu) *
+ CLOCK_FLL;
/*
- * For the PLL the integration interval
- * (numerator) is the minimum of the update
- * interval and poll interval. This allows
- * oversampling, but not undersampling.
+ * The PLL frequency gain (numerator) depends on
+ * the minimum of the update interval and Allan
+ * intercept. This reduces the PLL gain when the
+ * FLL becomes effective.
*/
- etemp = min(mu, (u_long)ULOGTOD(sys_poll));
+ etemp = min(ULOGTOD(allan_xpt), mu);
dtemp = 4 * CLOCK_PLL * ULOGTOD(sys_poll);
- plladj = fp_offset * etemp / (dtemp * dtemp);
- rstclock(S_SYNC, peer->epoch, fp_offset);
+ clock_frequency += fp_offset * etemp / (dtemp *
+ dtemp);
+ rstclock(EVNT_SYNC, fp_offset);
break;
}
}
-#ifdef OPENSSL
- /*
- * Scan the loopsecond table to determine the TAI offset. If
- * there is a scheduled leap in future, set the leap warning,
- * but only if less than 30 days before the leap.
- */
- tpt = (u_int32 *)tai_leap.ptr;
- len = ntohl(tai_leap.vallen) / sizeof(u_int32);
- if (tpt != NULL) {
- for (i = 0; i < len; i++) {
- togo = (long)ntohl(tpt[i]) -
- (long)peer->rec.l_ui;
- if (togo > 0) {
- if (togo < CLOCK_JUNE)
- leap_next |= LEAP_ADDSECOND;
- break;
- }
- }
-#if defined(STA_NANO) && NTP_API == 4
- if (pll_control && kern_enable && sys_tai == 0) {
- memset(&ntv, 0, sizeof(ntv));
- ntv.modes = MOD_TAI;
- ntv.constant = i + TAI_1972 - 1;
- ntp_adjtime(&ntv);
- }
-#endif /* STA_NANO */
- sys_tai = i + TAI_1972 - 1;
- }
-#endif /* OPENSSL */
#ifdef KERNEL_PLL
/*
* This code segment works when clock adjustments are made using
@@ -564,9 +516,6 @@ local_clock(
if (ext_enable) {
ntv.modes = MOD_STATUS;
} else {
- struct tm *tm = NULL;
- time_t tstamp;
-
#ifdef STA_NANO
ntv.modes = MOD_BITS | MOD_NANO;
#else /* STA_NANO */
@@ -585,73 +534,41 @@ local_clock(
dtemp);
ntv.constant = sys_poll - 4;
#endif /* STA_NANO */
-
- /*
- * The frequency is set directly only if
- * clock_frequency is nonzero coming out of FREQ
- * state.
- */
- if (clock_frequency != 0) {
- ntv.modes |= MOD_FREQUENCY;
- ntv.freq = (int32)((clock_frequency +
- drift_comp) * 65536e6);
- }
ntv.esterror = (u_int32)(clock_jitter * 1e6);
ntv.maxerror = (u_int32)((sys_rootdelay / 2 +
- sys_rootdispersion) * 1e6);
+ sys_rootdisp) * 1e6);
ntv.status = STA_PLL;
/*
- * Set the leap bits in the status word, but
- * only on the last day of June or December.
- */
- tstamp = peer->rec.l_ui - JAN_1970;
- tm = gmtime(&tstamp);
- if (tm != NULL) {
- if ((tm->tm_mon + 1 == 6 &&
- tm->tm_mday == 30) || (tm->tm_mon +
- 1 == 12 && tm->tm_mday == 31)) {
- if (leap_next & LEAP_ADDSECOND)
- ntv.status |= STA_INS;
- else if (leap_next &
- LEAP_DELSECOND)
- ntv.status |= STA_DEL;
- }
- }
-
- /*
- * 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.
+ * Enable/disable the PPS if requested.
*/
- if (pps_enable && pll_status & STA_PPSSIGNAL) {
- ntv.status |= STA_PPSFREQ;
- if (pps_stratum < STRATUM_UNSPEC)
- ntv.status |= STA_PPSTIME;
+ if (pps_enable) {
+ if (!(pll_status & STA_PPSTIME))
+ report_event(EVNT_KERN,
+ NULL, "PPS enabled");
+ ntv.status |= STA_PPSTIME | STA_PPSFREQ;
} else {
- ntv.status &= ~(STA_PPSFREQ |
- STA_PPSTIME);
+ if (pll_status & STA_PPSTIME)
+ report_event(EVNT_KERN,
+ NULL, "PPS disabled");
+ ntv.status &= ~(STA_PPSTIME |
+ STA_PPSFREQ);
}
+ if (sys_leap == LEAP_ADDSECOND)
+ ntv.status |= STA_INS;
+ else if (sys_leap == LEAP_DELSECOND)
+ ntv.status |= STA_DEL;
}
/*
* Pass the stuff to the kernel. If it squeals, turn off
- * the pig. In any case, fetch the kernel offset and
- * frequency and pretend we did it here.
+ * the pps. In any case, fetch the kernel offset,
+ * frequency and jitter.
*/
if (ntp_adjtime(&ntv) == TIME_ERROR) {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "kernel time sync error %04x", ntv.status);
- ntv.status &= ~(STA_PPSFREQ | STA_PPSTIME);
- } else {
- if ((ntv.status ^ pll_status) & ~STA_FLL)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "kernel time sync status change %04x",
- ntv.status);
+ if (!(ntv.status & STA_PPSSIGNAL))
+ report_event(EVNT_KERN, NULL,
+ "PPS no signal");
}
pll_status = ntv.status;
#ifdef STA_NANO
@@ -659,42 +576,39 @@ local_clock(
#else /* STA_NANO */
clock_offset = ntv.offset / 1e6;
#endif /* STA_NANO */
- clock_frequency = ntv.freq / 65536e6;
- flladj = plladj = 0;
+ clock_frequency = FREQTOD(ntv.freq);
/*
* If the kernel PPS is lit, monitor its performance.
*/
if (ntv.status & STA_PPSTIME) {
- pps_control = current_time;
#ifdef STA_NANO
clock_jitter = ntv.jitter / 1e9;
#else /* STA_NANO */
clock_jitter = ntv.jitter / 1e6;
#endif /* STA_NANO */
}
- } else {
-#endif /* KERNEL_PLL */
-
+
+#if defined(STA_NANO) && NTP_API == 4
/*
- * We get here if the kernel discipline is not enabled.
- * Adjust the clock frequency as the sum of the directly
- * computed frequency (if measured) and the PLL and FLL
- * increments.
+ * If the TAI changes, update the kernel TAI.
*/
- clock_frequency = drift_comp + clock_frequency +
- flladj + plladj;
-#ifdef KERNEL_PLL
+ if (loop_tai != sys_tai) {
+ loop_tai = sys_tai;
+ ntv.modes = MOD_TAI;
+ ntv.constant = sys_tai;
+ ntp_adjtime(&ntv);
+ }
+#endif /* STA_NANO */
}
#endif /* KERNEL_PLL */
/*
* Clamp the frequency within the tolerance range and calculate
- * the frequency change since the last update.
+ * the frequency difference since the last update.
*/
if (fabs(clock_frequency) > NTP_MAXFREQ)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
+ msyslog(LOG_NOTICE,
"frequency error %.0f PPM exceeds tolerance %.0f PPM",
clock_frequency * 1e6, NTP_MAXFREQ * 1e6);
dtemp = SQUARE(clock_frequency - drift_comp);
@@ -706,14 +620,16 @@ local_clock(
drift_comp = clock_frequency;
/*
- * Calculate the wander as the exponentially weighted frequency
- * differences.
+ * Calculate the wander as the exponentially weighted RMS
+ * frequency differences. Record the change for the frequency
+ * file update.
*/
etemp = SQUARE(clock_stability);
clock_stability = SQRT(etemp + (dtemp - etemp) / CLOCK_AVG);
+ drift_file_sw = TRUE;
/*
- * Here we adjust the poll interval by comparing the current
+ * Here we adjust the timeconstan by comparing the current
* offset with the clock jitter. If the offset is less than the
* clock jitter times a constant, then the averaging interval is
* increased, otherwise it is decreased. A bit of hysteresis
@@ -740,6 +656,12 @@ local_clock(
}
/*
+ * If the time constant has changed, update the poll variables.
+ */
+ if (osys_poll != sys_poll)
+ poll_update(peer, sys_poll);
+
+ /*
* Yibbidy, yibbbidy, yibbidy; that'h all folks.
*/
record_loop_stats(clock_offset, drift_comp, clock_jitter,
@@ -747,9 +669,9 @@ local_clock(
#ifdef DEBUG
if (debug)
printf(
- "local_clock: mu %lu jitr %.6f freq %.3f stab %.6f poll %d count %d\n",
- mu, clock_jitter, drift_comp * 1e6,
- clock_stability * 1e6, sys_poll, tc_counter);
+ "local_clock: offset %.9f jit %.9f freq %.3f stab %.3f poll %d\n",
+ clock_offset, clock_jitter, drift_comp * 1e6,
+ clock_stability * 1e6, sys_poll);
#endif /* DEBUG */
return (rval);
#endif /* LOCKCLOCK */
@@ -760,7 +682,7 @@ local_clock(
* adj_host_clock - Called once every second to update the local clock.
*
* LOCKCLOCK: The only thing this routine does is increment the
- * sys_rootdispersion variable.
+ * sys_rootdisp variable.
*/
void
adj_host_clock(
@@ -774,12 +696,9 @@ adj_host_clock(
* NTPv3, NTPv4 does not declare unsynchronized after one day,
* since the dispersion check serves this function. Also,
* since the poll interval can exceed one day, the old test
- * would be counterproductive. Note we do this even with
- * external clocks, since the clock driver will recompute the
- * maximum error and the local clock driver will pick it up and
- * pass to the common refclock routines. Very elegant.
+ * would be counterproductive.
*/
- sys_rootdispersion += clock_phi;
+ sys_rootdisp += clock_phi;
#ifndef LOCKCLOCK
/*
@@ -791,25 +710,11 @@ adj_host_clock(
return;
/*
- * Declare PPS kernel unsync if the pps signal has not been
- * heard for a few minutes.
- */
- if (pps_control && current_time - pps_control > PPS_MAXAGE) {
- if (pps_control)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "pps sync disabled");
- pps_control = 0;
- }
-
- /*
* Implement the phase and frequency adjustments. The gain
- * factor (denominator) is not allowed to increase beyond the
- * Allan intercept. It doesn't make sense to average phase noise
- * beyond this point and it helps to damp residual offset at the
- * longer poll intervals.
- */
- adjustment = clock_offset / (CLOCK_PLL * min(ULOGTOD(sys_poll),
- allan_xpt));
+ * factor (denominator) increases with poll interval, so is
+ * dominated by the FLL above the Allan intercept.
+ */
+ adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
clock_offset -= adjustment;
adj_systime(adjustment + drift_comp);
#endif /* LOCKCLOCK */
@@ -817,29 +722,104 @@ adj_host_clock(
/*
- * Clock state machine. Enter new state and set state variables. Note we
- * use the time of the last clock filter sample, which may be earlier
- * than the current time.
+ * Clock state machine. Enter new state and set state variables.
*/
static void
rstclock(
int trans, /* new state */
- u_long update, /* new update time */
double offset /* new offset */
)
{
#ifdef DEBUG
- if (debug)
- printf("local_clock: time %lu offset %.6f freq %.3f state %d\n",
- update, offset, drift_comp * 1e6, trans);
+ if (debug > 1)
+ printf("local_clock: mu %lu state %d poll %d count %d\n",
+ current_time - clock_epoch, trans, sys_poll,
+ tc_counter);
#endif
+ if (trans != state && trans != EVNT_FSET)
+ report_event(trans, NULL, NULL);
state = trans;
- sys_clocktime = update;
last_offset = clock_offset = offset;
+ clock_epoch = current_time;
+}
+
+/*
+ * calc_freq - calculate frequency directly
+ *
+ * This is very carefully done. When the offset is first computed at the
+ * first update, a residual frequency component results. Subsequently,
+ * updates are suppresed until the end of the measurement interval while
+ * the offset is amortized. At the end of the interval the frequency is
+ * calculated from the current offset, residual offset, length of the
+ * interval and residual frequency component. At the same time the
+ * frequenchy file is armed for update at the next hourly stats.
+ */
+static double
+direct_freq(
+ double fp_offset
+ )
+{
+
+#ifdef KERNEL_PLL
+ /*
+ * If the kernel is enabled, we need the residual offset to
+ * calculate the frequency correction.
+ */
+ if (pll_control && kern_enable) {
+ memset(&ntv, 0, sizeof(ntv));
+ ntp_adjtime(&ntv);
+#ifdef STA_NANO
+ clock_offset = ntv.offset / 1e9;
+#else /* STA_NANO */
+ clock_offset = ntv.offset / 1e6;
+#endif /* STA_NANO */
+ drift_comp = FREQTOD(ntv.freq);
+ }
+#endif /* KERNEL_PLL */
+ set_freq((fp_offset - clock_offset) / (current_time -
+ clock_epoch) + drift_comp);
+ wander_resid = 0;
+ return (drift_comp);
}
/*
+ * set_freq - set clock frequency
+ */
+static void
+set_freq(
+ double freq /* frequency update */
+ )
+{
+ char tbuf[80];
+
+ drift_comp = freq;
+
+#ifdef KERNEL_PLL
+ /*
+ * If the kernel is enabled, update the kernel frequency.
+ */
+ if (pll_control && kern_enable) {
+ memset(&ntv, 0, sizeof(ntv));
+ ntv.modes = MOD_FREQUENCY;
+ ntv.freq = DTOFREQ(drift_comp);
+ ntp_adjtime(&ntv);
+ snprintf(tbuf, sizeof(tbuf), "kernel %.3f PPM",
+ drift_comp * 1e6);
+ report_event(EVNT_FSET, NULL, tbuf);
+ } else {
+ snprintf(tbuf, sizeof(tbuf), "ntpd %.3f PPM",
+ drift_comp * 1e6);
+ report_event(EVNT_FSET, NULL, tbuf);
+ }
+#else /* KERNEL_PLL */
+ snprintf(tbuf, sizeof(tbuf), "ntpd %.3f PPM", drift_comp *
+ 1e6);
+ report_event(EVNT_FSET, NULL, tbuf);
+#endif /* KERNEL_PLL */
+}
+
+/*
* huff-n'-puff filter
*/
void
@@ -867,39 +847,36 @@ huffpuff()
*/
void
loop_config(
- int item,
- double freq
+ int item,
+ double freq
)
{
int i;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("loop_config: item %d freq %f\n", item, freq);
+#endif
switch (item) {
+ /*
+ * We first assume the kernel supports the ntp_adjtime()
+ * syscall. If that syscall works, initialize the kernel time
+ * variables. Otherwise, continue leaving no harm behind.
+ */
case LOOP_DRIFTINIT:
-
#ifndef LOCKCLOCK
#ifdef KERNEL_PLL
- /*
- * Assume the kernel supports the ntp_adjtime() syscall.
- * If that syscall works, initialize the kernel time
- * variables. Otherwise, continue leaving no harm
- * behind. While at it, ask to set nanosecond mode. If
- * the kernel agrees, rejoice; othewise, it does only
- * microseconds.
- */
if (mode_ntpdate)
break;
pll_control = 1;
memset(&ntv, 0, sizeof(ntv));
-#ifdef STA_NANO
- ntv.modes = MOD_BITS | MOD_NANO;
-#else /* STA_NANO */
ntv.modes = MOD_BITS;
-#endif /* STA_NANO */
+ ntv.status = STA_PLL;
ntv.maxerror = MAXDISPERSE;
ntv.esterror = MAXDISPERSE;
- ntv.status = STA_UNSYNC;
+ ntv.constant = sys_poll;
#ifdef SIGSYS
/*
* Use sigsetjmp() to save state and then call
@@ -935,91 +912,73 @@ loop_config(
if (pll_status & STA_CLK)
ext_enable = 1;
#endif /* STA_NANO */
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_INFO,
- "kernel time sync status %04x",
- pll_status);
+ report_event(EVNT_KERN, NULL,
+ "kernel time sync enabled");
}
#endif /* KERNEL_PLL */
#endif /* LOCKCLOCK */
break;
+ /*
+ * Initialize the frequency. If the frequency file is missing or
+ * broken, set the initial frequency to zero and set the state
+ * to NSET. Otherwise, set the initial frequency to the given
+ * value and the state to FSET.
+ */
case LOOP_DRIFTCOMP:
-
#ifndef LOCKCLOCK
- /*
- * If the frequency value is reasonable, set the initial
- * frequency to the given value and the state to S_FSET.
- * Otherwise, the drift file may be missing or broken,
- * so set the frequency to zero. This erases past
- * history should somebody break something.
- */
- if (freq <= NTP_MAXFREQ && freq >= -NTP_MAXFREQ) {
- drift_comp = freq;
- rstclock(S_FSET, 0, 0);
+ if (freq > NTP_MAXFREQ || freq < -NTP_MAXFREQ) {
+ set_freq(0);
+ rstclock(EVNT_NSET, 0);
} else {
- drift_comp = 0;
+ set_freq(freq);
+ rstclock(EVNT_FSET, 0);
}
-
-#ifdef KERNEL_PLL
- /*
- * Sanity check. If the kernel is available, load the
- * frequency and light up the loop. Make sure the offset
- * is zero to cancel any previous nonsense. If you don't
- * want this initialization, remove the ntp.drift file.
- */
- if (pll_control && kern_enable) {
- memset((char *)&ntv, 0, sizeof(ntv));
- ntv.modes = MOD_OFFSET | MOD_FREQUENCY;
- ntv.freq = (int32)(drift_comp * 65536e6);
- ntp_adjtime(&ntv);
- }
-#endif /* KERNEL_PLL */
#endif /* LOCKCLOCK */
break;
+ /*
+ * Disable the kernel at shutdown. The microkernel just abandons
+ * ship. The nanokernel carefully cleans up so applications can
+ * see this. Note the last programmed offset and frequency are
+ * left in place.
+ */
case LOOP_KERN_CLEAR:
#ifndef LOCKCLOCK
#ifdef KERNEL_PLL
- /* Completely turn off the kernel time adjustments. */
- if (pll_control) {
+ if (pll_control && kern_enable) {
memset((char *)&ntv, 0, sizeof(ntv));
- ntv.modes = MOD_BITS | MOD_OFFSET | MOD_FREQUENCY;
+ ntv.modes = MOD_STATUS;
ntv.status = STA_UNSYNC;
ntp_adjtime(&ntv);
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_INFO,
- "kernel time sync disabled %04x",
- ntv.status);
+ report_event(EVNT_KERN, NULL,
+ "kernel time sync disabledx");
}
#endif /* KERNEL_PLL */
#endif /* LOCKCLOCK */
break;
/*
- * Special tinker variables for Ulrich Windl. Very dangerous.
+ * Tinker command variables for Ulrich Windl. Very dangerous.
*/
- case LOOP_MAX: /* step threshold */
- clock_max = freq;
+ case LOOP_ALLAN: /* Allan intercept (log2) (allan) */
+ allan_xpt = (u_char)freq;
break;
- case LOOP_PANIC: /* panic threshold */
- clock_panic = freq;
+ case LOOP_CODEC: /* audio codec frequency (codec) */
+ clock_codec = freq / 1e6;
break;
-
- case LOOP_PHI: /* dispersion rate */
- clock_phi = freq;
+
+ case LOOP_PHI: /* dispersion threshold (dispersion) */
+ clock_phi = freq / 1e6;
break;
- case LOOP_MINSTEP: /* watchdog bark */
- clock_minstep = freq;
+ case LOOP_FREQ: /* initial frequency (freq) */
+ set_freq(freq / 1e6);
+ rstclock(EVNT_FSET, 0);
break;
- case LOOP_ALLAN: /* Allan intercept */
- allan_xpt = freq;
- break;
-
- case LOOP_HUFFPUFF: /* huff-n'-puff filter length */
+ case LOOP_HUFFPUFF: /* huff-n'-puff length (huffpuff) */
if (freq < HUFFPUFF)
freq = HUFFPUFF;
sys_hufflen = (int)(freq / HUFFPUFF);
@@ -1030,10 +989,24 @@ loop_config(
sys_mindly = 1e9;
break;
- case LOOP_FREQ: /* initial frequency */
- drift_comp = freq / 1e6;
- rstclock(S_FSET, 0, 0);
+ case LOOP_PANIC: /* panic threshold (panic) */
+ clock_panic = freq;
+ break;
+
+ case LOOP_MAX: /* step threshold (step) */
+ clock_max = freq;
+ if (clock_max == 0 || clock_max > 0.5)
+ kern_enable = 0;
break;
+
+ case LOOP_MINSTEP: /* stepout threshold (stepout) */
+ clock_minstep = freq;
+ break;
+
+ case LOOP_LEAP: /* not used */
+ default:
+ msyslog(LOG_NOTICE,
+ "loop_config: unsupported option %d", item);
}
}
diff --git a/ntpd/ntp_monitor.c b/ntpd/ntp_monitor.c
index 753fa767ce80..200a9028dd9f 100644
--- a/ntpd/ntp_monitor.c
+++ b/ntpd/ntp_monitor.c
@@ -18,17 +18,14 @@
#endif
/*
- * I'm still not sure I like what I've done here. It certainly consumes
- * memory like it is going out of style, and also may not be as low
- * overhead as I'd imagined.
+ * Record statistics based on source address, mode and version. The
+ * receive procedure calls us with the incoming rbufp before it does
+ * anything else. While at it, implement rate controls for inbound
+ * traffic.
*
- * Anyway, we record statistics based on source address, mode and
- * version (for now, anyway. Check the code). The receive procedure
- * calls us with the incoming rbufp before it does anything else.
- *
- * Each entry is doubly linked into two lists, a hash table and a
- * most-recently-used list. When a packet arrives it is looked up in
- * the hash table. If found, the statistics are updated and the entry
+ * Each entry is doubly linked into two lists, a hash table and a most-
+ * recently-used (MRU) list. When a packet arrives it is looked up in
+ * the hash table. If found, the statistics are updated and the entry
* relinked at the head of the MRU list. If not found, a new entry is
* allocated, initialized and linked into both the hash table and at the
* head of the MRU list.
@@ -38,14 +35,12 @@
* the memory limit. Then we free memory by grabbing entries off the
* tail for the MRU list, unlinking from the hash table, and
* reinitializing.
- *
- * trimmed back memory consumption ... jdg 8/94
*/
/*
* Limits on the number of structures allocated. This limit is picked
- * with the illicit knowlege that we can only return somewhat less
- * than 8K bytes in a mode 7 response packet, and that each structure
- * will require about 20 bytes of space in the response.
+ * with the illicit knowlege that we can only return somewhat less than
+ * 8K bytes in a mode 7 response packet, and that each structure will
+ * require about 20 bytes of space in the response.
*
* ... I don't believe the above is true anymore ... jdg
*/
@@ -59,9 +54,9 @@
/*
* Hashing stuff
*/
-#define MON_HASH_SIZE 128
-#define MON_HASH_MASK (MON_HASH_SIZE-1)
-#define MON_HASH(addr) sock_hash(addr)
+#define MON_HASH_SIZE NTP_HASH_SIZE
+#define MON_HASH_MASK NTP_HASH_MASK
+#define MON_HASH(addr) NTP_HASH_ADDR(addr)
/*
* Pointers to the hash table, the MRU list and the count table. Memory
@@ -73,21 +68,30 @@ struct mon_data mon_mru_list;
/*
* List of free structures structures, and counters of free and total
- * structures. The free structures are linked with the hash_next field.
+ * structures. The free structures are linked with the hash_next field.
*/
static struct mon_data *mon_free; /* free list or null if none */
static int mon_total_mem; /* total structures allocated */
static int mon_mem_increments; /* times called malloc() */
/*
+ * Parameters of the RES_LIMITED restriction option. We define headway
+ * as the idle time between packets. A packet is discarded if the
+ * headway is less than the minimum, as well as if the average headway
+ * is less than eight times the increment.
+ */
+int ntp_minpkt = NTP_MINPKT; /* minimum (log 2 s) */
+int ntp_minpoll = NTP_MINPOLL; /* increment (log 2 s) */
+
+/*
* Initialization state. We may be monitoring, we may not. If
* we aren't, we may not even have allocated any memory yet.
*/
int mon_enabled; /* enable switch */
-u_long mon_age = 3000; /* preemption limit */
+int mon_age = 3000; /* preemption limit */
static int mon_have_memory;
-static void mon_getmoremem P((void));
-static void remove_from_hash P((struct mon_data *));
+static void mon_getmoremem (void);
+static void remove_from_hash (struct mon_data *);
/*
* init_mon - initialize monitoring global data
@@ -101,7 +105,6 @@ init_mon(void)
*/
mon_enabled = MON_OFF;
mon_have_memory = 0;
-
mon_total_mem = 0;
mon_mem_increments = 0;
mon_free = NULL;
@@ -152,13 +155,13 @@ mon_stop(
register int i;
if (mon_enabled == MON_OFF)
- return;
+ return;
if ((mon_enabled & mode) == 0 || mode == MON_OFF)
- return;
+ return;
mon_enabled &= ~mode;
if (mon_enabled != MON_OFF)
- return;
+ return;
/*
* Put everything back on the free list
@@ -173,7 +176,6 @@ mon_stop(
md = md_next;
}
}
-
mon_mru_list.mru_next = &mon_mru_list;
mon_mru_list.mru_prev = &mon_mru_list;
}
@@ -184,37 +186,39 @@ ntp_monclearinterface(struct interface *interface)
struct mon_data *md;
for (md = mon_mru_list.mru_next; md != &mon_mru_list;
- md = md->mru_next) {
- if (md->interface == interface)
- {
- /* dequeue from mru list and put to free list */
- md->mru_prev->mru_next = md->mru_next;
- md->mru_next->mru_prev = md->mru_prev;
- remove_from_hash(md);
- md->hash_next = mon_free;
- mon_free = md;
- }
+ md = md->mru_next) {
+ if (md->interface == interface) {
+ /* dequeue from mru list and put to free list */
+ md->mru_prev->mru_next = md->mru_next;
+ md->mru_next->mru_prev = md->mru_prev;
+ remove_from_hash(md);
+ md->hash_next = mon_free;
+ mon_free = md;
+ }
}
}
+
/*
* ntp_monitor - record stats about this packet
*
- * Returns 1 if the packet is at the head of the list, 0 otherwise.
+ * Returns flags
*/
int
ntp_monitor(
- struct recvbuf *rbufp
+ struct recvbuf *rbufp,
+ int flags
)
{
register struct pkt *pkt;
register struct mon_data *md;
- struct sockaddr_storage addr;
- register int hash;
+ sockaddr_u addr;
+ register u_int hash;
register int mode;
+ int interval;
if (mon_enabled == MON_OFF)
- return 0;
+ return (flags);
pkt = &rbufp->recv_pkt;
memset(&addr, 0, sizeof(addr));
@@ -223,14 +227,18 @@ ntp_monitor(
mode = PKT_MODE(pkt->li_vn_mode);
md = mon_hash[hash];
while (md != NULL) {
+ int head; /* headway increment */
+ int leak; /* new headway */
+ int limit; /* average threshold */
/*
* Match address only to conserve MRU size.
*/
- if (SOCKCMP(&md->rmtadr, &addr)) {
- md->drop_count = current_time - md->lasttime;
+ if (SOCK_EQ(&md->rmtadr, &addr)) {
+ interval = current_time - md->lasttime;
md->lasttime = current_time;
md->count++;
+ md->flags = flags;
md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
md->mode = (u_char) mode;
md->version = PKT_VERSION(pkt->li_vn_mode);
@@ -244,7 +252,49 @@ ntp_monitor(
md->mru_prev = &mon_mru_list;
mon_mru_list.mru_next->mru_prev = md;
mon_mru_list.mru_next = md;
- return 1;
+
+ /*
+ * At this point the most recent arrival is
+ * first in the MRU list. Decrease the counter
+ * by the headway, but not less than zero.
+ */
+ md->leak -= interval;
+ if (md->leak < 0)
+ md->leak = 0;
+ head = 1 << ntp_minpoll;
+ leak = md->leak + head;
+ limit = NTP_SHIFT * head;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("restrict: interval %d headway %d limit %d\n",
+ interval, leak, limit);
+#endif
+
+ /*
+ * If the minimum and average thresholds are not
+ * exceeded, douse the RES_LIMITED and RES_KOD
+ * bits and increase the counter by the headway
+ * increment. Note that we give a 1-s grace for
+ * the minimum threshold and a 2-s grace for the
+ * headway increment. If one or both thresholds
+ * are exceeded and the old counter is less than
+ * the average threshold, set the counter to the
+ * average threshold plus the inrcrment and
+ * leave the RES_KOD bit lit. Othewise, leave
+ * the counter alone and douse the RES_KOD bit.
+ * This rate-limits the KoDs to no less than the
+ * average headway.
+ */
+ if (interval + 1 >= (1 << ntp_minpkt) &&
+ leak < limit) {
+ md->leak = leak - 2;
+ md->flags &= ~(RES_LIMITED | RES_KOD);
+ } else if (md->leak < limit) {
+ md->leak = limit + head;
+ } else {
+ md->flags &= ~RES_KOD;
+ }
+ return (md->flags);
}
md = md->hash_next;
}
@@ -260,10 +310,9 @@ ntp_monitor(
* Preempt from the MRU list if old enough.
*/
md = mon_mru_list.mru_prev;
- /* We get 31 bits from ntp_random() */
- if (((u_long)ntp_random()) / FRAC >
- (double)(current_time - md->lasttime) / mon_age)
- return 0;
+ if (ntp_random() / (2. * FRAC) > (double)(current_time
+ - md->lasttime) / mon_age)
+ return (flags & ~(RES_LIMITED | RES_KOD));
md->mru_prev->mru_next = &mon_mru_list;
mon_mru_list.mru_prev = md->mru_prev;
@@ -278,19 +327,20 @@ ntp_monitor(
/*
* Got one, initialize it
*/
- md->avg_interval = 0;
- md->lasttime = current_time;
+ md->lasttime = md->firsttime = current_time;
md->count = 1;
- md->drop_count = 0;
+ md->flags = flags & ~(RES_LIMITED | RES_KOD);
+ md->leak = 0;
memset(&md->rmtadr, 0, sizeof(md->rmtadr));
memcpy(&md->rmtadr, &addr, sizeof(addr));
md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
md->mode = (u_char) mode;
md->version = PKT_VERSION(pkt->li_vn_mode);
md->interface = rbufp->dstadr;
- md->cast_flags = (u_char)(((rbufp->dstadr->flags & INT_MCASTOPEN) &&
- rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
- md->interface->bfd ? MDF_BCAST : MDF_UCAST);
+ md->cast_flags = (u_char)(((rbufp->dstadr->flags &
+ INT_MCASTOPEN) && rbufp->fd == md->interface->fd) ?
+ MDF_MCAST: rbufp->fd == md->interface->bfd ? MDF_BCAST :
+ MDF_UCAST);
/*
* Drop him into front of the hash table. Also put him on top of
@@ -302,7 +352,7 @@ ntp_monitor(
md->mru_prev = &mon_mru_list;
mon_mru_list.mru_next->mru_prev = md;
mon_mru_list.mru_next = md;
- return 1;
+ return (md->flags);
}
@@ -338,7 +388,7 @@ remove_from_hash(
struct mon_data *md
)
{
- register int hash;
+ register u_int hash;
register struct mon_data *md_prev;
hash = MON_HASH(&md->rmtadr);
diff --git a/ntpd/ntp_parser.c b/ntpd/ntp_parser.c
new file mode 100644
index 000000000000..248545f067c3
--- /dev/null
+++ b/ntpd/ntp_parser.c
@@ -0,0 +1,3630 @@
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 11 "ntp_parser.y"
+
+ #ifdef HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+
+ #include "ntp.h"
+ #include "ntpd.h"
+ #include "ntp_machine.h"
+ #include "ntp_stdlib.h"
+ #include "ntp_filegen.h"
+ #include "ntp_data_structures.h"
+ #include "ntp_scanner.h"
+ #include "ntp_config.h"
+ #include "ntp_crypto.h"
+
+ #include "ntpsim.h" /* HMS: Do we really want this all the time? */
+ /* SK: It might be a good idea to always
+ include the simulator code. That way
+ someone can use the same configuration file
+ for both the simulator and the daemon
+ */
+
+
+ struct FILE_INFO *ip_file; /* Pointer to the configuration file stream */
+
+ #define YYMALLOC emalloc
+ #define YYFREE free
+ #define YYERROR_VERBOSE
+ #define YYMAXDEPTH 1000 /* stop the madness sooner */
+ void yyerror(const char *msg);
+ extern int input_from_file; /* 0=input from ntpq :config */
+
+
+/* Line 189 of yacc.c */
+#line 106 "ntp_parser.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 1
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_Age = 258,
+ T_All = 259,
+ T_Allan = 260,
+ T_Auth = 261,
+ T_Autokey = 262,
+ T_Automax = 263,
+ T_Average = 264,
+ T_Bclient = 265,
+ T_Beacon = 266,
+ T_Bias = 267,
+ T_Broadcast = 268,
+ T_Broadcastclient = 269,
+ T_Broadcastdelay = 270,
+ T_Burst = 271,
+ T_Calibrate = 272,
+ T_Calldelay = 273,
+ T_Ceiling = 274,
+ T_Clockstats = 275,
+ T_Cohort = 276,
+ T_ControlKey = 277,
+ T_Crypto = 278,
+ T_Cryptostats = 279,
+ T_Day = 280,
+ T_Default = 281,
+ T_Digest = 282,
+ T_Disable = 283,
+ T_Discard = 284,
+ T_Dispersion = 285,
+ T_Double = 286,
+ T_Driftfile = 287,
+ T_Drop = 288,
+ T_Ellipsis = 289,
+ T_Enable = 290,
+ T_End = 291,
+ T_False = 292,
+ T_File = 293,
+ T_Filegen = 294,
+ T_Flag1 = 295,
+ T_Flag2 = 296,
+ T_Flag3 = 297,
+ T_Flag4 = 298,
+ T_Flake = 299,
+ T_Floor = 300,
+ T_Freq = 301,
+ T_Fudge = 302,
+ T_Host = 303,
+ T_Huffpuff = 304,
+ T_Iburst = 305,
+ T_Ident = 306,
+ T_Ignore = 307,
+ T_Includefile = 308,
+ T_Integer = 309,
+ T_Interface = 310,
+ T_Ipv4 = 311,
+ T_Ipv4_flag = 312,
+ T_Ipv6 = 313,
+ T_Ipv6_flag = 314,
+ T_Kernel = 315,
+ T_Key = 316,
+ T_Keys = 317,
+ T_Keysdir = 318,
+ T_Kod = 319,
+ T_Mssntp = 320,
+ T_Leapfile = 321,
+ T_Limited = 322,
+ T_Link = 323,
+ T_Listen = 324,
+ T_Logconfig = 325,
+ T_Logfile = 326,
+ T_Loopstats = 327,
+ T_Lowpriotrap = 328,
+ T_Manycastclient = 329,
+ T_Manycastserver = 330,
+ T_Mask = 331,
+ T_Maxclock = 332,
+ T_Maxdist = 333,
+ T_Maxpoll = 334,
+ T_Minclock = 335,
+ T_Mindist = 336,
+ T_Minimum = 337,
+ T_Minpoll = 338,
+ T_Minsane = 339,
+ T_Mode = 340,
+ T_Monitor = 341,
+ T_Month = 342,
+ T_Multicastclient = 343,
+ T_Nic = 344,
+ T_Nolink = 345,
+ T_Nomodify = 346,
+ T_None = 347,
+ T_Nopeer = 348,
+ T_Noquery = 349,
+ T_Noselect = 350,
+ T_Noserve = 351,
+ T_Notrap = 352,
+ T_Notrust = 353,
+ T_Ntp = 354,
+ T_Ntpport = 355,
+ T_NtpSignDsocket = 356,
+ T_Orphan = 357,
+ T_Panic = 358,
+ T_Peer = 359,
+ T_Peerstats = 360,
+ T_Phone = 361,
+ T_Pid = 362,
+ T_Pidfile = 363,
+ T_Pool = 364,
+ T_Port = 365,
+ T_Preempt = 366,
+ T_Prefer = 367,
+ T_Protostats = 368,
+ T_Pw = 369,
+ T_Qos = 370,
+ T_Randfile = 371,
+ T_Rawstats = 372,
+ T_Refid = 373,
+ T_Requestkey = 374,
+ T_Restrict = 375,
+ T_Revoke = 376,
+ T_Saveconfigdir = 377,
+ T_Server = 378,
+ T_Setvar = 379,
+ T_Sign = 380,
+ T_Statistics = 381,
+ T_Stats = 382,
+ T_Statsdir = 383,
+ T_Step = 384,
+ T_Stepout = 385,
+ T_Stratum = 386,
+ T_String = 387,
+ T_Sysstats = 388,
+ T_Tick = 389,
+ T_Time1 = 390,
+ T_Time2 = 391,
+ T_Timingstats = 392,
+ T_Tinker = 393,
+ T_Tos = 394,
+ T_Trap = 395,
+ T_True = 396,
+ T_Trustedkey = 397,
+ T_Ttl = 398,
+ T_Type = 399,
+ T_Unconfig = 400,
+ T_Unpeer = 401,
+ T_Version = 402,
+ T_WanderThreshold = 403,
+ T_Week = 404,
+ T_Wildcard = 405,
+ T_Xleave = 406,
+ T_Year = 407,
+ T_Flag = 408,
+ T_Void = 409,
+ T_EOC = 410,
+ T_Simulate = 411,
+ T_Beep_Delay = 412,
+ T_Sim_Duration = 413,
+ T_Server_Offset = 414,
+ T_Duration = 415,
+ T_Freq_Offset = 416,
+ T_Wander = 417,
+ T_Jitter = 418,
+ T_Prop_Delay = 419,
+ T_Proc_Delay = 420
+ };
+#endif
+/* Tokens. */
+#define T_Age 258
+#define T_All 259
+#define T_Allan 260
+#define T_Auth 261
+#define T_Autokey 262
+#define T_Automax 263
+#define T_Average 264
+#define T_Bclient 265
+#define T_Beacon 266
+#define T_Bias 267
+#define T_Broadcast 268
+#define T_Broadcastclient 269
+#define T_Broadcastdelay 270
+#define T_Burst 271
+#define T_Calibrate 272
+#define T_Calldelay 273
+#define T_Ceiling 274
+#define T_Clockstats 275
+#define T_Cohort 276
+#define T_ControlKey 277
+#define T_Crypto 278
+#define T_Cryptostats 279
+#define T_Day 280
+#define T_Default 281
+#define T_Digest 282
+#define T_Disable 283
+#define T_Discard 284
+#define T_Dispersion 285
+#define T_Double 286
+#define T_Driftfile 287
+#define T_Drop 288
+#define T_Ellipsis 289
+#define T_Enable 290
+#define T_End 291
+#define T_False 292
+#define T_File 293
+#define T_Filegen 294
+#define T_Flag1 295
+#define T_Flag2 296
+#define T_Flag3 297
+#define T_Flag4 298
+#define T_Flake 299
+#define T_Floor 300
+#define T_Freq 301
+#define T_Fudge 302
+#define T_Host 303
+#define T_Huffpuff 304
+#define T_Iburst 305
+#define T_Ident 306
+#define T_Ignore 307
+#define T_Includefile 308
+#define T_Integer 309
+#define T_Interface 310
+#define T_Ipv4 311
+#define T_Ipv4_flag 312
+#define T_Ipv6 313
+#define T_Ipv6_flag 314
+#define T_Kernel 315
+#define T_Key 316
+#define T_Keys 317
+#define T_Keysdir 318
+#define T_Kod 319
+#define T_Mssntp 320
+#define T_Leapfile 321
+#define T_Limited 322
+#define T_Link 323
+#define T_Listen 324
+#define T_Logconfig 325
+#define T_Logfile 326
+#define T_Loopstats 327
+#define T_Lowpriotrap 328
+#define T_Manycastclient 329
+#define T_Manycastserver 330
+#define T_Mask 331
+#define T_Maxclock 332
+#define T_Maxdist 333
+#define T_Maxpoll 334
+#define T_Minclock 335
+#define T_Mindist 336
+#define T_Minimum 337
+#define T_Minpoll 338
+#define T_Minsane 339
+#define T_Mode 340
+#define T_Monitor 341
+#define T_Month 342
+#define T_Multicastclient 343
+#define T_Nic 344
+#define T_Nolink 345
+#define T_Nomodify 346
+#define T_None 347
+#define T_Nopeer 348
+#define T_Noquery 349
+#define T_Noselect 350
+#define T_Noserve 351
+#define T_Notrap 352
+#define T_Notrust 353
+#define T_Ntp 354
+#define T_Ntpport 355
+#define T_NtpSignDsocket 356
+#define T_Orphan 357
+#define T_Panic 358
+#define T_Peer 359
+#define T_Peerstats 360
+#define T_Phone 361
+#define T_Pid 362
+#define T_Pidfile 363
+#define T_Pool 364
+#define T_Port 365
+#define T_Preempt 366
+#define T_Prefer 367
+#define T_Protostats 368
+#define T_Pw 369
+#define T_Qos 370
+#define T_Randfile 371
+#define T_Rawstats 372
+#define T_Refid 373
+#define T_Requestkey 374
+#define T_Restrict 375
+#define T_Revoke 376
+#define T_Saveconfigdir 377
+#define T_Server 378
+#define T_Setvar 379
+#define T_Sign 380
+#define T_Statistics 381
+#define T_Stats 382
+#define T_Statsdir 383
+#define T_Step 384
+#define T_Stepout 385
+#define T_Stratum 386
+#define T_String 387
+#define T_Sysstats 388
+#define T_Tick 389
+#define T_Time1 390
+#define T_Time2 391
+#define T_Timingstats 392
+#define T_Tinker 393
+#define T_Tos 394
+#define T_Trap 395
+#define T_True 396
+#define T_Trustedkey 397
+#define T_Ttl 398
+#define T_Type 399
+#define T_Unconfig 400
+#define T_Unpeer 401
+#define T_Version 402
+#define T_WanderThreshold 403
+#define T_Week 404
+#define T_Wildcard 405
+#define T_Xleave 406
+#define T_Year 407
+#define T_Flag 408
+#define T_Void 409
+#define T_EOC 410
+#define T_Simulate 411
+#define T_Beep_Delay 412
+#define T_Sim_Duration 413
+#define T_Server_Offset 414
+#define T_Duration 415
+#define T_Freq_Offset 416
+#define T_Wander 417
+#define T_Jitter 418
+#define T_Prop_Delay 419
+#define T_Proc_Delay 420
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c */
+#line 50 "ntp_parser.y"
+
+ char *String;
+ double Double;
+ int Integer;
+ void *VoidPtr;
+ queue *Queue;
+ struct attr_val *Attr_val;
+ struct address_node *Address_node;
+ struct setvar_node *Set_var;
+
+ /* Simulation types */
+ server_info *Sim_server;
+ script_info *Sim_script;
+
+
+
+/* Line 214 of yacc.c */
+#line 489 "ntp_parser.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 501 "ntp_parser.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 168
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 630
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 171
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 89
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 267
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 375
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 420
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 167, 168, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 166, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 169, 2, 170, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+ 165
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 5, 9, 12, 15, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
+ 44, 47, 49, 51, 53, 55, 57, 59, 62, 64,
+ 66, 68, 71, 73, 75, 77, 80, 82, 84, 86,
+ 88, 90, 92, 94, 96, 98, 101, 103, 105, 107,
+ 109, 111, 113, 116, 118, 120, 122, 125, 128, 131,
+ 134, 137, 140, 143, 146, 149, 152, 155, 156, 159,
+ 162, 165, 167, 169, 171, 173, 175, 177, 180, 183,
+ 185, 188, 191, 194, 196, 198, 200, 202, 204, 206,
+ 208, 210, 212, 215, 218, 222, 225, 227, 229, 231,
+ 233, 235, 237, 239, 241, 243, 244, 247, 250, 253,
+ 255, 257, 259, 261, 263, 265, 267, 269, 271, 273,
+ 275, 277, 279, 282, 286, 290, 295, 300, 306, 307,
+ 310, 312, 314, 316, 318, 320, 322, 324, 326, 328,
+ 330, 332, 334, 336, 338, 341, 343, 346, 348, 350,
+ 352, 356, 359, 361, 364, 367, 370, 373, 375, 377,
+ 379, 381, 383, 385, 388, 391, 394, 396, 398, 400,
+ 402, 404, 406, 408, 410, 412, 415, 418, 420, 423,
+ 425, 427, 429, 431, 433, 435, 437, 439, 442, 445,
+ 448, 452, 454, 457, 460, 463, 466, 469, 472, 476,
+ 479, 481, 483, 485, 487, 489, 491, 493, 495, 498,
+ 499, 504, 506, 507, 510, 512, 515, 518, 521, 523,
+ 525, 529, 533, 535, 537, 539, 541, 543, 545, 547,
+ 549, 551, 554, 556, 559, 561, 563, 565, 571, 574,
+ 576, 579, 581, 583, 585, 587, 589, 591, 597, 599,
+ 603, 606, 610, 614, 617, 619, 625, 630, 634, 637,
+ 639, 646, 650, 653, 657, 661, 665, 669
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 172, 0, -1, 173, -1, 173, 174, 155, -1, 174,
+ 155, -1, 1, 155, -1, -1, 175, -1, 186, -1,
+ 188, -1, 189, -1, 198, -1, 206, -1, 193, -1,
+ 212, -1, 217, -1, 221, -1, 225, -1, 248, -1,
+ 176, 177, 180, -1, 176, 177, -1, 123, -1, 109,
+ -1, 104, -1, 13, -1, 74, -1, 178, -1, 179,
+ 132, -1, 132, -1, 57, -1, 59, -1, 180, 181,
+ -1, 181, -1, 182, -1, 184, -1, 12, 247, -1,
+ 183, -1, 7, -1, 16, -1, 50, -1, 95, -1,
+ 111, -1, 112, -1, 141, -1, 151, -1, 185, 54,
+ -1, 61, -1, 83, -1, 79, -1, 143, -1, 85,
+ -1, 147, -1, 187, 177, -1, 145, -1, 146, -1,
+ 14, -1, 75, 245, -1, 88, 245, -1, 8, 54,
+ -1, 22, 54, -1, 23, 190, -1, 62, 132, -1,
+ 63, 132, -1, 119, 54, -1, 121, 54, -1, 142,
+ 241, -1, 101, 132, -1, -1, 190, 191, -1, 192,
+ 132, -1, 121, 54, -1, 48, -1, 51, -1, 114,
+ -1, 116, -1, 125, -1, 27, -1, 139, 194, -1,
+ 194, 195, -1, 195, -1, 196, 54, -1, 197, 247,
+ -1, 21, 246, -1, 19, -1, 45, -1, 102, -1,
+ 84, -1, 11, -1, 81, -1, 78, -1, 80, -1,
+ 77, -1, 126, 199, -1, 128, 132, -1, 39, 200,
+ 201, -1, 199, 200, -1, 200, -1, 20, -1, 24,
+ -1, 72, -1, 105, -1, 117, -1, 133, -1, 137,
+ -1, 113, -1, -1, 201, 202, -1, 38, 132, -1,
+ 144, 205, -1, 203, -1, 204, -1, 68, -1, 90,
+ -1, 35, -1, 28, -1, 92, -1, 107, -1, 25,
+ -1, 149, -1, 87, -1, 152, -1, 3, -1, 29,
+ 209, -1, 120, 177, 207, -1, 120, 26, 207, -1,
+ 120, 57, 26, 207, -1, 120, 59, 26, 207, -1,
+ 120, 178, 76, 178, 207, -1, -1, 207, 208, -1,
+ 44, -1, 52, -1, 64, -1, 65, -1, 67, -1,
+ 73, -1, 91, -1, 93, -1, 94, -1, 96, -1,
+ 97, -1, 98, -1, 100, -1, 147, -1, 209, 210,
+ -1, 210, -1, 211, 54, -1, 9, -1, 82, -1,
+ 86, -1, 47, 177, 213, -1, 213, 214, -1, 214,
+ -1, 215, 247, -1, 216, 246, -1, 131, 54, -1,
+ 118, 132, -1, 135, -1, 136, -1, 40, -1, 41,
+ -1, 42, -1, 43, -1, 35, 218, -1, 28, 218,
+ -1, 218, 219, -1, 219, -1, 220, -1, 127, -1,
+ 6, -1, 10, -1, 17, -1, 60, -1, 86, -1,
+ 99, -1, 138, 222, -1, 222, 223, -1, 223, -1,
+ 224, 247, -1, 5, -1, 30, -1, 46, -1, 49,
+ -1, 103, -1, 129, -1, 130, -1, 236, -1, 226,
+ 247, -1, 227, 132, -1, 228, 132, -1, 53, 132,
+ 174, -1, 36, -1, 18, 54, -1, 32, 229, -1,
+ 70, 234, -1, 106, 244, -1, 124, 230, -1, 140,
+ 178, -1, 140, 178, 232, -1, 143, 240, -1, 15,
+ -1, 134, -1, 66, -1, 108, -1, 115, -1, 71,
+ -1, 122, -1, 132, -1, 132, 31, -1, -1, 132,
+ 166, 132, 231, -1, 26, -1, -1, 232, 233, -1,
+ 233, -1, 110, 54, -1, 55, 178, -1, 234, 235,
+ -1, 235, -1, 132, -1, 237, 239, 238, -1, 237,
+ 239, 132, -1, 55, -1, 89, -1, 4, -1, 56,
+ -1, 58, -1, 150, -1, 69, -1, 52, -1, 33,
+ -1, 240, 54, -1, 54, -1, 241, 242, -1, 242,
+ -1, 54, -1, 243, -1, 167, 54, 34, 54, 168,
+ -1, 244, 132, -1, 132, -1, 245, 177, -1, 177,
+ -1, 54, -1, 141, -1, 37, -1, 54, -1, 31,
+ -1, 249, 169, 250, 252, 170, -1, 156, -1, 250,
+ 251, 155, -1, 251, 155, -1, 157, 166, 247, -1,
+ 158, 166, 247, -1, 252, 253, -1, 253, -1, 255,
+ 169, 254, 256, 170, -1, 159, 166, 247, 155, -1,
+ 123, 166, 177, -1, 256, 257, -1, 257, -1, 160,
+ 166, 247, 169, 258, 170, -1, 258, 259, 155, -1,
+ 259, 155, -1, 161, 166, 247, -1, 162, 166, 247,
+ -1, 163, 166, 247, -1, 164, 166, 247, -1, 165,
+ 166, 247, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 318, 318, 322, 323, 324, 338, 339, 340, 341,
+ 342, 343, 344, 345, 346, 347, 348, 349, 350, 358,
+ 364, 373, 374, 375, 376, 377, 381, 382, 387, 392,
+ 394, 399, 400, 404, 405, 406, 411, 416, 417, 418,
+ 419, 420, 421, 422, 423, 427, 432, 433, 434, 435,
+ 436, 437, 447, 455, 456, 466, 468, 470, 481, 483,
+ 485, 490, 492, 494, 496, 498, 500, 506, 507, 517,
+ 519, 531, 532, 533, 534, 535, 536, 545, 550, 551,
+ 555, 557, 559, 564, 565, 566, 567, 568, 572, 573,
+ 574, 575, 584, 586, 595, 603, 604, 608, 609, 610,
+ 611, 612, 613, 614, 615, 620, 621, 631, 641, 650,
+ 665, 670, 671, 675, 676, 680, 681, 682, 683, 684,
+ 685, 686, 695, 699, 704, 709, 722, 735, 744, 745,
+ 750, 751, 752, 753, 754, 755, 756, 757, 758, 759,
+ 760, 761, 762, 763, 767, 769, 774, 779, 780, 781,
+ 790, 795, 797, 802, 804, 806, 808, 813, 814, 818,
+ 819, 820, 821, 830, 832, 837, 844, 854, 856, 868,
+ 869, 870, 871, 872, 873, 882, 886, 887, 891, 896,
+ 897, 898, 899, 900, 901, 902, 911, 912, 919, 926,
+ 942, 961, 966, 968, 970, 972, 974, 976, 978, 980,
+ 985, 986, 990, 991, 992, 996, 997, 1001, 1003, 1007,
+ 1011, 1016, 1018, 1022, 1024, 1028, 1029, 1033, 1034, 1038,
+ 1053, 1058, 1066, 1067, 1071, 1072, 1073, 1074, 1078, 1079,
+ 1080, 1090, 1091, 1095, 1097, 1102, 1104, 1108, 1113, 1114,
+ 1118, 1119, 1123, 1132, 1133, 1137, 1138, 1147, 1162, 1166,
+ 1167, 1171, 1172, 1176, 1177, 1181, 1186, 1190, 1194, 1195,
+ 1199, 1204, 1205, 1209, 1211, 1213, 1215, 1217
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "T_Age", "T_All", "T_Allan", "T_Auth",
+ "T_Autokey", "T_Automax", "T_Average", "T_Bclient", "T_Beacon", "T_Bias",
+ "T_Broadcast", "T_Broadcastclient", "T_Broadcastdelay", "T_Burst",
+ "T_Calibrate", "T_Calldelay", "T_Ceiling", "T_Clockstats", "T_Cohort",
+ "T_ControlKey", "T_Crypto", "T_Cryptostats", "T_Day", "T_Default",
+ "T_Digest", "T_Disable", "T_Discard", "T_Dispersion", "T_Double",
+ "T_Driftfile", "T_Drop", "T_Ellipsis", "T_Enable", "T_End", "T_False",
+ "T_File", "T_Filegen", "T_Flag1", "T_Flag2", "T_Flag3", "T_Flag4",
+ "T_Flake", "T_Floor", "T_Freq", "T_Fudge", "T_Host", "T_Huffpuff",
+ "T_Iburst", "T_Ident", "T_Ignore", "T_Includefile", "T_Integer",
+ "T_Interface", "T_Ipv4", "T_Ipv4_flag", "T_Ipv6", "T_Ipv6_flag",
+ "T_Kernel", "T_Key", "T_Keys", "T_Keysdir", "T_Kod", "T_Mssntp",
+ "T_Leapfile", "T_Limited", "T_Link", "T_Listen", "T_Logconfig",
+ "T_Logfile", "T_Loopstats", "T_Lowpriotrap", "T_Manycastclient",
+ "T_Manycastserver", "T_Mask", "T_Maxclock", "T_Maxdist", "T_Maxpoll",
+ "T_Minclock", "T_Mindist", "T_Minimum", "T_Minpoll", "T_Minsane",
+ "T_Mode", "T_Monitor", "T_Month", "T_Multicastclient", "T_Nic",
+ "T_Nolink", "T_Nomodify", "T_None", "T_Nopeer", "T_Noquery",
+ "T_Noselect", "T_Noserve", "T_Notrap", "T_Notrust", "T_Ntp", "T_Ntpport",
+ "T_NtpSignDsocket", "T_Orphan", "T_Panic", "T_Peer", "T_Peerstats",
+ "T_Phone", "T_Pid", "T_Pidfile", "T_Pool", "T_Port", "T_Preempt",
+ "T_Prefer", "T_Protostats", "T_Pw", "T_Qos", "T_Randfile", "T_Rawstats",
+ "T_Refid", "T_Requestkey", "T_Restrict", "T_Revoke", "T_Saveconfigdir",
+ "T_Server", "T_Setvar", "T_Sign", "T_Statistics", "T_Stats",
+ "T_Statsdir", "T_Step", "T_Stepout", "T_Stratum", "T_String",
+ "T_Sysstats", "T_Tick", "T_Time1", "T_Time2", "T_Timingstats",
+ "T_Tinker", "T_Tos", "T_Trap", "T_True", "T_Trustedkey", "T_Ttl",
+ "T_Type", "T_Unconfig", "T_Unpeer", "T_Version", "T_WanderThreshold",
+ "T_Week", "T_Wildcard", "T_Xleave", "T_Year", "T_Flag", "T_Void",
+ "T_EOC", "T_Simulate", "T_Beep_Delay", "T_Sim_Duration",
+ "T_Server_Offset", "T_Duration", "T_Freq_Offset", "T_Wander", "T_Jitter",
+ "T_Prop_Delay", "T_Proc_Delay", "'='", "'('", "')'", "'{'", "'}'",
+ "$accept", "configuration", "command_list", "command", "server_command",
+ "client_type", "address", "ip_address", "address_fam", "option_list",
+ "option", "option_flag", "option_flag_keyword", "option_int",
+ "option_int_keyword", "unpeer_command", "unpeer_keyword",
+ "other_mode_command", "authentication_command", "crypto_command_list",
+ "crypto_command", "crypto_str_keyword", "orphan_mode_command",
+ "tos_option_list", "tos_option", "tos_option_int_keyword",
+ "tos_option_dbl_keyword", "monitoring_command", "stats_list", "stat",
+ "filegen_option_list", "filegen_option", "link_nolink", "enable_disable",
+ "filegen_type", "access_control_command", "ac_flag_list",
+ "access_control_flag", "discard_option_list", "discard_option",
+ "discard_option_keyword", "fudge_command", "fudge_factor_list",
+ "fudge_factor", "fudge_factor_dbl_keyword", "fudge_factor_bool_keyword",
+ "system_option_command", "system_option_list", "system_option",
+ "system_option_flag_keyword", "tinker_command", "tinker_option_list",
+ "tinker_option", "tinker_option_keyword", "miscellaneous_command",
+ "misc_cmd_dbl_keyword", "misc_cmd_str_keyword",
+ "misc_cmd_str_lcl_keyword", "drift_parm", "variable_assign",
+ "t_default_or_zero", "trap_option_list", "trap_option",
+ "log_config_list", "log_config_command", "interface_command",
+ "interface_nic", "nic_rule_class", "nic_rule_action", "integer_list",
+ "integer_list_range", "integer_list_range_elt", "integer_range",
+ "string_list", "address_list", "boolean", "number", "simulate_command",
+ "sim_conf_start", "sim_init_statement_list", "sim_init_statement",
+ "sim_server_list", "sim_server", "sim_server_offset", "sim_server_name",
+ "sim_act_list", "sim_act", "sim_act_stmt_list", "sim_act_stmt", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
+ 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 388, 389, 390, 391, 392, 393, 394,
+ 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
+ 415, 416, 417, 418, 419, 420, 61, 40, 41, 123,
+ 125
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint16 yyr1[] =
+{
+ 0, 171, 172, 173, 173, 173, 174, 174, 174, 174,
+ 174, 174, 174, 174, 174, 174, 174, 174, 174, 175,
+ 175, 176, 176, 176, 176, 176, 177, 177, 178, 179,
+ 179, 180, 180, 181, 181, 181, 182, 183, 183, 183,
+ 183, 183, 183, 183, 183, 184, 185, 185, 185, 185,
+ 185, 185, 186, 187, 187, 188, 188, 188, 189, 189,
+ 189, 189, 189, 189, 189, 189, 189, 190, 190, 191,
+ 191, 192, 192, 192, 192, 192, 192, 193, 194, 194,
+ 195, 195, 195, 196, 196, 196, 196, 196, 197, 197,
+ 197, 197, 198, 198, 198, 199, 199, 200, 200, 200,
+ 200, 200, 200, 200, 200, 201, 201, 202, 202, 202,
+ 202, 203, 203, 204, 204, 205, 205, 205, 205, 205,
+ 205, 205, 206, 206, 206, 206, 206, 206, 207, 207,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 209, 209, 210, 211, 211, 211,
+ 212, 213, 213, 214, 214, 214, 214, 215, 215, 216,
+ 216, 216, 216, 217, 217, 218, 218, 219, 219, 220,
+ 220, 220, 220, 220, 220, 221, 222, 222, 223, 224,
+ 224, 224, 224, 224, 224, 224, 225, 225, 225, 225,
+ 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
+ 226, 226, 227, 227, 227, 228, 228, 229, 229, 229,
+ 230, 231, 231, 232, 232, 233, 233, 234, 234, 235,
+ 236, 236, 237, 237, 238, 238, 238, 238, 239, 239,
+ 239, 240, 240, 241, 241, 242, 242, 243, 244, 244,
+ 245, 245, 246, 246, 246, 247, 247, 248, 249, 250,
+ 250, 251, 251, 252, 252, 253, 254, 255, 256, 256,
+ 257, 258, 258, 259, 259, 259, 259, 259
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 3, 2, 2, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 2, 1, 1, 1, 1, 1, 1, 2, 1, 1,
+ 1, 2, 1, 1, 1, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
+ 1, 1, 2, 1, 1, 1, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 2, 2, 1,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 3, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 3, 3, 4, 4, 5, 0, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 1, 1, 1,
+ 3, 2, 1, 2, 2, 2, 2, 1, 1, 1,
+ 1, 1, 1, 2, 2, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 3, 1, 2, 2, 2, 2, 2, 2, 3, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 0,
+ 4, 1, 0, 2, 1, 2, 2, 2, 1, 1,
+ 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 2, 1, 1, 1, 5, 2, 1,
+ 2, 1, 1, 1, 1, 1, 1, 5, 1, 3,
+ 2, 3, 3, 2, 1, 5, 4, 3, 2, 1,
+ 6, 3, 2, 3, 3, 3, 3, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 0, 0, 0, 24, 55, 200, 0, 0, 67, 0,
+ 0, 209, 0, 191, 0, 0, 0, 222, 0, 0,
+ 202, 0, 205, 25, 0, 0, 223, 0, 23, 0,
+ 203, 22, 204, 0, 0, 0, 206, 21, 0, 0,
+ 0, 201, 0, 0, 0, 0, 0, 53, 54, 248,
+ 0, 2, 0, 7, 0, 8, 0, 9, 10, 13,
+ 11, 12, 14, 15, 16, 17, 0, 0, 0, 186,
+ 0, 18, 0, 5, 58, 192, 59, 60, 169, 170,
+ 171, 172, 173, 174, 168, 164, 166, 167, 147, 148,
+ 149, 122, 145, 0, 207, 193, 163, 97, 98, 99,
+ 100, 104, 101, 102, 103, 105, 29, 30, 28, 0,
+ 26, 0, 6, 61, 62, 219, 194, 218, 241, 56,
+ 57, 66, 239, 195, 63, 128, 29, 30, 128, 26,
+ 64, 0, 196, 92, 96, 93, 179, 180, 181, 182,
+ 183, 184, 185, 175, 177, 0, 87, 83, 0, 84,
+ 91, 89, 90, 88, 86, 85, 77, 79, 0, 0,
+ 197, 235, 0, 65, 234, 236, 232, 199, 1, 0,
+ 4, 20, 52, 246, 245, 187, 188, 189, 230, 229,
+ 228, 0, 0, 76, 71, 72, 73, 74, 0, 75,
+ 68, 0, 165, 144, 146, 208, 94, 159, 160, 161,
+ 162, 0, 0, 157, 158, 150, 152, 0, 0, 27,
+ 190, 217, 240, 238, 124, 128, 128, 123, 0, 0,
+ 95, 176, 178, 244, 242, 243, 82, 78, 80, 81,
+ 0, 0, 198, 214, 0, 233, 231, 3, 37, 0,
+ 38, 39, 46, 48, 47, 50, 40, 41, 42, 43,
+ 49, 51, 44, 19, 32, 33, 36, 34, 0, 224,
+ 225, 226, 221, 227, 220, 0, 0, 0, 0, 70,
+ 69, 114, 113, 0, 111, 112, 0, 106, 109, 110,
+ 156, 155, 151, 153, 154, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 129,
+ 125, 126, 128, 212, 216, 215, 213, 0, 35, 31,
+ 45, 0, 0, 0, 0, 0, 254, 0, 250, 107,
+ 121, 117, 119, 115, 116, 118, 120, 108, 127, 211,
+ 210, 0, 251, 252, 0, 249, 247, 253, 0, 237,
+ 257, 0, 0, 0, 0, 0, 259, 0, 0, 255,
+ 258, 256, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 260, 0, 262, 263,
+ 264, 265, 266, 267, 261
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 50, 51, 52, 53, 54, 118, 110, 111, 253,
+ 254, 255, 256, 257, 258, 55, 56, 57, 58, 77,
+ 190, 191, 59, 156, 157, 158, 159, 60, 133, 105,
+ 196, 277, 278, 279, 327, 61, 214, 299, 91, 92,
+ 93, 62, 205, 206, 207, 208, 63, 85, 86, 87,
+ 64, 143, 144, 145, 65, 66, 67, 68, 95, 132,
+ 330, 232, 233, 116, 117, 69, 70, 264, 181, 167,
+ 163, 164, 165, 123, 119, 226, 175, 71, 72, 267,
+ 268, 315, 316, 342, 317, 345, 346, 359, 360
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -145
+static const yytype_int16 yypact[] =
+{
+ 126, -121, -19, -145, -145, -145, -2, -1, -145, 8,
+ 20, -95, 8, -145, 47, -46, -78, -145, -76, -73,
+ -145, -72, -145, -145, -46, -46, -145, -71, -145, -67,
+ -145, -145, -145, 12, -17, 19, -145, -145, -58, 47,
+ -56, -145, 0, 295, -55, -47, 24, -145, -145, -145,
+ 80, 262, -70, -145, -46, -145, -46, -145, -145, -145,
+ -145, -145, -145, -145, -145, -145, -10, -50, -49, -145,
+ 3, -145, -85, -145, -145, -145, -145, 142, -145, -145,
+ -145, -145, -145, -145, -145, 8, -145, -145, -145, -145,
+ -145, 20, -145, 33, 58, -145, 8, -145, -145, -145,
+ -145, -145, -145, -145, -145, -145, -145, -145, -145, 168,
+ -145, -36, 398, -145, -145, -145, -72, -145, -145, -46,
+ -46, -145, -145, -34, -145, -145, 71, 73, -145, 25,
+ -145, -57, -145, 47, -145, -145, -145, -145, -145, -145,
+ -145, -145, -145, 0, -145, -10, -145, -145, -9, -145,
+ -145, -145, -145, -145, -145, -145, 295, -145, 57, -10,
+ -35, -145, 59, -47, -145, -145, -145, 63, -145, -37,
+ -145, 31, -145, -145, -145, -145, -145, -145, -145, -145,
+ -145, 6, -126, -145, -145, -145, -145, -145, 74, -145,
+ -145, -20, -145, -145, -145, -145, -11, -145, -145, -145,
+ -145, 4, 77, -145, -145, 168, -145, -10, -9, -145,
+ -145, -145, -145, -145, 483, -145, -145, 483, -55, 5,
+ -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+ -55, 91, -35, -145, 112, -145, -145, -145, -145, -10,
+ -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+ -145, -145, -145, 31, -145, -145, -145, -145, 93, -145,
+ -145, -145, -145, -145, -145, -7, -3, -107, -4, -145,
+ -145, -145, -145, 34, -145, -145, 1, -145, -145, -145,
+ -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+ -145, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+ 483, 483, -145, 131, -145, -145, -145, 116, -145, -145,
+ -145, -10, -10, 9, 16, -100, -145, 7, -145, -145,
+ -145, -145, -145, -145, -145, -145, -145, -145, 483, -145,
+ -145, 15, -145, -145, -46, -145, -145, -145, 26, -145,
+ -145, 21, 35, -10, 28, -112, -145, 36, -10, -145,
+ -145, -145, 37, -40, 39, 41, 46, 50, 62, 61,
+ 48, -10, -10, -10, -10, -10, -145, 78, -145, -145,
+ -145, -145, -145, -145, -145
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -145, -145, -145, -43, -145, -145, -15, -32, -145, -145,
+ -51, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+ -145, -145, -145, -145, 81, -145, -145, -145, -145, -33,
+ -145, -145, -145, -145, -145, -145, -125, -145, -145, 122,
+ -145, -145, -145, 38, -145, -145, -145, 217, -63, -145,
+ -145, -145, 95, -145, -145, -145, -145, -145, -145, -145,
+ -145, -145, 10, -145, 120, -145, -145, -145, -145, -145,
+ -145, 76, -145, -145, 215, 43, -144, -145, -145, -145,
+ -23, -145, -62, -145, -145, -145, -90, -145, -102
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -7
+static const yytype_int16 yytable[] =
+{
+ 109, 222, 129, 217, 320, 136, 134, 161, 169, 125,
+ 259, 106, 160, 107, 78, 229, 313, 271, 79, 128,
+ 230, 173, 192, 313, 272, 80, 321, 273, 223, 88,
+ 137, 265, 266, 192, 73, 74, 178, 94, 238, 171,
+ 126, 172, 127, 239, 174, 224, 138, 240, 344, 139,
+ 265, 266, 75, 76, 112, 179, 113, 274, 349, 114,
+ 115, 121, 260, 283, 261, 122, 124, 97, 81, 210,
+ 336, 98, 180, 130, 131, 231, 135, 108, 166, 275,
+ 168, 241, 176, 177, 182, 170, 108, 194, 322, 195,
+ 300, 301, 242, 323, 82, 308, 209, 215, 213, 216,
+ 220, 218, 89, 140, 212, 212, 90, 83, 324, 219,
+ 243, 228, 270, 234, 244, 108, 245, 236, 237, 99,
+ 162, 354, 355, 356, 357, 358, 246, 1, 269, 141,
+ 142, 281, 225, 276, 2, 84, 280, 303, 262, 3,
+ 4, 5, 247, 248, 6, 305, 307, 310, 7, 8,
+ 325, 318, 100, 326, 9, 10, 263, 329, 11, 311,
+ 101, 12, 13, 312, 102, 14, 319, 332, 333, 183,
+ 331, 335, 249, 15, 250, 334, 338, 328, 251, 16,
+ 103, 17, 252, 339, 104, 341, 302, 343, 18, 19,
+ 184, 351, 20, 185, 348, 344, 21, 22, 304, 347,
+ 23, 24, 309, 368, 352, 361, 353, 362, 197, 198,
+ 199, 200, 363, 193, 25, 26, 364, 369, 370, 371,
+ 372, 373, 354, 355, 356, 357, 358, 27, 365, 96,
+ 28, 366, 29, 374, 30, 31, 211, 227, 221, 235,
+ 120, 32, 306, 282, 314, 33, 34, 35, 36, 37,
+ 38, 284, 39, 337, 40, 350, 186, 367, 187, 0,
+ 41, 0, 0, 188, 42, 43, 44, 189, 45, 46,
+ 2, 47, 48, 0, 0, 3, 4, 5, 0, 0,
+ 6, -6, 49, 0, 7, 8, 201, 0, 0, 0,
+ 9, 10, 0, 0, 11, 0, 0, 12, 13, 202,
+ 0, 14, 0, 203, 204, 0, 146, 0, 0, 15,
+ 0, 0, 0, 0, 147, 16, 148, 17, 0, 340,
+ 0, 0, 0, 0, 18, 19, 0, 0, 20, 0,
+ 0, 0, 21, 22, 0, 0, 23, 24, 0, 0,
+ 149, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 25, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 27, 0, 0, 28, 0, 29, 0,
+ 30, 31, 150, 151, 0, 152, 153, 32, 0, 154,
+ 0, 33, 34, 35, 36, 37, 38, 0, 39, 0,
+ 40, 0, 0, 0, 0, 0, 41, 155, 0, 0,
+ 42, 43, 44, 0, 45, 46, 2, 47, 48, 0,
+ 0, 3, 4, 5, 0, 0, 6, -6, 49, 0,
+ 7, 8, 0, 0, 0, 0, 9, 10, 0, 0,
+ 11, 0, 0, 12, 13, 0, 0, 14, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
+ 0, 16, 0, 17, 0, 0, 0, 0, 0, 0,
+ 18, 19, 0, 0, 20, 0, 0, 0, 21, 22,
+ 0, 0, 23, 24, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 25, 26, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 27,
+ 0, 0, 28, 0, 29, 0, 30, 31, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 33, 34, 35,
+ 36, 37, 38, 0, 39, 0, 40, 285, 0, 0,
+ 0, 0, 41, 0, 0, 286, 42, 43, 44, 0,
+ 45, 46, 0, 47, 48, 0, 0, 287, 288, 0,
+ 289, 0, 0, 0, 49, 0, 290, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 291, 0, 292, 293, 0, 294,
+ 295, 296, 0, 297, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 298
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 15, 145, 34, 128, 3, 5, 39, 54, 51, 26,
+ 4, 57, 44, 59, 6, 159, 123, 28, 10, 34,
+ 55, 31, 85, 123, 35, 17, 25, 38, 37, 9,
+ 30, 157, 158, 96, 155, 54, 33, 132, 7, 54,
+ 57, 56, 59, 12, 54, 54, 46, 16, 160, 49,
+ 157, 158, 54, 54, 132, 52, 132, 68, 170, 132,
+ 132, 132, 56, 207, 58, 132, 54, 20, 60, 112,
+ 170, 24, 69, 54, 132, 110, 132, 132, 54, 90,
+ 0, 50, 132, 132, 169, 155, 132, 54, 87, 31,
+ 215, 216, 61, 92, 86, 239, 132, 26, 132, 26,
+ 133, 76, 82, 103, 119, 120, 86, 99, 107, 166,
+ 79, 54, 132, 54, 83, 132, 85, 54, 155, 72,
+ 167, 161, 162, 163, 164, 165, 95, 1, 54, 129,
+ 130, 54, 141, 144, 8, 127, 132, 132, 132, 13,
+ 14, 15, 111, 112, 18, 54, 34, 54, 22, 23,
+ 149, 155, 105, 152, 28, 29, 150, 26, 32, 166,
+ 113, 35, 36, 166, 117, 39, 132, 311, 312, 27,
+ 54, 155, 141, 47, 143, 166, 169, 302, 147, 53,
+ 133, 55, 151, 168, 137, 159, 218, 166, 62, 63,
+ 48, 155, 66, 51, 166, 160, 70, 71, 230, 343,
+ 74, 75, 253, 155, 348, 166, 169, 166, 40, 41,
+ 42, 43, 166, 91, 88, 89, 166, 361, 362, 363,
+ 364, 365, 161, 162, 163, 164, 165, 101, 166, 12,
+ 104, 170, 106, 155, 108, 109, 116, 156, 143, 163,
+ 25, 115, 232, 205, 267, 119, 120, 121, 122, 123,
+ 124, 208, 126, 315, 128, 345, 114, 359, 116, -1,
+ 134, -1, -1, 121, 138, 139, 140, 125, 142, 143,
+ 8, 145, 146, -1, -1, 13, 14, 15, -1, -1,
+ 18, 155, 156, -1, 22, 23, 118, -1, -1, -1,
+ 28, 29, -1, -1, 32, -1, -1, 35, 36, 131,
+ -1, 39, -1, 135, 136, -1, 11, -1, -1, 47,
+ -1, -1, -1, -1, 19, 53, 21, 55, -1, 334,
+ -1, -1, -1, -1, 62, 63, -1, -1, 66, -1,
+ -1, -1, 70, 71, -1, -1, 74, 75, -1, -1,
+ 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 88, 89, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 101, -1, -1, 104, -1, 106, -1,
+ 108, 109, 77, 78, -1, 80, 81, 115, -1, 84,
+ -1, 119, 120, 121, 122, 123, 124, -1, 126, -1,
+ 128, -1, -1, -1, -1, -1, 134, 102, -1, -1,
+ 138, 139, 140, -1, 142, 143, 8, 145, 146, -1,
+ -1, 13, 14, 15, -1, -1, 18, 155, 156, -1,
+ 22, 23, -1, -1, -1, -1, 28, 29, -1, -1,
+ 32, -1, -1, 35, 36, -1, -1, 39, -1, -1,
+ -1, -1, -1, -1, -1, 47, -1, -1, -1, -1,
+ -1, 53, -1, 55, -1, -1, -1, -1, -1, -1,
+ 62, 63, -1, -1, 66, -1, -1, -1, 70, 71,
+ -1, -1, 74, 75, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 88, 89, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 101,
+ -1, -1, 104, -1, 106, -1, 108, 109, -1, -1,
+ -1, -1, -1, 115, -1, -1, -1, 119, 120, 121,
+ 122, 123, 124, -1, 126, -1, 128, 44, -1, -1,
+ -1, -1, 134, -1, -1, 52, 138, 139, 140, -1,
+ 142, 143, -1, 145, 146, -1, -1, 64, 65, -1,
+ 67, -1, -1, -1, 156, -1, 73, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 91, -1, 93, 94, -1, 96,
+ 97, 98, -1, 100, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 147
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint16 yystos[] =
+{
+ 0, 1, 8, 13, 14, 15, 18, 22, 23, 28,
+ 29, 32, 35, 36, 39, 47, 53, 55, 62, 63,
+ 66, 70, 71, 74, 75, 88, 89, 101, 104, 106,
+ 108, 109, 115, 119, 120, 121, 122, 123, 124, 126,
+ 128, 134, 138, 139, 140, 142, 143, 145, 146, 156,
+ 172, 173, 174, 175, 176, 186, 187, 188, 189, 193,
+ 198, 206, 212, 217, 221, 225, 226, 227, 228, 236,
+ 237, 248, 249, 155, 54, 54, 54, 190, 6, 10,
+ 17, 60, 86, 99, 127, 218, 219, 220, 9, 82,
+ 86, 209, 210, 211, 132, 229, 218, 20, 24, 72,
+ 105, 113, 117, 133, 137, 200, 57, 59, 132, 177,
+ 178, 179, 132, 132, 132, 132, 234, 235, 177, 245,
+ 245, 132, 132, 244, 54, 26, 57, 59, 177, 178,
+ 54, 132, 230, 199, 200, 132, 5, 30, 46, 49,
+ 103, 129, 130, 222, 223, 224, 11, 19, 21, 45,
+ 77, 78, 80, 81, 84, 102, 194, 195, 196, 197,
+ 178, 54, 167, 241, 242, 243, 54, 240, 0, 174,
+ 155, 177, 177, 31, 54, 247, 132, 132, 33, 52,
+ 69, 239, 169, 27, 48, 51, 114, 116, 121, 125,
+ 191, 192, 219, 210, 54, 31, 201, 40, 41, 42,
+ 43, 118, 131, 135, 136, 213, 214, 215, 216, 132,
+ 174, 235, 177, 132, 207, 26, 26, 207, 76, 166,
+ 200, 223, 247, 37, 54, 141, 246, 195, 54, 247,
+ 55, 110, 232, 233, 54, 242, 54, 155, 7, 12,
+ 16, 50, 61, 79, 83, 85, 95, 111, 112, 141,
+ 143, 147, 151, 180, 181, 182, 183, 184, 185, 4,
+ 56, 58, 132, 150, 238, 157, 158, 250, 251, 54,
+ 132, 28, 35, 38, 68, 90, 144, 202, 203, 204,
+ 132, 54, 214, 247, 246, 44, 52, 64, 65, 67,
+ 73, 91, 93, 94, 96, 97, 98, 100, 147, 208,
+ 207, 207, 178, 132, 178, 54, 233, 34, 247, 181,
+ 54, 166, 166, 123, 251, 252, 253, 255, 155, 132,
+ 3, 25, 87, 92, 107, 149, 152, 205, 207, 26,
+ 231, 54, 247, 247, 166, 155, 170, 253, 169, 168,
+ 177, 159, 254, 166, 160, 256, 257, 247, 166, 170,
+ 257, 155, 247, 169, 161, 162, 163, 164, 165, 258,
+ 259, 166, 166, 166, 166, 166, 170, 259, 155, 247,
+ 247, 247, 247, 247, 155
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 5:
+
+/* Line 1464 of yacc.c */
+#line 325 "ntp_parser.y"
+ {
+ /* I will need to incorporate much more fine grained
+ * error messages. The following should suffice for
+ * the time being.
+ */
+ msyslog(LOG_ERR,
+ "syntax error in %s line %d, column %d",
+ ip_file->fname,
+ ip_file->err_line_no,
+ ip_file->err_col_no);
+ }
+ break;
+
+ case 19:
+
+/* Line 1464 of yacc.c */
+#line 359 "ntp_parser.y"
+ {
+ struct peer_node *my_node = create_peer_node((yyvsp[(1) - (3)].Integer), (yyvsp[(2) - (3)].Address_node), (yyvsp[(3) - (3)].Queue));
+ if (my_node)
+ enqueue(cfgt.peers, my_node);
+ }
+ break;
+
+ case 20:
+
+/* Line 1464 of yacc.c */
+#line 365 "ntp_parser.y"
+ {
+ struct peer_node *my_node = create_peer_node((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Address_node), NULL);
+ if (my_node)
+ enqueue(cfgt.peers, my_node);
+ }
+ break;
+
+ case 27:
+
+/* Line 1464 of yacc.c */
+#line 383 "ntp_parser.y"
+ { (yyval.Address_node) = create_address_node((yyvsp[(2) - (2)].String), (yyvsp[(1) - (2)].Integer)); }
+ break;
+
+ case 28:
+
+/* Line 1464 of yacc.c */
+#line 388 "ntp_parser.y"
+ { (yyval.Address_node) = create_address_node((yyvsp[(1) - (1)].String), 0); }
+ break;
+
+ case 29:
+
+/* Line 1464 of yacc.c */
+#line 393 "ntp_parser.y"
+ { (yyval.Integer) = AF_INET; }
+ break;
+
+ case 30:
+
+/* Line 1464 of yacc.c */
+#line 395 "ntp_parser.y"
+ { (yyval.Integer) = AF_INET6; }
+ break;
+
+ case 31:
+
+/* Line 1464 of yacc.c */
+#line 399 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 32:
+
+/* Line 1464 of yacc.c */
+#line 400 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 35:
+
+/* Line 1464 of yacc.c */
+#line 407 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Double)); }
+ break;
+
+ case 36:
+
+/* Line 1464 of yacc.c */
+#line 412 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival(T_Flag, (yyvsp[(1) - (1)].Integer)); }
+ break;
+
+ case 45:
+
+/* Line 1464 of yacc.c */
+#line 428 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 52:
+
+/* Line 1464 of yacc.c */
+#line 448 "ntp_parser.y"
+ {
+ struct unpeer_node *my_node = create_unpeer_node((yyvsp[(2) - (2)].Address_node));
+ if (my_node)
+ enqueue(cfgt.unpeers, my_node);
+ }
+ break;
+
+ case 55:
+
+/* Line 1464 of yacc.c */
+#line 467 "ntp_parser.y"
+ { cfgt.broadcastclient = 1; }
+ break;
+
+ case 56:
+
+/* Line 1464 of yacc.c */
+#line 469 "ntp_parser.y"
+ { append_queue(cfgt.manycastserver, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 57:
+
+/* Line 1464 of yacc.c */
+#line 471 "ntp_parser.y"
+ { append_queue(cfgt.multicastclient, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 58:
+
+/* Line 1464 of yacc.c */
+#line 482 "ntp_parser.y"
+ { enqueue(cfgt.vars, create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer))); }
+ break;
+
+ case 59:
+
+/* Line 1464 of yacc.c */
+#line 484 "ntp_parser.y"
+ { cfgt.auth.control_key = (yyvsp[(2) - (2)].Integer); }
+ break;
+
+ case 60:
+
+/* Line 1464 of yacc.c */
+#line 486 "ntp_parser.y"
+ {
+ cfgt.auth.cryptosw++;
+ append_queue(cfgt.auth.crypto_cmd_list, (yyvsp[(2) - (2)].Queue));
+ }
+ break;
+
+ case 61:
+
+/* Line 1464 of yacc.c */
+#line 491 "ntp_parser.y"
+ { cfgt.auth.keys = (yyvsp[(2) - (2)].String); }
+ break;
+
+ case 62:
+
+/* Line 1464 of yacc.c */
+#line 493 "ntp_parser.y"
+ { cfgt.auth.keysdir = (yyvsp[(2) - (2)].String); }
+ break;
+
+ case 63:
+
+/* Line 1464 of yacc.c */
+#line 495 "ntp_parser.y"
+ { cfgt.auth.request_key = (yyvsp[(2) - (2)].Integer); }
+ break;
+
+ case 64:
+
+/* Line 1464 of yacc.c */
+#line 497 "ntp_parser.y"
+ { cfgt.auth.revoke = (yyvsp[(2) - (2)].Integer); }
+ break;
+
+ case 65:
+
+/* Line 1464 of yacc.c */
+#line 499 "ntp_parser.y"
+ { cfgt.auth.trusted_key_list = (yyvsp[(2) - (2)].Queue); }
+ break;
+
+ case 66:
+
+/* Line 1464 of yacc.c */
+#line 501 "ntp_parser.y"
+ { cfgt.auth.ntp_signd_socket = (yyvsp[(2) - (2)].String); }
+ break;
+
+ case 67:
+
+/* Line 1464 of yacc.c */
+#line 506 "ntp_parser.y"
+ { (yyval.Queue) = create_queue(); }
+ break;
+
+ case 68:
+
+/* Line 1464 of yacc.c */
+#line 508 "ntp_parser.y"
+ {
+ if ((yyvsp[(2) - (2)].Attr_val) != NULL)
+ (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val));
+ else
+ (yyval.Queue) = (yyvsp[(1) - (2)].Queue);
+ }
+ break;
+
+ case 69:
+
+/* Line 1464 of yacc.c */
+#line 518 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_sval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].String)); }
+ break;
+
+ case 70:
+
+/* Line 1464 of yacc.c */
+#line 520 "ntp_parser.y"
+ {
+ (yyval.Attr_val) = NULL;
+ cfgt.auth.revoke = (yyvsp[(2) - (2)].Integer);
+ msyslog(LOG_WARNING,
+ "'crypto revoke %d' is deprecated, "
+ "please use 'revoke %d' instead.",
+ cfgt.auth.revoke, cfgt.auth.revoke);
+ }
+ break;
+
+ case 77:
+
+/* Line 1464 of yacc.c */
+#line 546 "ntp_parser.y"
+ { append_queue(cfgt.orphan_cmds,(yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 78:
+
+/* Line 1464 of yacc.c */
+#line 550 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 79:
+
+/* Line 1464 of yacc.c */
+#line 551 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 80:
+
+/* Line 1464 of yacc.c */
+#line 556 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (2)].Integer), (double)(yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 81:
+
+/* Line 1464 of yacc.c */
+#line 558 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Double)); }
+ break;
+
+ case 82:
+
+/* Line 1464 of yacc.c */
+#line 560 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (2)].Integer), (double)(yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 92:
+
+/* Line 1464 of yacc.c */
+#line 585 "ntp_parser.y"
+ { append_queue(cfgt.stats_list, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 93:
+
+/* Line 1464 of yacc.c */
+#line 587 "ntp_parser.y"
+ {
+ if (input_from_file) {
+ cfgt.stats_dir = (yyvsp[(2) - (2)].String);
+ } else {
+ YYFREE((yyvsp[(2) - (2)].String));
+ yyerror("statsdir remote configuration ignored");
+ }
+ }
+ break;
+
+ case 94:
+
+/* Line 1464 of yacc.c */
+#line 596 "ntp_parser.y"
+ {
+ enqueue(cfgt.filegen_opts,
+ create_filegen_node((yyvsp[(2) - (3)].Integer), (yyvsp[(3) - (3)].Queue)));
+ }
+ break;
+
+ case 95:
+
+/* Line 1464 of yacc.c */
+#line 603 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), create_ival((yyvsp[(2) - (2)].Integer))); }
+ break;
+
+ case 96:
+
+/* Line 1464 of yacc.c */
+#line 604 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue(create_ival((yyvsp[(1) - (1)].Integer))); }
+ break;
+
+ case 105:
+
+/* Line 1464 of yacc.c */
+#line 620 "ntp_parser.y"
+ { (yyval.Queue) = create_queue(); }
+ break;
+
+ case 106:
+
+/* Line 1464 of yacc.c */
+#line 622 "ntp_parser.y"
+ {
+ if ((yyvsp[(2) - (2)].Attr_val) != NULL)
+ (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val));
+ else
+ (yyval.Queue) = (yyvsp[(1) - (2)].Queue);
+ }
+ break;
+
+ case 107:
+
+/* Line 1464 of yacc.c */
+#line 632 "ntp_parser.y"
+ {
+ if (input_from_file) {
+ (yyval.Attr_val) = create_attr_sval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].String));
+ } else {
+ (yyval.Attr_val) = NULL;
+ YYFREE((yyvsp[(2) - (2)].String));
+ yyerror("filegen file remote config ignored");
+ }
+ }
+ break;
+
+ case 108:
+
+/* Line 1464 of yacc.c */
+#line 642 "ntp_parser.y"
+ {
+ if (input_from_file) {
+ (yyval.Attr_val) = create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer));
+ } else {
+ (yyval.Attr_val) = NULL;
+ yyerror("filegen type remote config ignored");
+ }
+ }
+ break;
+
+ case 109:
+
+/* Line 1464 of yacc.c */
+#line 651 "ntp_parser.y"
+ {
+ const char *err;
+
+ if (input_from_file) {
+ (yyval.Attr_val) = create_attr_ival(T_Flag, (yyvsp[(1) - (1)].Integer));
+ } else {
+ (yyval.Attr_val) = NULL;
+ if (T_Link == (yyvsp[(1) - (1)].Integer))
+ err = "filegen link remote config ignored";
+ else
+ err = "filegen nolink remote config ignored";
+ yyerror(err);
+ }
+ }
+ break;
+
+ case 110:
+
+/* Line 1464 of yacc.c */
+#line 666 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival(T_Flag, (yyvsp[(1) - (1)].Integer)); }
+ break;
+
+ case 122:
+
+/* Line 1464 of yacc.c */
+#line 696 "ntp_parser.y"
+ {
+ append_queue(cfgt.discard_opts, (yyvsp[(2) - (2)].Queue));
+ }
+ break;
+
+ case 123:
+
+/* Line 1464 of yacc.c */
+#line 700 "ntp_parser.y"
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node((yyvsp[(2) - (3)].Address_node), NULL, (yyvsp[(3) - (3)].Queue), ip_file->line_no));
+ }
+ break;
+
+ case 124:
+
+/* Line 1464 of yacc.c */
+#line 705 "ntp_parser.y"
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node(NULL, NULL, (yyvsp[(3) - (3)].Queue), ip_file->line_no));
+ }
+ break;
+
+ case 125:
+
+/* Line 1464 of yacc.c */
+#line 710 "ntp_parser.y"
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node(
+ create_address_node(
+ estrdup("0.0.0.0"),
+ AF_INET),
+ create_address_node(
+ estrdup("0.0.0.0"),
+ AF_INET),
+ (yyvsp[(4) - (4)].Queue),
+ ip_file->line_no));
+ }
+ break;
+
+ case 126:
+
+/* Line 1464 of yacc.c */
+#line 723 "ntp_parser.y"
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node(
+ create_address_node(
+ estrdup("::"),
+ AF_INET6),
+ create_address_node(
+ estrdup("::"),
+ AF_INET6),
+ (yyvsp[(4) - (4)].Queue),
+ ip_file->line_no));
+ }
+ break;
+
+ case 127:
+
+/* Line 1464 of yacc.c */
+#line 736 "ntp_parser.y"
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node((yyvsp[(2) - (5)].Address_node), (yyvsp[(4) - (5)].Address_node), (yyvsp[(5) - (5)].Queue), ip_file->line_no));
+ }
+ break;
+
+ case 128:
+
+/* Line 1464 of yacc.c */
+#line 744 "ntp_parser.y"
+ { (yyval.Queue) = create_queue(); }
+ break;
+
+ case 129:
+
+/* Line 1464 of yacc.c */
+#line 746 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), create_ival((yyvsp[(2) - (2)].Integer))); }
+ break;
+
+ case 144:
+
+/* Line 1464 of yacc.c */
+#line 768 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 145:
+
+/* Line 1464 of yacc.c */
+#line 770 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 146:
+
+/* Line 1464 of yacc.c */
+#line 775 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 150:
+
+/* Line 1464 of yacc.c */
+#line 791 "ntp_parser.y"
+ { enqueue(cfgt.fudge, create_addr_opts_node((yyvsp[(2) - (3)].Address_node), (yyvsp[(3) - (3)].Queue))); }
+ break;
+
+ case 151:
+
+/* Line 1464 of yacc.c */
+#line 796 "ntp_parser.y"
+ { enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 152:
+
+/* Line 1464 of yacc.c */
+#line 798 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 153:
+
+/* Line 1464 of yacc.c */
+#line 803 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Double)); }
+ break;
+
+ case 154:
+
+/* Line 1464 of yacc.c */
+#line 805 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 155:
+
+/* Line 1464 of yacc.c */
+#line 807 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 156:
+
+/* Line 1464 of yacc.c */
+#line 809 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_sval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].String)); }
+ break;
+
+ case 163:
+
+/* Line 1464 of yacc.c */
+#line 831 "ntp_parser.y"
+ { append_queue(cfgt.enable_opts, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 164:
+
+/* Line 1464 of yacc.c */
+#line 833 "ntp_parser.y"
+ { append_queue(cfgt.disable_opts, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 165:
+
+/* Line 1464 of yacc.c */
+#line 838 "ntp_parser.y"
+ {
+ if ((yyvsp[(2) - (2)].Attr_val) != NULL)
+ (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val));
+ else
+ (yyval.Queue) = (yyvsp[(1) - (2)].Queue);
+ }
+ break;
+
+ case 166:
+
+/* Line 1464 of yacc.c */
+#line 845 "ntp_parser.y"
+ {
+ if ((yyvsp[(1) - (1)].Attr_val) != NULL)
+ (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val));
+ else
+ (yyval.Queue) = create_queue();
+ }
+ break;
+
+ case 167:
+
+/* Line 1464 of yacc.c */
+#line 855 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival(T_Flag, (yyvsp[(1) - (1)].Integer)); }
+ break;
+
+ case 168:
+
+/* Line 1464 of yacc.c */
+#line 857 "ntp_parser.y"
+ {
+ if (input_from_file) {
+ (yyval.Attr_val) = create_attr_ival(T_Flag, (yyvsp[(1) - (1)].Integer));
+ } else {
+ (yyval.Attr_val) = NULL;
+ yyerror("enable/disable stats remote config ignored");
+ }
+ }
+ break;
+
+ case 175:
+
+/* Line 1464 of yacc.c */
+#line 882 "ntp_parser.y"
+ { append_queue(cfgt.tinker, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 176:
+
+/* Line 1464 of yacc.c */
+#line 886 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 177:
+
+/* Line 1464 of yacc.c */
+#line 887 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 178:
+
+/* Line 1464 of yacc.c */
+#line 892 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Double)); }
+ break;
+
+ case 187:
+
+/* Line 1464 of yacc.c */
+#line 913 "ntp_parser.y"
+ {
+ struct attr_val *av;
+
+ av = create_attr_dval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Double));
+ enqueue(cfgt.vars, av);
+ }
+ break;
+
+ case 188:
+
+/* Line 1464 of yacc.c */
+#line 920 "ntp_parser.y"
+ {
+ struct attr_val *av;
+
+ av = create_attr_sval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].String));
+ enqueue(cfgt.vars, av);
+ }
+ break;
+
+ case 189:
+
+/* Line 1464 of yacc.c */
+#line 927 "ntp_parser.y"
+ {
+ char error_text[64];
+ struct attr_val *av;
+
+ if (input_from_file) {
+ av = create_attr_sval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].String));
+ enqueue(cfgt.vars, av);
+ } else {
+ YYFREE((yyvsp[(2) - (2)].String));
+ snprintf(error_text, sizeof(error_text),
+ "%s remote config ignored",
+ keyword((yyvsp[(1) - (2)].Integer)));
+ yyerror(error_text);
+ }
+ }
+ break;
+
+ case 190:
+
+/* Line 1464 of yacc.c */
+#line 943 "ntp_parser.y"
+ {
+ if (!input_from_file) {
+ yyerror("remote includefile ignored");
+ break;
+ }
+ if (curr_include_level >= MAXINCLUDELEVEL) {
+ fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
+ msyslog(LOG_ERR, "getconfig: Maximum include file level exceeded.\n");
+ } else {
+ fp[curr_include_level + 1] = F_OPEN(FindConfig((yyvsp[(2) - (3)].String)), "r");
+ if (fp[curr_include_level + 1] == NULL) {
+ fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig((yyvsp[(2) - (3)].String)));
+ msyslog(LOG_ERR, "getconfig: Couldn't open <%s>\n", FindConfig((yyvsp[(2) - (3)].String)));
+ } else {
+ ip_file = fp[++curr_include_level];
+ }
+ }
+ }
+ break;
+
+ case 191:
+
+/* Line 1464 of yacc.c */
+#line 962 "ntp_parser.y"
+ {
+ while (curr_include_level != -1)
+ FCLOSE(fp[curr_include_level--]);
+ }
+ break;
+
+ case 192:
+
+/* Line 1464 of yacc.c */
+#line 967 "ntp_parser.y"
+ { enqueue(cfgt.vars, create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer))); }
+ break;
+
+ case 193:
+
+/* Line 1464 of yacc.c */
+#line 969 "ntp_parser.y"
+ { /* Null action, possibly all null parms */ }
+ break;
+
+ case 194:
+
+/* Line 1464 of yacc.c */
+#line 971 "ntp_parser.y"
+ { append_queue(cfgt.logconfig, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 195:
+
+/* Line 1464 of yacc.c */
+#line 973 "ntp_parser.y"
+ { append_queue(cfgt.phone, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 196:
+
+/* Line 1464 of yacc.c */
+#line 975 "ntp_parser.y"
+ { enqueue(cfgt.setvar, (yyvsp[(2) - (2)].Set_var)); }
+ break;
+
+ case 197:
+
+/* Line 1464 of yacc.c */
+#line 977 "ntp_parser.y"
+ { enqueue(cfgt.trap, create_addr_opts_node((yyvsp[(2) - (2)].Address_node), NULL)); }
+ break;
+
+ case 198:
+
+/* Line 1464 of yacc.c */
+#line 979 "ntp_parser.y"
+ { enqueue(cfgt.trap, create_addr_opts_node((yyvsp[(2) - (3)].Address_node), (yyvsp[(3) - (3)].Queue))); }
+ break;
+
+ case 199:
+
+/* Line 1464 of yacc.c */
+#line 981 "ntp_parser.y"
+ { append_queue(cfgt.ttl, (yyvsp[(2) - (2)].Queue)); }
+ break;
+
+ case 207:
+
+/* Line 1464 of yacc.c */
+#line 1002 "ntp_parser.y"
+ { enqueue(cfgt.vars, create_attr_sval(T_Driftfile, (yyvsp[(1) - (1)].String))); }
+ break;
+
+ case 208:
+
+/* Line 1464 of yacc.c */
+#line 1004 "ntp_parser.y"
+ { enqueue(cfgt.vars, create_attr_dval(T_WanderThreshold, (yyvsp[(2) - (2)].Double)));
+ enqueue(cfgt.vars, create_attr_sval(T_Driftfile, (yyvsp[(1) - (2)].String))); }
+ break;
+
+ case 209:
+
+/* Line 1464 of yacc.c */
+#line 1007 "ntp_parser.y"
+ { enqueue(cfgt.vars, create_attr_sval(T_Driftfile, "\0")); }
+ break;
+
+ case 210:
+
+/* Line 1464 of yacc.c */
+#line 1012 "ntp_parser.y"
+ { (yyval.Set_var) = create_setvar_node((yyvsp[(1) - (4)].String), (yyvsp[(3) - (4)].String), (yyvsp[(4) - (4)].Integer)); }
+ break;
+
+ case 212:
+
+/* Line 1464 of yacc.c */
+#line 1018 "ntp_parser.y"
+ { (yyval.Integer) = 0; }
+ break;
+
+ case 213:
+
+/* Line 1464 of yacc.c */
+#line 1023 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 214:
+
+/* Line 1464 of yacc.c */
+#line 1024 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 215:
+
+/* Line 1464 of yacc.c */
+#line 1028 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Integer)); }
+ break;
+
+ case 216:
+
+/* Line 1464 of yacc.c */
+#line 1029 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_pval((yyvsp[(1) - (2)].Integer), (yyvsp[(2) - (2)].Address_node)); }
+ break;
+
+ case 217:
+
+/* Line 1464 of yacc.c */
+#line 1033 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 218:
+
+/* Line 1464 of yacc.c */
+#line 1034 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 219:
+
+/* Line 1464 of yacc.c */
+#line 1039 "ntp_parser.y"
+ {
+ char prefix = (yyvsp[(1) - (1)].String)[0];
+ char *type = (yyvsp[(1) - (1)].String) + 1;
+
+ if (prefix != '+' && prefix != '-' && prefix != '=') {
+ yyerror("Logconfig prefix is not '+', '-' or '='\n");
+ }
+ else
+ (yyval.Attr_val) = create_attr_sval(prefix, estrdup(type));
+ YYFREE((yyvsp[(1) - (1)].String));
+ }
+ break;
+
+ case 220:
+
+/* Line 1464 of yacc.c */
+#line 1054 "ntp_parser.y"
+ {
+ enqueue(cfgt.nic_rules,
+ create_nic_rule_node((yyvsp[(3) - (3)].Integer), NULL, (yyvsp[(2) - (3)].Integer)));
+ }
+ break;
+
+ case 221:
+
+/* Line 1464 of yacc.c */
+#line 1059 "ntp_parser.y"
+ {
+ enqueue(cfgt.nic_rules,
+ create_nic_rule_node(0, (yyvsp[(3) - (3)].String), (yyvsp[(2) - (3)].Integer)));
+ }
+ break;
+
+ case 231:
+
+/* Line 1464 of yacc.c */
+#line 1090 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), create_ival((yyvsp[(2) - (2)].Integer))); }
+ break;
+
+ case 232:
+
+/* Line 1464 of yacc.c */
+#line 1091 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue(create_ival((yyvsp[(1) - (1)].Integer))); }
+ break;
+
+ case 233:
+
+/* Line 1464 of yacc.c */
+#line 1096 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Attr_val)); }
+ break;
+
+ case 234:
+
+/* Line 1464 of yacc.c */
+#line 1098 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Attr_val)); }
+ break;
+
+ case 235:
+
+/* Line 1464 of yacc.c */
+#line 1103 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_ival('i', (yyvsp[(1) - (1)].Integer)); }
+ break;
+
+ case 237:
+
+/* Line 1464 of yacc.c */
+#line 1109 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_shorts('-', (yyvsp[(2) - (5)].Integer), (yyvsp[(4) - (5)].Integer)); }
+ break;
+
+ case 238:
+
+/* Line 1464 of yacc.c */
+#line 1113 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), create_pval((yyvsp[(2) - (2)].String))); }
+ break;
+
+ case 239:
+
+/* Line 1464 of yacc.c */
+#line 1114 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue(create_pval((yyvsp[(1) - (1)].String))); }
+ break;
+
+ case 240:
+
+/* Line 1464 of yacc.c */
+#line 1118 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Address_node)); }
+ break;
+
+ case 241:
+
+/* Line 1464 of yacc.c */
+#line 1119 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Address_node)); }
+ break;
+
+ case 242:
+
+/* Line 1464 of yacc.c */
+#line 1124 "ntp_parser.y"
+ {
+ if ((yyvsp[(1) - (1)].Integer) != 0 && (yyvsp[(1) - (1)].Integer) != 1) {
+ yyerror("Integer value is not boolean (0 or 1). Assuming 1");
+ (yyval.Integer) = 1;
+ } else {
+ (yyval.Integer) = (yyvsp[(1) - (1)].Integer);
+ }
+ }
+ break;
+
+ case 243:
+
+/* Line 1464 of yacc.c */
+#line 1132 "ntp_parser.y"
+ { (yyval.Integer) = 1; }
+ break;
+
+ case 244:
+
+/* Line 1464 of yacc.c */
+#line 1133 "ntp_parser.y"
+ { (yyval.Integer) = 0; }
+ break;
+
+ case 245:
+
+/* Line 1464 of yacc.c */
+#line 1137 "ntp_parser.y"
+ { (yyval.Double) = (double)(yyvsp[(1) - (1)].Integer); }
+ break;
+
+ case 247:
+
+/* Line 1464 of yacc.c */
+#line 1148 "ntp_parser.y"
+ {
+ cfgt.sim_details = create_sim_node((yyvsp[(3) - (5)].Queue), (yyvsp[(4) - (5)].Queue));
+
+ /* Reset the old_config_style variable */
+ old_config_style = 1;
+ }
+ break;
+
+ case 248:
+
+/* Line 1464 of yacc.c */
+#line 1162 "ntp_parser.y"
+ { old_config_style = 0; }
+ break;
+
+ case 249:
+
+/* Line 1464 of yacc.c */
+#line 1166 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (3)].Queue), (yyvsp[(2) - (3)].Attr_val)); }
+ break;
+
+ case 250:
+
+/* Line 1464 of yacc.c */
+#line 1167 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (2)].Attr_val)); }
+ break;
+
+ case 251:
+
+/* Line 1464 of yacc.c */
+#line 1171 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+ case 252:
+
+/* Line 1464 of yacc.c */
+#line 1172 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+ case 253:
+
+/* Line 1464 of yacc.c */
+#line 1176 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Sim_server)); }
+ break;
+
+ case 254:
+
+/* Line 1464 of yacc.c */
+#line 1177 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Sim_server)); }
+ break;
+
+ case 255:
+
+/* Line 1464 of yacc.c */
+#line 1182 "ntp_parser.y"
+ { (yyval.Sim_server) = create_sim_server((yyvsp[(1) - (5)].Address_node), (yyvsp[(3) - (5)].Double), (yyvsp[(4) - (5)].Queue)); }
+ break;
+
+ case 256:
+
+/* Line 1464 of yacc.c */
+#line 1186 "ntp_parser.y"
+ { (yyval.Double) = (yyvsp[(3) - (4)].Double); }
+ break;
+
+ case 257:
+
+/* Line 1464 of yacc.c */
+#line 1190 "ntp_parser.y"
+ { (yyval.Address_node) = (yyvsp[(3) - (3)].Address_node); }
+ break;
+
+ case 258:
+
+/* Line 1464 of yacc.c */
+#line 1194 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (2)].Queue), (yyvsp[(2) - (2)].Sim_script)); }
+ break;
+
+ case 259:
+
+/* Line 1464 of yacc.c */
+#line 1195 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (1)].Sim_script)); }
+ break;
+
+ case 260:
+
+/* Line 1464 of yacc.c */
+#line 1200 "ntp_parser.y"
+ { (yyval.Sim_script) = create_sim_script_info((yyvsp[(3) - (6)].Double), (yyvsp[(5) - (6)].Queue)); }
+ break;
+
+ case 261:
+
+/* Line 1464 of yacc.c */
+#line 1204 "ntp_parser.y"
+ { (yyval.Queue) = enqueue((yyvsp[(1) - (3)].Queue), (yyvsp[(2) - (3)].Attr_val)); }
+ break;
+
+ case 262:
+
+/* Line 1464 of yacc.c */
+#line 1205 "ntp_parser.y"
+ { (yyval.Queue) = enqueue_in_new_queue((yyvsp[(1) - (2)].Attr_val)); }
+ break;
+
+ case 263:
+
+/* Line 1464 of yacc.c */
+#line 1210 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+ case 264:
+
+/* Line 1464 of yacc.c */
+#line 1212 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+ case 265:
+
+/* Line 1464 of yacc.c */
+#line 1214 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+ case 266:
+
+/* Line 1464 of yacc.c */
+#line 1216 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+ case 267:
+
+/* Line 1464 of yacc.c */
+#line 1218 "ntp_parser.y"
+ { (yyval.Attr_val) = create_attr_dval((yyvsp[(1) - (3)].Integer), (yyvsp[(3) - (3)].Double)); }
+ break;
+
+
+
+/* Line 1464 of yacc.c */
+#line 3356 "ntp_parser.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1684 of yacc.c */
+#line 1222 "ntp_parser.y"
+
+
+void
+yyerror(
+ const char *msg
+ )
+{
+ int retval;
+
+ ip_file->err_line_no = ip_file->prev_token_line_no;
+ ip_file->err_col_no = ip_file->prev_token_col_no;
+
+ msyslog(LOG_ERR,
+ "line %d column %d %s",
+ ip_file->err_line_no,
+ ip_file->err_col_no,
+ msg);
+ if (!input_from_file) {
+ /* Save the error message in the correct buffer */
+ retval = snprintf(remote_config.err_msg + remote_config.err_pos,
+ MAXLINE - remote_config.err_pos,
+ "column %d %s",
+ ip_file->err_col_no, msg);
+
+ /* Increment the value of err_pos */
+ if (retval > 0)
+ remote_config.err_pos += retval;
+
+ /* Increment the number of errors */
+ ++remote_config.no_errors;
+ }
+}
+
+
+/*
+ * token_name - Convert T_ token integers to text.
+ * Example: token_name(T_Server) returns "T_Server".
+ * see also keyword(T_Server) which returns "server".
+ */
+const char *
+token_name(
+ int token
+ )
+{
+ return yytname[YYTRANSLATE(token)];
+}
+
+
+/* Initial Testing function -- ignore
+int main(int argc, char *argv[])
+{
+ ip_file = FOPEN(argv[1], "r");
+ if (!ip_file) {
+ fprintf(stderr, "ERROR!! Could not open file: %s\n", argv[1]);
+ }
+ key_scanner = create_keyword_scanner(keyword_list);
+ print_keyword_scanner(key_scanner, 0);
+ yyparse();
+ return 0;
+}
+*/
+
+
diff --git a/ntpd/ntp_parser.h b/ntpd/ntp_parser.h
new file mode 100644
index 000000000000..427f2237091f
--- /dev/null
+++ b/ntpd/ntp_parser.h
@@ -0,0 +1,407 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_Age = 258,
+ T_All = 259,
+ T_Allan = 260,
+ T_Auth = 261,
+ T_Autokey = 262,
+ T_Automax = 263,
+ T_Average = 264,
+ T_Bclient = 265,
+ T_Beacon = 266,
+ T_Bias = 267,
+ T_Broadcast = 268,
+ T_Broadcastclient = 269,
+ T_Broadcastdelay = 270,
+ T_Burst = 271,
+ T_Calibrate = 272,
+ T_Calldelay = 273,
+ T_Ceiling = 274,
+ T_Clockstats = 275,
+ T_Cohort = 276,
+ T_ControlKey = 277,
+ T_Crypto = 278,
+ T_Cryptostats = 279,
+ T_Day = 280,
+ T_Default = 281,
+ T_Digest = 282,
+ T_Disable = 283,
+ T_Discard = 284,
+ T_Dispersion = 285,
+ T_Double = 286,
+ T_Driftfile = 287,
+ T_Drop = 288,
+ T_Ellipsis = 289,
+ T_Enable = 290,
+ T_End = 291,
+ T_False = 292,
+ T_File = 293,
+ T_Filegen = 294,
+ T_Flag1 = 295,
+ T_Flag2 = 296,
+ T_Flag3 = 297,
+ T_Flag4 = 298,
+ T_Flake = 299,
+ T_Floor = 300,
+ T_Freq = 301,
+ T_Fudge = 302,
+ T_Host = 303,
+ T_Huffpuff = 304,
+ T_Iburst = 305,
+ T_Ident = 306,
+ T_Ignore = 307,
+ T_Includefile = 308,
+ T_Integer = 309,
+ T_Interface = 310,
+ T_Ipv4 = 311,
+ T_Ipv4_flag = 312,
+ T_Ipv6 = 313,
+ T_Ipv6_flag = 314,
+ T_Kernel = 315,
+ T_Key = 316,
+ T_Keys = 317,
+ T_Keysdir = 318,
+ T_Kod = 319,
+ T_Mssntp = 320,
+ T_Leapfile = 321,
+ T_Limited = 322,
+ T_Link = 323,
+ T_Listen = 324,
+ T_Logconfig = 325,
+ T_Logfile = 326,
+ T_Loopstats = 327,
+ T_Lowpriotrap = 328,
+ T_Manycastclient = 329,
+ T_Manycastserver = 330,
+ T_Mask = 331,
+ T_Maxclock = 332,
+ T_Maxdist = 333,
+ T_Maxpoll = 334,
+ T_Minclock = 335,
+ T_Mindist = 336,
+ T_Minimum = 337,
+ T_Minpoll = 338,
+ T_Minsane = 339,
+ T_Mode = 340,
+ T_Monitor = 341,
+ T_Month = 342,
+ T_Multicastclient = 343,
+ T_Nic = 344,
+ T_Nolink = 345,
+ T_Nomodify = 346,
+ T_None = 347,
+ T_Nopeer = 348,
+ T_Noquery = 349,
+ T_Noselect = 350,
+ T_Noserve = 351,
+ T_Notrap = 352,
+ T_Notrust = 353,
+ T_Ntp = 354,
+ T_Ntpport = 355,
+ T_NtpSignDsocket = 356,
+ T_Orphan = 357,
+ T_Panic = 358,
+ T_Peer = 359,
+ T_Peerstats = 360,
+ T_Phone = 361,
+ T_Pid = 362,
+ T_Pidfile = 363,
+ T_Pool = 364,
+ T_Port = 365,
+ T_Preempt = 366,
+ T_Prefer = 367,
+ T_Protostats = 368,
+ T_Pw = 369,
+ T_Qos = 370,
+ T_Randfile = 371,
+ T_Rawstats = 372,
+ T_Refid = 373,
+ T_Requestkey = 374,
+ T_Restrict = 375,
+ T_Revoke = 376,
+ T_Saveconfigdir = 377,
+ T_Server = 378,
+ T_Setvar = 379,
+ T_Sign = 380,
+ T_Statistics = 381,
+ T_Stats = 382,
+ T_Statsdir = 383,
+ T_Step = 384,
+ T_Stepout = 385,
+ T_Stratum = 386,
+ T_String = 387,
+ T_Sysstats = 388,
+ T_Tick = 389,
+ T_Time1 = 390,
+ T_Time2 = 391,
+ T_Timingstats = 392,
+ T_Tinker = 393,
+ T_Tos = 394,
+ T_Trap = 395,
+ T_True = 396,
+ T_Trustedkey = 397,
+ T_Ttl = 398,
+ T_Type = 399,
+ T_Unconfig = 400,
+ T_Unpeer = 401,
+ T_Version = 402,
+ T_WanderThreshold = 403,
+ T_Week = 404,
+ T_Wildcard = 405,
+ T_Xleave = 406,
+ T_Year = 407,
+ T_Flag = 408,
+ T_Void = 409,
+ T_EOC = 410,
+ T_Simulate = 411,
+ T_Beep_Delay = 412,
+ T_Sim_Duration = 413,
+ T_Server_Offset = 414,
+ T_Duration = 415,
+ T_Freq_Offset = 416,
+ T_Wander = 417,
+ T_Jitter = 418,
+ T_Prop_Delay = 419,
+ T_Proc_Delay = 420
+ };
+#endif
+/* Tokens. */
+#define T_Age 258
+#define T_All 259
+#define T_Allan 260
+#define T_Auth 261
+#define T_Autokey 262
+#define T_Automax 263
+#define T_Average 264
+#define T_Bclient 265
+#define T_Beacon 266
+#define T_Bias 267
+#define T_Broadcast 268
+#define T_Broadcastclient 269
+#define T_Broadcastdelay 270
+#define T_Burst 271
+#define T_Calibrate 272
+#define T_Calldelay 273
+#define T_Ceiling 274
+#define T_Clockstats 275
+#define T_Cohort 276
+#define T_ControlKey 277
+#define T_Crypto 278
+#define T_Cryptostats 279
+#define T_Day 280
+#define T_Default 281
+#define T_Digest 282
+#define T_Disable 283
+#define T_Discard 284
+#define T_Dispersion 285
+#define T_Double 286
+#define T_Driftfile 287
+#define T_Drop 288
+#define T_Ellipsis 289
+#define T_Enable 290
+#define T_End 291
+#define T_False 292
+#define T_File 293
+#define T_Filegen 294
+#define T_Flag1 295
+#define T_Flag2 296
+#define T_Flag3 297
+#define T_Flag4 298
+#define T_Flake 299
+#define T_Floor 300
+#define T_Freq 301
+#define T_Fudge 302
+#define T_Host 303
+#define T_Huffpuff 304
+#define T_Iburst 305
+#define T_Ident 306
+#define T_Ignore 307
+#define T_Includefile 308
+#define T_Integer 309
+#define T_Interface 310
+#define T_Ipv4 311
+#define T_Ipv4_flag 312
+#define T_Ipv6 313
+#define T_Ipv6_flag 314
+#define T_Kernel 315
+#define T_Key 316
+#define T_Keys 317
+#define T_Keysdir 318
+#define T_Kod 319
+#define T_Mssntp 320
+#define T_Leapfile 321
+#define T_Limited 322
+#define T_Link 323
+#define T_Listen 324
+#define T_Logconfig 325
+#define T_Logfile 326
+#define T_Loopstats 327
+#define T_Lowpriotrap 328
+#define T_Manycastclient 329
+#define T_Manycastserver 330
+#define T_Mask 331
+#define T_Maxclock 332
+#define T_Maxdist 333
+#define T_Maxpoll 334
+#define T_Minclock 335
+#define T_Mindist 336
+#define T_Minimum 337
+#define T_Minpoll 338
+#define T_Minsane 339
+#define T_Mode 340
+#define T_Monitor 341
+#define T_Month 342
+#define T_Multicastclient 343
+#define T_Nic 344
+#define T_Nolink 345
+#define T_Nomodify 346
+#define T_None 347
+#define T_Nopeer 348
+#define T_Noquery 349
+#define T_Noselect 350
+#define T_Noserve 351
+#define T_Notrap 352
+#define T_Notrust 353
+#define T_Ntp 354
+#define T_Ntpport 355
+#define T_NtpSignDsocket 356
+#define T_Orphan 357
+#define T_Panic 358
+#define T_Peer 359
+#define T_Peerstats 360
+#define T_Phone 361
+#define T_Pid 362
+#define T_Pidfile 363
+#define T_Pool 364
+#define T_Port 365
+#define T_Preempt 366
+#define T_Prefer 367
+#define T_Protostats 368
+#define T_Pw 369
+#define T_Qos 370
+#define T_Randfile 371
+#define T_Rawstats 372
+#define T_Refid 373
+#define T_Requestkey 374
+#define T_Restrict 375
+#define T_Revoke 376
+#define T_Saveconfigdir 377
+#define T_Server 378
+#define T_Setvar 379
+#define T_Sign 380
+#define T_Statistics 381
+#define T_Stats 382
+#define T_Statsdir 383
+#define T_Step 384
+#define T_Stepout 385
+#define T_Stratum 386
+#define T_String 387
+#define T_Sysstats 388
+#define T_Tick 389
+#define T_Time1 390
+#define T_Time2 391
+#define T_Timingstats 392
+#define T_Tinker 393
+#define T_Tos 394
+#define T_Trap 395
+#define T_True 396
+#define T_Trustedkey 397
+#define T_Ttl 398
+#define T_Type 399
+#define T_Unconfig 400
+#define T_Unpeer 401
+#define T_Version 402
+#define T_WanderThreshold 403
+#define T_Week 404
+#define T_Wildcard 405
+#define T_Xleave 406
+#define T_Year 407
+#define T_Flag 408
+#define T_Void 409
+#define T_EOC 410
+#define T_Simulate 411
+#define T_Beep_Delay 412
+#define T_Sim_Duration 413
+#define T_Server_Offset 414
+#define T_Duration 415
+#define T_Freq_Offset 416
+#define T_Wander 417
+#define T_Jitter 418
+#define T_Prop_Delay 419
+#define T_Proc_Delay 420
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
+#line 50 "ntp_parser.y"
+
+ char *String;
+ double Double;
+ int Integer;
+ void *VoidPtr;
+ queue *Queue;
+ struct attr_val *Attr_val;
+ struct address_node *Address_node;
+ struct setvar_node *Set_var;
+
+ /* Simulation types */
+ server_info *Sim_server;
+ script_info *Sim_script;
+
+
+
+/* Line 1676 of yacc.c */
+#line 399 "ntp_parser.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+extern YYSTYPE yylval;
+
+
diff --git a/ntpd/ntp_parser.y b/ntpd/ntp_parser.y
new file mode 100644
index 000000000000..a3e7a075c1d4
--- /dev/null
+++ b/ntpd/ntp_parser.y
@@ -0,0 +1,1283 @@
+/* ntp_parser.y
+ *
+ * The parser for the NTP configuration file.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Copyright (c) 2006
+ */
+
+%{
+ #ifdef HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+
+ #include "ntp.h"
+ #include "ntpd.h"
+ #include "ntp_machine.h"
+ #include "ntp_stdlib.h"
+ #include "ntp_filegen.h"
+ #include "ntp_data_structures.h"
+ #include "ntp_scanner.h"
+ #include "ntp_config.h"
+ #include "ntp_crypto.h"
+
+ #include "ntpsim.h" /* HMS: Do we really want this all the time? */
+ /* SK: It might be a good idea to always
+ include the simulator code. That way
+ someone can use the same configuration file
+ for both the simulator and the daemon
+ */
+
+
+ struct FILE_INFO *ip_file; /* Pointer to the configuration file stream */
+
+ #define YYMALLOC emalloc
+ #define YYFREE free
+ #define YYERROR_VERBOSE
+ #define YYMAXDEPTH 1000 /* stop the madness sooner */
+ void yyerror(const char *msg);
+ extern int input_from_file; /* 0=input from ntpq :config */
+%}
+
+/*
+ * Enable generation of token names array even without YYDEBUG.
+ * We access via token_name() defined below.
+ */
+%token-table
+
+%union {
+ char *String;
+ double Double;
+ int Integer;
+ void *VoidPtr;
+ queue *Queue;
+ struct attr_val *Attr_val;
+ struct address_node *Address_node;
+ struct setvar_node *Set_var;
+
+ /* Simulation types */
+ server_info *Sim_server;
+ script_info *Sim_script;
+}
+
+/* TERMINALS (do not appear left of colon) */
+%token <Integer> T_Age
+%token <Integer> T_All
+%token <Integer> T_Allan
+%token <Integer> T_Auth
+%token <Integer> T_Autokey
+%token <Integer> T_Automax
+%token <Integer> T_Average
+%token <Integer> T_Bclient
+%token <Integer> T_Beacon
+%token <Integer> T_Bias
+%token <Integer> T_Broadcast
+%token <Integer> T_Broadcastclient
+%token <Integer> T_Broadcastdelay
+%token <Integer> T_Burst
+%token <Integer> T_Calibrate
+%token <Integer> T_Calldelay
+%token <Integer> T_Ceiling
+%token <Integer> T_Clockstats
+%token <Integer> T_Cohort
+%token <Integer> T_ControlKey
+%token <Integer> T_Crypto
+%token <Integer> T_Cryptostats
+%token <Integer> T_Day
+%token <Integer> T_Default
+%token <Integer> T_Digest
+%token <Integer> T_Disable
+%token <Integer> T_Discard
+%token <Integer> T_Dispersion
+%token <Double> T_Double
+%token <Integer> T_Driftfile
+%token <Integer> T_Drop
+%token <Integer> T_Ellipsis /* "..." not "ellipsis" */
+%token <Integer> T_Enable
+%token <Integer> T_End
+%token <Integer> T_False
+%token <Integer> T_File
+%token <Integer> T_Filegen
+%token <Integer> T_Flag1
+%token <Integer> T_Flag2
+%token <Integer> T_Flag3
+%token <Integer> T_Flag4
+%token <Integer> T_Flake
+%token <Integer> T_Floor
+%token <Integer> T_Freq
+%token <Integer> T_Fudge
+%token <Integer> T_Host
+%token <Integer> T_Huffpuff
+%token <Integer> T_Iburst
+%token <Integer> T_Ident
+%token <Integer> T_Ignore
+%token <Integer> T_Includefile
+%token <Integer> T_Integer
+%token <Integer> T_Interface
+%token <Integer> T_Ipv4
+%token <Integer> T_Ipv4_flag
+%token <Integer> T_Ipv6
+%token <Integer> T_Ipv6_flag
+%token <Integer> T_Kernel
+%token <Integer> T_Key
+%token <Integer> T_Keys
+%token <Integer> T_Keysdir
+%token <Integer> T_Kod
+%token <Integer> T_Mssntp
+%token <Integer> T_Leapfile
+%token <Integer> T_Limited
+%token <Integer> T_Link
+%token <Integer> T_Listen
+%token <Integer> T_Logconfig
+%token <Integer> T_Logfile
+%token <Integer> T_Loopstats
+%token <Integer> T_Lowpriotrap
+%token <Integer> T_Manycastclient
+%token <Integer> T_Manycastserver
+%token <Integer> T_Mask
+%token <Integer> T_Maxclock
+%token <Integer> T_Maxdist
+%token <Integer> T_Maxpoll
+%token <Integer> T_Minclock
+%token <Integer> T_Mindist
+%token <Integer> T_Minimum
+%token <Integer> T_Minpoll
+%token <Integer> T_Minsane
+%token <Integer> T_Mode
+%token <Integer> T_Monitor
+%token <Integer> T_Month
+%token <Integer> T_Multicastclient
+%token <Integer> T_Nic
+%token <Integer> T_Nolink
+%token <Integer> T_Nomodify
+%token <Integer> T_None
+%token <Integer> T_Nopeer
+%token <Integer> T_Noquery
+%token <Integer> T_Noselect
+%token <Integer> T_Noserve
+%token <Integer> T_Notrap
+%token <Integer> T_Notrust
+%token <Integer> T_Ntp
+%token <Integer> T_Ntpport
+%token <Integer> T_NtpSignDsocket
+%token <Integer> T_Orphan
+%token <Integer> T_Panic
+%token <Integer> T_Peer
+%token <Integer> T_Peerstats
+%token <Integer> T_Phone
+%token <Integer> T_Pid
+%token <Integer> T_Pidfile
+%token <Integer> T_Pool
+%token <Integer> T_Port
+%token <Integer> T_Preempt
+%token <Integer> T_Prefer
+%token <Integer> T_Protostats
+%token <Integer> T_Pw
+%token <Integer> T_Qos
+%token <Integer> T_Randfile
+%token <Integer> T_Rawstats
+%token <Integer> T_Refid
+%token <Integer> T_Requestkey
+%token <Integer> T_Restrict
+%token <Integer> T_Revoke
+%token <Integer> T_Saveconfigdir
+%token <Integer> T_Server
+%token <Integer> T_Setvar
+%token <Integer> T_Sign
+%token <Integer> T_Statistics
+%token <Integer> T_Stats
+%token <Integer> T_Statsdir
+%token <Integer> T_Step
+%token <Integer> T_Stepout
+%token <Integer> T_Stratum
+%token <String> T_String
+%token <Integer> T_Sysstats
+%token <Integer> T_Tick
+%token <Integer> T_Time1
+%token <Integer> T_Time2
+%token <Integer> T_Timingstats
+%token <Integer> T_Tinker
+%token <Integer> T_Tos
+%token <Integer> T_Trap
+%token <Integer> T_True
+%token <Integer> T_Trustedkey
+%token <Integer> T_Ttl
+%token <Integer> T_Type
+%token <Integer> T_Unconfig
+%token <Integer> T_Unpeer
+%token <Integer> T_Version
+%token <Integer> T_WanderThreshold /* Not a token */
+%token <Integer> T_Week
+%token <Integer> T_Wildcard
+%token <Integer> T_Xleave
+%token <Integer> T_Year
+%token <Integer> T_Flag /* Not an actual token */
+%token <Integer> T_Void /* Not an actual token */
+%token <Integer> T_EOC
+
+
+/* NTP Simulator Tokens */
+%token <Integer> T_Simulate
+%token <Integer> T_Beep_Delay
+%token <Integer> T_Sim_Duration
+%token <Integer> T_Server_Offset
+%token <Integer> T_Duration
+%token <Integer> T_Freq_Offset
+%token <Integer> T_Wander
+%token <Integer> T_Jitter
+%token <Integer> T_Prop_Delay
+%token <Integer> T_Proc_Delay
+
+
+
+/*** NON-TERMINALS ***/
+%type <Integer> access_control_flag
+%type <Queue> ac_flag_list
+%type <Address_node> address
+%type <Integer> address_fam
+%type <Queue> address_list
+%type <Integer> boolean
+%type <Integer> client_type
+%type <Attr_val> crypto_command
+%type <Queue> crypto_command_list
+%type <Integer> crypto_str_keyword
+%type <Attr_val> discard_option
+%type <Integer> discard_option_keyword
+%type <Queue> discard_option_list
+%type <Integer> enable_disable
+%type <Attr_val> filegen_option
+%type <Queue> filegen_option_list
+%type <Integer> filegen_type
+%type <Attr_val> fudge_factor
+%type <Integer> fudge_factor_bool_keyword
+%type <Integer> fudge_factor_dbl_keyword
+%type <Queue> fudge_factor_list
+%type <Queue> integer_list
+%type <Queue> integer_list_range
+%type <Attr_val> integer_list_range_elt
+%type <Attr_val> integer_range
+%type <Integer> nic_rule_action
+%type <Integer> interface_command
+%type <Integer> interface_nic
+%type <Address_node> ip_address
+%type <Integer> link_nolink
+%type <Attr_val> log_config_command
+%type <Queue> log_config_list
+%type <Integer> misc_cmd_dbl_keyword
+%type <Integer> misc_cmd_str_keyword
+%type <Integer> misc_cmd_str_lcl_keyword
+%type <Integer> nic_rule_class
+%type <Double> number
+%type <Attr_val> option
+%type <Attr_val> option_flag
+%type <Integer> option_flag_keyword
+%type <Queue> option_list
+%type <Attr_val> option_int
+%type <Integer> option_int_keyword
+%type <Integer> stat
+%type <Queue> stats_list
+%type <Queue> string_list
+%type <Attr_val> system_option
+%type <Integer> system_option_flag_keyword
+%type <Queue> system_option_list
+%type <Integer> t_default_or_zero
+%type <Integer> tinker_option_keyword
+%type <Attr_val> tinker_option
+%type <Queue> tinker_option_list
+%type <Attr_val> tos_option
+%type <Integer> tos_option_dbl_keyword
+%type <Integer> tos_option_int_keyword
+%type <Queue> tos_option_list
+%type <Attr_val> trap_option
+%type <Queue> trap_option_list
+%type <Integer> unpeer_keyword
+%type <Set_var> variable_assign
+
+/* NTP Simulator non-terminals */
+%type <Queue> sim_init_statement_list
+%type <Attr_val> sim_init_statement
+%type <Queue> sim_server_list
+%type <Sim_server> sim_server
+%type <Double> sim_server_offset
+%type <Address_node> sim_server_name
+%type <Queue> sim_act_list
+%type <Sim_script> sim_act
+%type <Queue> sim_act_stmt_list
+%type <Attr_val> sim_act_stmt
+
+%%
+
+/* ntp.conf
+ * Configuration File Grammar
+ * --------------------------
+ */
+
+configuration
+ : command_list
+ ;
+
+command_list
+ : command_list command T_EOC
+ | command T_EOC
+ | error T_EOC
+ {
+ /* I will need to incorporate much more fine grained
+ * error messages. The following should suffice for
+ * the time being.
+ */
+ msyslog(LOG_ERR,
+ "syntax error in %s line %d, column %d",
+ ip_file->fname,
+ ip_file->err_line_no,
+ ip_file->err_col_no);
+ }
+ ;
+
+command : /* NULL STATEMENT */
+ | server_command
+ | unpeer_command
+ | other_mode_command
+ | authentication_command
+ | monitoring_command
+ | access_control_command
+ | orphan_mode_command
+ | fudge_command
+ | system_option_command
+ | tinker_command
+ | miscellaneous_command
+ | simulate_command
+ ;
+
+/* Server Commands
+ * ---------------
+ */
+
+server_command
+ : client_type address option_list
+ {
+ struct peer_node *my_node = create_peer_node($1, $2, $3);
+ if (my_node)
+ enqueue(cfgt.peers, my_node);
+ }
+ | client_type address
+ {
+ struct peer_node *my_node = create_peer_node($1, $2, NULL);
+ if (my_node)
+ enqueue(cfgt.peers, my_node);
+ }
+ ;
+
+client_type
+ : T_Server
+ | T_Pool
+ | T_Peer
+ | T_Broadcast
+ | T_Manycastclient
+ ;
+
+address
+ : ip_address
+ | address_fam T_String
+ { $$ = create_address_node($2, $1); }
+ ;
+
+ip_address
+ : T_String
+ { $$ = create_address_node($1, 0); }
+ ;
+
+address_fam
+ : T_Ipv4_flag
+ { $$ = AF_INET; }
+ | T_Ipv6_flag
+ { $$ = AF_INET6; }
+ ;
+
+option_list
+ : option_list option { $$ = enqueue($1, $2); }
+ | option { $$ = enqueue_in_new_queue($1); }
+ ;
+
+option
+ : option_flag
+ | option_int
+ | T_Bias number
+ { $$ = create_attr_dval($1, $2); }
+ ;
+
+option_flag
+ : option_flag_keyword
+ { $$ = create_attr_ival(T_Flag, $1); }
+ ;
+
+option_flag_keyword
+ : T_Autokey
+ | T_Burst
+ | T_Iburst
+ | T_Noselect
+ | T_Preempt
+ | T_Prefer
+ | T_True
+ | T_Xleave
+ ;
+
+option_int
+ : option_int_keyword T_Integer
+ { $$ = create_attr_ival($1, $2); }
+ ;
+
+option_int_keyword
+ : T_Key
+ | T_Minpoll
+ | T_Maxpoll
+ | T_Ttl
+ | T_Mode
+ | T_Version
+ ;
+
+
+
+/* unpeer commands
+ * ---------------
+ */
+
+unpeer_command
+ : unpeer_keyword address
+ {
+ struct unpeer_node *my_node = create_unpeer_node($2);
+ if (my_node)
+ enqueue(cfgt.unpeers, my_node);
+ }
+ ;
+unpeer_keyword
+ : T_Unconfig
+ | T_Unpeer
+ ;
+
+
+/* Other Modes
+ * (broadcastclient manycastserver multicastclient)
+ * ------------------------------------------------
+ */
+
+other_mode_command
+ : T_Broadcastclient
+ { cfgt.broadcastclient = 1; }
+ | T_Manycastserver address_list
+ { append_queue(cfgt.manycastserver, $2); }
+ | T_Multicastclient address_list
+ { append_queue(cfgt.multicastclient, $2); }
+ ;
+
+
+
+/* Authentication Commands
+ * -----------------------
+ */
+
+authentication_command
+ : T_Automax T_Integer
+ { enqueue(cfgt.vars, create_attr_ival($1, $2)); }
+ | T_ControlKey T_Integer
+ { cfgt.auth.control_key = $2; }
+ | T_Crypto crypto_command_list
+ {
+ cfgt.auth.cryptosw++;
+ append_queue(cfgt.auth.crypto_cmd_list, $2);
+ }
+ | T_Keys T_String
+ { cfgt.auth.keys = $2; }
+ | T_Keysdir T_String
+ { cfgt.auth.keysdir = $2; }
+ | T_Requestkey T_Integer
+ { cfgt.auth.request_key = $2; }
+ | T_Revoke T_Integer
+ { cfgt.auth.revoke = $2; }
+ | T_Trustedkey integer_list_range
+ { cfgt.auth.trusted_key_list = $2; }
+ | T_NtpSignDsocket T_String
+ { cfgt.auth.ntp_signd_socket = $2; }
+ ;
+
+crypto_command_list
+ : /* empty list */
+ { $$ = create_queue(); }
+ | crypto_command_list crypto_command
+ {
+ if ($2 != NULL)
+ $$ = enqueue($1, $2);
+ else
+ $$ = $1;
+ }
+ ;
+
+crypto_command
+ : crypto_str_keyword T_String
+ { $$ = create_attr_sval($1, $2); }
+ | T_Revoke T_Integer
+ {
+ $$ = NULL;
+ cfgt.auth.revoke = $2;
+ msyslog(LOG_WARNING,
+ "'crypto revoke %d' is deprecated, "
+ "please use 'revoke %d' instead.",
+ cfgt.auth.revoke, cfgt.auth.revoke);
+ }
+ ;
+
+crypto_str_keyword
+ : T_Host
+ | T_Ident
+ | T_Pw
+ | T_Randfile
+ | T_Sign
+ | T_Digest
+ ;
+
+
+/* Orphan Mode Commands
+ * --------------------
+ */
+
+orphan_mode_command
+ : T_Tos tos_option_list
+ { append_queue(cfgt.orphan_cmds,$2); }
+ ;
+
+tos_option_list
+ : tos_option_list tos_option { $$ = enqueue($1, $2); }
+ | tos_option { $$ = enqueue_in_new_queue($1); }
+ ;
+
+tos_option
+ : tos_option_int_keyword T_Integer
+ { $$ = create_attr_dval($1, (double)$2); }
+ | tos_option_dbl_keyword number
+ { $$ = create_attr_dval($1, $2); }
+ | T_Cohort boolean
+ { $$ = create_attr_dval($1, (double)$2); }
+ ;
+
+tos_option_int_keyword
+ : T_Ceiling
+ | T_Floor
+ | T_Orphan
+ | T_Minsane
+ | T_Beacon
+ ;
+
+tos_option_dbl_keyword
+ : T_Mindist
+ | T_Maxdist
+ | T_Minclock
+ | T_Maxclock
+ ;
+
+
+/* Monitoring Commands
+ * -------------------
+ */
+
+monitoring_command
+ : T_Statistics stats_list
+ { append_queue(cfgt.stats_list, $2); }
+ | T_Statsdir T_String
+ {
+ if (input_from_file) {
+ cfgt.stats_dir = $2;
+ } else {
+ YYFREE($2);
+ yyerror("statsdir remote configuration ignored");
+ }
+ }
+ | T_Filegen stat filegen_option_list
+ {
+ enqueue(cfgt.filegen_opts,
+ create_filegen_node($2, $3));
+ }
+ ;
+
+stats_list
+ : stats_list stat { $$ = enqueue($1, create_ival($2)); }
+ | stat { $$ = enqueue_in_new_queue(create_ival($1)); }
+ ;
+
+stat
+ : T_Clockstats
+ | T_Cryptostats
+ | T_Loopstats
+ | T_Peerstats
+ | T_Rawstats
+ | T_Sysstats
+ | T_Timingstats
+ | T_Protostats
+ ;
+
+filegen_option_list
+ : /* empty list */
+ { $$ = create_queue(); }
+ | filegen_option_list filegen_option
+ {
+ if ($2 != NULL)
+ $$ = enqueue($1, $2);
+ else
+ $$ = $1;
+ }
+ ;
+
+filegen_option
+ : T_File T_String
+ {
+ if (input_from_file) {
+ $$ = create_attr_sval($1, $2);
+ } else {
+ $$ = NULL;
+ YYFREE($2);
+ yyerror("filegen file remote config ignored");
+ }
+ }
+ | T_Type filegen_type
+ {
+ if (input_from_file) {
+ $$ = create_attr_ival($1, $2);
+ } else {
+ $$ = NULL;
+ yyerror("filegen type remote config ignored");
+ }
+ }
+ | link_nolink
+ {
+ const char *err;
+
+ if (input_from_file) {
+ $$ = create_attr_ival(T_Flag, $1);
+ } else {
+ $$ = NULL;
+ if (T_Link == $1)
+ err = "filegen link remote config ignored";
+ else
+ err = "filegen nolink remote config ignored";
+ yyerror(err);
+ }
+ }
+ | enable_disable
+ { $$ = create_attr_ival(T_Flag, $1); }
+ ;
+
+link_nolink
+ : T_Link
+ | T_Nolink
+ ;
+
+enable_disable
+ : T_Enable
+ | T_Disable
+ ;
+
+filegen_type
+ : T_None
+ | T_Pid
+ | T_Day
+ | T_Week
+ | T_Month
+ | T_Year
+ | T_Age
+ ;
+
+
+/* Access Control Commands
+ * -----------------------
+ */
+
+access_control_command
+ : T_Discard discard_option_list
+ {
+ append_queue(cfgt.discard_opts, $2);
+ }
+ | T_Restrict address ac_flag_list
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node($2, NULL, $3, ip_file->line_no));
+ }
+ | T_Restrict T_Default ac_flag_list
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node(NULL, NULL, $3, ip_file->line_no));
+ }
+ | T_Restrict T_Ipv4_flag T_Default ac_flag_list
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node(
+ create_address_node(
+ estrdup("0.0.0.0"),
+ AF_INET),
+ create_address_node(
+ estrdup("0.0.0.0"),
+ AF_INET),
+ $4,
+ ip_file->line_no));
+ }
+ | T_Restrict T_Ipv6_flag T_Default ac_flag_list
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node(
+ create_address_node(
+ estrdup("::"),
+ AF_INET6),
+ create_address_node(
+ estrdup("::"),
+ AF_INET6),
+ $4,
+ ip_file->line_no));
+ }
+ | T_Restrict ip_address T_Mask ip_address ac_flag_list
+ {
+ enqueue(cfgt.restrict_opts,
+ create_restrict_node($2, $4, $5, ip_file->line_no));
+ }
+ ;
+
+ac_flag_list
+ : /* empty list is allowed */
+ { $$ = create_queue(); }
+ | ac_flag_list access_control_flag
+ { $$ = enqueue($1, create_ival($2)); }
+ ;
+
+access_control_flag
+ : T_Flake
+ | T_Ignore
+ | T_Kod
+ | T_Mssntp
+ | T_Limited
+ | T_Lowpriotrap
+ | T_Nomodify
+ | T_Nopeer
+ | T_Noquery
+ | T_Noserve
+ | T_Notrap
+ | T_Notrust
+ | T_Ntpport
+ | T_Version
+ ;
+
+discard_option_list
+ : discard_option_list discard_option
+ { $$ = enqueue($1, $2); }
+ | discard_option
+ { $$ = enqueue_in_new_queue($1); }
+ ;
+
+discard_option
+ : discard_option_keyword T_Integer
+ { $$ = create_attr_ival($1, $2); }
+ ;
+
+discard_option_keyword
+ : T_Average
+ | T_Minimum
+ | T_Monitor
+ ;
+
+
+/* Fudge Commands
+ * --------------
+ */
+
+fudge_command
+ : T_Fudge address fudge_factor_list
+ { enqueue(cfgt.fudge, create_addr_opts_node($2, $3)); }
+ ;
+
+fudge_factor_list
+ : fudge_factor_list fudge_factor
+ { enqueue($1, $2); }
+ | fudge_factor
+ { $$ = enqueue_in_new_queue($1); }
+ ;
+
+fudge_factor
+ : fudge_factor_dbl_keyword number
+ { $$ = create_attr_dval($1, $2); }
+ | fudge_factor_bool_keyword boolean
+ { $$ = create_attr_ival($1, $2); }
+ | T_Stratum T_Integer
+ { $$ = create_attr_ival($1, $2); }
+ | T_Refid T_String
+ { $$ = create_attr_sval($1, $2); }
+ ;
+
+fudge_factor_dbl_keyword
+ : T_Time1
+ | T_Time2
+ ;
+
+fudge_factor_bool_keyword
+ : T_Flag1
+ | T_Flag2
+ | T_Flag3
+ | T_Flag4
+ ;
+
+
+/* Command for System Options
+ * --------------------------
+ */
+
+system_option_command
+ : T_Enable system_option_list
+ { append_queue(cfgt.enable_opts, $2); }
+ | T_Disable system_option_list
+ { append_queue(cfgt.disable_opts, $2); }
+ ;
+
+system_option_list
+ : system_option_list system_option
+ {
+ if ($2 != NULL)
+ $$ = enqueue($1, $2);
+ else
+ $$ = $1;
+ }
+ | system_option
+ {
+ if ($1 != NULL)
+ $$ = enqueue_in_new_queue($1);
+ else
+ $$ = create_queue();
+ }
+ ;
+
+system_option
+ : system_option_flag_keyword
+ { $$ = create_attr_ival(T_Flag, $1); }
+ | T_Stats
+ {
+ if (input_from_file) {
+ $$ = create_attr_ival(T_Flag, $1);
+ } else {
+ $$ = NULL;
+ yyerror("enable/disable stats remote config ignored");
+ }
+ }
+ ;
+
+system_option_flag_keyword
+ : T_Auth
+ | T_Bclient
+ | T_Calibrate
+ | T_Kernel
+ | T_Monitor
+ | T_Ntp
+ ;
+
+
+/* Tinker Commands
+ * ---------------
+ */
+
+tinker_command
+ : T_Tinker tinker_option_list { append_queue(cfgt.tinker, $2); }
+ ;
+
+tinker_option_list
+ : tinker_option_list tinker_option { $$ = enqueue($1, $2); }
+ | tinker_option { $$ = enqueue_in_new_queue($1); }
+ ;
+
+tinker_option
+ : tinker_option_keyword number
+ { $$ = create_attr_dval($1, $2); }
+ ;
+
+tinker_option_keyword
+ : T_Allan
+ | T_Dispersion
+ | T_Freq
+ | T_Huffpuff
+ | T_Panic
+ | T_Step
+ | T_Stepout
+ ;
+
+
+/* Miscellaneous Commands
+ * ----------------------
+ */
+
+miscellaneous_command
+ : interface_command
+ | misc_cmd_dbl_keyword number
+ {
+ struct attr_val *av;
+
+ av = create_attr_dval($1, $2);
+ enqueue(cfgt.vars, av);
+ }
+ | misc_cmd_str_keyword T_String
+ {
+ struct attr_val *av;
+
+ av = create_attr_sval($1, $2);
+ enqueue(cfgt.vars, av);
+ }
+ | misc_cmd_str_lcl_keyword T_String
+ {
+ char error_text[64];
+ struct attr_val *av;
+
+ if (input_from_file) {
+ av = create_attr_sval($1, $2);
+ enqueue(cfgt.vars, av);
+ } else {
+ YYFREE($2);
+ snprintf(error_text, sizeof(error_text),
+ "%s remote config ignored",
+ keyword($1));
+ yyerror(error_text);
+ }
+ }
+ | T_Includefile T_String command
+ {
+ if (!input_from_file) {
+ yyerror("remote includefile ignored");
+ break;
+ }
+ if (curr_include_level >= MAXINCLUDELEVEL) {
+ fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
+ msyslog(LOG_ERR, "getconfig: Maximum include file level exceeded.\n");
+ } else {
+ fp[curr_include_level + 1] = F_OPEN(FindConfig($2), "r");
+ if (fp[curr_include_level + 1] == NULL) {
+ fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig($2));
+ msyslog(LOG_ERR, "getconfig: Couldn't open <%s>\n", FindConfig($2));
+ } else {
+ ip_file = fp[++curr_include_level];
+ }
+ }
+ }
+ | T_End
+ {
+ while (curr_include_level != -1)
+ FCLOSE(fp[curr_include_level--]);
+ }
+ | T_Calldelay T_Integer
+ { enqueue(cfgt.vars, create_attr_ival($1, $2)); }
+ | T_Driftfile drift_parm
+ { /* Null action, possibly all null parms */ }
+ | T_Logconfig log_config_list
+ { append_queue(cfgt.logconfig, $2); }
+ | T_Phone string_list
+ { append_queue(cfgt.phone, $2); }
+ | T_Setvar variable_assign
+ { enqueue(cfgt.setvar, $2); }
+ | T_Trap ip_address
+ { enqueue(cfgt.trap, create_addr_opts_node($2, NULL)); }
+ | T_Trap ip_address trap_option_list
+ { enqueue(cfgt.trap, create_addr_opts_node($2, $3)); }
+ | T_Ttl integer_list
+ { append_queue(cfgt.ttl, $2); }
+ ;
+
+misc_cmd_dbl_keyword
+ : T_Broadcastdelay
+ | T_Tick
+ ;
+
+misc_cmd_str_keyword
+ : T_Leapfile
+ | T_Pidfile
+ | T_Qos
+ ;
+
+misc_cmd_str_lcl_keyword
+ : T_Logfile
+ | T_Saveconfigdir
+ ;
+
+drift_parm
+ : T_String
+ { enqueue(cfgt.vars, create_attr_sval(T_Driftfile, $1)); }
+ | T_String T_Double
+ { enqueue(cfgt.vars, create_attr_dval(T_WanderThreshold, $2));
+ enqueue(cfgt.vars, create_attr_sval(T_Driftfile, $1)); }
+ | /* Null driftfile, indicated by null string "\0" */
+ { enqueue(cfgt.vars, create_attr_sval(T_Driftfile, "\0")); }
+ ;
+
+variable_assign
+ : T_String '=' T_String t_default_or_zero
+ { $$ = create_setvar_node($1, $3, $4); }
+ ;
+
+t_default_or_zero
+ : T_Default
+ | /* empty, no "default" modifier */
+ { $$ = 0; }
+ ;
+
+trap_option_list
+ : trap_option_list trap_option
+ { $$ = enqueue($1, $2); }
+ | trap_option { $$ = enqueue_in_new_queue($1); }
+ ;
+
+trap_option
+ : T_Port T_Integer { $$ = create_attr_ival($1, $2); }
+ | T_Interface ip_address { $$ = create_attr_pval($1, $2); }
+ ;
+
+log_config_list
+ : log_config_list log_config_command { $$ = enqueue($1, $2); }
+ | log_config_command { $$ = enqueue_in_new_queue($1); }
+ ;
+
+log_config_command
+ : T_String
+ {
+ char prefix = $1[0];
+ char *type = $1 + 1;
+
+ if (prefix != '+' && prefix != '-' && prefix != '=') {
+ yyerror("Logconfig prefix is not '+', '-' or '='\n");
+ }
+ else
+ $$ = create_attr_sval(prefix, estrdup(type));
+ YYFREE($1);
+ }
+ ;
+
+interface_command
+ : interface_nic nic_rule_action nic_rule_class
+ {
+ enqueue(cfgt.nic_rules,
+ create_nic_rule_node($3, NULL, $2));
+ }
+ | interface_nic nic_rule_action T_String
+ {
+ enqueue(cfgt.nic_rules,
+ create_nic_rule_node(0, $3, $2));
+ }
+ ;
+
+interface_nic
+ : T_Interface
+ | T_Nic
+ ;
+
+nic_rule_class
+ : T_All
+ | T_Ipv4
+ | T_Ipv6
+ | T_Wildcard
+ ;
+
+nic_rule_action
+ : T_Listen
+ | T_Ignore
+ | T_Drop
+ ;
+
+
+
+/* Miscellaneous Rules
+ * -------------------
+ */
+
+integer_list
+ : integer_list T_Integer { $$ = enqueue($1, create_ival($2)); }
+ | T_Integer { $$ = enqueue_in_new_queue(create_ival($1)); }
+ ;
+
+integer_list_range
+ : integer_list_range integer_list_range_elt
+ { $$ = enqueue($1, $2); }
+ | integer_list_range_elt
+ { $$ = enqueue_in_new_queue($1); }
+ ;
+
+integer_list_range_elt
+ : T_Integer
+ { $$ = create_attr_ival('i', $1); }
+ | integer_range /* default of $$ = $1 is good */
+ ;
+
+integer_range /* limited to unsigned shorts */
+ : '(' T_Integer T_Ellipsis T_Integer ')'
+ { $$ = create_attr_shorts('-', $2, $4); }
+ ;
+
+string_list
+ : string_list T_String { $$ = enqueue($1, create_pval($2)); }
+ | T_String { $$ = enqueue_in_new_queue(create_pval($1)); }
+ ;
+
+address_list
+ : address_list address { $$ = enqueue($1, $2); }
+ | address { $$ = enqueue_in_new_queue($1); }
+ ;
+
+boolean
+ : T_Integer
+ {
+ if ($1 != 0 && $1 != 1) {
+ yyerror("Integer value is not boolean (0 or 1). Assuming 1");
+ $$ = 1;
+ } else {
+ $$ = $1;
+ }
+ }
+ | T_True { $$ = 1; }
+ | T_False { $$ = 0; }
+ ;
+
+number
+ : T_Integer { $$ = (double)$1; }
+ | T_Double
+ ;
+
+
+/* Simulator Configuration Commands
+ * --------------------------------
+ */
+
+simulate_command
+ : sim_conf_start '{' sim_init_statement_list sim_server_list '}'
+ {
+ cfgt.sim_details = create_sim_node($3, $4);
+
+ /* Reset the old_config_style variable */
+ old_config_style = 1;
+ }
+ ;
+
+/* The following is a terrible hack to get the configuration file to
+ * treat newlines as whitespace characters within the simulation.
+ * This is needed because newlines are significant in the rest of the
+ * configuration file.
+ */
+sim_conf_start
+ : T_Simulate { old_config_style = 0; }
+ ;
+
+sim_init_statement_list
+ : sim_init_statement_list sim_init_statement T_EOC { $$ = enqueue($1, $2); }
+ | sim_init_statement T_EOC { $$ = enqueue_in_new_queue($1); }
+ ;
+
+sim_init_statement
+ : T_Beep_Delay '=' number { $$ = create_attr_dval($1, $3); }
+ | T_Sim_Duration '=' number { $$ = create_attr_dval($1, $3); }
+ ;
+
+sim_server_list
+ : sim_server_list sim_server { $$ = enqueue($1, $2); }
+ | sim_server { $$ = enqueue_in_new_queue($1); }
+ ;
+
+sim_server
+ : sim_server_name '{' sim_server_offset sim_act_list '}'
+ { $$ = create_sim_server($1, $3, $4); }
+ ;
+
+sim_server_offset
+ : T_Server_Offset '=' number T_EOC { $$ = $3; }
+ ;
+
+sim_server_name
+ : T_Server '=' address { $$ = $3; }
+ ;
+
+sim_act_list
+ : sim_act_list sim_act { $$ = enqueue($1, $2); }
+ | sim_act { $$ = enqueue_in_new_queue($1); }
+ ;
+
+sim_act
+ : T_Duration '=' number '{' sim_act_stmt_list '}'
+ { $$ = create_sim_script_info($3, $5); }
+ ;
+
+sim_act_stmt_list
+ : sim_act_stmt_list sim_act_stmt T_EOC { $$ = enqueue($1, $2); }
+ | sim_act_stmt T_EOC { $$ = enqueue_in_new_queue($1); }
+ ;
+
+sim_act_stmt
+ : T_Freq_Offset '=' number
+ { $$ = create_attr_dval($1, $3); }
+ | T_Wander '=' number
+ { $$ = create_attr_dval($1, $3); }
+ | T_Jitter '=' number
+ { $$ = create_attr_dval($1, $3); }
+ | T_Prop_Delay '=' number
+ { $$ = create_attr_dval($1, $3); }
+ | T_Proc_Delay '=' number
+ { $$ = create_attr_dval($1, $3); }
+ ;
+
+
+%%
+
+void
+yyerror(
+ const char *msg
+ )
+{
+ int retval;
+
+ ip_file->err_line_no = ip_file->prev_token_line_no;
+ ip_file->err_col_no = ip_file->prev_token_col_no;
+
+ msyslog(LOG_ERR,
+ "line %d column %d %s",
+ ip_file->err_line_no,
+ ip_file->err_col_no,
+ msg);
+ if (!input_from_file) {
+ /* Save the error message in the correct buffer */
+ retval = snprintf(remote_config.err_msg + remote_config.err_pos,
+ MAXLINE - remote_config.err_pos,
+ "column %d %s",
+ ip_file->err_col_no, msg);
+
+ /* Increment the value of err_pos */
+ if (retval > 0)
+ remote_config.err_pos += retval;
+
+ /* Increment the number of errors */
+ ++remote_config.no_errors;
+ }
+}
+
+
+/*
+ * token_name - Convert T_ token integers to text.
+ * Example: token_name(T_Server) returns "T_Server".
+ * see also keyword(T_Server) which returns "server".
+ */
+const char *
+token_name(
+ int token
+ )
+{
+ return yytname[YYTRANSLATE(token)];
+}
+
+
+/* Initial Testing function -- ignore
+int main(int argc, char *argv[])
+{
+ ip_file = FOPEN(argv[1], "r");
+ if (!ip_file) {
+ fprintf(stderr, "ERROR!! Could not open file: %s\n", argv[1]);
+ }
+ key_scanner = create_keyword_scanner(keyword_list);
+ print_keyword_scanner(key_scanner, 0);
+ yyparse();
+ return 0;
+}
+*/
+
diff --git a/ntpd/ntp_peer.c b/ntpd/ntp_peer.c
index deeec5bc3cfc..619e389f0339 100644
--- a/ntpd/ntp_peer.c
+++ b/ntpd/ntp_peer.c
@@ -9,14 +9,18 @@
#include <sys/types.h>
#include "ntpd.h"
+#include "ntp_lists.h"
#include "ntp_stdlib.h"
+#include "ntp_control.h"
#include <ntp_random.h>
#ifdef OPENSSL
#include "openssl/rand.h"
#endif /* OPENSSL */
#ifdef SYS_WINNT
-extern int accept_wildcard_if_for_winnt;
+int accept_wildcard_if_for_winnt;
+#else
+const int accept_wildcard_if_for_winnt = FALSE;
#endif
/*
@@ -29,7 +33,7 @@ extern int accept_wildcard_if_for_winnt;
* NO_PEER | e 1 0 1 1 1
* ACTIVE | e 1 1 0 0 0
* PASSIVE | e 1 e 0 0 0
- * CLIENT | e 0 0 0 1 1
+ * CLIENT | e 0 0 0 1 0
* SERVER | e 0 0 0 0 0
* BCAST | e 0 0 0 0 0
* BCLIENT | e 0 0 0 e 1
@@ -53,7 +57,7 @@ int AM[AM_MODES][AM_MODES] = {
/*P*/ { AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-/*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_POSSBCL},
+/*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_NOMATCH},
/*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
@@ -62,12 +66,12 @@ int AM[AM_MODES][AM_MODES] = {
/*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT},
};
-#define MATCH_ASSOC(x,y) AM[(x)][(y)]
+#define MATCH_ASSOC(x, y) AM[(x)][(y)]
/*
* These routines manage the allocation of memory to peer structures
- * and the maintenance of the peer hash table. The two main entry
- * points are findpeer(), which looks for matching peer sturctures in
+ * and the maintenance of the peer hash table. The three main entry
+ * points are findpeer(), which looks for matching peer structures 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.
@@ -76,11 +80,11 @@ int AM[AM_MODES][AM_MODES] = {
* Peer hash tables
*/
struct peer *peer_hash[NTP_HASH_SIZE]; /* peer hash table */
-int peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
+int peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
struct peer *assoc_hash[NTP_HASH_SIZE]; /* association ID hash table */
-int assoc_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
+int assoc_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
static struct peer *peer_free; /* peer structures free list */
-int peer_free_count; /* count of free structures */
+int peer_free_count; /* count of free structures */
/*
* Association ID. We initialize this value randomly, then assign a new
@@ -97,18 +101,20 @@ static associd_t current_association_ID; /* association ID */
/*
* Miscellaneous statistic counters which may be queried.
*/
-u_long peer_timereset; /* time stat counters zeroed */
-u_long findpeer_calls; /* calls to findpeer */
-u_long assocpeer_calls; /* calls to findpeerbyassoc */
-u_long peer_allocations; /* allocations from free list */
-u_long peer_demobilizations; /* structs freed to free list */
-int total_peer_structs; /* peer structs */
-int peer_associations; /* mobilized associations */
-int peer_preempt; /* preemptable associations */
+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; /* mobilized associations */
+int peer_preempt; /* preemptable associations */
static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
-static void getmorepeermem P((void));
-static struct interface *select_peerinterface P((struct peer *, struct sockaddr_storage *, struct interface *, u_char));
+static void getmorepeermem (void);
+static struct interface *select_peerinterface (struct peer *, sockaddr_u *, struct interface *, u_char);
+
+static int score(struct peer *);
/*
* init_peer - initialize peer data structures and counters
@@ -122,14 +128,12 @@ init_peer(void)
register int i;
/*
- * Clear hash table and counters.
+ * Clear hash tables and counters.
*/
- for (i = 0; i < NTP_HASH_SIZE; i++) {
- peer_hash[i] = 0;
- peer_hash_count[i] = 0;
- assoc_hash[i] = 0;
- assoc_hash_count[i] = 0;
- }
+ memset(peer_hash, 0, sizeof(peer_hash));
+ memset(peer_hash_count, 0, sizeof(peer_hash_count));
+ memset(assoc_hash, 0, sizeof(assoc_hash));
+ memset(assoc_hash_count, 0, sizeof(assoc_hash_count));
/*
* Clear stat counters
@@ -140,11 +144,9 @@ init_peer(void)
/*
* Initialize peer memory.
*/
- peer_free = 0;
- for (i = 0; i < INIT_PEER_ALLOC; i++) {
- init_peer_alloc[i].next = peer_free;
- peer_free = &init_peer_alloc[i];
- }
+ peer_free = NULL;
+ for (i = 0; i < INIT_PEER_ALLOC; i++)
+ LINK_SLIST(peer_free, &init_peer_alloc[i], next);
total_peer_structs = INIT_PEER_ALLOC;
peer_free_count = INIT_PEER_ALLOC;
@@ -167,8 +169,7 @@ getmorepeermem(void)
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;
+ LINK_SLIST(peer_free, peer, next);
peer++;
}
@@ -182,9 +183,10 @@ getmorepeermem(void)
*/
struct peer *
findexistingpeer(
- struct sockaddr_storage *addr,
- struct peer *start_peer,
- int mode
+ sockaddr_u * addr,
+ struct peer * start_peer,
+ int mode,
+ u_char cast_flags
)
{
register struct peer *peer;
@@ -192,59 +194,86 @@ findexistingpeer(
/*
* start_peer is included so we can locate instances of the
* same peer through different interfaces in the hash table.
+ * Without MDF_BCLNT, a match requires the same mode and remote
+ * address. MDF_BCLNT associations start out as MODE_CLIENT
+ * if broadcastdelay is not specified, and switch to
+ * MODE_BCLIENT after estimating the one-way delay. Duplicate
+ * associations are expanded in definition to match any other
+ * MDF_BCLNT with the same srcadr (remote, unicast address).
*/
- if (start_peer == 0)
+ if (NULL == start_peer)
peer = peer_hash[NTP_HASH_ADDR(addr)];
else
peer = start_peer->next;
- while (peer != 0) {
- if (SOCKCMP(addr, &peer->srcadr)
- && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
- if (mode == -1)
- return (peer);
- else if (peer->hmode == mode)
- break;
- }
+ while (peer != NULL) {
+ if (ADDR_PORT_EQ(addr, &peer->srcadr)
+ && (-1 == mode || peer->hmode == mode ||
+ ((MDF_BCLNT & peer->cast_flags) &&
+ (MDF_BCLNT & cast_flags))))
+ break;
peer = peer->next;
}
- return (peer);
+
+ return peer;
}
/*
- * findpeer - find and return a peer in the hash table.
+ * findpeer - find and return a peer match for a received datagram in
+ * the peer_hash table.
*/
struct peer *
findpeer(
- struct sockaddr_storage *srcadr,
- struct interface *dstadr,
- int pkt_mode,
- int *action
+ struct recvbuf *rbufp,
+ int pkt_mode,
+ int * action
)
{
- register struct peer *peer;
- int hash;
+ struct peer * p;
+ sockaddr_u * srcadr;
+ u_int hash;
+ struct pkt * pkt;
+ l_fp pkt_org;
findpeer_calls++;
+ srcadr = &rbufp->recv_srcadr;
hash = NTP_HASH_ADDR(srcadr);
- for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) {
- if (SOCKCMP(srcadr, &peer->srcadr) &&
- NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
+ for (p = peer_hash[hash]; p != NULL; p = p->next) {
+ if (SOCK_EQ(srcadr, &p->srcadr) &&
+ NSRCPORT(srcadr) == NSRCPORT(&p->srcadr)) {
/*
* if the association matching rules determine
* that this is not a valid combination, then
* look for the next valid peer association.
*/
- *action = MATCH_ASSOC(peer->hmode, pkt_mode);
+ *action = MATCH_ASSOC(p->hmode, pkt_mode);
+
+ /*
+ * A response to our manycastclient solicitation
+ * might be misassociated with an ephemeral peer
+ * already spun for the server. If the packet's
+ * org timestamp doesn't match the peer's, check
+ * if it matches the ACST prototype peer's. If
+ * so it is a redundant solicitation response,
+ * return AM_ERR to discard it. [Bug 1762]
+ */
+ if (MODE_SERVER == pkt_mode &&
+ AM_PROCPKT == *action) {
+ pkt = &rbufp->recv_pkt;
+ NTOHL_FP(&pkt->org, &pkt_org);
+ if (!L_ISEQU(&p->aorg, &pkt_org) &&
+ findmanycastpeer(rbufp))
+ *action = AM_ERR;
+ }
/*
* if an error was returned, exit back right
* here.
*/
if (*action == AM_ERR)
- return ((struct peer *)0);
+ return NULL;
/*
* if a match is found, we stop our search.
@@ -257,14 +286,17 @@ findpeer(
/*
* If no matching association is found
*/
- if (peer == 0) {
+ if (NULL == p) {
*action = MATCH_ASSOC(NO_PEER, pkt_mode);
- return ((struct peer *)0);
+ } else if (p->dstadr != rbufp->dstadr) {
+ set_peerdstadr(p, rbufp->dstadr);
+ if (p->dstadr == rbufp->dstadr) {
+ DPRINTF(1, ("Changed %s local address to match response\n",
+ stoa(&p->srcadr)));
+ return findpeer(rbufp, pkt_mode, action);
+ }
}
-
- set_peerdstadr(peer, dstadr);
-
- return (peer);
+ return p;
}
/*
@@ -275,18 +307,17 @@ findpeerbyassoc(
u_int assoc
)
{
- register struct peer *peer;
- int hash;
+ struct peer *p;
+ u_int hash;
assocpeer_calls++;
hash = assoc & NTP_HASH_MASK;
- for (peer = assoc_hash[hash]; peer != 0; peer =
- peer->ass_next) {
- if (assoc == peer->associd)
- return (peer);
+ for (p = assoc_hash[hash]; p != NULL; p = p->ass_next) {
+ if (assoc == p->associd)
+ return p;
}
- return (NULL);
+ return NULL;
}
@@ -306,9 +337,8 @@ clear_all(void)
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
- if (!(peer->cast_flags & (MDF_ACAST | MDF_MCAST |
- MDF_BCAST))) {
- peer->hpoll = peer->minpoll;
+ if (!(peer->cast_flags & (MDF_ACAST |
+ MDF_MCAST | MDF_BCAST))) {
peer_clear(peer, "STEP");
}
}
@@ -321,37 +351,93 @@ clear_all(void)
/*
- * unpeer - remove peer structure from hash table and free structure
+ * score_all() - determine if an association can be demobilized
*/
-void
-unpeer(
- struct peer *peer_to_remove
+int
+score_all(
+ struct peer *peer /* peer structure pointer */
)
{
- int hash;
-#ifdef OPENSSL
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
+ struct peer *speer, *next_peer;
+ int n;
+ int temp, tamp;
- if (peer_to_remove->flags & FLAG_SKEY) {
- sprintf(statstr, "unpeer %d flash %x reach %03o flags %04x",
- peer_to_remove->associd, peer_to_remove->flash,
- peer_to_remove->reach, peer_to_remove->flags);
- record_crypto_stats(&peer_to_remove->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("peer: %s\n", statstr);
-#endif
+ /*
+ * This routine finds the minimum score for all ephemeral
+ * assocations and returns > 0 if the association can be
+ * demobilized.
+ */
+ tamp = score(peer);
+ temp = 100;
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
+ for (speer = peer_hash[n]; speer != 0; speer =
+ next_peer) {
+ int x;
+
+ next_peer = speer->next;
+ if ((x = score(speer)) < temp && (peer->flags &
+ FLAG_PREEMPT))
+ temp = x;
+ }
}
-#endif /* OPENSSL */
#ifdef DEBUG
if (debug)
- printf("demobilize %u %d %d\n", peer_to_remove->associd,
- peer_associations, peer_preempt);
+ printf("score_all: at %lu score %d min %d\n",
+ current_time, tamp, temp);
#endif
- set_peerdstadr(peer_to_remove, NULL);
+ if (tamp != temp)
+ temp = 0;
+ return (temp);
+}
- /* XXXMEMLEAK? peer_clear->crypto allocation */
+/*
+ * score() - calculate preemption score
+ */
+static int
+score(
+ struct peer *peer /* peer structure pointer */
+ )
+{
+ int temp;
+
+ /*
+ * This routine calculates the premption score from the peer
+ * error bits and status. Increasing values are more cherished.
+ */
+ temp = 0;
+ if (!(peer->flash & TEST10))
+ temp++; /* 1 good synch and stratum */
+ if (!(peer->flash & TEST13))
+ temp++; /* 2 reachable */
+ if (!(peer->flash & TEST12))
+ temp++; /* 3 no loop */
+ if (!(peer->flash & TEST11))
+ temp++; /* 4 good distance */
+ if (peer->status >= CTL_PST_SEL_SELCAND)
+ temp++; /* 5 in the hunt */
+ if (peer->status != CTL_PST_SEL_EXCESS)
+ temp++; /* 6 not spare tire */
+ return (temp); /* selection status */
+}
+
+
+/*
+ * unpeer - remove peer structure from hash table and free structure
+ */
+void
+unpeer(
+ struct peer *peer_to_remove
+ )
+{
+ register struct peer *unlinked;
+ int hash;
+ char tbuf[80];
+
+ snprintf(tbuf, sizeof(tbuf), "assoc %d",
+ peer_to_remove->associd);
+ report_event(PEVNT_DEMOBIL, peer_to_remove, tbuf);
+ set_peerdstadr(peer_to_remove, NULL);
hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);
peer_hash_count[hash]--;
peer_demobilizations++;
@@ -366,22 +452,14 @@ unpeer(
refclock_unpeer(peer_to_remove);
#endif
peer_to_remove->action = 0; /* disable timeout actions */
- if (peer_hash[hash] == peer_to_remove)
- peer_hash[hash] = peer_to_remove->next;
- else {
- register struct peer *peer;
-
- peer = peer_hash[hash];
- while (peer != 0 && peer->next != peer_to_remove)
- peer = peer->next;
-
- if (peer == 0) {
- peer_hash_count[hash]++;
- msyslog(LOG_ERR, "peer struct for %s not in table!",
- stoa(&peer->srcadr));
- } else {
- peer->next = peer_to_remove->next;
- }
+
+ UNLINK_SLIST(unlinked, peer_hash[hash], peer_to_remove, next,
+ struct peer);
+
+ if (NULL == unlinked) {
+ peer_hash_count[hash]++;
+ msyslog(LOG_ERR, "peer struct for %s not in table!",
+ stoa(&peer_to_remove->srcadr));
}
/*
@@ -389,26 +467,18 @@ unpeer(
*/
hash = peer_to_remove->associd & NTP_HASH_MASK;
assoc_hash_count[hash]--;
- if (assoc_hash[hash] == peer_to_remove)
- assoc_hash[hash] = peer_to_remove->ass_next;
- else {
- register struct peer *peer;
-
- peer = assoc_hash[hash];
- while (peer != 0 && peer->ass_next != peer_to_remove)
- peer = peer->ass_next;
-
- if (peer == 0) {
- assoc_hash_count[hash]++;
- msyslog(LOG_ERR,
- "peer struct for %s not in association table!",
- stoa(&peer->srcadr));
- } else {
- peer->ass_next = peer_to_remove->ass_next;
- }
+
+ UNLINK_SLIST(unlinked, assoc_hash[hash], peer_to_remove,
+ ass_next, struct peer);
+
+ if (NULL == unlinked) {
+ assoc_hash_count[hash]++;
+ msyslog(LOG_ERR,
+ "peer struct for %s not in association table!",
+ stoa(&peer_to_remove->srcadr));
}
- peer_to_remove->next = peer_free;
- peer_free = peer_to_remove;
+
+ LINK_SLIST(peer_free, peer_to_remove, next);
peer_free_count++;
}
@@ -418,7 +488,7 @@ unpeer(
*/
struct peer *
peer_config(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *dstadr,
int hmode,
int version,
@@ -430,140 +500,79 @@ peer_config(
u_char *keystr
)
{
- register struct peer *peer;
u_char cast_flags;
/*
- * First search from the beginning for an association with given
- * remote address and mode. If an interface is given, search
- * from there to find the association which matches that
- * destination. If the given interface is "any", track down
- * the actual interface, because that's what gets put into the
- * peer structure.
- */
- peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
- if (dstadr != 0) {
- while (peer != 0) {
- if (peer->dstadr == dstadr)
- break;
- if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
- peer->dstadr == findinterface(srcadr))
- break;
- peer = findexistingpeer(srcadr, peer, hmode);
- }
- }
-
- /*
* We do a dirty little jig to figure the cast flags. This is
* probably not the best place to do this, at least until the
* configure code is rebuilt. Note only one flag can be set.
*/
switch (hmode) {
-
case MODE_BROADCAST:
- if(srcadr->ss_family == AF_INET) {
- if (IN_CLASSD(ntohl(((struct sockaddr_in*)srcadr)->sin_addr.s_addr)))
- cast_flags = MDF_MCAST;
- else
- cast_flags = MDF_BCAST;
- break;
- }
- else {
- if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)srcadr)->sin6_addr))
- cast_flags = MDF_MCAST;
- else
- cast_flags = MDF_BCAST;
- break;
- }
+ if (IS_MCAST(srcadr))
+ cast_flags = MDF_MCAST;
+ else
+ cast_flags = MDF_BCAST;
+ break;
case MODE_CLIENT:
- if(srcadr->ss_family == AF_INET) {
- if (IN_CLASSD(ntohl(((struct sockaddr_in*)srcadr)->sin_addr.s_addr)))
- cast_flags = MDF_ACAST;
- else
- cast_flags = MDF_UCAST;
- break;
- }
- else {
- if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)srcadr)->sin6_addr))
- cast_flags = MDF_ACAST;
- else
- cast_flags = MDF_UCAST;
- break;
- }
+ if (IS_MCAST(srcadr))
+ cast_flags = MDF_ACAST;
+ else
+ cast_flags = MDF_UCAST;
+ break;
default:
cast_flags = MDF_UCAST;
}
/*
- * If the peer is already configured, some dope has a duplicate
- * configureation entry or another dope is wiggling from afar.
- */
- if (peer != 0) {
- peer->hmode = (u_char)hmode;
- peer->version = (u_char) version;
- peer->minpoll = (u_char) minpoll;
- peer->maxpoll = (u_char) maxpoll;
- peer->flags = flags | FLAG_CONFIG |
- (peer->flags & FLAG_REFCLOCK);
- peer->cast_flags = cast_flags;
- peer->ttl = (u_char) ttl;
- peer->keyid = key;
- peer->precision = sys_precision;
- peer_clear(peer, "RMOT");
- return (peer);
- }
-
- /*
- * Here no match has been found, so presumably this is a new
- * persistent association. Mobilize the thing and initialize its
- * variables. If emulating ntpdate, force iburst.
+ * Mobilize the association and initialize its variables. If
+ * emulating ntpdate, force iburst.
*/
if (mode_ntpdate)
flags |= FLAG_IBURST;
- peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
- flags | FLAG_CONFIG, cast_flags, ttl, key);
- return (peer);
+ return(newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
+ flags | FLAG_CONFIG, cast_flags, ttl, key));
}
/*
- * setup peer dstadr field keeping it in sync with the interface structures
+ * setup peer dstadr field keeping it in sync with the interface
+ * structures
*/
void
-set_peerdstadr(struct peer *peer, struct interface *interface)
+set_peerdstadr(
+ struct peer * p,
+ endpt * dstadr
+ )
{
- if (peer->dstadr != interface) {
- if (interface != NULL &&
- (peer->cast_flags & MDF_BCLNT) &&
- (interface->flags & INT_MCASTIF) &&
- peer->burst) {
- /*
- * don't accept updates to a true multicast reception
- * interface while a BCLNT peer is running it's
- * unicast protocol
- */
- return;
- }
+ struct peer * unlinked;
- if (peer->dstadr != NULL)
- {
- peer->dstadr->peercnt--;
- ISC_LIST_UNLINK_TYPE(peer->dstadr->peers, peer, ilink, struct peer);
- }
-
- DPRINTF(4, ("set_peerdstadr(%s): change interface from %s to %s\n",
- stoa(&peer->srcadr),
- (peer->dstadr != NULL) ? stoa(&peer->dstadr->sin) : "<null>",
- (interface != NULL) ? stoa(&interface->sin) : "<null>"));
-
- peer->dstadr = interface;
+ if (p->dstadr == dstadr)
+ return;
- if (peer->dstadr != NULL)
- {
- ISC_LIST_APPEND(peer->dstadr->peers, peer, ilink);
- peer->dstadr->peercnt++;
- }
+ /*
+ * Don't accept updates to a separate multicast receive-only
+ * endpt while a BCLNT peer is running its unicast protocol.
+ */
+ if (dstadr != NULL && (FLAG_BC_VOL & p->flags) &&
+ (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) {
+ return;
+ }
+ if (p->dstadr != NULL) {
+ p->dstadr->peercnt--;
+ UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
+ struct peer);
+ msyslog(LOG_INFO, "%s interface %s -> %s",
+ stoa(&p->srcadr), stoa(&p->dstadr->sin),
+ (dstadr != NULL)
+ ? stoa(&dstadr->sin)
+ : "(none)");
+ }
+ p->dstadr = dstadr;
+ if (dstadr != NULL) {
+ LINK_SLIST(dstadr->peers, p, ilink);
+ dstadr->peercnt++;
}
}
@@ -571,57 +580,46 @@ set_peerdstadr(struct peer *peer, struct interface *interface)
* attempt to re-rebind interface if necessary
*/
static void
-peer_refresh_interface(struct peer *peer)
+peer_refresh_interface(
+ struct peer *peer
+ )
{
- struct interface *niface, *piface;
-
- niface = select_peerinterface(peer, &peer->srcadr, NULL, peer->cast_flags);
-
-#ifdef DEBUG
- if (debug > 3)
- {
- printf(
- "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
- peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
- stoa(&peer->srcadr),
- peer->hmode, peer->version, peer->minpoll,
- peer->maxpoll, peer->flags, peer->cast_flags,
- peer->ttl, peer->keyid);
- if (niface != NULL)
- {
- printf("fd=%d, bfd=%d, name=%.16s, flags=0x%x, scope=%d, ",
- niface->fd,
- niface->bfd,
- niface->name,
- niface->flags,
- niface->scopeid);
- /* Leave these as three printf calls. */
- printf(", sin=%s",
- stoa((&niface->sin)));
- if (niface->flags & INT_BROADCAST)
- printf(", bcast=%s,",
- stoa((&niface->bcast)));
- printf(", mask=%s\n",
- stoa((&niface->mask)));
- }
- else
- {
- printf("<NONE>\n");
- }
+ endpt * niface;
+ endpt * piface;
+
+ niface = select_peerinterface(peer, &peer->srcadr, NULL,
+ peer->cast_flags);
+
+ DPRINTF(4, (
+ "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
+ peer->dstadr == NULL ? "<null>" :
+ stoa(&peer->dstadr->sin), stoa(&peer->srcadr),
+ peer->hmode, peer->version, peer->minpoll,
+ peer->maxpoll, peer->flags, peer->cast_flags,
+ peer->ttl, peer->keyid));
+ if (niface != NULL) {
+ DPRINTF(4, (
+ "fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s",
+ niface->fd, niface->bfd, niface->name,
+ niface->flags, niface->ifindex,
+ stoa(&niface->sin)));
+ if (niface->flags & INT_BROADCAST)
+ DPRINTF(4, (", bcast=%s",
+ stoa(&niface->bcast)));
+ DPRINTF(4, (", mask=%s\n", stoa(&niface->mask)));
+ } else {
+ DPRINTF(4, ("<NONE>\n"));
}
-#endif
piface = peer->dstadr;
-
set_peerdstadr(peer, niface);
-
if (peer->dstadr) {
- /*
- * clear crypto if we change the local address
- */
- if (peer->dstadr != piface && !(peer->cast_flags & MDF_BCLNT)) {
- peer_crypto_clear(peer);
- }
+ /*
+ * clear crypto if we change the local address
+ */
+ if (peer->dstadr != piface && !(peer->cast_flags &
+ MDF_ACAST) && peer->pmode != MODE_BROADCAST)
+ peer_clear(peer, "XFAC");
/*
* Broadcast needs the socket enabled for broadcast
@@ -631,16 +629,19 @@ peer_refresh_interface(struct peer *peer)
}
/*
- * Multicast needs the socket interface enabled for multicast
+ * Multicast needs the socket interface enabled for
+ * multicast
*/
if (peer->cast_flags & MDF_MCAST) {
- enable_multicast_if(peer->dstadr, &peer->srcadr);
+ enable_multicast_if(peer->dstadr,
+ &peer->srcadr);
}
}
}
/*
- * refresh_all_peerinterfaces - see that all interface bindings are up to date
+ * refresh_all_peerinterfaces - see that all interface bindings are up
+ * to date
*/
void
refresh_all_peerinterfaces(void)
@@ -664,11 +665,19 @@ refresh_all_peerinterfaces(void)
/*
* find an interface suitable for the src address
*/
-static struct interface *
-select_peerinterface(struct peer *peer, struct sockaddr_storage *srcadr, struct interface *dstadr, u_char cast_flags)
+static endpt *
+select_peerinterface(
+ struct peer * peer,
+ sockaddr_u * srcadr,
+ endpt * dstadr,
+ u_char cast_flags
+ )
{
- struct interface *interface;
-
+ endpt *ep;
+ endpt *wild;
+
+ wild = ANY_INTERFACE_CHOOSE(srcadr);
+
/*
* Initialize the peer structure and dance the interface jig.
* Reference clocks step the loopback waltz, the others
@@ -677,46 +686,40 @@ select_peerinterface(struct peer *peer, struct sockaddr_storage *srcadr, struct
* This might happen in some systems and would preclude proper
* operation with public key cryptography.
*/
- if (ISREFCLOCKADR(srcadr))
- interface = loopback_interface;
- else
- if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
- interface = findbcastinter(srcadr);
-#ifdef DEBUG
- if (debug > 3) {
- if (interface != NULL)
- printf("Found *-cast interface address %s, for address %s\n",
- stoa(&(interface)->sin), stoa(srcadr));
- else
- printf("No *-cast local address found for address %s\n",
- stoa(srcadr));
- }
-#endif
- /*
- * If it was a multicast packet, findbcastinter() may not
- * find it, so try a little harder.
- */
- if (interface == ANY_INTERFACE_CHOOSE(srcadr))
- interface = findinterface(srcadr);
- }
- else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr))
- interface = dstadr;
+ if (ISREFCLOCKADR(srcadr)) {
+ ep = loopback_interface;
+ } else if (cast_flags &
+ (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
+ ep = findbcastinter(srcadr);
+ if (ep != NULL)
+ DPRINTF(4, ("Found *-cast interface %s for address %s\n",
+ stoa(&ep->sin), stoa(srcadr)));
else
- interface = findinterface(srcadr);
-
+ DPRINTF(4, ("No *-cast local address found for address %s\n",
+ stoa(srcadr)));
+ } else {
+ ep = dstadr;
+ if (NULL == ep)
+ ep = wild;
+ }
+ /*
+ * If it is a multicast address, findbcastinter() may not find
+ * it. For unicast, we get to find the interface when dstadr is
+ * given to us as the wildcard (ANY_INTERFACE_CHOOSE). Either
+ * way, try a little harder.
+ */
+ if (wild == ep)
+ ep = findinterface(srcadr);
/*
* we do not bind to the wildcard interfaces for output
* as our (network) source address would be undefined and
* crypto will not work without knowing the own transmit address
*/
- if (interface != NULL && interface->flags & INT_WILDCARD)
-#ifdef SYS_WINNT
- if ( !accept_wildcard_if_for_winnt )
-#endif
- interface = NULL;
+ if (ep != NULL && INT_WILDCARD & ep->flags)
+ if (!accept_wildcard_if_for_winnt)
+ ep = NULL;
-
- return interface;
+ return ep;
}
/*
@@ -724,37 +727,86 @@ select_peerinterface(struct peer *peer, struct sockaddr_storage *srcadr, struct
*/
struct peer *
newpeer(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *dstadr,
- int hmode,
- int version,
- int minpoll,
- int maxpoll,
- u_int flags,
- u_char cast_flags,
- int ttl,
- keyid_t key
+ int hmode,
+ int version,
+ int minpoll,
+ int maxpoll,
+ u_int flags,
+ u_char cast_flags,
+ int ttl,
+ keyid_t key
)
{
- register struct peer *peer;
- register int i;
+ struct peer *peer;
+ u_int hash;
+ char tbuf[80];
+
#ifdef OPENSSL
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
+ /*
+ * If Autokey is requested but not configured, complain loudly.
+ */
+ if (!crypto_flags) {
+ if (key > NTP_MAXKEY) {
+ return (NULL);
+
+ } else if (flags & FLAG_SKEY) {
+ msyslog(LOG_ERR, "Autokey not configured");
+ return (NULL);
+ }
+ }
#endif /* OPENSSL */
/*
+ * 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. If the given interface is "any", track down the
+ * actual interface, because that's what gets put into the peer
+ * structure.
+ */
+ if (dstadr != NULL) {
+ peer = findexistingpeer(srcadr, NULL, hmode, cast_flags);
+ while (peer != NULL) {
+ if (peer->dstadr == dstadr ||
+ ((MDF_BCLNT & cast_flags) &&
+ (MDF_BCLNT & peer->cast_flags)))
+ break;
+
+ if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
+ peer->dstadr == findinterface(srcadr))
+ break;
+
+ peer = findexistingpeer(srcadr, peer, hmode,
+ cast_flags);
+ }
+ } else {
+ /* no endpt address given */
+ peer = findexistingpeer(srcadr, NULL, hmode, cast_flags);
+ }
+
+ /*
+ * If a peer is found, this would be a duplicate and we don't
+ * allow that. This avoids duplicate ephemeral (broadcast/
+ * multicast) and preemptible (manycast and pool) client
+ * associations.
+ */
+ if (peer != NULL)
+ return (NULL);
+
+ /*
* Allocate a new peer structure. Some dirt here, since some of
* the initialization requires knowlege of our system state.
*/
if (peer_free_count == 0)
getmorepeermem();
- peer = peer_free;
- peer_free = peer->next;
+ UNLINK_HEAD_SLIST(peer, peer_free, next);
peer_free_count--;
peer_associations++;
if (flags & FLAG_PREEMPT)
peer_preempt++;
- memset((char *)peer, 0, sizeof(struct peer));
+ memset(peer, 0, sizeof(*peer));
/*
* Assign an association ID and increment the system variable.
@@ -766,42 +818,53 @@ newpeer(
DPRINTF(3, ("newpeer: cast flags: 0x%x for address: %s\n",
cast_flags, stoa(srcadr)));
- ISC_LINK_INIT(peer, ilink); /* set up interface link chain */
peer->srcadr = *srcadr;
set_peerdstadr(peer, select_peerinterface(peer, srcadr, dstadr,
cast_flags));
peer->hmode = (u_char)hmode;
peer->version = (u_char)version;
- peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
- peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
peer->flags = flags;
-#ifdef DEBUG
- if (debug > 2) {
- if (peer->dstadr)
- printf("newpeer: using fd %d and our addr %s\n",
- peer->dstadr->fd,
- stoa(&peer->dstadr->sin));
- else
- printf("newpeer: local interface currently not bound\n");
- }
-#endif
+
+ /*
+ * It is an error to set minpoll less than NTP_MINPOLL or to
+ * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
+ * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
+ * not less than NTP_MINPOLL without complaint. Finally,
+ * minpoll is clamped not greater than maxpoll.
+ */
+ if (minpoll == 0)
+ peer->minpoll = NTP_MINDPOLL;
+ else
+ peer->minpoll = (u_char)min(minpoll, NTP_MAXPOLL);
+ if (maxpoll == 0)
+ peer->maxpoll = NTP_MAXDPOLL;
+ else
+ peer->maxpoll = (u_char)max(maxpoll, NTP_MINPOLL);
+ if (peer->minpoll > peer->maxpoll)
+ peer->minpoll = peer->maxpoll;
+
+ if (peer->dstadr)
+ DPRINTF(3, ("newpeer: using fd %d and our addr %s\n",
+ peer->dstadr->fd, stoa(&peer->dstadr->sin)));
+ else
+ DPRINTF(3, ("newpeer: local interface currently not bound\n"));
/*
* Broadcast needs the socket enabled for broadcast
*/
- if (cast_flags & MDF_BCAST && peer->dstadr) {
+ if ((cast_flags & MDF_BCAST) && peer->dstadr)
enable_broadcast(peer->dstadr, srcadr);
- }
+
/*
* Multicast needs the socket interface enabled for multicast
*/
- if (cast_flags & MDF_MCAST && peer->dstadr) {
+ if ((cast_flags & MDF_MCAST) && peer->dstadr)
enable_multicast_if(peer->dstadr, srcadr);
- }
- if (key != 0)
- peer->flags |= FLAG_AUTHENABLE;
+
+#ifdef OPENSSL
if (key > NTP_MAXKEY)
peer->flags |= FLAG_SKEY;
+#endif /* OPENSSL */
peer->cast_flags = cast_flags;
peer->ttl = (u_char)ttl;
peer->keyid = key;
@@ -834,14 +897,14 @@ newpeer(
* the peer timer, since the clock may have requirements
* for this.
*/
+ if (maxpoll == 0)
+ peer->maxpoll = peer->minpoll;
if (!refclock_newpeer(peer)) {
/*
* Dump it, something screwed up
*/
set_peerdstadr(peer, NULL);
-
- peer->next = peer_free;
- peer_free = peer;
+ LINK_SLIST(peer_free, peer, next);
peer_free_count++;
return (NULL);
}
@@ -851,79 +914,25 @@ newpeer(
/*
* Put the new peer in the hash tables.
*/
- i = NTP_HASH_ADDR(&peer->srcadr);
- peer->next = peer_hash[i];
- peer_hash[i] = peer;
- peer_hash_count[i]++;
- i = peer->associd & NTP_HASH_MASK;
- peer->ass_next = assoc_hash[i];
- assoc_hash[i] = peer;
- assoc_hash_count[i]++;
-
-#ifdef OPENSSL
- if (peer->flags & FLAG_SKEY) {
- sprintf(statstr, "newpeer %d", peer->associd);
- record_crypto_stats(&peer->srcadr, statstr);
- DPRINTF(1, ("peer: %s\n", statstr));
- }
-#endif /* OPENSSL */
-
+ hash = NTP_HASH_ADDR(&peer->srcadr);
+ LINK_SLIST(peer_hash[hash], peer, next);
+ peer_hash_count[hash]++;
+ hash = peer->associd & NTP_HASH_MASK;
+ LINK_SLIST(assoc_hash[hash], peer, ass_next);
+ assoc_hash_count[hash]++;
+ snprintf(tbuf, sizeof(tbuf), "assoc %d", peer->associd);
+ report_event(PEVNT_MOBIL, peer, tbuf);
DPRINTF(1, ("newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n",
- peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
- stoa(&peer->srcadr),
- peer->hmode, peer->version, peer->minpoll,
- peer->maxpoll, peer->flags, peer->cast_flags,
- peer->ttl, peer->keyid));
-
+ peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
+ stoa(&peer->srcadr), peer->hmode, peer->version,
+ peer->minpoll, peer->maxpoll, peer->flags, peer->cast_flags,
+ peer->ttl, peer->keyid));
return (peer);
}
/*
- * peer_unconfig - remove the configuration bit from a peer
- */
-int
-peer_unconfig(
- struct sockaddr_storage *srcadr,
- struct interface *dstadr,
- int mode
- )
-{
- register struct peer *peer;
- int num_found;
-
- num_found = 0;
- peer = findexistingpeer(srcadr, (struct peer *)0, mode);
- while (peer != 0) {
- if (peer->flags & FLAG_CONFIG
- && (dstadr == 0 || peer->dstadr == dstadr)) {
- num_found++;
-
- /*
- * Tricky stuff here. If the peer is polling us
- * in active mode, turn off the configuration
- * bit and make the mode passive. This allows us
- * to avoid dumping a lot of history for peers
- * we might choose to keep track of in passive
- * mode. The protocol will eventually terminate
- * undesirables on its own.
- */
- if (peer->hmode == MODE_ACTIVE
- && peer->pmode == MODE_ACTIVE) {
- peer->hmode = MODE_PASSIVE;
- peer->flags &= ~FLAG_CONFIG;
- } else {
- unpeer(peer);
- peer = 0;
- }
- }
- peer = findexistingpeer(srcadr, peer, mode);
- }
- return (num_found);
-}
-
-/*
- * peer_clr_stats - clear peer module stat counters
+ * peer_clr_stats - clear peer module statiistics counters
*/
void
peer_clr_stats(void)
@@ -936,15 +945,17 @@ peer_clr_stats(void)
}
/*
- * peer_reset - reset stat counters in a peer structure
+ * peer_reset - reset statistics counters
*/
void
peer_reset(
struct peer *peer
)
{
- if (peer == 0)
- return;
+ if (peer == NULL)
+ return;
+
+ peer->timereset = current_time;
peer->sent = 0;
peer->received = 0;
peer->processed = 0;
@@ -952,12 +963,12 @@ peer_reset(
peer->bogusorg = 0;
peer->oldpkt = 0;
peer->seldisptoolarge = 0;
- peer->timereset = current_time;
+ peer->selbroken = 0;
}
/*
- * peer_all_reset - reset all peer stat counters
+ * peer_all_reset - reset all peer statistics counters
*/
void
peer_all_reset(void)
@@ -971,54 +982,12 @@ peer_all_reset(void)
}
-#ifdef OPENSSL
-/*
- * expire_all - flush all crypto data and update timestamps.
- */
-void
-expire_all(void)
-{
- struct peer *peer, *next_peer;
- int n;
-
- /*
- * This routine is called about once per day from the timer
- * routine and when the client is first synchronized. Search the
- * peer list for all associations and flush only the key list
- * and cookie. If a manycast client association, flush
- * everything. Then, recompute and sign the agreement public
- * value, if present.
- */
- if (!crypto_flags)
- return;
-
- for (n = 0; n < NTP_HASH_SIZE; n++) {
- for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
- next_peer = peer->next;
- if (!(peer->flags & FLAG_SKEY)) {
- continue;
-
- } else if (peer->hmode == MODE_ACTIVE ||
- peer->hmode == MODE_PASSIVE) {
- key_expire(peer);
- peer->crypto &= ~(CRYPTO_FLAG_AUTO |
- CRYPTO_FLAG_AGREE);
- }
-
- }
- }
- RAND_bytes((u_char *)&sys_private, 4);
- crypto_update();
-}
-#endif /* OPENSSL */
-
-
/*
* findmanycastpeer - find and return a manycast peer
*/
struct peer *
findmanycastpeer(
- struct recvbuf *rbufp
+ struct recvbuf *rbufp /* receive buffer pointer */
)
{
register struct peer *peer;
@@ -1042,7 +1011,7 @@ findmanycastpeer(
peer->next) {
if (peer->cast_flags & MDF_ACAST) {
NTOHL_FP(&pkt->org, &p_org);
- if (L_ISEQU(&peer->xmt, &p_org))
+ if (L_ISEQU(&p_org, &peer->aorg))
return (peer);
}
}
diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c
index 0ab249883010..03e3593b9435 100644
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -15,15 +15,16 @@
#include "ntp_string.h"
#include <stdio.h>
+#ifdef HAVE_LIBSCF_H
+#include <libscf.h>
+#include <unistd.h>
+#endif /* HAVE_LIBSCF_H */
+
#if defined(VMS) && defined(VMS_LOCALUNIT) /*wjm*/
#include "ntp_refclock.h"
#endif
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-#include <sys/sysctl.h>
-#endif
-
/*
* This macro defines the authentication state. If x is 1 authentication
* is required; othewise it is optional.
@@ -31,49 +32,62 @@
#define AUTH(x, y) ((x) ? (y) == AUTH_OK : (y) == AUTH_OK || \
(y) == AUTH_NONE)
+#define AUTH_NONE 0 /* authentication not required */
+#define AUTH_OK 1 /* authentication OK */
+#define AUTH_ERROR 2 /* authentication error */
+#define AUTH_CRYPTO 3 /* crypto_NAK */
+
+/*
+ * traffic shaping parameters
+ */
+#define NTP_IBURST 6 /* packets in iburst */
+#define RESP_DELAY 1 /* refclock burst delay (s) */
+
/*
- * System variables are declared here. See Section 3.2 of the
- * specification.
+ * System variables are declared here. Unless specified otherwise, all
+ * times are in seconds.
*/
u_char sys_leap; /* system leap indicator */
-u_char sys_stratum; /* stratum of system */
+u_char sys_stratum; /* system stratum */
s_char sys_precision; /* local clock precision (log2 s) */
double sys_rootdelay; /* roundtrip delay to primary source */
-double sys_rootdispersion; /* dispersion to primary source */
-u_int32 sys_refid; /* source/loop in network byte order */
-static double sys_offset; /* current local clock offset */
-l_fp sys_reftime; /* time we were last updated */
-struct peer *sys_peer; /* our current peer */
-struct peer *sys_pps; /* our PPS peer */
-struct peer *sys_prefer; /* our cherished peer */
-int sys_kod; /* kod credit */
-int sys_kod_rate = 2; /* max kod packets per second */
-#ifdef OPENSSL
-u_long sys_automax; /* maximum session key lifetime */
-#endif /* OPENSSL */
+double sys_rootdisp; /* dispersion to primary source */
+u_int32 sys_refid; /* reference id (network byte order) */
+l_fp sys_reftime; /* last update time */
+struct peer *sys_peer; /* current peer */
/*
- * Nonspecified system state variables.
+ * Rate controls. Leaky buckets are used to throttle the packet
+ * transmission rates in order to protect busy servers such as at NIST
+ * and USNO. There is a counter for each association and another for KoD
+ * packets. The association counter decrements each second, but not
+ * below zero. Each time a packet is sent the counter is incremented by
+ * a configurable value representing the average interval between
+ * packets. A packet is delayed as long as the counter is greater than
+ * zero. Note this does not affect the time value computations.
+ */
+/*
+ * Nonspecified system state variables
*/
int sys_bclient; /* broadcast client enable */
double sys_bdelay; /* broadcast client default delay */
-int sys_calldelay; /* modem callup delay (s) */
int sys_authenticate; /* requre authentication for config */
l_fp sys_authdelay; /* authentication delay */
-static u_long sys_authdly[2]; /* authentication delay shift reg */
-static double sys_mindisp = MINDISPERSE; /* min disp increment (s) */
-static double sys_maxdist = MAXDISTANCE; /* selection threshold (s) */
-double sys_jitter; /* system jitter (s) */
-static int sys_hopper; /* anticlockhop counter */
-static int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */
-int leap_next; /* leap consensus */
+double sys_offset; /* current local clock offset */
+double sys_mindisp = MINDISPERSE; /* minimum distance (s) */
+double sys_maxdist = MAXDISTANCE; /* selection threshold */
+double sys_jitter; /* system jitter */
+u_long sys_epoch; /* last clock update time */
+static double sys_clockhop; /* clockhop threshold */
+int leap_tai; /* TAI at next next leap */
+u_long leap_sec; /* next scheduled leap from file */
+u_long leap_peers; /* next scheduled leap from peers */
+u_long leap_expire; /* leap information expiration */
+static int leap_vote; /* leap consensus */
keyid_t sys_private; /* private value for session seed */
int sys_manycastserver; /* respond to manycast client pkts */
int peer_ntpdate; /* active peers in ntpdate mode */
int sys_survivors; /* truest of the truechimers */
-#ifdef OPENSSL
-char *sys_hostname; /* gethostname() name */
-#endif /* OPENSSL */
/*
* TOS and multicast mapping stuff
@@ -81,42 +95,42 @@ char *sys_hostname; /* gethostname() name */
int sys_floor = 0; /* cluster stratum floor */
int sys_ceiling = STRATUM_UNSPEC; /* cluster stratum ceiling */
int sys_minsane = 1; /* minimum candidates */
-int sys_minclock = NTP_MINCLOCK; /* minimum survivors */
+int sys_minclock = NTP_MINCLOCK; /* minimum candidates */
int sys_maxclock = NTP_MAXCLOCK; /* maximum candidates */
int sys_cohort = 0; /* cohort switch */
int sys_orphan = STRATUM_UNSPEC + 1; /* orphan stratum */
-double sys_orphandelay = 0; /* orphan root delay */
int sys_beacon = BEACON; /* manycast beacon interval */
int sys_ttlmax; /* max ttl mapping vector index */
u_char sys_ttl[MAX_TTL]; /* ttl mapping vector */
/*
- * Statistics counters
+ * Statistics counters - first the good, then the bad
*/
-u_long sys_stattime; /* time since reset */
+u_long sys_stattime; /* elapsed time */
u_long sys_received; /* packets received */
-u_long sys_processed; /* packets processed */
-u_long sys_newversionpkt; /* current version */
-u_long sys_oldversionpkt; /* recent version */
-u_long sys_unknownversion; /* invalid version */
+u_long sys_processed; /* packets for this host */
+u_long sys_newversion; /* current version */
+u_long sys_oldversion; /* old version */
u_long sys_restricted; /* access denied */
u_long sys_badlength; /* bad length or format */
u_long sys_badauth; /* bad authentication */
+u_long sys_declined; /* declined */
u_long sys_limitrejected; /* rate exceeded */
+u_long sys_kodsent; /* KoD sent */
-static double root_distance P((struct peer *));
-static void clock_combine P((struct peer **, int));
-static void peer_xmit P((struct peer *));
-static void fast_xmit P((struct recvbuf *, int, keyid_t,
- int));
-static void clock_update P((void));
-static int default_get_precision P((void));
-static int peer_unfit P((struct peer *));
+static double root_distance (struct peer *);
+static void clock_combine (struct peer **, int);
+static void peer_xmit (struct peer *);
+static void fast_xmit (struct recvbuf *, int, keyid_t,
+ int);
+static void clock_update (struct peer *);
+static int default_get_precision (void);
+static int local_refid (struct peer *);
+static int peer_unfit (struct peer *);
/*
- * transmit - Transmit Procedure. See Section 3.4.2 of the
- * specification.
+ * transmit - transmit procedure called by poll timeout
*/
void
transmit(
@@ -131,24 +145,7 @@ transmit(
* server modes) and those that do (all other modes). The dance
* is intricate...
*/
- /*
- * Orphan mode is active when enabled and when no servers less
- * than the orphan statum are available. In this mode packets
- * are sent at the orphan stratum. An orphan with no other
- * synchronization source is an orphan parent. It assumes root
- * delay zero and reference ID the loopback address. All others
- * are orphan children with root delay randomized over a 1-s
- * range. The root delay is used by the election algorithm to
- * select the order of synchronization.
- */
hpoll = peer->hpoll;
- if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) {
- sys_leap = LEAP_NOWARNING;
- sys_stratum = sys_orphan;
- sys_refid = htonl(LOOPBACKADR);
- sys_rootdelay = 0;
- sys_rootdispersion = 0;
- }
/*
* In broadcast mode the poll interval is never changed from
@@ -156,7 +153,8 @@ transmit(
*/
if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
peer->outdate = current_time;
- peer_xmit(peer);
+ if (sys_leap != LEAP_NOTINSYNC)
+ peer_xmit(peer);
poll_update(peer, hpoll);
return;
}
@@ -177,7 +175,7 @@ transmit(
peer->ttl = 0;
peer_xmit(peer);
} else if (sys_survivors < sys_minclock ||
- peer_preempt < sys_maxclock) {
+ peer_associations < sys_maxclock) {
if (peer->ttl < sys_ttlmax)
peer->ttl++;
peer_xmit(peer);
@@ -202,96 +200,63 @@ transmit(
*/
oreach = peer->reach;
peer->outdate = current_time;
- if (peer == sys_peer)
- sys_hopper++;
+ peer->unreach++;
peer->reach <<= 1;
- if (!(peer->reach & 0x07))
+ if (!(peer->reach & 0x0f))
clock_filter(peer, 0., 0., MAXDISPERSE);
if (!peer->reach) {
/*
* Here the peer is unreachable. If it was
- * previously reachable, raise a trap.
+ * previously reachable raise a trap. Send a
+ * burst if enabled.
*/
- if (oreach) {
- report_event(EVNT_UNREACH, peer);
- peer->timereachable = current_time;
- }
-
- /*
- * Send a burst if enabled, but only once after
- * a peer becomes unreachable. If the prempt
- * flag is dim, bump the unreach counter by one;
- * otherwise, bump it by three.
- */
- if (peer->flags & FLAG_IBURST &&
- peer->unreach == 0) {
- peer->burst = NTP_BURST;
- }
- if (!(peer->flags & FLAG_PREEMPT))
- peer->unreach++;
- else
- peer->unreach += 3;
+ if (oreach)
+ report_event(PEVNT_UNREACH, peer, NULL);
+ if ((peer->flags & FLAG_IBURST) &&
+ peer->retry == 0)
+ peer->retry = NTP_RETRY;
} else {
/*
- * Here the peer is reachable. Set the poll
- * interval to the system poll interval. Send a
- * burst only if enabled and the peer is fit.
- *
- * Respond to the peer evaluation produced by
- * the selection algorithm. If less than the
- * outlyer level, up the unreach by three. If
- * there are excess associations, up the unreach
- * by two if not a candidate and by one if so.
+ * Here the peer is reachable. Send a burst if
+ * enabled and the peer is fit.
*/
- if (!(peer->flags & FLAG_PREEMPT)) {
- peer->unreach = 0;
- } else if (peer->status < CTL_PST_SEL_SELCAND) {
- peer->unreach += 3;
- } else if (peer_preempt > sys_maxclock) {
- if (peer->status < CTL_PST_SEL_SYNCCAND)
- peer->unreach += 2;
- else
- peer->unreach++;
- } else {
- peer->unreach = 0;
- }
hpoll = sys_poll;
- if (peer->flags & FLAG_BURST &&
- !peer_unfit(peer))
- peer->burst = NTP_BURST;
+ if (!(peer->flags & FLAG_PREEMPT &&
+ peer->hmode == MODE_CLIENT))
+ peer->unreach = 0;
+ if ((peer->flags & FLAG_BURST) && peer->retry ==
+ 0 && !peer_unfit(peer))
+ peer->retry = NTP_RETRY;
}
/*
- * Watch for timeout. If ephemeral or preemptable, toss
- * the rascal; otherwise, bump the poll interval.
+ * Watch for timeout. If preemptable, toss the rascal;
+ * otherwise, bump the poll interval. Note the
+ * poll_update() routine will clamp it to maxpoll.
*/
if (peer->unreach >= NTP_UNREACH) {
- if (peer->flags & FLAG_PREEMPT ||
- !(peer->flags & FLAG_CONFIG)) {
- peer_clear(peer, "TIME");
- unpeer(peer);
- return;
- } else {
- hpoll++;
+ hpoll++;
+ if (peer->flags & FLAG_PREEMPT) {
+ report_event(PEVNT_RESTART, peer,
+ "timeout");
+ if (peer->hmode != MODE_CLIENT) {
+ peer_clear(peer, "TIME");
+ unpeer(peer);
+ return;
+ }
+ if (peer_associations > sys_maxclock &&
+ score_all(peer)) {
+ peer_clear(peer, "TIME");
+ unpeer(peer);
+ return;
+ }
}
}
} else {
peer->burst--;
-
- /*
- * If a broadcast client at this point, the burst has
- * concluded, so we switch to client mode and purge the
- * keylist, since no further transmissions will be made.
- */
if (peer->burst == 0) {
- if (peer->cast_flags & MDF_BCLNT) {
- peer->hmode = MODE_BCLIENT;
-#ifdef OPENSSL
- key_expire(peer);
-#endif /* OPENSSL */
- }
/*
* If ntpdate mode and the clock has not been
@@ -302,12 +267,16 @@ transmit(
peer_ntpdate--;
if (peer_ntpdate == 0) {
msyslog(LOG_NOTICE,
- "no reply; clock not set");
+ "ntpd: no servers found");
+ printf(
+ "ntpd: no servers found\n");
exit (0);
}
}
}
}
+ if (peer->retry > 0)
+ peer->retry--;
/*
* Do not transmit if in broadcast client mode.
@@ -319,7 +288,7 @@ transmit(
/*
- * receive - Receive Procedure. See section 3.4.3 in the specification.
+ * receive - receive procedure called for each packet received
*/
void
receive(
@@ -336,42 +305,40 @@ receive(
int has_mac; /* length of MAC field */
int authlen; /* offset of MAC field */
int is_authentic = 0; /* cryptosum ok */
- keyid_t skeyid = 0; /* key ID */
- struct sockaddr_storage *dstadr_sin; /* active runway */
+ int retcode = AM_NOMATCH; /* match code */
+ keyid_t skeyid = 0; /* key IDs */
+ u_int32 opcode = 0; /* extension field opcode */
+ sockaddr_u *dstadr_sin; /* active runway */
struct peer *peer2; /* aux peer structure pointer */
+ endpt * match_ep; /* newpeer() local address */
l_fp p_org; /* origin timestamp */
l_fp p_rec; /* receive timestamp */
l_fp p_xmt; /* transmit timestamp */
#ifdef OPENSSL
- keyid_t tkeyid = 0; /* temporary key ID */
- keyid_t pkeyid = 0; /* previous key ID */
struct autokey *ap; /* autokey structure pointer */
int rval; /* cookie snatcher */
+ keyid_t pkeyid = 0, tkeyid = 0; /* key IDs */
#endif /* OPENSSL */
- int retcode = AM_NOMATCH;
- int at_listhead;
+#ifdef HAVE_NTP_SIGND
+ static unsigned char zero_key[16];
+#endif /* HAVE_NTP_SIGND */
/*
* 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.
+ * by the service routines. Some restrictions have to be handled
+ * later in order to generate a kiss-o'-death packet.
*/
/*
* Bogus port check is before anything, since it probably
* reveals a clogging attack.
*/
sys_received++;
- if (SRCPORT(&rbufp->recv_srcadr) == 0) {
+ if (SRCPORT(&rbufp->recv_srcadr) < NTP_PORT) {
sys_badlength++;
return; /* bogus port */
}
- at_listhead = ntp_monitor(rbufp);
- restrict_mask = restrictions(&rbufp->recv_srcadr, at_listhead);
+ restrict_mask = restrictions(&rbufp->recv_srcadr);
#ifdef DEBUG
if (debug > 1)
printf("receive: at %ld %s<-%s flags %x restrict %03x\n",
@@ -379,15 +346,15 @@ receive(
stoa(&rbufp->recv_srcadr),
rbufp->dstadr->flags, restrict_mask);
#endif
- if (restrict_mask & RES_IGNORE) {
- sys_restricted++;
- return; /* ignore everything */
- }
pkt = &rbufp->recv_pkt;
hisversion = PKT_VERSION(pkt->li_vn_mode);
hisleap = PKT_LEAP(pkt->li_vn_mode);
hismode = (int)PKT_MODE(pkt->li_vn_mode);
hisstratum = PKT_TO_STRATUM(pkt->stratum);
+ if (restrict_mask & RES_IGNORE) {
+ sys_restricted++;
+ return; /* ignore everything */
+ }
if (hismode == MODE_PRIVATE) {
if (restrict_mask & RES_NOQUERY) {
sys_restricted++;
@@ -407,24 +374,31 @@ receive(
}
if (restrict_mask & RES_DONTSERVE) {
sys_restricted++;
- return; /* no time */
+ return; /* no time serve */
}
- if (rbufp->recv_length < LEN_PKT_NOMAC) {
- sys_badlength++;
- return; /* runt packet */
+
+ /*
+ * This is for testing. If restricted drop ten percent of
+ * surviving packets.
+ */
+ if (restrict_mask & RES_TIMEOUT) {
+ if ((double)ntp_random() / 0x7fffffff < .1) {
+ sys_restricted++;
+ return; /* no flakeway */
+ }
}
/*
* Version check must be after the query packets, since they
- * intentionally use early version.
+ * intentionally use an early version.
*/
if (hisversion == NTP_VERSION) {
- sys_newversionpkt++; /* new version */
+ sys_newversion++; /* new version */
} else if (!(restrict_mask & RES_VERSION) && hisversion >=
NTP_OLDVERSION) {
- sys_oldversionpkt++; /* previous version */
+ sys_oldversion++; /* previous version */
} else {
- sys_unknownversion++;
+ sys_badlength++;
return; /* old version */
}
@@ -449,47 +423,70 @@ receive(
* the number of words following the packet header is 0, no MAC
* is present and the packet is not authenticated. If 1, the
* packet is a crypto-NAK; if 3, the packet is authenticated
- * with DES; if 5, the packet is authenticated with MD5. If 2 or
- * 4, the packet is a runt and discarded forthwith. If greater
- * than 5, an extension field is present, so we subtract the
- * length of the field and go around again.
+ * with DES; if 5, the packet is authenticated with MD5; if 6,
+ * the packet is authenticated with SHA. If 2 or * 4, the packet
+ * is a runt and discarded forthwith. If greater than 6, an
+ * extension field is present, so we subtract the length of the
+ * field and go around again.
*/
authlen = LEN_PKT_NOMAC;
has_mac = rbufp->recv_length - authlen;
- while (has_mac > 0) {
- int temp;
+ while (has_mac != 0) {
+ u_int32 len;
- if (has_mac % 4 != 0 || has_mac < 0) {
+ if (has_mac % 4 != 0 || has_mac < MIN_MAC_LEN) {
sys_badlength++;
- return; /* bad MAC length */
+ return; /* bad length */
}
- if (has_mac == 1 * 4 || has_mac == 3 * 4 || has_mac ==
- MAX_MAC_LEN) {
+ if (has_mac <= MAX_MAC_LEN) {
skeyid = ntohl(((u_int32 *)pkt)[authlen / 4]);
break;
- } else if (has_mac > MAX_MAC_LEN) {
- temp = ntohl(((u_int32 *)pkt)[authlen / 4]) &
- 0xffff;
- if (temp < 4 || temp > NTP_MAXEXTEN || temp % 4
- != 0) {
+ } else {
+ opcode = ntohl(((u_int32 *)pkt)[authlen / 4]);
+ len = opcode & 0xffff;
+ if (len % 4 != 0 || len < 4 || len + authlen >
+ rbufp->recv_length) {
sys_badlength++;
- return; /* bad MAC length */
+ return; /* bad length */
}
- authlen += temp;
- has_mac -= temp;
- } else {
- sys_badlength++;
- return; /* bad MAC length */
+ authlen += len;
+ has_mac -= len;
}
}
-#ifdef OPENSSL
- pkeyid = tkeyid = 0;
-#endif /* OPENSSL */
+
+ /*
+ * If authentication required, a MAC must be present.
+ */
+ if (restrict_mask & RES_DONTTRUST && has_mac == 0) {
+ sys_restricted++;
+ return; /* access denied */
+ }
+
+ /*
+ * Update the MRU list and finger the cloggers. It can be a
+ * little expensive, so turn it off for production use.
+ */
+ restrict_mask = ntp_monitor(rbufp, restrict_mask);
+ if (restrict_mask & RES_LIMITED) {
+ sys_limitrejected++;
+ if (!(restrict_mask & RES_KOD) || MODE_BROADCAST ==
+ hismode || MODE_SERVER == hismode)
+ return; /* rate exceeded */
+
+ if (hismode == MODE_CLIENT)
+ fast_xmit(rbufp, MODE_SERVER, skeyid,
+ restrict_mask);
+ else
+ fast_xmit(rbufp, MODE_ACTIVE, skeyid,
+ restrict_mask);
+ return; /* rate exceeded */
+ }
+ restrict_mask &= ~RES_KOD;
/*
* We have tossed out as many buggy packets as possible early in
- * the game to reduce the exposure to a clogging attack. Now we
+ * the game to reduce the exposure to a clogging attack. now we
* have to burn some cycles to find the association and
* authenticate the packet if required. Note that we burn only
* MD5 cycles, again to reduce exposure. There may be no
@@ -502,12 +499,11 @@ receive(
* address used to construct the autokey is the unicast address
* of the interface. However, if the sender is a broadcaster,
* the interface broadcast address is used instead.
- & Notwithstanding this technobabble, if the sender is a
+ * Notwithstanding this technobabble, if the sender is a
* multicaster, the broadcast address is null, so we use the
* unicast address anyway. Don't ask.
*/
- peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, hismode,
- &retcode);
+ peer = findpeer(rbufp, hismode, &retcode);
dstadr_sin = &rbufp->dstadr->sin;
NTOHL_FP(&pkt->org, &p_org);
NTOHL_FP(&pkt->rec, &p_rec);
@@ -536,33 +532,56 @@ receive(
* is zero, acceptable outcomes of y are NONE and OK. If x is
* one, the only acceptable outcome of y is OK.
*/
+
if (has_mac == 0) {
+ restrict_mask &= ~RES_MSSNTP;
is_authentic = AUTH_NONE; /* not required */
#ifdef DEBUG
if (debug)
- printf("receive: at %ld %s<-%s mode %d code %d auth %d\n",
+ printf(
+ "receive: at %ld %s<-%s mode %d len %d\n",
current_time, stoa(dstadr_sin),
- stoa(&rbufp->recv_srcadr), hismode, retcode,
- is_authentic);
+ stoa(&rbufp->recv_srcadr), hismode,
+ authlen);
#endif
} else if (has_mac == 4) {
- is_authentic = AUTH_CRYPTO; /* crypto-NAK */
+ restrict_mask &= ~RES_MSSNTP;
+ is_authentic = AUTH_CRYPTO; /* crypto-NAK */
#ifdef DEBUG
if (debug)
printf(
- "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
+ "receive: at %ld %s<-%s mode %d keyid %08x len %d auth %d\n",
current_time, stoa(dstadr_sin),
- stoa(&rbufp->recv_srcadr), hismode, retcode,
- skeyid, authlen, has_mac, is_authentic);
+ stoa(&rbufp->recv_srcadr), hismode, skeyid,
+ authlen + has_mac, is_authentic);
#endif
+
+#ifdef HAVE_NTP_SIGND
+ /*
+ * If the signature is 20 bytes long, the last 16 of
+ * which are zero, then this is a Microsoft client
+ * wanting AD-style authentication of the server's
+ * reply.
+ *
+ * This is described in Microsoft's WSPP docs, in MS-SNTP:
+ * http://msdn.microsoft.com/en-us/library/cc212930.aspx
+ */
+ } else if (has_mac == MAX_MD5_LEN && (restrict_mask & RES_MSSNTP) &&
+ (retcode == AM_FXMIT || retcode == AM_NEWPASS) &&
+ (memcmp(zero_key, (char *)pkt + authlen + 4, MAX_MD5_LEN - 4) ==
+ 0)) {
+ is_authentic = AUTH_NONE;
+#endif /* HAVE_NTP_SIGND */
+
} else {
+ restrict_mask &= ~RES_MSSNTP;
#ifdef OPENSSL
/*
* For autokey modes, generate the session key
* and install in the key cache. Use the socket
* broadcast or unicast address as appropriate.
*/
- if (skeyid > NTP_MAXKEY) {
+ if (crypto_flags && skeyid > NTP_MAXKEY) {
/*
* More on the autokey dance (AKD). A cookie is
@@ -589,6 +608,10 @@ receive(
* # if unsync, 0
* % can't happen
*/
+ if (has_mac < MAX_MD5_LEN) {
+ sys_badauth++;
+ return;
+ }
if (hismode == MODE_BROADCAST) {
/*
@@ -605,7 +628,7 @@ receive(
return; /* no wildcard */
}
pkeyid = 0;
- if (!SOCKNUL(&rbufp->dstadr->bcast))
+ if (!SOCK_UNSPEC(&rbufp->dstadr->bcast))
dstadr_sin =
&rbufp->dstadr->bcast;
} else if (peer == NULL) {
@@ -646,23 +669,21 @@ receive(
* association. Note that there is no key zero.
*/
if (!authdecrypt(skeyid, (u_int32 *)pkt, authlen,
- has_mac)) {
+ has_mac))
is_authentic = AUTH_ERROR;
- sys_badauth++;
- } else {
+ else
is_authentic = AUTH_OK;
- }
#ifdef OPENSSL
- if (skeyid > NTP_MAXKEY)
+ if (crypto_flags && skeyid > NTP_MAXKEY)
authtrust(skeyid, 0);
#endif /* OPENSSL */
#ifdef DEBUG
if (debug)
printf(
- "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
+ "receive: at %ld %s<-%s mode %d keyid %08x len %d auth %d\n",
current_time, stoa(dstadr_sin),
- stoa(&rbufp->recv_srcadr), hismode, retcode,
- skeyid, authlen, has_mac, is_authentic);
+ stoa(&rbufp->recv_srcadr), hismode, skeyid,
+ authlen + has_mac, is_authentic);
#endif
}
@@ -687,19 +708,21 @@ receive(
case AM_FXMIT:
/*
- * The vanilla case is when this is not a multicast
- * interface. If authentication succeeds, return a
- * server mode packet; if not and the key ID is nonzero,
- * return a crypto-NAK.
+ * If authentication OK, send a server reply; otherwise,
+ * send a crypto-NAK.
*/
if (!(rbufp->dstadr->flags & INT_MCASTOPEN)) {
if (AUTH(restrict_mask & RES_DONTTRUST,
- is_authentic))
+ is_authentic)) {
fast_xmit(rbufp, MODE_SERVER, skeyid,
restrict_mask);
- else if (is_authentic == AUTH_ERROR)
+ } else if (is_authentic == AUTH_ERROR) {
fast_xmit(rbufp, MODE_SERVER, 0,
restrict_mask);
+ sys_badauth++;
+ } else {
+ sys_restricted++;
+ }
return; /* hooray */
}
@@ -713,21 +736,17 @@ receive(
}
/*
- * Do not respond if unsynchronized or stratum is below
- * the floor or at or above the ceiling.
- */
- if (sys_leap == LEAP_NOTINSYNC || sys_stratum <
- sys_floor || sys_stratum >= sys_ceiling)
- return; /* bad stratum */
-
- /*
- * Do not respond if our stratum is greater than the
- * manycaster or it has already synchronized to us.
+ * Do not respond if we are not synchronized or our
+ * stratum is greater than the manycaster or the
+ * manycaster has already synchronized to us.
*/
- if (sys_peer == NULL || hisstratum < sys_stratum ||
- (sys_cohort && hisstratum == sys_stratum) ||
- rbufp->dstadr->addr_refid == pkt->refid)
+ if (sys_leap == LEAP_NOTINSYNC || sys_stratum >=
+ hisstratum || (!sys_cohort && sys_stratum ==
+ hisstratum + 1) || rbufp->dstadr->addr_refid ==
+ pkt->refid) {
+ sys_declined++;
return; /* no help */
+ }
/*
* Respond only if authentication succeeds. Don't do a
@@ -736,7 +755,6 @@ receive(
if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic))
fast_xmit(rbufp, MODE_SERVER, skeyid,
restrict_mask);
-
return; /* hooray */
/*
@@ -758,24 +776,39 @@ receive(
*/
case AM_MANYCAST:
if (!AUTH(sys_authenticate | (restrict_mask &
- (RES_NOPEER | RES_DONTTRUST)), is_authentic))
- return; /* bad auth */
+ (RES_NOPEER | RES_DONTTRUST)), is_authentic)) {
+ sys_restricted++;
+ return; /* access denied */
+ }
+ /*
+ * Do not respond if unsynchronized or stratum is below
+ * the floor or at or above the ceiling.
+ */
+ if (hisleap == LEAP_NOTINSYNC || hisstratum <
+ sys_floor || hisstratum >= sys_ceiling) {
+ sys_declined++;
+ return; /* no help */
+ }
if ((peer2 = findmanycastpeer(rbufp)) == NULL) {
sys_restricted++;
return; /* not enabled */
}
- if ((peer = newpeer(&rbufp->recv_srcadr,
- rbufp->dstadr, MODE_CLIENT,
- hisversion, NTP_MINDPOLL, NTP_MAXDPOLL,
- FLAG_IBURST | FLAG_PREEMPT, MDF_UCAST | MDF_ACLNT,
- 0, skeyid)) == NULL)
- return; /* system error */
+ if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
+ MODE_CLIENT, hisversion, NTP_MINDPOLL, NTP_MAXDPOLL,
+ FLAG_PREEMPT, MDF_UCAST | MDF_ACLNT, 0, skeyid)) ==
+ NULL) {
+ sys_declined++;
+ return; /* ignore duplicate */
+ }
/*
* We don't need these, but it warms the billboards.
*/
- peer->ttl = peer2->ttl;
+ if (peer2->flags & FLAG_IBURST)
+ peer->flags |= FLAG_IBURST;
+ peer->minpoll = peer2->minpoll;
+ peer->maxpoll = peer2->maxpoll;
break;
/*
@@ -785,68 +818,108 @@ receive(
* kiss any frogs here.
*/
case AM_NEWBCL:
+ if (sys_bclient == 0) {
+ sys_restricted++;
+ return; /* not enabled */
+ }
if (!AUTH(sys_authenticate | (restrict_mask &
- (RES_NOPEER | RES_DONTTRUST)), is_authentic))
- return; /* bad auth */
+ (RES_NOPEER | RES_DONTTRUST)), is_authentic)) {
+ sys_restricted++;
+ return; /* access denied */
+ }
/*
* Do not respond if unsynchronized or stratum is below
* the floor or at or above the ceiling.
*/
if (hisleap == LEAP_NOTINSYNC || hisstratum <
- sys_floor || hisstratum >= sys_ceiling)
- return; /* bad stratum */
-
- switch (sys_bclient) {
+ sys_floor || hisstratum >= sys_ceiling) {
+ sys_declined++;
+ return; /* no help */
+ }
+#ifdef OPENSSL
/*
- * If not enabled, just skedaddle.
+ * Do not respond if Autokey and the opcode is not a
+ * CRYPTO_ASSOC response with associationn ID.
*/
- case 0:
- sys_restricted++;
- return; /* not enabled */
+ if (crypto_flags && skeyid > NTP_MAXKEY && (opcode &
+ 0xffff0000) != (CRYPTO_ASSOC | CRYPTO_RESP)) {
+ sys_declined++;
+ return; /* protocol error */
+ }
+#endif /* OPENSSL */
/*
- * Execute the initial volley in order to calibrate the
- * propagation delay and run the Autokey protocol, if
- * enabled.
+ * Broadcasts received via a multicast address may
+ * arrive after a unicast volley has begun
+ * with the same remote address. newpeer() will not
+ * find duplicate associations on other local endpoints
+ * if a non-NULL endpoint is supplied. multicastclient
+ * ephemeral associations are unique across all local
+ * endpoints.
*/
- case 1:
- if ((peer = newpeer(&rbufp->recv_srcadr,
- rbufp->dstadr, MODE_CLIENT, hisversion,
- NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_MCAST |
- FLAG_IBURST, MDF_BCLNT, 0, skeyid)) ==
- NULL)
- return; /* system error */
-#ifdef OPENSSL
- if (skeyid > NTP_MAXKEY)
- crypto_recv(peer, rbufp);
-#endif /* OPENSSL */
- return; /* hooray */
-
+ if (!(INT_MCASTOPEN & rbufp->dstadr->flags))
+ match_ep = rbufp->dstadr;
+ else
+ match_ep = NULL;
/*
- * Do not execute the initial volley.
+ * Determine whether to execute the initial volley.
*/
- case 2:
+ if (sys_bdelay != 0) {
#ifdef OPENSSL
/*
* If a two-way exchange is not possible,
* neither is Autokey.
*/
- if (skeyid > NTP_MAXKEY) {
- msyslog(LOG_INFO,
- "receive: autokey requires two-way communication");
+ if (crypto_flags && skeyid > NTP_MAXKEY) {
+ sys_restricted++;
return; /* no autokey */
}
#endif /* OPENSSL */
- if ((peer = newpeer(&rbufp->recv_srcadr,
- rbufp->dstadr, MODE_BCLIENT, hisversion,
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_BCLNT, 0,
- skeyid)) == NULL)
- return; /* system error */
+
+ /*
+ * Do not execute the volley. Start out in
+ * broadcast client mode.
+ */
+ peer = newpeer(&rbufp->recv_srcadr, match_ep,
+ MODE_BCLIENT, hisversion, pkt->ppoll,
+ pkt->ppoll, FLAG_PREEMPT, MDF_BCLNT, 0,
+ skeyid);
+ if (NULL == peer) {
+ sys_restricted++;
+ return; /* ignore duplicate */
+
+ } else {
+ peer->delay = sys_bdelay;
+ peer->bias = -sys_bdelay / 2.;
+ }
+ break;
}
- break;
+
+ /*
+ * Execute the initial volley in order to calibrate the
+ * propagation delay and run the Autokey protocol.
+ *
+ * Note that the minpoll is taken from the broadcast
+ * packet, normally 6 (64 s) and that the poll interval
+ * is fixed at this value.
+ */
+ peer = newpeer(&rbufp->recv_srcadr, match_ep,
+ MODE_CLIENT, hisversion, pkt->ppoll, pkt->ppoll,
+ FLAG_BC_VOL | FLAG_IBURST | FLAG_PREEMPT, MDF_BCLNT,
+ 0, skeyid);
+ if (NULL == peer) {
+ sys_restricted++;
+ return; /* ignore duplicate */
+ }
+#ifdef OPENSSL
+ if (skeyid > NTP_MAXKEY)
+ crypto_recv(peer, rbufp);
+#endif /* OPENSSL */
+
+ return; /* hooray */
/*
* This is the first packet received from a symmetric active
@@ -854,41 +927,57 @@ receive(
* mobilize a passive association. If not, kiss the frog.
*/
case AM_NEWPASS:
+ if (!AUTH(sys_authenticate | (restrict_mask &
+ (RES_NOPEER | RES_DONTTRUST)), is_authentic)) {
- /*
- * If the inbound packet is correctly authenticated and
- * enabled, a symmetric passive association is
- * mobilized. If not but correctly authenticated, a
- * symmetric active response is sent. If authentication
- * fails, send a crypto-NAK packet.
- */
- if (!AUTH(restrict_mask & RES_DONTTRUST, is_authentic))
- {
- if (is_authentic == AUTH_ERROR)
+ /*
+ * If authenticated but cannot mobilize an
+ * association, send a symmetric passive
+ * response without mobilizing an association.
+ * This is for drat broken Windows clients. See
+ * Microsoft KB 875424 for preferred workaround.
+ */
+ if (AUTH(restrict_mask & RES_DONTTRUST,
+ is_authentic)) {
+ fast_xmit(rbufp, MODE_PASSIVE, skeyid,
+ restrict_mask);
+ return; /* hooray */
+ }
+ if (is_authentic == AUTH_ERROR) {
fast_xmit(rbufp, MODE_ACTIVE, 0,
restrict_mask);
- return; /* bad auth */
- }
- if (!AUTH(sys_authenticate | (restrict_mask &
- RES_NOPEER), is_authentic)) {
- fast_xmit(rbufp, MODE_ACTIVE, skeyid,
- restrict_mask);
- return; /* hooray */
+ sys_restricted++;
+ }
}
/*
- * Do not respond if stratum is below the floor.
+ * Do not respond if synchronized and stratum is either
+ * below the floor or at or above the ceiling. Note,
+ * this allows an unsynchronized peer to synchronize to
+ * us. It would be very strange if he did and then was
+ * nipped, but that could only happen if we were
+ * operating at the top end of the range.
*/
- if (hisstratum < sys_floor)
- return; /* bad stratum */
+ if (hisleap != LEAP_NOTINSYNC && (hisstratum <
+ sys_floor || hisstratum >= sys_ceiling)) {
+ sys_declined++;
+ return; /* no help */
+ }
+ /*
+ * The message is correctly authenticated and
+ * allowed. Mobiliae a symmetric passive association.
+ */
if ((peer = newpeer(&rbufp->recv_srcadr,
- rbufp->dstadr, MODE_PASSIVE, hisversion,
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_UCAST, 0,
- skeyid)) == NULL)
- return; /* system error */
+ rbufp->dstadr, MODE_PASSIVE, hisversion, pkt->ppoll,
+ NTP_MAXDPOLL, FLAG_PREEMPT, MDF_UCAST, 0,
+ skeyid)) == NULL) {
+ sys_declined++;
+ return; /* ignore duplicate */
+ }
break;
+
/*
* Process regular packet. Nothing special.
*/
@@ -902,99 +991,191 @@ receive(
* attempt to deny service, just ignore it.
*/
case AM_ERR:
+ sys_declined++;
return;
/*
* For everything else there is the bit bucket.
*/
default:
+ sys_declined++;
return;
}
+
+#ifdef OPENSSL
+ /*
+ * If the association is configured for Autokey, the packet must
+ * have a public key ID; if not, the packet must have a
+ * symmetric key ID.
+ */
+ if (is_authentic != AUTH_CRYPTO && (((peer->flags &
+ FLAG_SKEY) && skeyid <= NTP_MAXKEY) || (!(peer->flags &
+ FLAG_SKEY) && skeyid > NTP_MAXKEY))) {
+ sys_badauth++;
+ return;
+ }
+#endif /* OPENSSL */
+ peer->received++;
peer->flash &= ~PKT_TEST_MASK;
+ if (peer->flags & FLAG_XBOGUS) {
+ peer->flags &= ~FLAG_XBOGUS;
+ peer->flash |= TEST3;
+ }
/*
* Next comes a rigorous schedule of timestamp checking. If the
- * transmit timestamp is zero, the server is horribly broken.
+ * transmit timestamp is zero, the server has not initialized in
+ * interleaved modes or is horribly broken.
*/
if (L_ISZERO(&p_xmt)) {
- return; /* read rfc1305 */
+ peer->flash |= TEST3; /* unsynch */
/*
* If the transmit timestamp duplicates a previous one, the
* packet is a replay. This prevents the bad guys from replaying
* the most recent packet, authenticated or not.
*/
- } else if (L_ISEQU(&peer->org, &p_xmt)) {
- peer->flash |= TEST1;
+ } else if (L_ISEQU(&peer->xmt, &p_xmt)) {
+ peer->flash |= TEST1; /* duplicate */
peer->oldpkt++;
- return; /* duplicate packet */
-
+ return;
/*
- * If this is a broadcast mode packet, skip further checking.
+ * If this is a broadcast mode packet, skip further checking. If
+ * an intial volley, bail out now and let the client do its
+ * stuff. If the origin timestamp is nonzero, this is an
+ * interleaved broadcast. so restart the protocol.
*/
- } else if (hismode != MODE_BROADCAST) {
- if (L_ISZERO(&p_org))
- peer->flash |= TEST3; /* protocol unsynch */
- else if (!L_ISEQU(&p_org, &peer->xmt))
- peer->flash |= TEST2; /* bogus packet */
- }
+ } else if (hismode == MODE_BROADCAST) {
+ if (!L_ISZERO(&p_org) && !(peer->flags & FLAG_XB)) {
+ peer->flags |= FLAG_XB;
+ peer->aorg = p_xmt;
+ peer->borg = rbufp->recv_time;
+ report_event(PEVNT_XLEAVE, peer, NULL);
+ return;
+ }
/*
- * Update the origin and destination timestamps. If
- * unsynchronized or bogus abandon ship. If the crypto machine
- * breaks, light the crypto bit and plaint the log.
+ * Check for bogus packet in basic mode. If found, switch to
+ * interleaved mode and resynchronize, but only after confirming
+ * the packet is not bogus in symmetric interleaved mode.
*/
- peer->org = p_xmt;
- peer->rec = rbufp->recv_time;
- if (peer->flash & PKT_TEST_MASK) {
-#ifdef OPENSSL
- if (crypto_flags && (peer->flags & FLAG_SKEY)) {
- rval = crypto_recv(peer, rbufp);
- if (rval != XEVNT_OK) {
- peer_clear(peer, "CRYP");
- peer->flash |= TEST9; /* crypto error */
+ } else if (peer->flip == 0) {
+ if (!L_ISEQU(&p_org, &peer->aorg)) {
+ peer->bogusorg++;
+ peer->flash |= TEST2; /* bogus */
+ if (!L_ISZERO(&peer->dst) && L_ISEQU(&p_org,
+ &peer->dst)) {
+ peer->flip = 1;
+ report_event(PEVNT_XLEAVE, peer, NULL);
}
+ } else {
+ L_CLR(&peer->aorg);
}
-#endif /* OPENSSL */
- return; /* unsynch */
+
+ /*
+ * Check for valid nonzero timestamp fields.
+ */
+ } else if (L_ISZERO(&p_org) || L_ISZERO(&p_rec) ||
+ L_ISZERO(&peer->dst)) {
+ peer->flash |= TEST3; /* unsynch */
+
+ /*
+ * Check for bogus packet in interleaved symmetric mode. This
+ * can happen if a packet is lost, duplicat or crossed. If
+ * found, flip and resynchronize.
+ */
+ } else if (!L_ISZERO(&peer->dst) && !L_ISEQU(&p_org,
+ &peer->dst)) {
+ peer->bogusorg++;
+ peer->flags |= FLAG_XBOGUS;
+ peer->flash |= TEST2; /* bogus */
+ }
+
+ /*
+ * Update the state variables.
+ */
+ if (peer->flip == 0) {
+ if (hismode != MODE_BROADCAST)
+ peer->rec = p_xmt;
+ peer->dst = rbufp->recv_time;
}
+ peer->xmt = p_xmt;
/*
- * The timestamps are valid and the receive packet matches the
- * last one sent. If the packet is a crypto-NAK, the server
- * might have just changed keys. We reset the association
- * and restart the protocol.
+ * If this is a crypto_NAK, the server cannot authenticate a
+ * client packet. The server might have just changed keys. Clear
+ * the association and restart the protocol.
*/
if (is_authentic == AUTH_CRYPTO) {
- peer_clear(peer, "AUTH");
- return; /* crypto-NAK */
+ report_event(PEVNT_AUTH, peer, "crypto_NAK");
+ peer->flash |= TEST5; /* bad auth */
+ peer->badauth++;
+ if (peer->flags & FLAG_PREEMPT) {
+ unpeer(peer);
+ return;
+ }
+#ifdef OPENSSL
+ if (peer->crypto)
+ peer_clear(peer, "AUTH");
+#endif /* OPENSSL */
+ return;
/*
- * If the association is authenticated, the key ID is nonzero
- * and received packets must be authenticated. This is designed
- * to avoid a bait-and-switch attack, which was possible in past
- * versions. If symmetric modes, return a crypto-NAK. The peer
- * should restart the protocol.
+ * If the digest fails, the client cannot authenticate a server
+ * reply to a client packet previously sent. The loopback check
+ * is designed to avoid a bait-and-switch attack, which was
+ * possible in past versions. If symmetric modes, return a
+ * crypto-NAK. The peer should restart the protocol.
*/
- } else if (!AUTH(peer->keyid || (restrict_mask & RES_DONTTRUST),
+ } else if (!AUTH(has_mac || (restrict_mask & RES_DONTTRUST),
is_authentic)) {
- peer->flash |= TEST5;
+ report_event(PEVNT_AUTH, peer, "digest");
+ peer->flash |= TEST5; /* bad auth */
+ peer->badauth++;
if (hismode == MODE_ACTIVE || hismode == MODE_PASSIVE)
fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);
- return; /* bad auth */
+ if (peer->flags & FLAG_PREEMPT) {
+ unpeer(peer);
+ return;
+ }
+#ifdef OPENSSL
+ if (peer->crypto)
+ peer_clear(peer, "AUTH");
+#endif /* OPENSSL */
+ return;
+ }
+
+ /*
+ * Set the peer ppoll to the maximum of the packet ppoll and the
+ * peer minpoll. If a kiss-o'-death, set the peer minpoll to
+ * this maximumn and advance the headway to give the sender some
+ * headroom. Very intricate.
+ */
+ peer->ppoll = max(peer->minpoll, pkt->ppoll);
+ if (hismode == MODE_SERVER && hisleap == LEAP_NOTINSYNC &&
+ hisstratum == STRATUM_UNSPEC && memcmp(&pkt->refid,
+ "RATE", 4) == 0) {
+ peer->selbroken++;
+ report_event(PEVNT_RATE, peer, NULL);
+ if (pkt->ppoll > peer->minpoll)
+ peer->minpoll = peer->ppoll;
+ peer->burst = peer->retry = 0;
+ peer->throttle = (NTP_SHIFT + 1) * (1 << peer->minpoll);
+ poll_update(peer, pkt->ppoll);
+ return; /* kiss-o'-death */
}
/*
* That was hard and I am sweaty, but the packet is squeaky
* clean. Get on with real work.
*/
- peer->received++;
peer->timereceived = current_time;
if (is_authentic == AUTH_OK)
peer->flags |= FLAG_AUTHENTIC;
else
peer->flags &= ~FLAG_AUTHENTIC;
+
#ifdef OPENSSL
/*
* More autokey dance. The rules of the cha-cha are as follows:
@@ -1014,31 +1195,64 @@ receive(
* 5. Check to see that one or more hashes of the current key ID
* matches the previous key ID or ultimate original key ID
* obtained from the broadcaster or symmetric peer. If no
- * match, sit the dance and wait for timeout.
+ * match, sit the dance and call for new autokey values.
*
- * In case of crypto error, fire the orchestra and stop dancing.
- * This is considered a permanant error, so light the crypto bit
- * to suppress further requests. If preemptable or ephemeral,
- * scuttle the ship.
+ * In case of crypto error, fire the orchestra, stop dancing and
+ * restart the protocol.
*/
- if (crypto_flags && (peer->flags & FLAG_SKEY)) {
+ if (peer->flags & FLAG_SKEY) {
+ /*
+ * Decrement remaining audokey hashes. This isn't
+ * perfect if a packet is lost, but results in no harm.
+ */
+ ap = (struct autokey *)peer->recval.ptr;
+ if (ap != NULL) {
+ if (ap->seq > 0)
+ ap->seq--;
+ }
peer->flash |= TEST8;
rval = crypto_recv(peer, rbufp);
- if (rval != XEVNT_OK) {
- peer_clear(peer, "CRYP");
- peer->flash |= TEST9; /* crypto error */
- if (peer->flags & FLAG_PREEMPT ||
- !(peer->flags & FLAG_CONFIG))
- unpeer(peer);
+ if (rval == XEVNT_OK) {
+ peer->unreach = 0;
+ } else {
+ if (rval == XEVNT_ERR) {
+ report_event(PEVNT_RESTART, peer,
+ "crypto error");
+ peer_clear(peer, "CRYP");
+ peer->flash |= TEST9; /* bad crypt */
+ if (peer->flags & FLAG_PREEMPT)
+ unpeer(peer);
+ }
return;
+ }
- } else if (hismode == MODE_SERVER) {
+ /*
+ * If server mode, verify the receive key ID matches
+ * the transmit key ID.
+ */
+ if (hismode == MODE_SERVER) {
if (skeyid == peer->keyid)
peer->flash &= ~TEST8;
+
+ /*
+ * If an extension field is present, verify only that it
+ * has been correctly signed. We don't need a sequence
+ * check here, but the sequence continues.
+ */
} else if (!(peer->flash & TEST8)) {
peer->pkeyid = skeyid;
- } else if ((ap = (struct autokey *)peer->recval.ptr) !=
- NULL) {
+
+ /*
+ * Now the fun part. Here, skeyid is the current ID in
+ * the packet, pkeyid is the ID in the last packet and
+ * tkeyid is the hash of skeyid. If the autokey values
+ * have not been received, this is an automatic error.
+ * If so, check that the tkeyid matches pkeyid. If not,
+ * hash tkeyid and try again. If the number of hashes
+ * exceeds the number remaining in the sequence, declare
+ * a successful failure and refresh the autokey values.
+ */
+ } else if (ap != NULL) {
int i;
for (i = 0; ; i++) {
@@ -1046,25 +1260,34 @@ receive(
tkeyid == ap->key) {
peer->flash &= ~TEST8;
peer->pkeyid = skeyid;
+ ap->seq -= i;
break;
}
- if (i > ap->seq)
+ if (i > ap->seq) {
+ peer->crypto &=
+ ~CRYPTO_FLAG_AUTO;
break;
+ }
tkeyid = session_key(
&rbufp->recv_srcadr, dstadr_sin,
tkeyid, pkeyid, 0);
}
+ if (peer->flash & TEST8)
+ report_event(PEVNT_AUTH, peer, "keylist");
}
if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 9 */
- peer->flash |= TEST8; /* not proventic */
+ peer->flash |= TEST8; /* bad autokey */
/*
- * If the transmit queue is nonempty, clamp the host
- * poll interval to the packet poll interval.
+ * The maximum lifetime of the protocol is about one
+ * week before restarting the Autokey protocol to
+ * refreshed certificates and leapseconds values.
*/
- if (peer->cmmd != 0) {
- peer->ppoll = pkt->ppoll;
- poll_update(peer, peer->hpoll);
+ if (current_time > peer->refresh) {
+ report_event(PEVNT_RESTART, peer,
+ "crypto refresh");
+ peer_clear(peer, "TIME");
+ return;
}
}
#endif /* OPENSSL */
@@ -1074,17 +1297,20 @@ receive(
* the packet over the fence for processing, which may light up
* more flashers.
*/
- process_packet(peer, pkt);
+ process_packet(peer, pkt, rbufp->recv_length);
/*
- * Well, that was nice. If TEST4 is lit, either the crypto
- * machine jammed or a kiss-o'-death packet flew in, either of
- * which is fatal.
+ * In interleaved mode update the state variables. Also adjust the
+ * transmit phase to avoid crossover.
*/
- if (peer->flash & TEST4) {
- msyslog(LOG_INFO, "receive: fatal error %04x for %s",
- peer->flash, stoa(&peer->srcadr));
- return;
+ if (peer->flip != 0) {
+ peer->rec = p_rec;
+ peer->dst = rbufp->recv_time;
+ if (peer->nextdate - current_time < (1 << min(peer->ppoll,
+ peer->hpoll)) / 2)
+ peer->nextdate++;
+ else
+ peer->nextdate--;
}
}
@@ -1098,66 +1324,73 @@ receive(
void
process_packet(
register struct peer *peer,
- register struct pkt *pkt
+ register struct pkt *pkt,
+ u_int len
)
{
double t34, t21;
double p_offset, p_del, p_disp;
- l_fp p_rec, p_xmt, p_org, p_reftime;
- l_fp ci;
+ l_fp p_rec, p_xmt, p_org, p_reftime, ci;
u_char pmode, pleap, pstratum;
+ char statstr[NTP_MAXSTRLEN];
+#ifdef ASSYM
+ int itemp;
+ double etemp, ftemp, td;
+#endif /* ASSYM */
sys_processed++;
peer->processed++;
p_del = FPTOD(NTOHS_FP(pkt->rootdelay));
- p_disp = FPTOD(NTOHS_FP(pkt->rootdispersion));
+ p_offset = 0;
+ p_disp = FPTOD(NTOHS_FP(pkt->rootdisp));
NTOHL_FP(&pkt->reftime, &p_reftime);
+ NTOHL_FP(&pkt->org, &p_org);
NTOHL_FP(&pkt->rec, &p_rec);
NTOHL_FP(&pkt->xmt, &p_xmt);
pmode = PKT_MODE(pkt->li_vn_mode);
pleap = PKT_LEAP(pkt->li_vn_mode);
- if (pmode != MODE_BROADCAST)
- NTOHL_FP(&pkt->org, &p_org);
- else
- p_org = peer->rec;
pstratum = PKT_TO_STRATUM(pkt->stratum);
/*
- * Test for kiss-o'death packet)
+ * Capture the header values in the client/peer association..
*/
- if (pleap == LEAP_NOTINSYNC && pstratum == STRATUM_UNSPEC) {
- if (memcmp(&pkt->refid, "DENY", 4) == 0) {
- peer_clear(peer, "DENY");
- peer->flash |= TEST4; /* access denied */
- }
- }
-
- /*
- * Capture the header values.
- */
- record_raw_stats(&peer->srcadr, peer->dstadr ? &peer->dstadr->sin : NULL, &p_org,
- &p_rec, &p_xmt, &peer->rec);
+ record_raw_stats(&peer->srcadr, peer->dstadr ?
+ &peer->dstadr->sin : NULL, &p_org, &p_rec, &p_xmt,
+ &peer->dst);
peer->leap = pleap;
peer->stratum = min(pstratum, STRATUM_UNSPEC);
peer->pmode = pmode;
- peer->ppoll = pkt->ppoll;
peer->precision = pkt->precision;
peer->rootdelay = p_del;
- peer->rootdispersion = p_disp;
+ peer->rootdisp = p_disp;
peer->refid = pkt->refid; /* network byte order */
peer->reftime = p_reftime;
/*
- * Verify the server is synchronized; that is, the leap bits and
- * stratum are valid, the root delay and root dispersion are
- * valid and the reference timestamp is not later than the
- * transmit timestamp.
+ * First, if either burst mode is armed, enable the burst.
+ * Compute the headway for the next packet and delay if
+ * necessary to avoid exceeding the threshold.
+ */
+ if (peer->retry > 0) {
+ peer->retry = 0;
+ if (peer->reach)
+ peer->burst = min(1 << (peer->hpoll -
+ peer->minpoll), NTP_SHIFT) - 1;
+ else
+ peer->burst = NTP_IBURST - 1;
+ if (peer->burst > 0)
+ peer->nextdate = current_time;
+ }
+ poll_update(peer, peer->hpoll);
+
+ /*
+ * Verify the server is synchronized; that is, the leap bits,
+ * stratum and root distance are valid.
*/
if (pleap == LEAP_NOTINSYNC || /* test 6 */
pstratum < sys_floor || pstratum >= sys_ceiling)
- peer->flash |= TEST6; /* peer not synch */
- if (p_del < 0 || p_disp < 0 || p_del / /* test 7 */
- 2 + p_disp >= MAXDISPERSE || !L_ISHIS(&p_xmt, &p_reftime))
+ peer->flash |= TEST6; /* bad synch or strat */
+ if (p_del / 2 + p_disp >= MAXDISPERSE) /* test 7 */
peer->flash |= TEST7; /* bad header */
/*
@@ -1166,6 +1399,7 @@ process_packet(
* receive() routine.
*/
if (peer->flash & PKT_TEST_MASK) {
+ peer->seldisptoolarge++;
#ifdef DEBUG
if (debug)
printf("packet: flash header %04x\n",
@@ -1173,11 +1407,15 @@ process_packet(
#endif
return;
}
- if (!(peer->reach)) {
- report_event(EVNT_REACH, peer);
+
+ /*
+ * If the peer was previously unreachable, raise a trap. In any
+ * case, mark it reachable.
+ */
+ if (!peer->reach) {
+ report_event(PEVNT_REACH, peer, NULL);
peer->timereachable = current_time;
}
- poll_update(peer, peer->hpoll);
peer->reach |= 1;
/*
@@ -1185,8 +1423,7 @@ process_packet(
* roundtrip delay and dispersion. The equations are reordered
* from the spec for more efficient use of temporaries. For a
* broadcast association, offset the last measurement by the
- * computed delay during the client/server volley. Note that
- * org has been set to the time of last reception. Note the
+ * computed delay during the client/server volley. Note the
* computation of dispersion includes the system precision plus
* that due to the frequency error since the origin time.
*
@@ -1201,52 +1438,201 @@ process_packet(
* only half that span. Since the typical first-order
* differences are usually very small, they are converted to 64-
* bit doubles and all remaining calculations done in floating-
- * point arithmetic. This preserves the accuracy while retaining
- * the 68-year span.
+ * double arithmetic. This preserves the accuracy while
+ * retaining the 68-year span.
+ *
+ * There are three interleaving schemes, basic, interleaved
+ * symmetric and interleaved broadcast. The timestamps are
+ * idioscyncratically different. See the onwire briefing/white
+ * paper at www.eecis.udel.edu/~mills for details.
*
- * Let t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->rec:
- */
- ci = p_xmt; /* t3 - t4 */
- L_SUB(&ci, &peer->rec);
- LFPTOD(&ci, t34);
- ci = p_rec; /* t2 - t1 */
- L_SUB(&ci, &p_org);
- LFPTOD(&ci, t21);
- ci = peer->rec; /* t4 - t1 */
- L_SUB(&ci, &p_org);
-
- /*
- * If running in a broadcast association, the clock offset is
- * (t1 - t0) corrected by the one-way delay, but we can't
- * measure that directly. Therefore, we start up in MODE_CLIENT
- * mode, set FLAG_MCAST and exchange eight messages to determine
- * the clock offset. When the last message is sent, we switch to
- * MODE_BCLIENT mode. The next broadcast message after that
- * computes the broadcast offset and clears FLAG_MCAST.
- */
- if (pmode == MODE_BROADCAST) {
- p_offset = t34;
- if (peer->flags & FLAG_MCAST) {
- peer->estbdelay = peer->offset - p_offset;
- if (peer->hmode == MODE_CLIENT)
+ * Interleaved symmetric mode
+ * t1 = peer->aorg/borg, t2 = peer->rec, t3 = p_xmt,
+ * t4 = peer->dst
+ */
+ if (peer->flip != 0) {
+ ci = p_xmt; /* t3 - t4 */
+ L_SUB(&ci, &peer->dst);
+ LFPTOD(&ci, t34);
+ ci = p_rec; /* t2 - t1 */
+ if (peer->flip > 0)
+ L_SUB(&ci, &peer->borg);
+ else
+ L_SUB(&ci, &peer->aorg);
+ LFPTOD(&ci, t21);
+ p_del = t21 - t34;
+ p_offset = (t21 + t34) / 2.;
+ if (p_del < 0 || p_del > 1.) {
+ sprintf(statstr, "t21 %.6f t34 %.6f", t21, t34);
+ report_event(PEVNT_XERR, peer, statstr);
+ return;
+ }
+
+ /*
+ * Broadcast modes
+ */
+ } else if (peer->pmode == MODE_BROADCAST) {
+
+ /*
+ * Interleaved broadcast mode. Use interleaved timestamps.
+ * t1 = peer->borg, t2 = p_org, t3 = p_org, t4 = aorg
+ */
+ if (peer->flags & FLAG_XB) {
+ ci = p_org; /* delay */
+ L_SUB(&ci, &peer->aorg);
+ LFPTOD(&ci, t34);
+ ci = p_org; /* t2 - t1 */
+ L_SUB(&ci, &peer->borg);
+ LFPTOD(&ci, t21);
+ peer->aorg = p_xmt;
+ peer->borg = peer->dst;
+ if (t34 < 0 || t34 > 1.) {
+ sprintf(statstr,
+ "offset %.6f delay %.6f", t21, t34);
+ report_event(PEVNT_XERR, peer, statstr);
return;
+ }
+ p_offset = t21;
+ peer->xleave = t34;
- peer->flags &= ~(FLAG_MCAST | FLAG_BURST);
+ /*
+ * Basic broadcast - use direct timestamps.
+ * t3 = p_xmt, t4 = peer->dst
+ */
+ } else {
+ ci = p_xmt; /* t3 - t4 */
+ L_SUB(&ci, &peer->dst);
+ LFPTOD(&ci, t34);
+ p_offset = t34;
+ }
+
+ /*
+ * When calibration is complete and the clock is
+ * synchronized, the bias is calculated as the difference
+ * between the unicast timestamp and the broadcast
+ * timestamp. This works for both basic and interleaved
+ * modes.
+ */
+ if (FLAG_BC_VOL & peer->flags) {
+ peer->flags &= ~FLAG_BC_VOL;
+ peer->delay = (peer->offset - p_offset) * 2;
}
- p_offset += peer->estbdelay;
p_del = peer->delay;
- p_disp = 0;
+ p_offset += p_del / 2;
+
+
+ /*
+ * Basic mode, otherwise known as the old fashioned way.
+ *
+ * t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->dst
+ */
} else {
+ ci = p_xmt; /* t3 - t4 */
+ L_SUB(&ci, &peer->dst);
+ LFPTOD(&ci, t34);
+ ci = p_rec; /* t2 - t1 */
+ L_SUB(&ci, &p_org);
+ LFPTOD(&ci, t21);
+ p_del = fabs(t21 - t34);
p_offset = (t21 + t34) / 2.;
- p_del = t21 - t34;
- LFPTOD(&ci, p_disp);
- p_disp = LOGTOD(sys_precision) +
- LOGTOD(peer->precision) + clock_phi * p_disp;
}
- p_del = max(p_del, LOGTOD(sys_precision));
+ p_offset += peer->bias;
+ p_disp = LOGTOD(sys_precision) + LOGTOD(peer->precision) +
+ clock_phi * p_del;
+
+#if ASSYM
+ /*
+ * This code calculates the outbound and inbound data rates by
+ * measuring the differences between timestamps at different
+ * packet lengths. This is helpful in cases of large asymmetric
+ * delays commonly experienced on deep space communication
+ * links.
+ */
+ if (peer->t21_last > 0 && peer->t34_bytes > 0) {
+ itemp = peer->t21_bytes - peer->t21_last;
+ if (itemp > 25) {
+ etemp = t21 - peer->t21;
+ if (fabs(etemp) > 1e-6) {
+ ftemp = itemp / etemp;
+ if (ftemp > 1000.)
+ peer->r21 = ftemp;
+ }
+ }
+ itemp = len - peer->t34_bytes;
+ if (itemp > 25) {
+ etemp = -t34 - peer->t34;
+ if (fabs(etemp) > 1e-6) {
+ ftemp = itemp / etemp;
+ if (ftemp > 1000.)
+ peer->r34 = ftemp;
+ }
+ }
+ }
+
+ /*
+ * The following section compensates for different data rates on
+ * the outbound (d21) and inbound (t34) directions. To do this,
+ * it finds t such that r21 * t - r34 * (d - t) = 0, where d is
+ * the roundtrip delay. Then it calculates the correction as a
+ * fraction of d.
+ */
+ peer->t21 = t21;
+ peer->t21_last = peer->t21_bytes;
+ peer->t34 = -t34;
+ peer->t34_bytes = len;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("packet: t21 %.9lf %d t34 %.9lf %d\n", peer->t21,
+ peer->t21_bytes, peer->t34, peer->t34_bytes);
+#endif
+ if (peer->r21 > 0 && peer->r34 > 0 && p_del > 0) {
+ if (peer->pmode != MODE_BROADCAST)
+ td = (peer->r34 / (peer->r21 + peer->r34) -
+ .5) * p_del;
+ else
+ td = 0;
+
+ /*
+ * Unfortunately, in many cases the errors are
+ * unacceptable, so for the present the rates are not
+ * used. In future, we might find conditions where the
+ * calculations are useful, so this should be considered
+ * a work in progress.
+ */
+ t21 -= td;
+ t34 -= td;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("packet: del %.6lf r21 %.1lf r34 %.1lf %.6lf\n",
+ p_del, peer->r21 / 1e3, peer->r34 / 1e3,
+ td);
+#endif
+ }
+#endif /* ASSYM */
+
+ /*
+ * That was awesome. Now hand off to the clock filter.
+ */
clock_filter(peer, p_offset, p_del, p_disp);
- record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
- peer->offset, peer->delay, peer->disp, peer->jitter);
+
+ /*
+ * If we are in broadcast calibrate mode, return to broadcast
+ * client mode when the client is fit and the autokey dance is
+ * complete.
+ */
+ if ((FLAG_BC_VOL & peer->flags) && MODE_CLIENT == peer->hmode &&
+ !(TEST11 & peer_unfit(peer))) { /* distance exceeded */
+#ifdef OPENSSL
+ if (peer->flags & FLAG_SKEY) {
+ if (!(~peer->crypto & CRYPTO_FLAG_ALL))
+ peer->hmode = MODE_BCLIENT;
+ } else {
+ peer->hmode = MODE_BCLIENT;
+ }
+#else /* OPENSSL */
+ peer->hmode = MODE_BCLIENT;
+#endif /* OPENSSL */
+ }
}
@@ -1254,39 +1640,74 @@ process_packet(
* clock_update - Called at system process update intervals.
*/
static void
-clock_update(void)
+clock_update(
+ struct peer *peer /* peer structure pointer */
+ )
{
- u_char oleap;
- u_char ostratum;
double dtemp;
-
- /*
- * There must be a system peer at this point. If we just changed
- * the system peer, but have a newer sample from the old one,
- * wait until newer data are available.
- */
- if (sys_poll < sys_peer->minpoll)
- sys_poll = sys_peer->minpoll;
- if (sys_poll > sys_peer->maxpoll)
- sys_poll = sys_peer->maxpoll;
- poll_update(sys_peer, sys_poll);
- if (sys_peer->epoch <= sys_clocktime)
- return;
+ l_fp now;
+#ifdef HAVE_LIBSCF_H
+ char *fmri;
+#endif /* HAVE_LIBSCF_H */
+
+ /*
+ * Update the system state variables. We do this very carefully,
+ * as the poll interval might need to be clamped differently.
+ */
+ sys_peer = peer;
+ sys_epoch = peer->epoch;
+ if (sys_poll < peer->minpoll)
+ sys_poll = peer->minpoll;
+ if (sys_poll > peer->maxpoll)
+ sys_poll = peer->maxpoll;
+ poll_update(peer, sys_poll);
+ sys_stratum = min(peer->stratum + 1, STRATUM_UNSPEC);
+ if (peer->stratum == STRATUM_REFCLOCK ||
+ peer->stratum == STRATUM_UNSPEC)
+ sys_refid = peer->refid;
+ else
+ sys_refid = addr2refid(&peer->srcadr);
+ dtemp = sys_jitter + fabs(sys_offset) + peer->disp +
+ (peer->delay + peer->rootdelay) / 2 + clock_phi *
+ (current_time - peer->update);
+ sys_rootdisp = dtemp + peer->rootdisp;
+ sys_rootdelay = peer->delay + peer->rootdelay;
+ sys_reftime = peer->dst;
#ifdef DEBUG
if (debug)
- printf("clock_update: at %ld assoc %d \n", current_time,
- peer_associations);
+ printf(
+ "clock_update: at %lu sample %lu associd %d\n",
+ current_time, peer->epoch, peer->associd);
#endif
- oleap = sys_leap;
- ostratum = sys_stratum;
- switch (local_clock(sys_peer, sys_offset)) {
+
+ /*
+ * Comes now the moment of truth. Crank the clock discipline and
+ * see what comes out.
+ */
+ switch (local_clock(peer, sys_offset)) {
/*
* Clock exceeds panic threshold. Life as we know it ends.
*/
case -1:
- report_event(EVNT_SYSFAULT, NULL);
+#ifdef HAVE_LIBSCF_H
+ /*
+ * For Solaris enter the maintenance mode.
+ */
+ if ((fmri = getenv("SMF_FMRI")) != NULL) {
+ if (smf_maintain_instance(fmri, 0) < 0) {
+ printf("smf_maintain_instance: %s\n",
+ scf_strerror(scf_error()));
+ exit(1);
+ }
+ /*
+ * Sleep until SMF kills us.
+ */
+ for (;;)
+ pause();
+ }
+#endif /* HAVE_LIBSCF_H */
exit (-1);
/* not reached */
@@ -1297,62 +1718,67 @@ clock_update(void)
clear_all();
sys_leap = LEAP_NOTINSYNC;
sys_stratum = STRATUM_UNSPEC;
- sys_peer = NULL;
- sys_rootdelay = 0;
- sys_rootdispersion = 0;
memcpy(&sys_refid, "STEP", 4);
- report_event(EVNT_CLOCKRESET, NULL);
+ sys_rootdelay = 0;
+ sys_rootdisp = 0;
+ L_CLR(&sys_reftime);
+ sys_jitter = LOGTOD(sys_precision);
+ leapsec = 0;
break;
/*
- * Clock was slewed. Update the system stratum, leap bits, root
- * delay, root dispersion, reference ID and reference time. If
- * the leap changes, we gotta reroll the keys. Except for
- * reference clocks, the minimum dispersion increment is not
- * less than sys_mindisp.
+ * Clock was slewed. Handle the leapsecond stuff.
*/
case 1:
- sys_leap = leap_next;
- sys_stratum = min(sys_peer->stratum + 1,
- STRATUM_UNSPEC);
- sys_reftime = sys_peer->rec;
/*
- * In orphan mode the stratum defaults to the orphan
- * stratum. The root delay is set to a random value
- * generated at startup. The root dispersion is set from
- * the peer dispersion; the peer root dispersion is
- * ignored.
+ * If this is the first time the clock is set, reset the
+ * leap bits. If crypto, the timer will goose the setup
+ * process.
*/
- dtemp = sys_peer->disp + clock_phi * (current_time -
- sys_peer->update) + sys_jitter +
- fabs(sys_peer->offset);
-#ifdef REFCLOCK
- if (!(sys_peer->flags & FLAG_REFCLOCK) && dtemp <
- sys_mindisp)
- dtemp = sys_mindisp;
-#else
- if (dtemp < sys_mindisp)
- dtemp = sys_mindisp;
-#endif /* REFCLOCK */
- if (sys_stratum >= sys_orphan) {
- sys_stratum = sys_orphan;
- sys_rootdelay = sys_peer->delay;
- sys_rootdispersion = dtemp;
- } else {
- sys_rootdelay = sys_peer->delay +
- sys_peer->rootdelay;
- sys_rootdispersion = dtemp +
- sys_peer->rootdispersion;
- }
- if (oleap == LEAP_NOTINSYNC) {
- report_event(EVNT_SYNCCHG, NULL);
+ if (sys_leap == LEAP_NOTINSYNC) {
+ sys_leap = LEAP_NOWARNING;
#ifdef OPENSSL
- expire_all();
- crypto_update();
+ if (crypto_flags)
+ crypto_update();
#endif /* OPENSSL */
}
+
+ /*
+ * If the leapseconds values are from file or network
+ * and the leap is in the future, schedule a leap at the
+ * given epoch. Otherwise, if the number of survivor
+ * leap bits is greater than half the number of
+ * survivors, schedule a leap for the end of the current
+ * month.
+ */
+ get_systime(&now);
+ if (leap_sec > 0) {
+ if (leap_sec > now.l_ui) {
+ sys_tai = leap_tai - 1;
+ if (leapsec == 0)
+ report_event(EVNT_ARMED, NULL,
+ NULL);
+ leapsec = leap_sec - now.l_ui;
+ } else {
+ sys_tai = leap_tai;
+ }
+ break;
+
+ } else if (leap_vote > sys_survivors / 2) {
+ leap_peers = now.l_ui + leap_month(now.l_ui);
+ if (leap_peers > now.l_ui) {
+ if (leapsec == 0)
+ report_event(PEVNT_ARMED, peer,
+ NULL);
+ leapsec = leap_peers - now.l_ui;
+ }
+ } else if (leapsec > 0) {
+ report_event(EVNT_DISARMED, NULL, NULL);
+ leapsec = 0;
+ }
break;
+
/*
* Popcorn spike or step threshold exceeded. Pretend it never
* happened.
@@ -1360,8 +1786,6 @@ clock_update(void)
default:
break;
}
- if (ostratum != sys_stratum)
- report_event(EVNT_PEERSTCHG, NULL);
}
@@ -1370,115 +1794,144 @@ clock_update(void)
*/
void
poll_update(
- struct peer *peer,
+ struct peer *peer, /* peer structure pointer */
int mpoll
)
{
- int hpoll;
+ int hpoll, minpkt;
+ u_long next, utemp;
/*
* This routine figures out when the next poll should be sent.
- * That turns out to be wickedly complicated. The big problem is
- * that sometimes the time for the next poll is in the past.
- * Watch out for races here between the receive process and the
- * poll process. The key assertion is that, if nextdate equals
- * current_time, the call is from the poll process; otherwise,
- * it is from the receive process.
+ * That turns out to be wickedly complicated. One problem is
+ * that sometimes the time for the next poll is in the past when
+ * the poll interval is reduced. We watch out for races here
+ * between the receive process and the poll process.
*
* First, bracket the poll interval according to the type of
* association and options. If a fixed interval is configured,
* use minpoll. This primarily is for reference clocks, but
- * works for any association.
+ * works for any association. Otherwise, clamp the poll interval
+ * between minpoll and maxpoll.
*/
- if (peer->flags & FLAG_FIXPOLL) {
+ if (peer->cast_flags & MDF_BCLNT)
hpoll = peer->minpoll;
-
- /*
- * The ordinary case; clamp the poll interval between minpoll
- * and maxpoll.
- */
- } else {
+ else
hpoll = max(min(peer->maxpoll, mpoll), peer->minpoll);
- }
+
#ifdef OPENSSL
/*
- * Bit of crass arrogance at this point. If the poll interval
- * has changed and we have a keylist, the lifetimes in the
- * keylist are probably bogus. In this case purge the keylist
- * and regenerate it later.
+ * If during the crypto protocol the poll interval has changed,
+ * the lifetimes in the key list are probably bogus. Purge the
+ * the key list and regenerate it later.
*/
- if (hpoll != peer->hpoll)
+ if ((peer->flags & FLAG_SKEY) && hpoll != peer->hpoll)
key_expire(peer);
#endif /* OPENSSL */
peer->hpoll = hpoll;
/*
- * Now we figure out if there is an override. If during the
- * crypto protocol and a message is pending, make it wait not
- * more than two seconds.
- */
-#ifdef OPENSSL
- if (peer->cmmd != NULL && (sys_leap != LEAP_NOTINSYNC ||
- peer->crypto)) {
- peer->nextdate = current_time + RESP_DELAY;
-
- /*
- * If we get called from the receive routine while a burst is
- * pending, just slink away. If from the poll routine and a
- * reference clock or a pending crypto response, delay for one
- * second. If this is the first sent in a burst, wait for the
- * modem to come up. For others in the burst, delay two seconds.
- */
- } else if (peer->burst > 0) {
-#else /* OPENSSL */
+ * There are three variables important for poll scheduling, the
+ * current time (current_time), next scheduled time (nextdate)
+ * and the earliest time (utemp). The earliest time is 2 s
+ * seconds, but could be more due to rate management. When
+ * sending in a burst, use the earliest time. When not in a
+ * burst but with a reply pending, send at the earliest time
+ * unless the next scheduled time has not advanced. This can
+ * only happen if multiple replies are peinding in the same
+ * response interval. Otherwise, send at the later of the next
+ * scheduled time and the earliest time.
+ *
+ * Now we figure out if there is an override. If a burst is in
+ * progress and we get called from the receive process, just
+ * slink away. If called from the poll process, delay 1 s for a
+ * reference clock, otherwise 2 s.
+ */
+ minpkt = 1 << ntp_minpkt;
+ utemp = current_time + max(peer->throttle - (NTP_SHIFT - 1) *
+ (1 << peer->minpoll), minpkt);
if (peer->burst > 0) {
-#endif /* OPENSSL */
- if (peer->nextdate != current_time)
+ if (peer->nextdate > current_time)
return;
#ifdef REFCLOCK
else if (peer->flags & FLAG_REFCLOCK)
- peer->nextdate += RESP_DELAY;
+ peer->nextdate = current_time + RESP_DELAY;
#endif /* REFCLOCK */
- else if (peer->flags & (FLAG_IBURST | FLAG_BURST) &&
- peer->burst == NTP_BURST)
- peer->nextdate += sys_calldelay;
else
- peer->nextdate += BURST_DELAY;
+ peer->nextdate = utemp;
+
+#ifdef OPENSSL
/*
- * The ordinary case; use the minimum of the host and peer
- * intervals, but not less than minpoll. In other words,
- * oversampling is okay but understampling is evil.
+ * If a burst is not in progress and a crypto response message
+ * is pending, delay 2 s, but only if this is a new interval.
*/
- } else {
- peer->nextdate = peer->outdate +
- RANDPOLL(max(min(peer->ppoll, hpoll),
- peer->minpoll));
- }
+ } else if (peer->cmmd != NULL) {
+ if (peer->nextdate > current_time) {
+ if (peer->nextdate + minpkt != utemp)
+ peer->nextdate = utemp;
+ } else {
+ peer->nextdate = utemp;
+ }
+#endif /* OPENSSL */
/*
- * If the time for the next poll has already happened, bring it
- * up to the next second after this one. This way the only way
- * to get nexdate == current time is from the poll routine.
+ * The ordinary case. If a retry, use minpoll; if unreachable,
+ * use host poll; otherwise, use the minimum of host and peer
+ * polls; In other words, oversampling is okay but
+ * understampling is evil. Use the maximum of this value and the
+ * headway. If the average headway is greater than the headway
+ * threshold, increase the headway by the minimum interval.
*/
- if (peer->nextdate <= current_time)
- peer->nextdate = current_time + 1;
+ } else {
+ if (peer->retry > 0)
+ hpoll = peer->minpoll;
+ else if (!(peer->reach))
+ hpoll = peer->hpoll;
+ else
+ hpoll = min(peer->ppoll, peer->hpoll);
+#ifdef REFCLOCK
+ if (peer->flags & FLAG_REFCLOCK)
+ next = 1 << hpoll;
+ else
+ next = ((0x1000UL | (ntp_random() & 0x0ff)) <<
+ hpoll) >> 12;
+#else /* REFCLOCK */
+ next = ((0x1000UL | (ntp_random() & 0x0ff)) << hpoll) >>
+ 12;
+#endif /* REFCLOCK */
+ next += peer->outdate;
+ if (next > utemp)
+ peer->nextdate = next;
+ else
+ peer->nextdate = utemp;
+ hpoll = peer->throttle - (1 << peer->minpoll);
+ if (hpoll > 0)
+ peer->nextdate += minpkt;
+ }
#ifdef DEBUG
if (debug > 1)
- printf("poll_update: at %lu %s flags %04x poll %d burst %d last %lu next %lu\n",
- current_time, ntoa(&peer->srcadr), peer->flags,
- peer->hpoll, peer->burst, peer->outdate,
- peer->nextdate);
+ printf("poll_update: at %lu %s poll %d burst %d retry %d head %d early %lu next %lu\n",
+ current_time, ntoa(&peer->srcadr), peer->hpoll,
+ peer->burst, peer->retry, peer->throttle,
+ utemp - current_time, peer->nextdate -
+ current_time);
#endif
}
+
/*
- * peer_crypto_clear - discard crypto information
+ * peer_clear - clear peer filter registers. See Section 3.4.8 of the
+ * spec.
*/
void
-peer_crypto_clear(
- struct peer *peer
- )
+peer_clear(
+ struct peer *peer, /* peer structure */
+ char *ident /* tally lights */
+ )
{
+ int i;
+
+#ifdef OPENSSL
/*
* If cryptographic credentials have been acquired, toss them to
* Valhalla. Note that autokeys are ephemeral, in that they are
@@ -1488,84 +1941,36 @@ peer_crypto_clear(
* purged, too. This makes it much harder to sneak in some
* unauthenticated data in the clock filter.
*/
- DPRINTF(1, ("peer_crypto_clear: at %ld next %ld assoc ID %d\n",
- current_time, peer->nextdate, peer->associd));
-
-#ifdef OPENSSL
- peer->assoc = 0;
- peer->crypto = 0;
-
- if (peer->pkey != NULL)
- EVP_PKEY_free(peer->pkey);
- peer->pkey = NULL;
-
- peer->digest = NULL; /* XXX MEMLEAK? check whether this needs to be freed in any way - never was freed */
-
- if (peer->subject != NULL)
- free(peer->subject);
- peer->subject = NULL;
-
- if (peer->issuer != NULL)
- free(peer->issuer);
- peer->issuer = NULL;
-
- peer->pkeyid = 0;
-
- peer->pcookie = 0;
-
- if (peer->ident_pkey != NULL)
- EVP_PKEY_free(peer->ident_pkey);
- peer->ident_pkey = NULL;
-
- memset(&peer->fstamp, 0, sizeof(peer->fstamp));
-
+ key_expire(peer);
if (peer->iffval != NULL)
BN_free(peer->iffval);
- peer->iffval = NULL;
-
- if (peer->grpkey != NULL)
- BN_free(peer->grpkey);
- peer->grpkey = NULL;
-
value_free(&peer->cookval);
value_free(&peer->recval);
-
- if (peer->cmmd != NULL) {
- free(peer->cmmd);
- peer->cmmd = NULL;
- }
-
- key_expire(peer);
-
value_free(&peer->encrypt);
+ value_free(&peer->sndval);
+ if (peer->cmmd != NULL)
+ free(peer->cmmd);
+ if (peer->subject != NULL)
+ free(peer->subject);
+ if (peer->issuer != NULL)
+ free(peer->issuer);
#endif /* OPENSSL */
-}
-
-/*
- * peer_clear - clear peer filter registers. See Section 3.4.8 of the spec.
- */
-void
-peer_clear(
- struct peer *peer, /* peer structure */
- char *ident /* tally lights */
- )
-{
- int i;
-
- peer_crypto_clear(peer);
-
- if (peer == sys_peer)
- sys_peer = NULL;
/*
- * Wipe the association clean and initialize the nonzero values.
+ * Clear all values, including the optional crypto values above.
*/
memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
- peer->estbdelay = sys_bdelay;
peer->ppoll = peer->maxpoll;
peer->hpoll = peer->minpoll;
peer->disp = MAXDISPERSE;
+ peer->flash = peer_unfit(peer);
peer->jitter = LOGTOD(sys_precision);
+
+ /*
+ * If interleave mode, initialize the alternate origin switch.
+ */
+ if (peer->flags & FLAG_XLEAVE)
+ peer->flip = 1;
for (i = 0; i < NTP_SHIFT; i++) {
peer->filter_order[i] = i;
peer->filter_disp[i] = MAXDISPERSE;
@@ -1584,21 +1989,28 @@ peer_clear(
/*
* During initialization use the association count to spread out
- * the polls at one-second intervals. Othersie, randomize over
+ * the polls at one-second intervals. Otherwise, randomize over
* the minimum poll interval in order to avoid broadcast
* implosion.
*/
peer->nextdate = peer->update = peer->outdate = current_time;
- if (initializing)
+ if (initializing) {
peer->nextdate += peer_associations;
- else if (peer->hmode == MODE_PASSIVE)
- peer->nextdate += RESP_DELAY;
- else
- peer->nextdate += (ntp_random() & ((1 << NTP_MINDPOLL) -
- 1));
-
- DPRINTF(1, ("peer_clear: at %ld next %ld assoc ID %d refid %s\n",
- current_time, peer->nextdate, peer->associd, ident));
+ } else if (peer->hmode == MODE_PASSIVE) {
+ peer->nextdate += 1 << ntp_minpkt;
+ } else {
+ peer->nextdate += ntp_random() % peer_associations;
+ }
+#ifdef OPENSSL
+ peer->refresh = current_time + (1 << NTP_REFRESH);
+#endif /* OPENSSL */
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "peer_clear: at %ld next %ld associd %d refid %s\n",
+ current_time, peer->nextdate, peer->associd,
+ ident);
+#endif
}
@@ -1618,19 +2030,20 @@ clock_filter(
int ord[NTP_SHIFT]; /* index vector */
int i, j, k, m;
double dtemp, etemp;
+ char tbuf[80];
/*
- * 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.
+ * A sample consists of the offset, delay, dispersion and epoch
+ * of arrival. The offset and delay are determined by the on-
+ * wire protocol. The dispersion grows from the last outbound
+ * packet to the arrival of this one increased by the sum of the
+ * peer precision and the system precision as required by the
+ * error budget. First, shift the new arrival into the shift
+ * register discarding the oldest one.
*/
j = peer->filter_nextpt;
peer->filter_offset[j] = sample_offset;
- peer->filter_delay[j] = max(0, sample_delay);
+ peer->filter_delay[j] = sample_delay;
peer->filter_disp[j] = sample_disp;
peer->filter_epoch[j] = current_time;
j = (j + 1) % NTP_SHIFT;
@@ -1638,40 +2051,42 @@ clock_filter(
/*
* 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.
+ * time initialize the distance and index lists. Since samples
+ * become increasingly uncorrelated beyond the Allan intercept,
+ * only under exceptional cases will an older sample be used.
+ * Therefore, the distance list uses a compound metric. If the
+ * dispersion is greater than the maximum dispersion, clamp the
+ * distance at that value. If the time since the last update is
+ * less than the Allan intercept use the delay; otherwise, use
+ * the sum of the delay and dispersion.
*/
dtemp = clock_phi * (current_time - peer->update);
peer->update = current_time;
for (i = NTP_SHIFT - 1; i >= 0; i--) {
if (i != 0)
peer->filter_disp[j] += dtemp;
- if (peer->filter_disp[j] >= MAXDISPERSE)
+ 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] = sys_maxdist + peer->filter_disp[j];
- else
+ } else if (peer->update - peer->filter_epoch[j] >
+ ULOGTOD(allan_xpt)) {
+ dst[i] = peer->filter_delay[j] +
+ peer->filter_disp[j];
+ } else {
dst[i] = peer->filter_delay[j];
+ }
ord[i] = j;
- j++; j %= NTP_SHIFT;
+ j = (j + 1) % NTP_SHIFT;
}
/*
- * If the clock discipline has stabilized, sort the samples in
- * both lists by distance. Note, we do not displace a higher
- * distance sample by a lower distance one unless lower by at
- * least the precision.
+ * If the clock discipline has stabilized, sort the samples by
+ * distance.
*/
- if (state == 4) {
+ if (sys_leap != LEAP_NOTINSYNC) {
for (i = 1; i < NTP_SHIFT; i++) {
for (j = 0; j < i; j++) {
- if (dst[j] > dst[i] +
- LOGTOD(sys_precision)) {
+ if (dst[j] > dst[i]) {
k = ord[j];
ord[j] = ord[i];
ord[i] = k;
@@ -1685,9 +2100,12 @@ clock_filter(
/*
* Copy the index list to the association structure so ntpq
- * can see it later. Prune the distance list to samples less
- * than max distance, but keep at least two valid samples for
- * jitter calculation.
+ * can see it later. Prune the distance list to leave only
+ * samples less than the maximum dispersion, which disfavors
+ * uncorrelated samples older than the Allan intercept. To
+ * further improve the jitter estimate, of the remainder leave
+ * only samples less than the maximum distance, but keep at
+ * least two samples for jitter calculation.
*/
m = 0;
for (i = 0; i < NTP_SHIFT; i++) {
@@ -1702,9 +2120,7 @@ clock_filter(
* Compute the dispersion and jitter. The dispersion is weighted
* exponentially by NTP_FWEIGHT (0.5) so it is normalized close
* to 1.0. The jitter is the RMS differences relative to the
- * lowest delay sample. If no acceptable samples remain in the
- * shift register, quietly tiptoe home leaving only the
- * dispersion.
+ * lowest delay sample.
*/
peer->disp = peer->jitter = 0;
k = ord[0];
@@ -1723,8 +2139,10 @@ clock_filter(
* save the offset, delay and jitter. Note the jitter must not
* be less than the precision.
*/
- if (m == 0)
+ if (m == 0) {
+ clock_select();
return;
+ }
etemp = fabs(peer->offset - peer->filter_offset[k]);
peer->offset = peer->filter_offset[k];
@@ -1734,47 +2152,51 @@ clock_filter(
peer->jitter = max(SQRT(peer->jitter), LOGTOD(sys_precision));
/*
- * A new sample is useful only if it is younger than the last
- * one used. Note the order is FIFO if the clock discipline has
- * not stabilized.
+ * If the the new sample and the current sample are both valid
+ * and the difference between their offsets exceeds CLOCK_SGATE
+ * (3) times the jitter and the interval between them is less
+ * than twice the host poll interval, consider the new sample
+ * a popcorn spike and ignore it.
*/
- if (peer->filter_epoch[k] <= peer->epoch) {
-#ifdef DEBUG
- if (debug)
- printf("clock_filter: discard %lu\n",
- peer->epoch - peer->filter_epoch[k]);
-#endif
+ if (peer->disp < sys_maxdist && peer->filter_disp[k] <
+ sys_maxdist && etemp > CLOCK_SGATE * peer->jitter &&
+ peer->filter_epoch[k] - peer->epoch < 2. *
+ ULOGTOD(peer->hpoll)) {
+ snprintf(tbuf, sizeof(tbuf), "%.6f s", etemp);
+ report_event(PEVNT_POPCORN, peer, tbuf);
return;
}
/*
- * If the difference between the last offset and the current one
- * exceeds the jitter by CLOCK_SGATE and the interval since the
- * last update is less than twice the system poll interval,
- * consider the update a popcorn spike and ignore it.
+ * A new minimum sample is useful only if it is later than the
+ * last one used. In this design the maximum lifetime of any
+ * sample is not greater than eight times the poll interval, so
+ * the maximum interval between minimum samples is eight
+ * packets.
*/
- if (etemp > CLOCK_SGATE * peer->jitter && m > 1 &&
- peer->filter_epoch[k] - peer->epoch < 2. *
- ULOGTOD(sys_poll)) {
-#ifdef DEBUG
- if (debug)
- printf("clock_filter: popcorn %.6f %.6f\n",
- etemp, dtemp);
+ if (peer->filter_epoch[k] <= peer->epoch) {
+#if DEBUG
+ if (debug)
+ printf("clock_filter: old sample %lu\n", current_time -
+ peer->filter_epoch[k]);
#endif
return;
}
+ peer->epoch = peer->filter_epoch[k];
/*
* The mitigated sample statistics are saved for later
- * processing. If not in a burst, tickle the select.
+ * processing. If not synchronized or not in a burst, tickle the
+ * clock select algorithm.
*/
- peer->epoch = peer->filter_epoch[k];
+ record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
+ peer->offset, peer->delay, peer->disp, peer->jitter);
#ifdef DEBUG
if (debug)
printf(
- "clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f, age %lu\n",
+ "clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f\n",
m, peer->offset, peer->delay, peer->disp,
- peer->jitter, current_time - peer->epoch);
+ peer->jitter);
#endif
if (peer->burst == 0 || sys_leap == LEAP_NOTINSYNC)
clock_select();
@@ -1784,10 +2206,11 @@ clock_filter(
/*
* clock_select - find the pick-of-the-litter clock
*
- * LOCKCLOCK: If the local clock is the prefer peer, it will always be
- * enabled, even if declared falseticker, (2) only the prefer peer can
- * be selected as the system peer, (3) if the external source is down,
- * the system leap bits are set to 11 and the stratum set to infinity.
+ * LOCKCLOCK: (1) If the local clock is the prefer peer, it will always
+ * be enabled, even if declared falseticker, (2) only the prefer peer
+ * caN Be selected as the system peer, (3) if the external source is
+ * down, the system leap bits are set to 11 and the stratum set to
+ * infinity.
*/
void
clock_select(void)
@@ -1795,15 +2218,21 @@ clock_select(void)
struct peer *peer;
int i, j, k, n;
int nlist, nl3;
-
int allow, osurv;
double d, e, f, g;
double high, low;
+ double seljitter;
double synch[NTP_MAXASSOC], error[NTP_MAXASSOC];
- struct peer *osys_peer;
+ double orphmet = 2.0 * U_INT32_MAX; /* 2x is greater than */
+ struct peer *osys_peer = NULL;
+ struct peer *sys_prefer = NULL; /* prefer peer */
+ struct peer *typesystem = NULL;
+ struct peer *typeorphan = NULL;
+#ifdef REFCLOCK
struct peer *typeacts = NULL;
struct peer *typelocal = NULL;
- struct peer *typesystem = NULL;
+ struct peer *typepps = NULL;
+#endif /* REFCLOCK */
static int list_alloc = 0;
static struct endpoint *endpoint = NULL;
@@ -1818,9 +2247,6 @@ clock_select(void)
* enough to handle all associations.
*/
osys_peer = sys_peer;
- sys_peer = NULL;
- sys_pps = NULL;
- sys_prefer = NULL;
osurv = sys_survivors;
sys_survivors = 0;
#ifdef LOCKCLOCK
@@ -1862,8 +2288,7 @@ clock_select(void)
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != NULL; peer =
peer->next) {
- peer->flags &= ~FLAG_SYSPEER;
- peer->status = CTL_PST_SEL_REJECT;
+ peer->new_status = CTL_PST_SEL_REJECT;
/*
* Leave the island immediately if the peer is
@@ -1873,30 +2298,63 @@ clock_select(void)
continue;
/*
- * Don't allow the local clock or modem drivers
- * in the kitchen at this point, unless the
- * prefer peer. Do that later, but only if
- * nobody else is around. These guys are all
- * configured, so we never throw them away.
+ * If this peer is an orphan parent, elect the
+ * one with the lowest metric defined as the
+ * IPv4 address or the first 64 bits of the
+ * hashed IPv6 address. To ensure convergence
+ * on the same selected orphan, consider as
+ * well that this system may have the lowest
+ * metric and be the orphan parent. If this
+ * system wins, sys_peer will be NULL to trigger
+ * orphan mode in timer().
*/
-#ifdef REFCLOCK
- if (peer->refclktype == REFCLK_LOCALCLOCK
-#if defined(VMS) && defined(VMS_LOCALUNIT)
- /* wjm: VMS_LOCALUNIT taken seriously */
- && REFCLOCKUNIT(&peer->srcadr) !=
- VMS_LOCALUNIT
-#endif /* VMS && VMS_LOCALUNIT */
- ) {
- typelocal = peer;
-#ifndef LOCKCLOCK
- if (!(peer->flags & FLAG_PREFER))
- continue; /* no local clock */
-#endif /* LOCKCLOCK */
+ if (peer->stratum == sys_orphan) {
+ u_int32 localmet;
+ u_int32 peermet;
+
+ if (peer->dstadr != NULL)
+ localmet = ntohl(peer->dstadr->addr_refid);
+ else
+ localmet = U_INT32_MAX;
+ peermet = ntohl(addr2refid(&peer->srcadr));
+ if (peermet < localmet &&
+ peermet < orphmet) {
+ typeorphan = peer;
+ orphmet = peermet;
+ }
+ continue;
}
- if (peer->sstclktype == CTL_SST_TS_TELEPHONE) {
- typeacts = peer;
- if (!(peer->flags & FLAG_PREFER))
- continue; /* no acts */
+
+ /*
+ * If this peer could have the orphan parent
+ * as a synchronization ancestor, exclude it
+ * from selection to avoid forming a
+ * synchronization loop within the orphan mesh,
+ * triggering stratum climb to infinity
+ * instability. Peers at stratum higher than
+ * the orphan stratum could have the orphan
+ * parent in ancestry so are excluded.
+ * See http://bugs.ntp.org/2050
+ */
+ if (peer->stratum > sys_orphan)
+ continue;
+#ifdef REFCLOCK
+ /*
+ * The following are special cases. We deal
+ * with them later.
+ */
+ if (!(peer->flags & FLAG_PREFER)) {
+ switch (peer->refclktype) {
+ case REFCLK_LOCALCLOCK:
+ if (typelocal == NULL)
+ typelocal = peer;
+ continue;
+
+ case REFCLK_ACTS:
+ if (typeacts == NULL)
+ typeacts = peer;
+ continue;
+ }
}
#endif /* REFCLOCK */
@@ -1905,7 +2363,7 @@ clock_select(void)
* island, but does not yet have the immunity
* idol.
*/
- peer->status = CTL_PST_SEL_SANE;
+ peer->new_status = CTL_PST_SEL_SANE;
peer_list[nlist++] = peer;
/*
@@ -1974,7 +2432,7 @@ clock_select(void)
*
* Here, nlist is the number of candidates and allow is the
* number of falsetickers. Upon exit, the truechimers are the
- * susvivors with offsets not less than low and not greater than
+ * survivors with offsets not less than low and not greater than
* high. There may be none of them.
*/
low = 1e9;
@@ -2031,28 +2489,34 @@ clock_select(void)
* NTP_MAXASSOC of them. Scan the list to find falsetickers, who
* leave the island immediately. The TRUE peer is always a
* truechimer. We must leave at least one peer to collect the
- * million bucks. If in orphan mode, rascals found with lower
- * stratum are guaranteed a seat on the bus.
+ * million bucks.
*/
j = 0;
for (i = 0; i < nlist; i++) {
peer = peer_list[i];
if (nlist > 1 && (peer->offset <= low || peer->offset >=
- high) && !(peer->flags & FLAG_TRUE) &&
- !(sys_stratum >= sys_orphan && peer->stratum <
- sys_orphan))
+ high) && !(peer->flags & FLAG_TRUE))
continue;
- peer->status = CTL_PST_SEL_DISTSYSPEER;
+#ifdef REFCLOCK
+ /*
+ * Eligible PPS peers must survive the intersection
+ * algorithm. Use the first one found, but don't
+ * include any of them in the cluster population.
+ */
+ if (peer->flags & FLAG_PPS) {
+ if (typepps == NULL)
+ typepps = peer;
+ continue;
+ }
+#endif /* REFCLOCK */
/*
- * The order metric is formed from the stratum times
- * max distance (1.) plus the root distance. It strongly
- * favors the lowest stratum, but a higher stratum peer
- * can capture the clock if the low stratum dominant
- * hasn't been heard for awhile.
+ * The metric is the scaled root distance at the next
+ * poll interval plus the peer stratum.
*/
- d = root_distance(peer) + peer->stratum * sys_maxdist;
+ d = (root_distance(peer) + clock_phi * (peer->nextdate -
+ current_time)) / sys_maxdist + peer->stratum;
if (j >= NTP_MAXASSOC) {
if (d >= synch[j - 1])
continue;
@@ -2075,44 +2539,40 @@ clock_select(void)
nlist = j;
/*
- * If no survivors remain at this point, check if the local
- * clock or modem drivers have been found. If so, nominate one
- * of them as the only survivor. Otherwise, give up and leave
- * the island to the rats.
+ * If no survivors remain at this point, check if the modem
+ * driver, local driver or orphan parent in that order. If so,
+ * nominate the first one found as the only survivor.
+ * Otherwise, give up and leave the island to the rats.
*/
if (nlist == 0) {
- if (typeacts != 0) {
- typeacts->status = CTL_PST_SEL_DISTSYSPEER;
+ error[0] = 0;
+ synch[0] = 0;
+#ifdef REFCLOCK
+ if (typeacts != NULL) {
peer_list[0] = typeacts;
nlist = 1;
- } else if (typelocal != 0) {
- typelocal->status = CTL_PST_SEL_DISTSYSPEER;
+ } else if (typelocal != NULL) {
peer_list[0] = typelocal;
nlist = 1;
- } else {
- if (osys_peer != NULL) {
- NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO,
- "no servers reachable");
- report_event(EVNT_PEERSTCHG, NULL);
- }
+ } else
+#endif /* REFCLOCK */
+ if (typeorphan != NULL) {
+ peer_list[0] = typeorphan;
+ nlist = 1;
}
}
/*
- * We can only trust the survivors if the number of candidates
- * sys_minsane is at least the number required to detect and
- * cast out one falsticker. For the Byzantine agreement
- * algorithm used here, that number is 4; however, the default
- * sys_minsane is 1 to speed initial synchronization. Careful
- * operators will tinker a higher value and use at least that
- * number of synchronization sources.
+ * Mark the candidates at this point as truechimers.
*/
- if (nlist < sys_minsane)
- return;
-
- for (i = 0; i < nlist; i++)
- peer_list[i]->status = CTL_PST_SEL_SELCAND;
+ for (i = 0; i < nlist; i++) {
+ peer_list[i]->new_status = CTL_PST_SEL_SELCAND;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("select: survivor %s %f\n",
+ stoa(&peer_list[i]->srcadr), synch[i]);
+#endif
+ }
/*
* Now, vote outlyers off the island by select jitter weighted
@@ -2122,6 +2582,7 @@ clock_select(void)
* discard a TRUE or PREFER peer, who of course has the
* immunity idol.
*/
+ seljitter = 0;
while (1) {
d = 1e9;
e = -1e9;
@@ -2144,17 +2605,25 @@ clock_select(void)
}
}
f = max(f, LOGTOD(sys_precision));
- if (nlist <= sys_minclock || f <= d ||
- peer_list[k]->flags & (FLAG_TRUE | FLAG_PREFER))
+ if (nlist <= sys_minsane || nlist <= sys_minclock) {
+ break;
+
+ } else if (f <= d || peer_list[k]->flags &
+ (FLAG_TRUE | FLAG_PREFER)) {
+ seljitter = f;
break;
+ }
#ifdef DEBUG
if (debug > 2)
printf(
- "select: drop %s select %.6f jitter %.6f\n",
+ "select: drop %s seljit %.6f jit %.6f\n",
ntoa(&peer_list[k]->srcadr), g, d);
#endif
+ if (nlist > sys_maxclock)
+ peer_list[k]->new_status = CTL_PST_SEL_EXCESS;
for (j = k + 1; j < nlist; j++) {
peer_list[j - 1] = peer_list[j];
+ synch[j - 1] = synch[j];
error[j - 1] = error[j];
}
nlist--;
@@ -2162,156 +2631,147 @@ clock_select(void)
/*
* What remains is a list usually not greater than sys_minclock
- * peers. We want only a peer at the lowest stratum to become
- * the system peer, although all survivors are eligible for the
- * combining algorithm. Consider each peer in turn and OR the
- * leap bits on the assumption that, if some of them honk
- * nonzero bits, they must know what they are doing. Check for
- * prefer and pps peers at any stratum. Note that the head of
- * the list is at the lowest stratum and that unsynchronized
- * peers cannot survive this far.
- */
- leap_next = 0;
+ * peers. Note that the head of the list is the system peer at
+ * the lowest stratum and that unsynchronized peers cannot
+ * survive this far.
+ *
+ * While at it, count the number of leap warning bits found.
+ * This will be used later to vote the system leap warning bit.
+ * If a leap warning bit is found on a reference clock, the vote
+ * is always won.
+ */
+ leap_vote = 0;
for (i = 0; i < nlist; i++) {
peer = peer_list[i];
+ peer->unreach = 0;
+ peer->new_status = CTL_PST_SEL_SYNCCAND;
sys_survivors++;
- leap_next |= peer->leap;
- peer->status = CTL_PST_SEL_SYNCCAND;
+ if (peer->leap == LEAP_ADDSECOND) {
+ if (peer->flags & FLAG_REFCLOCK)
+ leap_vote = nlist;
+ else
+ leap_vote++;
+ }
if (peer->flags & FLAG_PREFER)
sys_prefer = peer;
- if (peer == osys_peer)
- typesystem = peer;
-#ifdef REFCLOCK
- if (peer->refclktype == REFCLK_ATOM_PPS)
- sys_pps = peer;
-#endif /* REFCLOCK */
-#if DEBUG
- if (debug > 1)
- printf("cluster: survivor %s metric %.6f\n",
- ntoa(&peer_list[i]->srcadr), synch[i]);
-#endif
}
/*
- * Anticlockhop provision. Keep the current system peer if it is
- * a survivor but not first in the list. But do that only HOPPER
- * times.
+ * Unless there are at least sys_misane survivors, leave the
+ * building dark. Otherwise, do a clockhop dance. Ordinarily,
+ * use the first survivor on the survivor list. However, if the
+ * last selection is not first on the list, use it as long as
+ * it doesn't get too old or too ugly.
*/
- if (osys_peer == NULL || typesystem == NULL || typesystem ==
- peer_list[0] || sys_hopper > sys_maxhop) {
+ if (nlist > 0 && nlist >= sys_minsane) {
+ double x;
+
typesystem = peer_list[0];
- sys_hopper = 0;
- } else {
- peer->selbroken++;
+ if (osys_peer == NULL || osys_peer == typesystem) {
+ sys_clockhop = 0;
+ } else if ((x = fabs(typesystem->offset -
+ osys_peer->offset)) < sys_mindisp) {
+ if (sys_clockhop == 0)
+ sys_clockhop = sys_mindisp;
+ else
+ sys_clockhop *= .5;
+#ifdef DEBUG
+ if (debug)
+ printf("select: clockhop %d %.6f %.6f\n",
+ j, x, sys_clockhop);
+#endif
+ if (fabs(x) < sys_clockhop)
+ typesystem = osys_peer;
+ else
+ sys_clockhop = 0;
+ } else {
+ sys_clockhop = 0;
+ }
}
/*
- * Mitigation rules of the game. There are several types of
- * peers that can be selected here: (1) orphan, (2) prefer peer
- * (flag FLAG_PREFER) (3) pps peers (type REFCLK_ATOM_PPS), (4)
- * the existing system peer, if any, and (5) the head of the
- * survivor list.
+ * Mitigation rules of the game. We have the pick of the
+ * litter in typesystem if any survivors are left. If
+ * there is a prefer peer, use its offset and jitter.
+ * Otherwise, use the combined offset and jitter of all kitters.
*/
- if (typesystem->stratum >= sys_orphan) {
-
- /*
- * If in orphan mode, choose the system peer. If the
- * lowest distance, we are the orphan parent and the
- * offset is zero.
- */
- sys_peer = typesystem;
- sys_peer->status = CTL_PST_SEL_SYSPEER;
- if (sys_orphandelay < sys_peer->rootdelay) {
- sys_offset = 0;
- sys_refid = htonl(LOOPBACKADR);
+ if (typesystem != NULL) {
+ if (sys_prefer == NULL) {
+ typesystem->new_status = CTL_PST_SEL_SYSPEER;
+ clock_combine(peer_list, sys_survivors);
+ sys_jitter = SQRT(SQUARE(sys_jitter) +
+ SQUARE(seljitter));
} else {
- sys_offset = sys_peer->offset;
- sys_refid = addr2refid(&sys_peer->srcadr);
+ typesystem = sys_prefer;
+ sys_clockhop = 0;
+ typesystem->new_status = CTL_PST_SEL_SYSPEER;
+ sys_offset = typesystem->offset;
+ sys_jitter = typesystem->jitter;
}
- sys_jitter = LOGTOD(sys_precision);
#ifdef DEBUG
- if (debug > 1)
- printf("select: orphan offset %.6f\n",
- sys_offset);
-#endif
- } else if (sys_prefer) {
-
- /*
- * If a pps peer is present, choose it; otherwise,
- * choose the prefer peer.
- */
- if (sys_pps) {
- sys_peer = sys_pps;
- sys_peer->status = CTL_PST_SEL_PPS;
- sys_offset = sys_peer->offset;
- if (!pps_control)
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO,
- "pps sync enabled");
- pps_control = current_time;
-#ifdef DEBUG
- if (debug > 1)
- printf("select: pps offset %.6f\n",
- sys_offset);
-#endif
- } else {
- sys_peer = sys_prefer;
- sys_peer->status = CTL_PST_SEL_SYSPEER;
- sys_offset = sys_peer->offset;
-#ifdef DEBUG
- if (debug > 1)
- printf("select: prefer offset %.6f\n",
- sys_offset);
+ if (debug)
+ printf("select: combine offset %.9f jitter %.9f\n",
+ sys_offset, sys_jitter);
#endif
- }
- if (sys_peer->stratum == STRATUM_REFCLOCK ||
- sys_peer->stratum == STRATUM_UNSPEC)
- sys_refid = sys_peer->refid;
- else
- sys_refid = addr2refid(&sys_peer->srcadr);
- sys_jitter = sys_peer->jitter;
- } else {
-
- /*
- * Otherwise, choose the anticlockhopper.
- */
- sys_peer = typesystem;
- sys_peer->status = CTL_PST_SEL_SYSPEER;
- clock_combine(peer_list, nlist);
- if (sys_peer->stratum == STRATUM_REFCLOCK ||
- sys_peer->stratum == STRATUM_UNSPEC)
- sys_refid = sys_peer->refid;
- else
- sys_refid = addr2refid(&sys_peer->srcadr);
- sys_jitter = SQRT(SQUARE(sys_peer->jitter) +
- SQUARE(sys_jitter));
+ }
+#ifdef REFCLOCK
+ /*
+ * If a PPS driver is lit and the combined offset is less than
+ * 0.4 s, select the driver as the PPS peer and use its offset
+ * and jitter. However, if this is the atom driver, use it only
+ * if there is a prefer peer or there are no survivors and none
+ * are required.
+ */
+ if (typepps != NULL && fabs(sys_offset) < 0.4 &&
+ (typepps->refclktype != REFCLK_ATOM_PPS ||
+ (typepps->refclktype == REFCLK_ATOM_PPS && (sys_prefer !=
+ NULL || (typesystem == NULL && sys_minsane == 0))))) {
+ typesystem = typepps;
+ sys_clockhop = 0;
+ typesystem->new_status = CTL_PST_SEL_PPS;
+ sys_offset = typesystem->offset;
+ sys_jitter = typesystem->jitter;
#ifdef DEBUG
- if (debug > 1)
- printf("select: combine offset %.6f\n",
- sys_offset);
+ if (debug)
+ printf("select: pps offset %.9f jitter %.9f\n",
+ sys_offset, sys_jitter);
#endif
}
+#endif /* REFCLOCK */
/*
- * We have found the alpha male.
+ * If there are no survivors at this point, there is no
+ * system peer. If so and this is an old update, keep the
+ * current statistics, but do not update the clock.
*/
- sys_peer->flags |= FLAG_SYSPEER;
- if (osys_peer != sys_peer) {
- char *src;
+ if (typesystem == NULL) {
+ if (osys_peer != NULL)
+ report_event(EVNT_NOPEER, NULL, NULL);
+ sys_peer = NULL;
+ for (n = 0; n < NTP_HASH_SIZE; n++)
+ for (peer = peer_hash[n]; peer != NULL; peer =
+ peer->next)
+ peer->status = peer->new_status;
+ return;
+ }
- report_event(EVNT_PEERSTCHG, NULL);
+ /*
+ * Do not use old data, as this may mess up the clock discipline
+ * stability.
+ */
+ if (typesystem->epoch <= sys_epoch)
+ return;
-#ifdef REFCLOCK
- if (sys_peer->flags & FLAG_REFCLOCK)
- src = refnumtoa(&sys_peer->srcadr);
- else
-#endif /* REFCLOCK */
- src = ntoa(&sys_peer->srcadr);
- NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO, "synchronized to %s, stratum %d",
- src, sys_peer->stratum);
- }
- clock_update();
+ /*
+ * We have found the alpha male. Wind the clock.
+ */
+ if (osys_peer != typesystem)
+ report_event(PEVNT_NEWPEER, typesystem, NULL);
+ for (n = 0; n < NTP_HASH_SIZE; n++)
+ for (peer = peer_hash[n]; peer != NULL; peer =
+ peer->next)
+ peer->status = peer->new_status;
+ clock_update(typesystem);
}
@@ -2320,8 +2780,8 @@ clock_select(void)
*/
static void
clock_combine(
- struct peer **peers, /* survivor list */
- int npeers /* number of survivors */
+ struct peer **peers, /* survivor list */
+ int npeers /* number of survivors */
)
{
int i;
@@ -2338,32 +2798,33 @@ clock_combine(
sys_jitter = SQRT(w / y);
}
+
/*
* root_distance - compute synchronization distance from peer to root
*/
static double
root_distance(
- struct peer *peer
+ struct peer *peer /* peer structure pointer */
)
{
- double dist;
+ double dtemp;
/*
* Careful squeak here. The value returned must be greater than
* the minimum root dispersion in order to avoid clockhop with
- * highly precise reference clocks. In orphan mode lose the peer
- * root delay, as that is used by the election algorithm.
- */
- if (peer->stratum >= sys_orphan)
- dist = 0;
- else
- dist = peer->rootdelay;
- dist += max(sys_mindisp, dist + peer->delay) / 2 +
- peer->rootdispersion + peer->disp + clock_phi *
- (current_time - peer->update) + peer->jitter;
- return (dist);
+ * highly precise reference clocks. Note that the root distance
+ * cannot exceed the sys_maxdist, as this is the cutoff by the
+ * selection algorithm.
+ */
+ dtemp = (peer->delay + peer->rootdelay) / 2 + peer->disp +
+ peer->rootdisp + clock_phi * (current_time - peer->update) +
+ peer->jitter;
+ if (dtemp < sys_mindisp)
+ dtemp = sys_mindisp;
+ return (dtemp);
}
+
/*
* peer_xmit - send packet for persistent association.
*/
@@ -2375,64 +2836,22 @@ peer_xmit(
struct pkt xpkt; /* transmit packet */
int sendlen, authlen;
keyid_t xkeyid = 0; /* transmit key ID */
- l_fp xmt_tx;
+ l_fp xmt_tx, xmt_ty;
- if (!peer->dstadr) /* don't bother with peers without interface */
+ if (!peer->dstadr) /* drop peers without interface */
return;
- /*
- * This is deliciously complicated. There are three cases.
- *
- * case leap stratum refid delay dispersion
- *
- * normal system system system system system
- * orphan child 00 orphan system orphan system
- * orphan parent 00 orphan loopbk 0 0
- */
- /*
- * This is a normal packet. Use the system variables.
- */
- if (sys_stratum < sys_orphan) {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
- peer->version, peer->hmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
- xpkt.refid = sys_refid;
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
-
- /*
- * This is a orphan child packet. The host is synchronized to an
- * orphan parent. Show leap synchronized, orphan stratum, system
- * reference ID, orphan root delay and system root dispersion.
- */
- } else if (sys_peer != NULL) {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
- peer->version, peer->hmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
- xpkt.refid = htonl(LOOPBACKADR);
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_orphandelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
-
- /*
- * This is an orphan parent. Show leap synchronized, orphan
- * stratum, loopack reference ID and zero root delay and root
- * dispersion.
- */
- } else {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
- peer->version, peer->hmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
- xpkt.refid = sys_refid;
- xpkt.rootdelay = 0;
- xpkt.rootdispersion = 0;
- }
+ xpkt.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.refid = sys_refid;
+ xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+ xpkt.rootdisp = HTONS_FP(DTOUFP(sys_rootdisp));
HTONL_FP(&sys_reftime, &xpkt.reftime);
- HTONL_FP(&peer->org, &xpkt.org);
- HTONL_FP(&peer->rec, &xpkt.rec);
+ HTONL_FP(&peer->rec, &xpkt.org);
+ HTONL_FP(&peer->dst, &xpkt.rec);
/*
* If the received packet contains a MAC, the transmitted packet
@@ -2447,28 +2866,73 @@ peer_xmit(
* might not be usable.
*/
sendlen = LEN_PKT_NOMAC;
- if (!(peer->flags & FLAG_AUTHENABLE)) {
- get_systime(&peer->xmt);
- HTONL_FP(&peer->xmt, &xpkt.xmt);
+#ifdef OPENSSL
+ if (!(peer->flags & FLAG_SKEY) && peer->keyid == 0) {
+#else
+ if (peer->keyid == 0) {
+#endif /* OPENSSL */
+
+ /*
+ * Transmit a-priori timestamps
+ */
+ get_systime(&xmt_tx);
+ if (peer->flip == 0) { /* basic mode */
+ peer->aorg = xmt_tx;
+ HTONL_FP(&xmt_tx, &xpkt.xmt);
+ } else { /* interleaved modes */
+ if (peer->hmode == MODE_BROADCAST) { /* bcst */
+ HTONL_FP(&xmt_tx, &xpkt.xmt);
+ if (peer->flip > 0)
+ HTONL_FP(&peer->borg,
+ &xpkt.org);
+ else
+ HTONL_FP(&peer->aorg,
+ &xpkt.org);
+ } else { /* symmetric */
+ if (peer->flip > 0)
+ HTONL_FP(&peer->borg,
+ &xpkt.xmt);
+ else
+ HTONL_FP(&peer->aorg,
+ &xpkt.xmt);
+ }
+ }
+ peer->t21_bytes = sendlen;
sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl],
- &xpkt, sendlen);
+ &xpkt, sendlen);
peer->sent++;
+ peer->throttle += (1 << peer->minpoll) - 2;
+
+ /*
+ * Capture a-posteriori timestamps
+ */
+ get_systime(&xmt_ty);
+ if (peer->flip != 0) { /* interleaved modes */
+ if (peer->flip > 0)
+ peer->aorg = xmt_ty;
+ else
+ peer->borg = xmt_ty;
+ peer->flip = -peer->flip;
+ }
+ L_SUB(&xmt_ty, &xmt_tx);
+ LFPTOD(&xmt_ty, peer->xleave);
#ifdef DEBUG
if (debug)
- printf("transmit: at %ld %s->%s mode %d\n",
- current_time, peer->dstadr ? stoa(&peer->dstadr->sin) : "-",
- stoa(&peer->srcadr), peer->hmode);
+ printf("transmit: at %ld %s->%s mode %d len %d\n",
+ current_time, peer->dstadr ?
+ stoa(&peer->dstadr->sin) : "-",
+ stoa(&peer->srcadr), peer->hmode, sendlen);
#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, symmetric key cryptography is used.
+ * Authentication is enabled, so the transmitted packet must be
+ * authenticated. If autokey is enabled, fuss with the various
+ * modes; otherwise, symmetric key cryptography is used.
*/
#ifdef OPENSSL
- if (crypto_flags && (peer->flags & FLAG_SKEY)) {
+ if (peer->flags & FLAG_SKEY) {
struct exten *exten; /* extension field */
/*
@@ -2484,7 +2948,7 @@ peer_xmit(
* 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.
+ * one command and one or more responses.
*
* Cryptographic session keys include both a public and
* a private componet. Request and response messages
@@ -2510,10 +2974,10 @@ peer_xmit(
* 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.
+ * key cache, a birthday has happened or the key
+ * has expired, so the pseudo-random sequence is
+ * broken. In that case, purge the keylist and
+ * regenerate it.
*/
if (peer->keynumber == 0)
make_keylist(peer, peer->dstadr);
@@ -2529,223 +2993,212 @@ peer_xmit(
exten = NULL;
switch (peer->hmode) {
- /*
- * In broadcast server mode the autokey values are
- * required by the broadcast clients. Push them when a
- * new keylist is generated; otherwise, push the
- * association message so the client can request them at
- * other times.
- */
+ /*
+ * In broadcast server mode the autokey values are
+ * required by the broadcast clients. Push them when a
+ * new keylist is generated; otherwise, push the
+ * association message so the client can request them at
+ * other times.
+ */
case MODE_BROADCAST:
if (peer->flags & FLAG_ASSOC)
exten = crypto_args(peer, CRYPTO_AUTO |
- CRYPTO_RESP, NULL);
+ CRYPTO_RESP, peer->associd, NULL);
else
exten = crypto_args(peer, CRYPTO_ASSOC |
- CRYPTO_RESP, NULL);
+ CRYPTO_RESP, peer->associd, NULL);
break;
/*
- * In symmetric modes the digest, certificate, agreement
- * parameters, cookie and autokey values are required.
- * The leapsecond table is optional. But, a passive peer
- * will not believe the active peer until the latter has
- * synchronized, so the agreement must be postponed
- * until then. In any case, if a new keylist is
- * generated, the autokey values are pushed.
- *
- * If the crypto bit is lit, don't send requests.
+ * In symmetric modes the parameter, certificate,
+ * identity, cookie and autokey exchanges are
+ * required. The leapsecond exchange is optional. But, a
+ * peer will not believe the other peer until the other
+ * peer has synchronized, so the certificate exchange
+ * might loop until then. If a peer finds a broken
+ * autokey sequence, it uses the autokey exchange to
+ * retrieve the autokey values. In any case, if a new
+ * keylist is generated, the autokey values are pushed.
*/
case MODE_ACTIVE:
case MODE_PASSIVE:
- if (peer->flash & TEST9)
- break;
+
/*
- * Parameter and certificate.
+ * Parameter, certificate and identity.
*/
if (!peer->crypto)
exten = crypto_args(peer, CRYPTO_ASSOC,
- sys_hostname);
- else if (!(peer->crypto & CRYPTO_FLAG_VALID))
+ peer->associd, sys_hostname);
+ else if (!(peer->crypto & CRYPTO_FLAG_CERT))
exten = crypto_args(peer, CRYPTO_CERT,
- peer->issuer);
-
- /*
- * Identity. Note we have to sign the
- * certificate before the cookie to avoid a
- * deadlock when the passive peer is walking the
- * certificate trail. Awesome.
- */
+ peer->associd, peer->issuer);
else if (!(peer->crypto & CRYPTO_FLAG_VRFY))
exten = crypto_args(peer,
- crypto_ident(peer), NULL);
- else if (sys_leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_SIGN))
- exten = crypto_args(peer, CRYPTO_SIGN,
- sys_hostname);
+ crypto_ident(peer), peer->associd,
+ NULL);
/*
- * Autokey. We request the cookie only when the
- * server and client are synchronized and
- * signatures work both ways. On the other hand,
- * the active peer needs the autokey values
- * before then and when the passive peer is
- * waiting for the active peer to synchronize.
- * Any time we regenerate the key list, we offer
- * the autokey values without being asked.
+ * Cookie and autokey. We request the cookie
+ * only when the this peer and the other peer
+ * are synchronized. But, this peer needs the
+ * autokey values when the cookie is zero. Any
+ * time we regenerate the key list, we offer the
+ * autokey values without being asked. If for
+ * some reason either peer finds a broken
+ * autokey sequence, the autokey exchange is
+ * used to retrieve the autokey values.
*/
else if (sys_leap != LEAP_NOTINSYNC &&
- peer->leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_AGREE))
+ peer->leap != LEAP_NOTINSYNC &&
+ !(peer->crypto & CRYPTO_FLAG_COOK))
exten = crypto_args(peer, CRYPTO_COOK,
- NULL);
- else if (peer->flags & FLAG_ASSOC)
- exten = crypto_args(peer, CRYPTO_AUTO |
- CRYPTO_RESP, NULL);
+ peer->associd, NULL);
else if (!(peer->crypto & CRYPTO_FLAG_AUTO))
exten = crypto_args(peer, CRYPTO_AUTO,
- NULL);
+ peer->associd, NULL);
+ else if (peer->flags & FLAG_ASSOC &&
+ peer->crypto & CRYPTO_FLAG_SIGN)
+ exten = crypto_args(peer, CRYPTO_AUTO |
+ CRYPTO_RESP, peer->assoc, NULL);
/*
- * Postamble. We trade leapseconds only when the
- * server and client are synchronized.
+ * Wait for clock sync, then sign the
+ * certificate and retrieve the leapsecond
+ * values.
*/
- else if (sys_leap != LEAP_NOTINSYNC &&
- peer->leap != LEAP_NOTINSYNC &&
- peer->crypto & CRYPTO_FLAG_TAI &&
- !(peer->crypto & CRYPTO_FLAG_LEAP))
- exten = crypto_args(peer, CRYPTO_TAI,
- NULL);
+ else if (sys_leap == LEAP_NOTINSYNC)
+ break;
+
+ else if (!(peer->crypto & CRYPTO_FLAG_SIGN))
+ exten = crypto_args(peer, CRYPTO_SIGN,
+ peer->associd, sys_hostname);
+ else if (!(peer->crypto & CRYPTO_FLAG_LEAP))
+ exten = crypto_args(peer, CRYPTO_LEAP,
+ peer->associd, NULL);
break;
/*
- * In client mode the digest, certificate, agreement
- * parameters and cookie are required. The leapsecond
- * table is optional. If broadcast client mode, the
- * autokey values are required as well. In broadcast
- * client mode, these values must be acquired during the
- * client/server exchange to avoid having to wait until
- * the next key list regeneration. Otherwise, the poor
- * dude may die a lingering death until becoming
- * unreachable and attempting rebirth.
- *
- * If neither the server or client have the agreement
- * parameters, the protocol transmits the cookie in the
- * clear. If the server has the parameters, the client
- * requests them and the protocol blinds it using the
- * agreed key. It is a protocol error if the client has
- * the parameters but the server does not.
- *
- * If the crypto bit is lit, don't send requests.
+ * In client mode the parameter, certificate, identity,
+ * cookie and sign exchanges are required. The
+ * leapsecond exchange is optional. If broadcast client
+ * mode the same exchanges are required, except that the
+ * autokey exchange is substitutes for the cookie
+ * exchange, since the cookie is always zero. If the
+ * broadcast client finds a broken autokey sequence, it
+ * uses the autokey exchange to retrieve the autokey
+ * values.
*/
case MODE_CLIENT:
- if (peer->flash & TEST9)
- break;
+
/*
- * Parameter and certificate.
+ * Parameter, certificate and identity.
*/
if (!peer->crypto)
exten = crypto_args(peer, CRYPTO_ASSOC,
- sys_hostname);
- else if (!(peer->crypto & CRYPTO_FLAG_VALID))
+ peer->associd, sys_hostname);
+ else if (!(peer->crypto & CRYPTO_FLAG_CERT))
exten = crypto_args(peer, CRYPTO_CERT,
- peer->issuer);
-
- /*
- * Identity
- */
+ peer->associd, peer->issuer);
else if (!(peer->crypto & CRYPTO_FLAG_VRFY))
exten = crypto_args(peer,
- crypto_ident(peer), NULL);
+ crypto_ident(peer), peer->associd,
+ NULL);
/*
- * Autokey
+ * Cookie and autokey. These are requests, but
+ * we use the peer association ID with autokey
+ * rather than our own.
*/
- else if (!(peer->crypto & CRYPTO_FLAG_AGREE))
+ else if (!(peer->crypto & CRYPTO_FLAG_COOK))
exten = crypto_args(peer, CRYPTO_COOK,
- NULL);
- else if (!(peer->crypto & CRYPTO_FLAG_AUTO) &&
- (peer->cast_flags & MDF_BCLNT))
+ peer->associd, NULL);
+ else if (!(peer->crypto & CRYPTO_FLAG_AUTO))
exten = crypto_args(peer, CRYPTO_AUTO,
- NULL);
+ peer->assoc, NULL);
/*
- * Postamble. We can sign the certificate here,
- * since there is no chance of deadlock.
+ * Wait for clock sync, then sign the
+ * certificate and retrieve the leapsecond
+ * values.
*/
- else if (sys_leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_SIGN))
+ else if (sys_leap == LEAP_NOTINSYNC)
+ break;
+
+ else if (!(peer->crypto & CRYPTO_FLAG_SIGN))
exten = crypto_args(peer, CRYPTO_SIGN,
- sys_hostname);
- else if (sys_leap != LEAP_NOTINSYNC &&
- peer->crypto & CRYPTO_FLAG_TAI &&
- !(peer->crypto & CRYPTO_FLAG_LEAP))
- exten = crypto_args(peer, CRYPTO_TAI,
- NULL);
+ peer->associd, sys_hostname);
+ else if (!(peer->crypto & CRYPTO_FLAG_LEAP))
+ exten = crypto_args(peer, CRYPTO_LEAP,
+ peer->associd, NULL);
break;
}
/*
- * Build the extension fields as directed. A response to
- * a request is always sent, even if an error. If an
- * error occurs when sending a request, the crypto
- * machinery broke or was misconfigured. In that case
- * light the crypto bit to suppress further requests.
+ * Add a queued extension field if present. This is
+ * always a request message, so the reply ID is already
+ * in the message. If an error occurs, the error bit is
+ * lit in the response.
*/
if (peer->cmmd != NULL) {
- peer->cmmd->associd = htonl(peer->associd);
- sendlen += crypto_xmit(&xpkt, &peer->srcadr,
- sendlen, peer->cmmd, 0);
+ u_int32 temp32;
+
+ temp32 = CRYPTO_RESP;
+ peer->cmmd->opcode |= htonl(temp32);
+ sendlen += crypto_xmit(peer, &xpkt, NULL,
+ sendlen, peer->cmmd, 0);
free(peer->cmmd);
peer->cmmd = NULL;
}
+
+ /*
+ * Add an extension field created above. All but the
+ * autokey response message are request messages.
+ */
if (exten != NULL) {
- int ltemp = 0;
-
- if (exten->opcode != 0) {
- ltemp = crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, exten, 0);
- if (ltemp == 0) {
- peer->flash |= TEST9; /* crypto error */
- free(exten);
- return;
- }
- }
- sendlen += ltemp;
+ if (exten->opcode != 0)
+ sendlen += crypto_xmit(peer, &xpkt,
+ NULL, sendlen, exten, 0);
free(exten);
}
/*
- * If extension fields are present, we must use a
- * private cookie value of zero. Don't send if the
- * crypto bit is set and no extension field is present,
- * but in that case give back the key. Most intricate.
+ * Calculate the next session key. Since extension
+ * fields are present, the cookie value is zero.
*/
if (sendlen > LEN_PKT_NOMAC) {
session_key(&peer->dstadr->sin, &peer->srcadr,
xkeyid, 0, 2);
- } else if (peer->flash & TEST9) {
- authtrust(xkeyid, 0);
- return;
}
}
#endif /* OPENSSL */
/*
- * Stash the transmit timestamp corrected for the encryption
- * delay. If autokey, give back the key, as we use keys only
- * once. Check for errors such as missing keys, buffer overflow,
- * etc.
+ * Transmit a-priori timestamps
*/
+ get_systime(&xmt_tx);
+ if (peer->flip == 0) { /* basic mode */
+ peer->aorg = xmt_tx;
+ HTONL_FP(&xmt_tx, &xpkt.xmt);
+ } else { /* interleaved modes */
+ if (peer->hmode == MODE_BROADCAST) { /* bcst */
+ HTONL_FP(&xmt_tx, &xpkt.xmt);
+ if (peer->flip > 0)
+ HTONL_FP(&peer->borg, &xpkt.org);
+ else
+ HTONL_FP(&peer->aorg, &xpkt.org);
+ } else { /* symmetric */
+ if (peer->flip > 0)
+ HTONL_FP(&peer->borg, &xpkt.xmt);
+ else
+ HTONL_FP(&peer->aorg, &xpkt.xmt);
+ }
+ }
xkeyid = peer->keyid;
- get_systime(&peer->xmt);
- L_ADD(&peer->xmt, &sys_authdelay);
- HTONL_FP(&peer->xmt, &xpkt.xmt);
authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
if (authlen == 0) {
- msyslog(LOG_INFO, "transmit: %s key %u not found",
- stoa(&peer->srcadr), xkeyid);
- peer->flash |= TEST9; /* no key found */
+ report_event(PEVNT_AUTH, peer, "no key");
+ peer->flash |= TEST5; /* auth error */
+ peer->badauth++;
return;
}
sendlen += authlen;
@@ -2753,44 +3206,45 @@ peer_xmit(
if (xkeyid > NTP_MAXKEY)
authtrust(xkeyid, 0);
#endif /* OPENSSL */
- get_systime(&xmt_tx);
if (sendlen > sizeof(xpkt)) {
- msyslog(LOG_ERR, "buffer overflow %u", sendlen);
+ msyslog(LOG_ERR, "proto: buffer overflow %u", sendlen);
exit (-1);
}
+ peer->t21_bytes = sendlen;
sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl], &xpkt,
- sendlen);
+ sendlen);
+ peer->sent++;
+ peer->throttle += (1 << peer->minpoll) - 2;
/*
- * Calculate the encryption delay. Keep the minimum over
- * the latest two samples.
+ * Capture a-posteriori timestamps
*/
- 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++;
+ get_systime(&xmt_ty);
+ if (peer->flip != 0) { /* interleaved modes */
+ if (peer->flip > 0)
+ peer->aorg = xmt_ty;
+ else
+ peer->borg = xmt_ty;
+ peer->flip = -peer->flip;
+ }
+ L_SUB(&xmt_ty, &xmt_tx);
+ LFPTOD(&xmt_ty, peer->xleave);
#ifdef OPENSSL
#ifdef DEBUG
if (debug)
- printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d index %d\n",
- current_time, peer->dstadr ? ntoa(&peer->dstadr->sin) : "-",
- ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
- authlen, authlen, peer->keynumber);
+ printf("transmit: at %ld %s->%s mode %d keyid %08x len %d index %d\n",
+ current_time, peer->dstadr ?
+ ntoa(&peer->dstadr->sin) : "-",
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen,
+ peer->keynumber);
#endif
-#else
+#else /* OPENSSL */
#ifdef DEBUG
if (debug)
- printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
- current_time, peer->dstadr ? ntoa(&peer->dstadr->sin) : "-",
- ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
- authlen, authlen);
+ printf("transmit: at %ld %s->%s mode %d keyid %08x len %d\n",
+ current_time, peer->dstadr ?
+ ntoa(&peer->dstadr->sin) : "-",
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen);
#endif
#endif /* OPENSSL */
}
@@ -2803,111 +3257,77 @@ peer_xmit(
static void
fast_xmit(
struct recvbuf *rbufp, /* receive packet pointer */
- int xmode, /* transmit mode */
+ int xmode, /* receive mode */
keyid_t xkeyid, /* transmit key ID */
- int mask /* restrict mask */
+ int flags /* restrict mask */
)
{
- struct pkt xpkt; /* transmit packet structure */
- struct pkt *rpkt; /* receive packet structure */
- l_fp xmt_ts; /* timestamp */
- l_fp xmt_tx; /* timestamp after authent */
- int sendlen, authlen;
+ struct pkt xpkt; /* transmit packet structure */
+ struct pkt *rpkt; /* receive packet structure */
+ l_fp xmt_tx, xmt_ty;
+ int sendlen;
#ifdef OPENSSL
u_int32 temp32;
#endif
/*
* Initialize transmit packet header fields from the receive
- * buffer provided. We leave some fields intact as received. If
- * the gazinta was from a multicast address, the gazoutta must
- * go out another way.
+ * buffer provided. We leave the fields intact as received, but
+ * set the peer poll at the maximum of the receive peer poll and
+ * the system minimum poll (ntp_minpoll). This is for KoD rate
+ * control and not strictly specification compliant, but doesn't
+ * break anything.
*
- * The root delay field is special. If the system stratum is
- * less than the orphan stratum, send the real root delay.
- * Otherwise, if there is no system peer, send the orphan delay.
- * Otherwise, we must be an orphan parent, so send zero.
+ * If the gazinta was from a multicast address, the gazoutta
+ * must go out another way.
*/
rpkt = &rbufp->recv_pkt;
if (rbufp->dstadr->flags & INT_MCASTOPEN)
rbufp->dstadr = findinterface(&rbufp->recv_srcadr);
/*
- * This is deliciously complicated. There are four cases.
- *
- * case leap stratum refid delay dispersion
- *
- * KoD 11 16 KISS system system
- * normal system system system system system
- * orphan child 00 orphan system orphan system
- * orphan parent 00 orphan loopbk 0 0
- */
- /*
- * This is a kiss-of-death (KoD) packet. Show leap
+ * If this is a kiss-o'-death (KoD) packet, show leap
* unsynchronized, stratum zero, reference ID the four-character
- * kiss code and system root delay. Note the rate limit on these
- * packets. Once a second initialize a bucket counter. Every
- * packet sent decrements the counter until reaching zero. If
- * the counter is zero, drop the kiss.
+ * kiss code and system root delay. Note we don't reveal the
+ * local time, so these packets can't be used for
+ * synchronization.
*/
- if (mask & RES_LIMITED) {
- sys_limitrejected++;
- if (sys_kod == 0 || !(mask & RES_DEMOBILIZE))
- return;
-
- sys_kod--;
+ if (flags & RES_KOD) {
+ sys_kodsent++;
xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_UNSPEC;
+ xpkt.stratum = STRATUM_PKT_UNSPEC;
+ xpkt.ppoll = max(rpkt->ppoll, ntp_minpoll);
memcpy(&xpkt.refid, "RATE", 4);
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
+ xpkt.org = rpkt->xmt;
+ xpkt.rec = rpkt->xmt;
+ xpkt.xmt = rpkt->xmt;
/*
* This is a normal packet. Use the system variables.
*/
- } else if (sys_stratum < sys_orphan) {
+ } 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.ppoll = max(rpkt->ppoll, ntp_minpoll);
+ xpkt.precision = sys_precision;
xpkt.refid = sys_refid;
xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
-
- /*
- * This is a orphan child packet. The host is synchronized to an
- * orphan parent. Show leap synchronized, orphan stratum, system
- * reference ID and orphan root delay.
- */
- } else if (sys_peer != NULL) {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
- PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
- xpkt.refid = sys_refid;
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_orphandelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
+ xpkt.rootdisp = HTONS_FP(DTOUFP(sys_rootdisp));
+ HTONL_FP(&sys_reftime, &xpkt.reftime);
+ xpkt.org = rpkt->xmt;
+ HTONL_FP(&rbufp->recv_time, &xpkt.rec);
+ get_systime(&xmt_tx);
+ HTONL_FP(&xmt_tx, &xpkt.xmt);
+ }
- /*
- * This is an orphan parent. Show leap synchronized, orphan
- * stratum, loopack reference ID and zero root delay.
- */
- } else {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
- PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
- xpkt.refid = htonl(LOOPBACKADR);
- xpkt.rootdelay = HTONS_FP(DTOFP(0));
- xpkt.rootdispersion = HTONS_FP(DTOFP(0));
+#ifdef HAVE_NTP_SIGND
+ if (flags & RES_MSSNTP) {
+ send_via_ntp_signd(rbufp, xmode, xkeyid, flags, &xpkt);
+ return;
}
- xpkt.ppoll = rpkt->ppoll;
- xpkt.precision = sys_precision;
- xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion));
- HTONL_FP(&sys_reftime, &xpkt.reftime);
- xpkt.org = rpkt->xmt;
- HTONL_FP(&rbufp->recv_time, &xpkt.rec);
+#endif /* HAVE_NTP_SIGND */
/*
* If the received packet contains a MAC, the transmitted packet
@@ -2916,15 +3336,14 @@ fast_xmit(
*/
sendlen = LEN_PKT_NOMAC;
if (rbufp->recv_length == sendlen) {
- get_systime(&xmt_ts);
- HTONL_FP(&xmt_ts, &xpkt.xmt);
sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt,
sendlen);
#ifdef DEBUG
if (debug)
- printf("transmit: at %ld %s->%s mode %d\n",
+ printf(
+ "transmit: at %ld %s->%s mode %d len %d\n",
current_time, stoa(&rbufp->dstadr->sin),
- stoa(&rbufp->recv_srcadr), xmode);
+ stoa(&rbufp->recv_srcadr), xmode, sendlen);
#endif
return;
}
@@ -2952,56 +3371,36 @@ fast_xmit(
*/
cookie = session_key(&rbufp->recv_srcadr,
&rbufp->dstadr->sin, 0, sys_private, 0);
- if (rbufp->recv_length >= (int)(sendlen + MAX_MAC_LEN +
- 2 * sizeof(u_int32))) {
+ if (rbufp->recv_length > sendlen + MAX_MAC_LEN) {
session_key(&rbufp->dstadr->sin,
&rbufp->recv_srcadr, xkeyid, 0, 2);
temp32 = CRYPTO_RESP;
rpkt->exten[0] |= htonl(temp32);
- sendlen += crypto_xmit(&xpkt,
- &rbufp->recv_srcadr, sendlen,
- (struct exten *)rpkt->exten, cookie);
+ sendlen += crypto_xmit(NULL, &xpkt, rbufp,
+ sendlen, (struct exten *)rpkt->exten,
+ cookie);
} else {
session_key(&rbufp->dstadr->sin,
&rbufp->recv_srcadr, xkeyid, cookie, 2);
}
}
#endif /* OPENSSL */
- get_systime(&xmt_ts);
- L_ADD(&xmt_ts, &sys_authdelay);
- HTONL_FP(&xmt_ts, &xpkt.xmt);
- authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
- sendlen += authlen;
+ get_systime(&xmt_tx);
+ sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
#ifdef OPENSSL
if (xkeyid > NTP_MAXKEY)
authtrust(xkeyid, 0);
#endif /* OPENSSL */
- get_systime(&xmt_tx);
- if (sendlen > sizeof(xpkt)) {
- msyslog(LOG_ERR, "buffer overflow %u", sendlen);
- exit (-1);
- }
sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt, sendlen);
-
- /*
- * Calculate the encryption delay. Keep the minimum over the
- * latest two samples.
- */
- L_SUB(&xmt_tx, &xmt_ts);
- L_ADD(&xmt_tx, &sys_authdelay);
- sys_authdly[1] = sys_authdly[0];
- sys_authdly[0] = xmt_tx.l_uf;
- if (sys_authdly[0] < sys_authdly[1])
- sys_authdelay.l_uf = sys_authdly[0];
- else
- sys_authdelay.l_uf = sys_authdly[1];
+ get_systime(&xmt_ty);
+ L_SUB(&xmt_ty, &xmt_tx);
+ sys_authdelay = xmt_ty;
#ifdef DEBUG
if (debug)
printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
+ "transmit: at %ld %s->%s mode %d keyid %08x len %d\n",
current_time, ntoa(&rbufp->dstadr->sin),
- ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen -
- authlen, authlen);
+ ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen);
#endif
}
@@ -3025,20 +3424,45 @@ key_expire(
}
value_free(&peer->sndval);
peer->keynumber = 0;
+ peer->flags &= ~FLAG_ASSOC;
#ifdef DEBUG
if (debug)
- printf("key_expire: at %lu\n", current_time);
+ printf("key_expire: at %lu associd %d\n", current_time,
+ peer->associd);
#endif
}
#endif /* OPENSSL */
/*
+ * local_refid(peer) - check peer refid to avoid selecting peers
+ * currently synced to this ntpd.
+ */
+static int
+local_refid(
+ struct peer * p
+ )
+{
+ endpt * unicast_ep;
+
+ if (p->dstadr != NULL && !(INT_MCASTIF & p->dstadr->flags))
+ unicast_ep = p->dstadr;
+ else
+ unicast_ep = findinterface(&p->srcadr);
+
+ if (unicast_ep != NULL && p->refid == unicast_ep->addr_refid)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+/*
* Determine if the peer is unfit for synchronization
*
* A peer is unfit for synchronization if
* > TEST10 bad leap or stratum below floor or at or above ceiling
- * > TEST11 root distance exceeded
+ * > TEST11 root distance exceeded for remote peer
* > TEST12 a direct or indirect synchronization loop would form
* > TEST13 unreachable or noselect
*/
@@ -3052,40 +3476,35 @@ peer_unfit(
/*
* A stratum error occurs if (1) the server has never been
* synchronized, (2) the server stratum is below the floor or
- * greater than or equal to the ceiling, (3) the system stratum
- * is below the orphan stratum and the server stratum is greater
- * than or equal to the orphan stratum.
+ * greater than or equal to the ceiling.
*/
if (peer->leap == LEAP_NOTINSYNC || peer->stratum < sys_floor ||
- peer->stratum >= sys_ceiling || (sys_stratum < sys_orphan &&
- peer->stratum >= sys_orphan))
- rval |= TEST10; /* stratum out of bounds */
+ peer->stratum >= sys_ceiling)
+ rval |= TEST10; /* bad synch or stratum */
/*
- * A distance error occurs if the root distance is greater than
- * or equal to the distance threshold plus the increment due to
- * one poll interval.
+ * A distance error for a remote peer occurs if the root
+ * distance is greater than or equal to the distance threshold
+ * plus the increment due to one host poll interval.
*/
- if (root_distance(peer) >= sys_maxdist + clock_phi *
- ULOGTOD(sys_poll))
+ if (!(peer->flags & FLAG_REFCLOCK) && root_distance(peer) >=
+ sys_maxdist + clock_phi * ULOGTOD(peer->hpoll))
rval |= TEST11; /* distance exceeded */
/*
* A loop error occurs if the remote peer is synchronized to the
- * local peer of if the remote peer is synchronized to the same
- * server as the local peer, but only if the remote peer is not
- * the orphan parent.
+ * local peer or if the remote peer is synchronized to the same
+ * server as the local peer but only if the remote peer is
+ * neither a reference clock nor an orphan.
*/
- if (peer->stratum > 1 && peer->refid != htonl(LOOPBACKADR) &&
- ((!peer->dstadr || peer->refid == peer->dstadr->addr_refid) ||
- peer->refid == sys_refid))
- rval |= TEST12; /* synch loop */
+ if (peer->stratum > 1 && local_refid(peer))
+ rval |= TEST12; /* synchronization loop */
/*
* An unreachable error occurs if the server is unreachable or
* the noselect bit is set.
*/
- if (!peer->reach || peer->flags & FLAG_NOSELECT)
+ if (!peer->reach || (peer->flags & FLAG_NOSELECT))
rval |= TEST13; /* unreachable */
peer->flash &= ~PEER_TEST_MASK;
@@ -3102,18 +3521,12 @@ peer_unfit(
#define MINLOOPS 5 /* minimum number of step samples */
/*
- * This routine calculates the system precision, defined as the minimum
- * of a sequence of differences between successive readings of the
- * system clock. However, if the system clock can be read more than once
- * during a tick interval, the difference can be zero or one LSB unit,
- * where the LSB corresponds to one nanosecond or one microsecond.
- * Conceivably, if some other process preempts this one and reads the
- * clock, the difference can be more than one LSB unit.
- *
- * For hardware clock frequencies of 10 MHz or less, we assume the
- * logical clock advances only at the hardware clock tick. For higher
- * frequencies, we assume the logical clock can advance no more than 100
- * nanoseconds between ticks.
+ * This routine measures the system precision defined as the minimum of
+ * a sequence of differences between successive readings of the system
+ * clock. However, if a difference is less than MINSTEP, the clock has
+ * been read more than once during a clock tick and the difference is
+ * ignored. We set MINSTEP greater than zero in case something happens
+ * like a cache miss.
*/
int
default_get_precision(void)
@@ -3126,13 +3539,12 @@ default_get_precision(void)
int i; /* log2 precision */
/*
- * Loop to find tick value in nanoseconds. Toss out outlyer
- * values less than the minimun tick value. In wacky cases, use
- * the default maximum value.
+ * Loop to find precision value in seconds.
*/
- get_systime(&last);
tick = MAXSTEP;
- for (i = 0; i < MINLOOPS;) {
+ i = 0;
+ get_systime(&last);
+ while (1) {
get_systime(&val);
diff = val;
L_SUB(&diff, &last);
@@ -3140,35 +3552,27 @@ default_get_precision(void)
LFPTOD(&diff, dtemp);
if (dtemp < MINSTEP)
continue;
- i++;
+
if (dtemp < tick)
tick = dtemp;
+ if (++i >= MINLOOPS)
+ break;
}
+ sys_tick = tick;
/*
* Find the nearest power of two.
*/
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "precision = %.3f usec", tick * 1e6);
+ msyslog(LOG_NOTICE, "proto: precision = %.3f usec", tick * 1e6);
for (i = 0; tick <= 1; i++)
tick *= 2;
- if (tick - 1. > 1. - tick / 2)
+ if (tick - 1 > 1 - tick / 2)
i--;
return (-i);
}
/*
- * kod_proto - called once per second to limit kiss-of-death packets
- */
-void
-kod_proto(void)
-{
- sys_kod = sys_kod_rate;
-}
-
-
-/*
* init_proto - initialize the protocol module's data
*/
void
@@ -3179,45 +3583,29 @@ init_proto(void)
/*
* Fill in the sys_* stuff. Default is don't listen to
- * broadcasting, authenticate.
+ * broadcasting, require authentication.
*/
sys_leap = LEAP_NOTINSYNC;
sys_stratum = STRATUM_UNSPEC;
memcpy(&sys_refid, "INIT", 4);
- sys_precision = (s_char)default_get_precision();
- sys_jitter = LOGTOD(sys_precision);
+ sys_peer = NULL;
sys_rootdelay = 0;
- sys_orphandelay = (double)(ntp_random() & 0xffff) / 65536. *
- sys_maxdist;
- sys_rootdispersion = 0;
+ sys_rootdisp = 0;
L_CLR(&sys_reftime);
- sys_peer = NULL;
- sys_survivors = 0;
+ sys_jitter = 0;
+ sys_precision = (s_char)default_get_precision();
get_systime(&dummy);
+ sys_survivors = 0;
sys_manycastserver = 0;
sys_bclient = 0;
- sys_bdelay = DEFBROADDELAY;
- sys_calldelay = BURST_DELAY;
+ sys_bdelay = 0;
sys_authenticate = 1;
- L_CLR(&sys_authdelay);
- sys_authdly[0] = sys_authdly[1] = 0;
- sys_stattime = 0;
+ sys_stattime = current_time;
proto_clr_stats();
for (i = 0; i < MAX_TTL; i++) {
sys_ttl[i] = (u_char)((i * 256) / MAX_TTL);
sys_ttlmax = i;
}
-#ifdef OPENSSL
- sys_automax = 1 << NTP_AUTOMAX;
-#endif /* OPENSSL */
-
- /*
- * Default these to enable
- */
- ntp_enable = 1;
-#ifndef KERNEL_FLL_BUG
- kern_enable = 1;
-#endif
pps_enable = 0;
stats_control = 1;
}
@@ -3231,49 +3619,25 @@ proto_config(
int item,
u_long value,
double dvalue,
- struct sockaddr_storage* svalue
+ sockaddr_u *svalue
)
{
/*
* Figure out what he wants to change, then do it
*/
- switch (item) {
+ DPRINTF(2, ("proto_config: code %d value %lu dvalue %lf\n",
+ item, value, dvalue));
- /*
- * Turn on/off kernel discipline.
- */
- case PROTO_KERNEL:
- kern_enable = (int)value;
- break;
-
- /*
- * Turn on/off clock discipline.
- */
- case PROTO_NTP:
- ntp_enable = (int)value;
- break;
-
- /*
- * Turn on/off monitoring.
- */
- case PROTO_MONITOR:
- if (value)
- mon_start(MON_ON);
- else
- mon_stop(MON_ON);
- break;
+ switch (item) {
/*
- * Turn on/off statistics.
+ * enable and disable commands - arguments are Boolean.
*/
- case PROTO_FILEGEN:
- stats_control = (int)value;
+ case PROTO_AUTHENTICATE: /* authentication (auth) */
+ sys_authenticate = value;
break;
- /*
- * Turn on/off enable broadcasts.
- */
- case PROTO_BROADCLIENT:
+ case PROTO_BROADCLIENT: /* broadcast client (bclient) */
sys_bclient = (int)value;
if (sys_bclient == 0)
io_unsetbclient();
@@ -3281,152 +3645,106 @@ proto_config(
io_setbclient();
break;
- /*
- * Turn on/off PPS discipline.
- */
- case PROTO_PPS:
- pps_enable = (int)value;
+#ifdef REFCLOCK
+ case PROTO_CAL: /* refclock calibrate (calibrate) */
+ cal_enable = value;
break;
+#endif /* REFCLOCK */
- /*
- * Add muliticast group address.
- */
- case PROTO_MULTICAST_ADD:
- if (svalue)
- io_multicast_add(*svalue);
- sys_bclient = 1;
+ case PROTO_KERNEL: /* kernel discipline (kernel) */
+ kern_enable = value;
break;
- /*
- * Delete multicast group address.
- */
- case PROTO_MULTICAST_DEL:
- if (svalue)
- io_multicast_del(*svalue);
+ case PROTO_MONITOR: /* monitoring (monitor) */
+ if (value)
+ mon_start(MON_ON);
+ else
+ mon_stop(MON_ON);
break;
- /*
- * Set default broadcast delay.
- */
- case PROTO_BROADDELAY:
- sys_bdelay = dvalue;
+ case PROTO_NTP: /* NTP discipline (ntp) */
+ ntp_enable = value;
break;
- /*
- * Set modem call delay.
- */
- case PROTO_CALLDELAY:
- sys_calldelay = (int)value;
+ case PROTO_PPS: /* PPS discipline (pps) */
+ pps_enable = value;
break;
- /*
- * Turn on/off authentication to mobilize ephemeral
- * associations.
- */
- case PROTO_AUTHENTICATE:
- sys_authenticate = (int)value;
+ case PROTO_FILEGEN: /* statistics (stats) */
+ stats_control = value;
break;
/*
- * Set minimum number of survivors.
+ * tos command - arguments are double, sometimes cast to int
*/
- case PROTO_MINCLOCK:
- sys_minclock = (int)dvalue;
+ case PROTO_BEACON: /* manycast beacon (beacon) */
+ sys_beacon = (int)dvalue;
break;
- /*
- * Set maximum number of preemptable associations.
- */
- case PROTO_MAXCLOCK:
- sys_maxclock = (int)dvalue;
+ case PROTO_BROADDELAY: /* default broadcast delay (bdelay) */
+ sys_bdelay = dvalue;
break;
- /*
- * Set minimum number of survivors.
- */
- case PROTO_MINSANE:
- sys_minsane = (int)dvalue;
+ case PROTO_CEILING: /* stratum ceiling (ceiling) */
+ sys_ceiling = (int)dvalue;
break;
- /*
- * Set stratum floor.
- */
- case PROTO_FLOOR:
+ case PROTO_COHORT: /* cohort switch (cohort) */
+ sys_cohort = (int)dvalue;
+ break;
+
+ case PROTO_FLOOR: /* stratum floor (floor) */
sys_floor = (int)dvalue;
break;
- /*
- * Set stratum ceiling.
- */
- case PROTO_CEILING:
- sys_ceiling = (int)dvalue;
+ case PROTO_MAXCLOCK: /* maximum candidates (maxclock) */
+ sys_maxclock = (int)dvalue;
break;
- /*
- * Set orphan stratum.
- */
- case PROTO_ORPHAN:
- sys_orphan = (int)dvalue;
+ case PROTO_MAXDIST: /* select threshold (maxdist) */
+ sys_maxdist = dvalue;
break;
- /*
- * Set cohort switch.
- */
- case PROTO_COHORT:
- sys_cohort = (int)dvalue;
+ case PROTO_CALLDELAY: /* modem call delay (mdelay) */
+ break; /* NOT USED */
+
+ case PROTO_MINCLOCK: /* minimum candidates (minclock) */
+ sys_minclock = (int)dvalue;
break;
- /*
- * Set minimum dispersion increment.
- */
- case PROTO_MINDISP:
+ case PROTO_MINDISP: /* minimum distance (mindist) */
sys_mindisp = dvalue;
break;
- /*
- * Set maximum distance (select threshold).
- */
- case PROTO_MAXDIST:
- sys_maxdist = dvalue;
+ case PROTO_MINSANE: /* minimum survivors (minsane) */
+ sys_minsane = (int)dvalue;
break;
- /*
- * Set anticlockhop threshold.
- */
- case PROTO_MAXHOP:
- sys_maxhop = (int)dvalue;
+ case PROTO_ORPHAN: /* orphan stratum (orphan) */
+ sys_orphan = (int)dvalue;
break;
- /*
- * Set adjtime() resolution (s).
- */
- case PROTO_ADJ:
+ case PROTO_ADJ: /* tick increment (tick) */
sys_tick = dvalue;
break;
/*
- * Set manycast beacon interval.
+ * Miscellaneous commands
*/
- case PROTO_BEACON:
- sys_beacon = (int)dvalue;
+ case PROTO_MULTICAST_ADD: /* add group address */
+ if (svalue != NULL)
+ io_multicast_add(svalue);
+ sys_bclient = 1;
break;
-#ifdef REFCLOCK
- /*
- * Turn on/off refclock calibrate
- */
- case PROTO_CAL:
- cal_enable = (int)value;
+ case PROTO_MULTICAST_DEL: /* delete group address */
+ if (svalue != NULL)
+ io_multicast_del(svalue);
break;
-#endif /* REFCLOCK */
- default:
- /*
- * Log this error.
- */
- msyslog(LOG_INFO,
- "proto_config: illegal item %d, value %ld", item,
- value);
+ default:
+ msyslog(LOG_NOTICE,
+ "proto: unsupported option %d", item);
}
}
@@ -3440,9 +3758,9 @@ proto_clr_stats(void)
sys_stattime = current_time;
sys_received = 0;
sys_processed = 0;
- sys_newversionpkt = 0;
- sys_oldversionpkt = 0;
- sys_unknownversion = 0;
+ sys_newversion = 0;
+ sys_oldversion = 0;
+ sys_declined = 0;
sys_restricted = 0;
sys_badlength = 0;
sys_badauth = 0;
diff --git a/ntpd/ntp_refclock.c b/ntpd/ntp_refclock.c
index a29ef085e8f2..a4d30e80b118 100644
--- a/ntpd/ntp_refclock.c
+++ b/ntpd/ntp_refclock.c
@@ -11,6 +11,7 @@
#include "ntp_tty.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
#include <stdio.h>
@@ -34,63 +35,57 @@
#include "ntp_syscall.h"
#endif /* KERNEL_PLL */
+#ifdef HAVE_PPSAPI
+#include "ppsapi_timepps.h"
+#include "refclock_atom.h"
+#endif /* HAVE_PPSAPI */
+
/*
* Reference clock support is provided here by maintaining the fiction
- * that the clock is actually a peer. As no packets are exchanged with a
- * reference clock, however, we replace the transmit, receive and packet
- * procedures with separate code to simulate them. Routines
+ * that the clock is actually a peer. As no packets are exchanged with
+ * a reference clock, however, we replace the transmit, receive and
+ * packet procedures with separate code to simulate them. Routines
* refclock_transmit() and refclock_receive() maintain the peer
* variables in a state analogous to an actual peer and pass reference
- * clock data on through the filters. Routines refclock_peer() and
+ * clock data on through the filters. Routines refclock_peer() and
* refclock_unpeer() are called to initialize and terminate reference
- * clock associations. A set of utility routines is included to open
+ * clock associations. A set of utility routines is included to open
* serial devices, process sample data, edit input lines to extract
- * embedded timestamps and to peform various debugging functions.
+ * embedded timestamps and to perform various debugging functions.
*
* The main interface used by these routines is the refclockproc
- * structure, which contains for most drivers the decimal equivalants of
- * the year, day, month, hour, second and millisecond/microsecond
- * decoded from the ASCII timecode. Additional information includes the
- * receive timestamp, exception report, statistics tallies, etc. In
- * addition, there may be a driver-specific unit structure used for
+ * structure, which contains for most drivers the decimal equivalants
+ * of the year, day, month, hour, second and millisecond/microsecond
+ * decoded from the ASCII timecode. Additional information includes
+ * the receive timestamp, exception report, statistics tallies, etc.
+ * In addition, there may be a driver-specific unit structure used for
* local control of the device.
*
* The support routines are passed a pointer to the peer structure,
- * which is used for all peer-specific processing and contains a pointer
- * to the refclockproc structure, which in turn containes a pointer to
- * the unit structure, if used. The peer structure is identified by an
- * interface address in the dotted quad form 127.127.t.u (for now only
- * IPv4 addresses are used, so we need to be sure the address is it),
- * where t is the clock type and u the unit. Some legacy drivers derive
- * the refclockproc structure pointer from the table
- * typeunit[type][unit]. This interface is strongly discouraged and may
- * be abandoned in future.
+ * which is used for all peer-specific processing and contains a
+ * pointer to the refclockproc structure, which in turn contains a
+ * pointer to the unit structure, if used. The peer structure is
+ * identified by an interface address in the dotted quad form
+ * 127.127.t.u, where t is the clock type and u the unit.
*/
-#define MAXUNIT 4 /* max units */
#define FUDGEFAC .1 /* fudge correction factor */
#define LF 0x0a /* ASCII LF */
#ifdef PPS
int fdpps; /* ppsclock legacy */
#endif /* PPS */
-int cal_enable; /* enable refclock calibrate */
-/*
- * Type/unit peer index. Used to find the peer structure for control and
- * debugging. When all clock drivers have been converted to new style,
- * this dissapears.
- */
-static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT];
+int cal_enable; /* enable refclock calibrate */
/*
* Forward declarations
*/
#ifdef QSORT_USES_VOID_P
-static int refclock_cmpl_fp P((const void *, const void *));
+static int refclock_cmpl_fp (const void *, const void *);
#else
-static int refclock_cmpl_fp P((const double *, const double *));
+static int refclock_cmpl_fp (const double *, const double *);
#endif /* QSORT_USES_VOID_P */
-static int refclock_sample P((struct refclockproc *));
+static int refclock_sample (struct refclockproc *);
/*
@@ -113,58 +108,36 @@ refclock_report(
return;
switch (code) {
- case CEVNT_NOMINAL:
- break;
- case CEVNT_TIMEOUT:
- pp->noreply++;
- break;
-
- case CEVNT_BADREPLY:
- pp->badformat++;
- break;
+ case CEVNT_TIMEOUT:
+ pp->noreply++;
+ break;
- case CEVNT_FAULT:
- break;
+ case CEVNT_BADREPLY:
+ pp->badformat++;
+ break;
- case CEVNT_PROP:
- break;
+ case CEVNT_FAULT:
+ break;
- case CEVNT_BADDATE:
- case CEVNT_BADTIME:
- pp->baddata++;
- break;
+ case CEVNT_BADDATE:
+ case CEVNT_BADTIME:
+ pp->baddata++;
+ break;
- default:
- /* shouldn't happen */
- break;
+ default:
+ /* ignore others */
+ break;
}
-
+ if (pp->lastevent < 15)
+ pp->lastevent++;
if (pp->currentstatus != code) {
pp->currentstatus = (u_char)code;
-
- /* RFC1305: copy only iff not CEVNT_NOMINAL */
- if (code != CEVNT_NOMINAL)
- pp->lastevent = (u_char)code;
-
- if (code == CEVNT_FAULT)
- msyslog(LOG_ERR,
- "clock %s event '%s' (0x%02x)",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
- else {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_INFO,
- "clock %s event '%s' (0x%02x)",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
- }
-
- /* RFC1305: post peer clock event */
- report_event(EVNT_PEERCLOCK, peer);
+ report_event(PEVNT_CLOCK, peer, ceventstr(code));
}
}
+
/*
* init_refclock - initialize the reference clock drivers
*
@@ -175,14 +148,11 @@ refclock_report(
void
init_refclock(void)
{
- int i, j;
+ int i;
- for (i = 0; i < (int)num_refclock_conf; i++) {
+ for (i = 0; i < (int)num_refclock_conf; i++)
if (refclock_conf[i]->clock_init != noentry)
(refclock_conf[i]->clock_init)();
- for (j = 0; j < MAXUNIT; j++)
- typeunit[i][j] = 0;
- }
}
@@ -211,12 +181,6 @@ refclock_newpeer(
* Check for valid clock address. If already running, shut it
* down first.
*/
- if (peer->srcadr.ss_family != AF_INET) {
- msyslog(LOG_ERR,
- "refclock_newpeer: clock address %s invalid, address family not implemented for refclock",
- stoa(&peer->srcadr));
- return (0);
- }
if (!ISREFCLOCKADR(&peer->srcadr)) {
msyslog(LOG_ERR,
"refclock_newpeer: clock address %s invalid",
@@ -225,7 +189,7 @@ refclock_newpeer(
}
clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
unit = REFCLOCKUNIT(&peer->srcadr);
- if (clktype >= num_refclock_conf || unit >= MAXUNIT ||
+ if (clktype >= num_refclock_conf ||
refclock_conf[clktype]->clock_start == noentry) {
msyslog(LOG_ERR,
"refclock_newpeer: clock type %d invalid\n",
@@ -236,12 +200,8 @@ refclock_newpeer(
/*
* Allocate and initialize interface structure
*/
- pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc));
- if (pp == NULL)
- return (0);
-
- memset((char *)pp, 0, sizeof(struct refclockproc));
- typeunit[clktype][unit] = peer;
+ pp = emalloc(sizeof(*pp));
+ memset(pp, 0, sizeof(*pp));
peer->procptr = pp;
/*
@@ -249,7 +209,7 @@ refclock_newpeer(
*/
peer->refclktype = clktype;
peer->refclkunit = (u_char)unit;
- peer->flags |= FLAG_REFCLOCK | FLAG_FIXPOLL;
+ peer->flags |= FLAG_REFCLOCK;
peer->leap = LEAP_NOTINSYNC;
peer->stratum = STRATUM_REFCLOCK;
peer->ppoll = peer->maxpoll;
@@ -297,7 +257,7 @@ refclock_unpeer(
* Wiggle the driver to release its resources, then give back
* the interface structure.
*/
- if (!peer->procptr)
+ if (NULL == peer->procptr)
return;
clktype = peer->refclktype;
@@ -305,7 +265,7 @@ refclock_unpeer(
if (refclock_conf[clktype]->clock_shutdown != noentry)
(refclock_conf[clktype]->clock_shutdown)(unit, peer);
free(peer->procptr);
- peer->procptr = 0;
+ peer->procptr = NULL;
}
@@ -365,19 +325,17 @@ refclock_transmit(
* Update reachability and poll variables like the
* network code.
*/
- oreach = peer->reach;
+ oreach = peer->reach & 0xfe;
peer->reach <<= 1;
+ if (!(peer->reach & 0x0f))
+ clock_filter(peer, 0., 0., MAXDISPERSE);
peer->outdate = current_time;
if (!peer->reach) {
if (oreach) {
- report_event(EVNT_UNREACH, peer);
+ report_event(PEVNT_UNREACH, peer, NULL);
peer->timereachable = current_time;
}
} else {
- if (!(oreach & 0x07)) {
- clock_filter(peer, 0., 0., MAXDISPERSE);
- clock_select();
- }
if (peer->flags & FLAG_BURST)
peer->burst = NSTAGE;
}
@@ -393,7 +351,6 @@ refclock_transmit(
/*
* Compare two doubles - used with qsort()
*/
-#ifdef QSORT_USES_VOID_P
static int
refclock_cmpl_fp(
const void *p1,
@@ -404,30 +361,11 @@ refclock_cmpl_fp(
const double *dp2 = (const double *)p2;
if (*dp1 < *dp2)
- return (-1);
-
- if (*dp1 > *dp2)
- return (1);
-
- return (0);
-}
-
-#else
-static int
-refclock_cmpl_fp(
- const double *dp1,
- const double *dp2
- )
-{
- if (*dp1 < *dp2)
- return (-1);
-
+ return -1;
if (*dp1 > *dp2)
- return (1);
-
- return (0);
+ return 1;
+ return 0;
}
-#endif /* QSORT_USES_VOID_P */
/*
@@ -458,6 +396,7 @@ refclock_process_offset(
/*
* refclock_process - process a sample from the clock
+ * refclock_process_f - refclock_process with other than time1 fudge
*
* This routine converts the timecode in the form days, hours, minutes,
* seconds and milliseconds/microseconds to internal timestamp format,
@@ -472,8 +411,9 @@ refclock_process_offset(
* zero and the fraction for pp->lastrec is set to the PPS offset.
*/
int
-refclock_process(
- struct refclockproc *pp /* refclock structure pointer */
+refclock_process_f(
+ struct refclockproc *pp, /* refclock structure pointer */
+ double fudge
)
{
l_fp offset, ltemp;
@@ -493,12 +433,20 @@ refclock_process(
offset.l_uf = 0;
DTOLFP(pp->nsec / 1e9, &ltemp);
L_ADD(&offset, &ltemp);
- refclock_process_offset(pp, offset, pp->lastrec,
- pp->fudgetime1);
+ refclock_process_offset(pp, offset, pp->lastrec, fudge);
return (1);
}
+int
+refclock_process(
+ struct refclockproc *pp /* refclock structure pointer */
+)
+{
+ return refclock_process_f(pp, pp->fudgetime1);
+}
+
+
/*
* refclock_sample - process a pile of samples from the clock
*
@@ -514,7 +462,7 @@ refclock_sample(
struct refclockproc *pp /* refclock structure pointer */
)
{
- int i, j, k, m, n;
+ size_t i, j, k, m, n;
double off[MAXSTAGE];
double offset;
@@ -532,13 +480,7 @@ refclock_sample(
return (0);
if (n > 1)
- qsort(
-#ifdef QSORT_USES_VOID_P
- (void *)
-#else
- (char *)
-#endif
- off, (size_t)n, sizeof(double), refclock_cmpl_fp);
+ qsort((void *)off, n, sizeof(off[0]), refclock_cmpl_fp);
/*
* Reject the furthest from the median of the samples until
@@ -572,7 +514,7 @@ refclock_sample(
"refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
n, pp->offset, pp->disp, pp->jitter);
#endif
- return (n);
+ return (int)n;
}
@@ -611,30 +553,23 @@ refclock_receive(
peer->received++;
peer->timereceived = current_time;
if (!peer->reach) {
- report_event(EVNT_REACH, peer);
+ report_event(PEVNT_REACH, peer, NULL);
peer->timereachable = current_time;
}
peer->reach |= 1;
peer->reftime = pp->lastref;
- peer->org = pp->lastrec;
- peer->rootdispersion = pp->disp;
- get_systime(&peer->rec);
+ peer->aorg = pp->lastrec;
+ peer->rootdisp = pp->disp;
+ get_systime(&peer->dst);
if (!refclock_sample(pp))
return;
clock_filter(peer, pp->offset, 0., pp->jitter);
- record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
- peer->offset, peer->delay, clock_phi * (current_time -
- peer->epoch), 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 */
+ if (cal_enable && fabs(last_offset) < sys_mindisp && sys_peer !=
+ NULL) {
+ if (sys_peer->refclktype == REFCLK_ATOM_PPS &&
+ peer->refclktype != REFCLK_ATOM_PPS)
pp->fudgetime1 -= pp->offset * FUDGEFAC;
- else
- pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC;
}
}
@@ -781,6 +716,9 @@ refclock_open(
{
int fd;
int omode;
+#ifdef O_NONBLOCK
+ char trash[128]; /* litter bin for old input data */
+#endif
/*
* Open serial port and set default options
@@ -798,6 +736,7 @@ refclock_open(
msyslog(LOG_ERR, "refclock_open %s: %m", dev);
return (0);
}
+ NTP_INSIST(fd != 0);
if (!refclock_setup(fd, speed, lflags)) {
close(fd);
return (0);
@@ -806,9 +745,20 @@ refclock_open(
close(fd);
return (0);
}
+#ifdef O_NONBLOCK
+ /*
+ * We want to make sure there is no pending trash in the input
+ * buffer. Since we have non-blocking IO available, this is a
+ * good moment to read and dump all available outdated stuff
+ * that might have become toxic for the driver.
+ */
+ while (read(fd, trash, sizeof(trash)) > 0 || errno == EINTR)
+ /*NOP*/;
+#endif
return (fd);
}
+
/*
* refclock_setup - initialize terminal interface structure
*/
@@ -900,6 +850,14 @@ refclock_setup(
"refclock_setup fd %d TCSANOW: %m", fd);
return (0);
}
+
+ /*
+ * flush input and output buffers to discard any outdated stuff
+ * that might have become toxic for the driver. Failing to do so
+ * is logged, but we keep our fingers crossed otherwise.
+ */
+ if (tcflush(fd, TCIOFLUSH) < 0)
+ msyslog(LOG_ERR, "refclock_setup fd %d tcflush(): %m", fd);
#endif /* HAVE_TERMIOS */
#ifdef HAVE_SYSV_TTYS
@@ -1064,7 +1022,7 @@ refclock_ioctl(
*/
void
refclock_control(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct refclockstat *in,
struct refclockstat *out
)
@@ -1077,22 +1035,15 @@ refclock_control(
/*
* Check for valid address and running peer
*/
- if (srcadr->ss_family != AF_INET)
- return;
-
if (!ISREFCLOCKADR(srcadr))
return;
clktype = (u_char)REFCLOCKTYPE(srcadr);
unit = REFCLOCKUNIT(srcadr);
- if (clktype >= num_refclock_conf || unit >= MAXUNIT)
- return;
- peer = typeunit[clktype][unit];
- if (peer == NULL)
- return;
+ peer = findexistingpeer(srcadr, NULL, -1, 0);
- if (peer->procptr == NULL)
+ if (NULL == peer || NULL == peer->procptr)
return;
pp = peer->procptr;
@@ -1149,7 +1100,7 @@ refclock_control(
out->currentstatus = pp->currentstatus;
out->type = pp->type;
out->clockdesc = pp->clockdesc;
- out->lencode = pp->lencode;
+ out->lencode = (u_short)pp->lencode;
out->p_lastcode = pp->a_lastcode;
}
@@ -1170,32 +1121,28 @@ refclock_control(
*/
void
refclock_buginfo(
- struct sockaddr_storage *srcadr, /* clock address */
+ sockaddr_u *srcadr, /* clock address */
struct refclockbug *bug /* output structure */
)
{
struct peer *peer;
struct refclockproc *pp;
- u_char clktype;
+ int clktype;
int unit;
- int i;
+ unsigned u;
/*
* Check for valid address and peer structure
*/
- if (srcadr->ss_family != AF_INET)
- return;
-
if (!ISREFCLOCKADR(srcadr))
return;
clktype = (u_char) REFCLOCKTYPE(srcadr);
unit = REFCLOCKUNIT(srcadr);
- if (clktype >= num_refclock_conf || unit >= MAXUNIT)
- return;
- peer = typeunit[clktype][unit];
- if (peer == NULL)
+ peer = findexistingpeer(srcadr, NULL, -1, 0);
+
+ if (NULL == peer || NULL == peer->procptr)
return;
pp = peer->procptr;
@@ -1216,8 +1163,8 @@ refclock_buginfo(
bug->stimes = 0xfffffffc;
bug->times[0] = pp->lastref;
bug->times[1] = pp->lastrec;
- for (i = 2; i < (int)bug->ntimes; i++)
- DTOLFP(pp->filter[i - 2], &bug->times[i]);
+ for (u = 2; u < bug->ntimes; u++)
+ DTOLFP(pp->filter[u - 2], &bug->times[u]);
/*
* Give the stuff to the clock
@@ -1226,4 +1173,154 @@ refclock_buginfo(
(refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);
}
+
+#ifdef HAVE_PPSAPI
+/*
+ * refclock_ppsapi - initialize/update ppsapi
+ *
+ * This routine is called after the fudge command to open the PPSAPI
+ * interface for later parameter setting after the fudge command.
+ */
+int
+refclock_ppsapi(
+ int fddev, /* fd device */
+ struct refclock_atom *ap /* atom structure pointer */
+ )
+{
+ if (ap->handle == 0) {
+ if (time_pps_create(fddev, &ap->handle) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_ppsapi: time_pps_create: %m");
+ return (0);
+ }
+ }
+ return (1);
+}
+
+
+/*
+ * refclock_params - set ppsapi parameters
+ *
+ * This routine is called to set the PPSAPI parameters after the fudge
+ * command.
+ */
+int
+refclock_params(
+ int mode, /* mode bits */
+ struct refclock_atom *ap /* atom structure pointer */
+ )
+{
+ memset(&ap->pps_params, 0, sizeof(pps_params_t));
+ ap->pps_params.api_version = PPS_API_VERS_1;
+
+ /*
+ * Solaris serial ports provide PPS pulse capture only on the
+ * assert edge. FreeBSD serial ports provide capture on the
+ * clear edge, while FreeBSD parallel ports provide capture
+ * on the assert edge. Your mileage may vary.
+ */
+ if (mode & CLK_FLAG2)
+ ap->pps_params.mode = PPS_TSFMT_TSPEC | PPS_CAPTURECLEAR;
+ else
+ ap->pps_params.mode = PPS_TSFMT_TSPEC | PPS_CAPTUREASSERT;
+ if (time_pps_setparams(ap->handle, &ap->pps_params) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_params: time_pps_setparams: %m");
+ return (0);
+ }
+
+ /*
+ * If flag3 is lit, select the kernel PPS.
+ */
+ if (mode & CLK_FLAG3) {
+ if (time_pps_kcbind(ap->handle, PPS_KC_HARDPPS,
+ ap->pps_params.mode & ~PPS_TSFMT_TSPEC,
+ PPS_TSFMT_TSPEC) < 0) {
+ if (errno != EOPNOTSUPP) {
+ msyslog(LOG_ERR,
+ "refclock_params: time_pps_kcbind: %m");
+ return (0);
+ }
+ }
+ pps_enable = 1;
+ }
+ return (1);
+}
+
+
+/*
+ * refclock_pps - called once per second
+ *
+ * This routine is called once per second. 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.
+ */
+int
+refclock_pps(
+ struct peer *peer, /* peer structure pointer */
+ struct refclock_atom *ap, /* atom structure pointer */
+ int mode /* mode bits */
+ )
+{
+ struct refclockproc *pp;
+ pps_info_t pps_info;
+ struct timespec timeout;
+ double dtemp;
+
+ /*
+ * We require the clock to be synchronized before setting the
+ * parameters. When the parameters have been set, fetch the
+ * most recent PPS timestamp.
+ */
+ pp = peer->procptr;
+ if (ap->handle == 0)
+ return (0);
+
+ if (ap->pps_params.mode == 0 && sys_leap != LEAP_NOTINSYNC) {
+ if (refclock_params(pp->sloppyclockflag, ap) < 1)
+ return (0);
+ }
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 0;
+ memset(&pps_info, 0, sizeof(pps_info_t));
+ if (time_pps_fetch(ap->handle, PPS_TSFMT_TSPEC, &pps_info,
+ &timeout) < 0) {
+ refclock_report(peer, CEVNT_FAULT);
+ return (0);
+ }
+ timeout = ap->ts;
+ if (ap->pps_params.mode & PPS_CAPTUREASSERT)
+ ap->ts = pps_info.assert_timestamp;
+ else if (ap->pps_params.mode & PPS_CAPTURECLEAR)
+ ap->ts = pps_info.clear_timestamp;
+ else
+ return (0);
+
+ /*
+ * There can be zero, one or two PPS pulses between polls,
+ * depending on the poll interval relative to the PPS interval.
+ * The pulse must be newer and within the range gate relative
+ * to the last pulse.
+ */
+ if (ap->ts.tv_sec <= timeout.tv_sec || abs(ap->ts.tv_nsec -
+ timeout.tv_nsec) > RANGEGATE)
+ return (0);
+
+ /*
+ * Convert to signed fraction offset and stuff in median filter.
+ */
+ pp->lastrec.l_ui = (u_int32)ap->ts.tv_sec + JAN_1970;
+ dtemp = ap->ts.tv_nsec / 1e9;
+ pp->lastrec.l_uf = (u_int32)(dtemp * FRAC);
+ if (dtemp > .5)
+ dtemp -= 1.;
+ SAMPLE(-dtemp + pp->fudgetime1);
+#ifdef DEBUG
+ if (debug > 1)
+ printf("refclock_pps: %lu %f %f\n", current_time,
+ dtemp, pp->fudgetime1);
+#endif
+ return (1);
+}
+#endif /* HAVE_PPSAPI */
#endif /* REFCLOCK */
diff --git a/ntpd/ntp_request.c b/ntpd/ntp_request.c
index f5eed4449d9a..a3c17e2267e8 100644
--- a/ntpd/ntp_request.c
+++ b/ntpd/ntp_request.c
@@ -13,11 +13,14 @@
#include "ntp_refclock.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
#include <stdio.h>
#include <stddef.h>
#include <signal.h>
+#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
#include <arpa/inet.h>
#include "recvbuff.h"
@@ -47,8 +50,8 @@ struct req_proc {
short needs_auth; /* true when authentication needed */
short sizeofitem; /* size of request data item (older size)*/
short v6_sizeofitem; /* size of request data item (new size)*/
- void (*handler) P((struct sockaddr_storage *, struct interface *,
- struct req_pkt *)); /* routine to handle request */
+ void (*handler) (sockaddr_u *, struct interface *,
+ struct req_pkt *); /* routine to handle request */
};
/*
@@ -58,58 +61,59 @@ static struct req_proc univ_codes[] = {
{ NO_REQUEST, NOAUTH, 0, 0 }
};
-static void req_ack P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
-static char * prepare_pkt P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int));
-static char * more_pkt P((void));
-static void flush_pkt P((void));
-static void peer_list P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void peer_list_sum P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void peer_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void peer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void sys_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void sys_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void mem_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void io_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void timer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void loop_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_conf P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_unconf P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void set_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void clr_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void setclr_flags P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
-static void list_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_resaddflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_ressubflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_unrestrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
-static void mon_getlist_0 P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void mon_getlist_1 P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void reset_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void reset_peer P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_key_reread P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void trust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void untrust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_trustkey P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
-static void get_auth_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void reset_auth_stats P((void));
-static void req_get_traps P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void req_set_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void req_clr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_setclr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
-static void set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void get_if_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_if_reload P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
+static void req_ack (sockaddr_u *, struct interface *, struct req_pkt *, int);
+static char * prepare_pkt (sockaddr_u *, struct interface *,
+ struct req_pkt *, size_t);
+static char * more_pkt (void);
+static void flush_pkt (void);
+static void peer_list (sockaddr_u *, struct interface *, struct req_pkt *);
+static void peer_list_sum (sockaddr_u *, struct interface *, struct req_pkt *);
+static void peer_info (sockaddr_u *, struct interface *, struct req_pkt *);
+static void peer_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void sys_info (sockaddr_u *, struct interface *, struct req_pkt *);
+static void sys_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void mem_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void io_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void timer_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void loop_info (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_conf (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_unconf (sockaddr_u *, struct interface *, struct req_pkt *);
+static void set_sys_flag (sockaddr_u *, struct interface *, struct req_pkt *);
+static void clr_sys_flag (sockaddr_u *, struct interface *, struct req_pkt *);
+static void setclr_flags (sockaddr_u *, struct interface *, struct req_pkt *, u_long);
+static void list_restrict (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_resaddflags (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_ressubflags (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_unrestrict (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_restrict (sockaddr_u *, struct interface *, struct req_pkt *, int);
+static void mon_getlist_0 (sockaddr_u *, struct interface *, struct req_pkt *);
+static void mon_getlist_1 (sockaddr_u *, struct interface *, struct req_pkt *);
+static void reset_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void reset_peer (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_key_reread (sockaddr_u *, struct interface *, struct req_pkt *);
+static void trust_key (sockaddr_u *, struct interface *, struct req_pkt *);
+static void untrust_key (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_trustkey (sockaddr_u *, struct interface *, struct req_pkt *, u_long);
+static void get_auth_info (sockaddr_u *, struct interface *, struct req_pkt *);
+static void reset_auth_stats (void);
+static void req_get_traps (sockaddr_u *, struct interface *, struct req_pkt *);
+static void req_set_trap (sockaddr_u *, struct interface *, struct req_pkt *);
+static void req_clr_trap (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_setclr_trap (sockaddr_u *, struct interface *, struct req_pkt *, int);
+static void set_request_keyid (sockaddr_u *, struct interface *, struct req_pkt *);
+static void set_control_keyid (sockaddr_u *, struct interface *, struct req_pkt *);
+static void get_ctl_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void get_if_stats (sockaddr_u *, struct interface *, struct req_pkt *);
+static void do_if_reload (sockaddr_u *, struct interface *, struct req_pkt *);
#ifdef KERNEL_PLL
-static void get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
+static void get_kernel_info (sockaddr_u *, struct interface *, struct req_pkt *);
#endif /* KERNEL_PLL */
#ifdef REFCLOCK
-static void get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
+static void get_clock_info (sockaddr_u *, struct interface *, struct req_pkt *);
+static void set_clock_fudge (sockaddr_u *, struct interface *, struct req_pkt *);
#endif /* REFCLOCK */
#ifdef REFCLOCK
-static void get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
+static void get_clkbug_info (sockaddr_u *, struct interface *, struct req_pkt *);
#endif /* REFCLOCK */
/*
@@ -216,7 +220,7 @@ static int itemsize;
static int databytes;
static char exbuf[RESP_DATA_SIZE];
static int usingexbuf;
-static struct sockaddr_storage *toaddr;
+static sockaddr_u *toaddr;
static struct interface *frominter;
/*
@@ -242,7 +246,7 @@ init_request (void)
*/
static void
req_ack(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
int errcode
@@ -272,16 +276,13 @@ req_ack(
*/
static char *
prepare_pkt(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *pkt,
- u_int structsize
+ size_t structsize
)
{
-#ifdef DEBUG
- if (debug > 3)
- printf("request: preparing pkt\n");
-#endif
+ DPRINTF(4, ("request: preparing pkt\n"));
/*
* Fill in the implementation, request and itemsize fields
@@ -319,21 +320,18 @@ more_pkt(void)
* If we were using the extra buffer, send the packet.
*/
if (usingexbuf) {
-#ifdef DEBUG
- if (debug > 2)
- printf("request: sending pkt\n");
-#endif
+ DPRINTF(3, ("request: sending pkt\n"));
rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
rpkt.auth_seq = AUTH_SEQ(0, seqno);
rpkt.err_nitems = htons((u_short)nitems);
sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
- RESP_HEADER_SIZE+databytes);
+ RESP_HEADER_SIZE + databytes);
numresppkts++;
/*
* Copy data out of exbuf into the packet.
*/
- memmove(&rpkt.data[0], exbuf, (unsigned)itemsize);
+ memcpy(&rpkt.data[0], exbuf, (unsigned)itemsize);
seqno++;
databytes = 0;
nitems = 0;
@@ -343,10 +341,7 @@ more_pkt(void)
databytes += itemsize;
nitems++;
if (databytes + itemsize <= RESP_DATA_SIZE) {
-#ifdef DEBUG
- if (debug > 3)
- printf("request: giving him more data\n");
-#endif
+ DPRINTF(4, ("request: giving him more data\n"));
/*
* More room in packet. Give him the
* next address.
@@ -357,12 +352,9 @@ more_pkt(void)
* No room in packet. Give him the extra
* buffer unless this was the last in the sequence.
*/
-#ifdef DEBUG
- if (debug > 3)
- printf("request: into extra buffer\n");
-#endif
+ DPRINTF(4, ("request: into extra buffer\n"));
if (seqno == MAXSEQ)
- return (char *)0;
+ return NULL;
else {
usingexbuf = 1;
return exbuf;
@@ -377,17 +369,14 @@ more_pkt(void)
static void
flush_pkt(void)
{
-#ifdef DEBUG
- if (debug > 2)
- printf("request: flushing packet, %d items\n", nitems);
-#endif
+ DPRINTF(3, ("request: flushing packet, %d items\n", nitems));
/*
* Must send the last packet. If nothing in here and nothing
* has been sent, send an error saying no data to be found.
*/
if (seqno == 0 && nitems == 0)
- req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
- INFO_ERR_NODATA);
+ req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
+ INFO_ERR_NODATA);
else {
rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
rpkt.auth_seq = AUTH_SEQ(0, seqno);
@@ -401,6 +390,17 @@ flush_pkt(void)
/*
+ * Given a buffer, return the packet mode
+ */
+int
+get_packet_mode(struct recvbuf *rbufp)
+{
+ struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt;
+ return (INFO_MODE(inpkt->rm_vn_mode));
+}
+
+
+/*
* process_private - process private mode (7) packets
*/
void
@@ -412,24 +412,27 @@ process_private(
static u_long quiet_until;
struct req_pkt *inpkt;
struct req_pkt_tail *tailinpkt;
- struct sockaddr_storage *srcadr;
+ sockaddr_u *srcadr;
struct interface *inter;
struct req_proc *proc;
int ec;
short temp_size;
+ l_fp ftmp;
+ double dtemp;
+ size_t recv_len;
+ size_t noslop_len;
+ size_t mac_len;
/*
* Initialize pointers, for convenience
*/
+ recv_len = rbufp->recv_length;
inpkt = (struct req_pkt *)&rbufp->recv_pkt;
srcadr = &rbufp->recv_srcadr;
inter = rbufp->dstadr;
-#ifdef DEBUG
- if (debug > 2)
- printf("process_private: impl %d req %d\n",
- inpkt->implementation, inpkt->request);
-#endif
+ DPRINTF(3, ("process_private: impl %d req %d\n",
+ inpkt->implementation, inpkt->request));
/*
* Do some sanity checks on the packet. Return a format
@@ -462,10 +465,10 @@ process_private(
* Get the appropriate procedure list to search.
*/
if (inpkt->implementation == IMPL_UNIV)
- proc = univ_codes;
+ proc = univ_codes;
else if ((inpkt->implementation == IMPL_XNTPD) ||
(inpkt->implementation == IMPL_XNTPD_OLD))
- proc = ntp_codes;
+ proc = ntp_codes;
else {
req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
return;
@@ -477,7 +480,7 @@ process_private(
*/
while (proc->request_code != NO_REQUEST) {
if (proc->request_code == (short) inpkt->request)
- break;
+ break;
proc++;
}
if (proc->request_code == NO_REQUEST) {
@@ -485,10 +488,7 @@ process_private(
return;
}
-#ifdef DEBUG
- if (debug > 3)
- printf("found request in tables\n");
-#endif
+ DPRINTF(4, ("found request in tables\n"));
/*
* If we need data, check to see if we have some. If we
@@ -507,21 +507,15 @@ process_private(
!(inpkt->implementation == IMPL_XNTPD &&
inpkt->request == REQ_CONFIG &&
temp_size == sizeof(struct old_conf_peer))) {
-#ifdef DEBUG
- if (debug > 2)
- printf("process_private: wrong item size, received %d, should be %d or %d\n",
- temp_size, proc->sizeofitem, proc->v6_sizeofitem);
-#endif
+ DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n",
+ temp_size, proc->sizeofitem, proc->v6_sizeofitem));
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
if ((proc->sizeofitem != 0) &&
- ((temp_size * INFO_NITEMS(inpkt->err_nitems)) >
- (rbufp->recv_length - REQ_LEN_HDR))) {
-#ifdef DEBUG
- if (debug > 2)
- printf("process_private: not enough data\n");
-#endif
+ ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) >
+ (recv_len - REQ_LEN_HDR))) {
+ DPRINTF(3, ("process_private: not enough data\n"));
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -547,54 +541,74 @@ process_private(
* time stamp.
*/
if (proc->needs_auth && sys_authenticate) {
- l_fp ftmp;
- double dtemp;
-
- if (rbufp->recv_length < (int)((REQ_LEN_HDR +
+
+ if (recv_len < (REQ_LEN_HDR +
(INFO_ITEMSIZE(inpkt->mbz_itemsize) *
- INFO_NITEMS(inpkt->err_nitems))
- + sizeof(struct req_pkt_tail)))) {
+ INFO_NITEMS(inpkt->err_nitems)) +
+ REQ_TAIL_MIN)) {
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
+ return;
}
- tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt +
- rbufp->recv_length - sizeof(struct req_pkt_tail));
/*
- * If this guy is restricted from doing this, don't let him
- * If wrong key was used, or packet doesn't have mac, return.
+ * For 16-octet digests, regardless of itemsize and
+ * nitems, authenticated requests are a fixed size
+ * with the timestamp, key ID, and digest located
+ * at the end of the packet. Because the key ID
+ * determining the digest size precedes the digest,
+ * for larger digests the fixed size request scheme
+ * is abandoned and the timestamp, key ID, and digest
+ * are located relative to the start of the packet,
+ * with the digest size determined by the packet size.
+ */
+ noslop_len = REQ_LEN_HDR
+ + INFO_ITEMSIZE(inpkt->mbz_itemsize) *
+ INFO_NITEMS(inpkt->err_nitems)
+ + sizeof(inpkt->tstamp);
+ /* 32-bit alignment */
+ noslop_len = (noslop_len + 3) & ~3;
+ if (recv_len > (noslop_len + MAX_MAC_LEN))
+ mac_len = 20;
+ else
+ mac_len = recv_len - noslop_len;
+
+ tailinpkt = (void *)((char *)inpkt + recv_len -
+ (mac_len + sizeof(inpkt->tstamp)));
+
+ /*
+ * If this guy is restricted from doing this, don't let
+ * him. If the wrong key was used, or packet doesn't
+ * have mac, return.
*/
- if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0
+ if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid
|| ntohl(tailinpkt->keyid) != info_auth_keyid) {
+ DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n",
+ INFO_IS_AUTH(inpkt->auth_seq),
+ info_auth_keyid,
+ ntohl(tailinpkt->keyid), (u_long)mac_len));
#ifdef DEBUG
- if (debug > 4)
- printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
- INFO_IS_AUTH(inpkt->auth_seq),
- (u_long)info_auth_keyid,
- (u_long)ntohl(tailinpkt->keyid));
msyslog(LOG_DEBUG,
- "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
+ "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n",
INFO_IS_AUTH(inpkt->auth_seq),
- (u_long)info_auth_keyid,
- (u_long)ntohl(tailinpkt->keyid));
+ info_auth_keyid,
+ ntohl(tailinpkt->keyid), (u_long)mac_len);
#endif
req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
return;
}
- if (rbufp->recv_length > REQ_LEN_MAC) {
-#ifdef DEBUG
- if (debug > 4)
- printf("bad pkt length %d\n",
- rbufp->recv_length);
-#endif
- msyslog(LOG_ERR, "process_private: bad pkt length %d",
- rbufp->recv_length);
+ if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) {
+ DPRINTF(5, ("bad pkt length %lu\n",
+ (u_long)recv_len));
+ msyslog(LOG_ERR,
+ "process_private: bad pkt length %lu",
+ (u_long)recv_len);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
if (!mod_okay || !authhavekey(info_auth_keyid)) {
+ DPRINTF(5, ("failed auth mod_okay %d\n",
+ mod_okay));
#ifdef DEBUG
- if (debug > 4)
- printf("failed auth mod_okay %d\n", mod_okay);
msyslog(LOG_DEBUG,
"process_private: failed auth mod_okay %d\n",
mod_okay);
@@ -610,14 +624,12 @@ process_private(
NTOHL_FP(&tailinpkt->tstamp, &ftmp);
L_SUB(&ftmp, &rbufp->recv_time);
LFPTOD(&ftmp, dtemp);
- if (fabs(dtemp) >= INFO_TS_MAXSKEW) {
+ if (fabs(dtemp) > INFO_TS_MAXSKEW) {
/*
* He's a loser. Tell him.
*/
-#ifdef DEBUG
- if (debug > 4)
- printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n");
-#endif
+ DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n",
+ dtemp, INFO_TS_MAXSKEW));
req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
return;
}
@@ -626,22 +638,14 @@ process_private(
* So far so good. See if decryption works out okay.
*/
if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
- rbufp->recv_length - sizeof(struct req_pkt_tail) +
- REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) {
-#ifdef DEBUG
- if (debug > 4)
- printf("authdecrypt failed\n");
-#endif
+ recv_len - mac_len, mac_len)) {
+ DPRINTF(5, ("authdecrypt failed\n"));
req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
return;
}
}
-#ifdef DEBUG
- if (debug > 3)
- printf("process_private: all okay, into handler\n");
-#endif
-
+ DPRINTF(3, ("process_private: all okay, into handler\n"));
/*
* Packet is okay. Call the handler to send him data.
*/
@@ -654,7 +658,7 @@ process_private(
*/
static void
peer_list(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -669,9 +673,9 @@ peer_list(
for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) {
pp = peer_hash[i];
while (pp != 0 && ip != 0) {
- if (pp->srcadr.ss_family == AF_INET6) {
+ if (IS_IPV6(&pp->srcadr)) {
if (client_v6_capable) {
- ip->addr6 = GET_INADDR6(pp->srcadr);
+ ip->addr6 = SOCK_ADDR6(&pp->srcadr);
ip->v6_flag = 1;
skip = 0;
} else {
@@ -679,7 +683,7 @@ peer_list(
break;
}
} else {
- ip->addr = GET_INADDR(pp->srcadr);
+ ip->addr = NSRCADR(&pp->srcadr);
if (client_v6_capable)
ip->v6_flag = 0;
skip = 0;
@@ -711,7 +715,7 @@ peer_list(
*/
static void
peer_list_sum(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -739,12 +743,12 @@ peer_list_sum(
* Be careful here not to return v6 peers when we
* want only v4.
*/
- if (pp->srcadr.ss_family == AF_INET6) {
+ if (IS_IPV6(&pp->srcadr)) {
if (client_v6_capable) {
- ips->srcadr6 = GET_INADDR6(pp->srcadr);
+ ips->srcadr6 = SOCK_ADDR6(&pp->srcadr);
ips->v6_flag = 1;
if (pp->dstadr)
- ips->dstadr6 = GET_INADDR6(pp->dstadr->sin);
+ ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin);
else
memset(&ips->dstadr6, 0, sizeof(ips->dstadr6));
skip = 0;
@@ -753,22 +757,24 @@ peer_list_sum(
break;
}
} else {
- ips->srcadr = GET_INADDR(pp->srcadr);
+ ips->srcadr = NSRCADR(&pp->srcadr);
if (client_v6_capable)
ips->v6_flag = 0;
-/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
- if (pp->dstadr)
- ips->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- GET_INADDR(pp->dstadr->bcast):
- pp->cast_flags ?
- GET_INADDR(pp->dstadr->sin) ?
- GET_INADDR(pp->dstadr->sin):
- GET_INADDR(pp->dstadr->bcast):
- 1 : GET_INADDR(pp->dstadr->sin);
- else
- memset(&ips->dstadr, 0, sizeof(ips->dstadr));
+ if (pp->dstadr) {
+ if (!pp->processed)
+ ips->dstadr = NSRCADR(&pp->dstadr->sin);
+ else {
+ if (MDF_BCAST == pp->cast_flags)
+ ips->dstadr = NSRCADR(&pp->dstadr->bcast);
+ else if (pp->cast_flags) {
+ ips->dstadr = NSRCADR(&pp->dstadr->sin);
+ if (!ips->dstadr)
+ ips->dstadr = NSRCADR(&pp->dstadr->bcast);
+ }
+ }
+ } else
+ ips->dstadr = 0;
skip = 0;
}
@@ -786,8 +792,6 @@ peer_list_sum(
ips->flags |= INFO_FLAG_CONFIG;
if (pp->flags & FLAG_REFCLOCK)
ips->flags |= INFO_FLAG_REFCLOCK;
- if (pp->flags & FLAG_AUTHENABLE)
- ips->flags |= INFO_FLAG_AUTHENABLE;
if (pp->flags & FLAG_PREFER)
ips->flags |= INFO_FLAG_PREFER;
if (pp->flags & FLAG_BURST)
@@ -815,7 +819,7 @@ peer_list_sum(
*/
static void
peer_info (
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -825,57 +829,60 @@ peer_info (
register struct info_peer *ip;
register int items;
register int i, j;
- struct sockaddr_storage addr;
+ sockaddr_u addr;
extern struct peer *sys_peer;
l_fp ltmp;
- memset((char *)&addr, 0, sizeof addr);
items = INFO_NITEMS(inpkt->err_nitems);
ipl = (struct info_peer_list *) inpkt->data;
ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
v6sizeof(struct info_peer));
while (items-- > 0 && ip != 0) {
- memset((char *)&addr, 0, sizeof(addr));
+ ZERO_SOCK(&addr);
NSRCPORT(&addr) = ipl->port;
- if (client_v6_capable && ipl->v6_flag != 0) {
- addr.ss_family = AF_INET6;
- GET_INADDR6(addr) = ipl->addr6;
+ if (client_v6_capable && ipl->v6_flag) {
+ AF(&addr) = AF_INET6;
+ SOCK_ADDR6(&addr) = ipl->addr6;
} else {
- addr.ss_family = AF_INET;
- GET_INADDR(addr) = ipl->addr;
+ AF(&addr) = AF_INET;
+ NSRCADR(&addr) = ipl->addr;
}
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
+#ifdef ISC_PLATFORM_HAVESALEN
+ addr.sa.sa_len = SOCKLEN(&addr);
#endif
ipl++;
- if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
- continue;
- if (pp->srcadr.ss_family == AF_INET6) {
+ pp = findexistingpeer(&addr, NULL, -1, 0);
+ if (NULL == pp)
+ continue;
+ if (IS_IPV6(srcadr)) {
if (pp->dstadr)
- ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
- GET_INADDR6(pp->dstadr->bcast) :
- GET_INADDR6(pp->dstadr->sin);
+ ip->dstadr6 =
+ (MDF_BCAST == pp->cast_flags)
+ ? SOCK_ADDR6(&pp->dstadr->bcast)
+ : SOCK_ADDR6(&pp->dstadr->sin);
else
memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
- ip->srcadr6 = GET_INADDR6(pp->srcadr);
+ ip->srcadr6 = SOCK_ADDR6(&pp->srcadr);
ip->v6_flag = 1;
} else {
-/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
- if (pp->dstadr)
- ip->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- GET_INADDR(pp->dstadr->bcast):
- pp->cast_flags ?
- GET_INADDR(pp->dstadr->sin) ?
- GET_INADDR(pp->dstadr->sin):
- GET_INADDR(pp->dstadr->bcast):
- 2 : GET_INADDR(pp->dstadr->sin);
- else
- memset(&ip->dstadr, 0, sizeof(ip->dstadr));
+ if (pp->dstadr) {
+ if (!pp->processed)
+ ip->dstadr = NSRCADR(&pp->dstadr->sin);
+ else {
+ if (MDF_BCAST == pp->cast_flags)
+ ip->dstadr = NSRCADR(&pp->dstadr->bcast);
+ else if (pp->cast_flags) {
+ ip->dstadr = NSRCADR(&pp->dstadr->sin);
+ if (!ip->dstadr)
+ ip->dstadr = NSRCADR(&pp->dstadr->bcast);
+ }
+ }
+ } else
+ ip->dstadr = 0;
- ip->srcadr = GET_INADDR(pp->srcadr);
+ ip->srcadr = NSRCADR(&pp->srcadr);
if (client_v6_capable)
ip->v6_flag = 0;
}
@@ -887,8 +894,6 @@ peer_info (
ip->flags |= INFO_FLAG_CONFIG;
if (pp->flags & FLAG_REFCLOCK)
ip->flags |= INFO_FLAG_REFCLOCK;
- if (pp->flags & FLAG_AUTHENABLE)
- ip->flags |= INFO_FLAG_AUTHENABLE;
if (pp->flags & FLAG_PREFER)
ip->flags |= INFO_FLAG_PREFER;
if (pp->flags & FLAG_BURST)
@@ -909,14 +914,14 @@ peer_info (
ip->unreach = (u_char) pp->unreach;
ip->flash = (u_char)pp->flash;
ip->flash2 = (u_short) pp->flash;
- ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay));
+ ip->estbdelay = HTONS_FP(DTOFP(pp->delay));
ip->ttl = pp->ttl;
ip->associd = htons(pp->associd);
ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
- ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion));
+ ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp));
ip->refid = pp->refid;
HTONL_FP(&pp->reftime, &ip->reftime);
- HTONL_FP(&pp->org, &ip->org);
+ HTONL_FP(&pp->aorg, &ip->org);
HTONL_FP(&pp->rec, &ip->rec);
HTONL_FP(&pp->xmt, &ip->xmt);
j = pp->filter_nextpt - 1;
@@ -947,7 +952,7 @@ peer_info (
*/
static void
peer_stats (
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -956,7 +961,7 @@ peer_stats (
register struct peer *pp;
register struct info_peer_stats *ip;
register int items;
- struct sockaddr_storage addr;
+ sockaddr_u addr;
extern struct peer *sys_peer;
#ifdef DEBUG
@@ -971,54 +976,56 @@ peer_stats (
memset((char *)&addr, 0, sizeof(addr));
NSRCPORT(&addr) = ipl->port;
if (client_v6_capable && ipl->v6_flag) {
- addr.ss_family = AF_INET6;
- GET_INADDR6(addr) = ipl->addr6;
+ AF(&addr) = AF_INET6;
+ SOCK_ADDR6(&addr) = ipl->addr6;
} else {
- addr.ss_family = AF_INET;
- GET_INADDR(addr) = ipl->addr;
+ AF(&addr) = AF_INET;
+ NSRCADR(&addr) = ipl->addr;
}
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
-#endif
-#ifdef DEBUG
- if (debug)
- printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr),
- ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port);
+#ifdef ISC_PLATFORM_HAVESALEN
+ addr.sa.sa_len = SOCKLEN(&addr);
#endif
+ DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n",
+ stoa(&addr), ipl->port, NSRCPORT(&addr)));
+
ipl = (struct info_peer_list *)((char *)ipl +
INFO_ITEMSIZE(inpkt->mbz_itemsize));
- if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
- continue;
-#ifdef DEBUG
- if (debug)
- printf("peer_stats: found %s\n", stoa(&addr));
-#endif
- if (pp->srcadr.ss_family == AF_INET) {
- if (pp->dstadr)
- ip->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- GET_INADDR(pp->dstadr->bcast):
- pp->cast_flags ?
- GET_INADDR(pp->dstadr->sin) ?
- GET_INADDR(pp->dstadr->sin):
- GET_INADDR(pp->dstadr->bcast):
- 3 : 7;
- else
- memset(&ip->dstadr, 0, sizeof(ip->dstadr));
+ pp = findexistingpeer(&addr, NULL, -1, 0);
+ if (NULL == pp)
+ continue;
+
+ DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr)));
+
+ if (IS_IPV4(&pp->srcadr)) {
+ if (pp->dstadr) {
+ if (!pp->processed)
+ ip->dstadr = NSRCADR(&pp->dstadr->sin);
+ else {
+ if (MDF_BCAST == pp->cast_flags)
+ ip->dstadr = NSRCADR(&pp->dstadr->bcast);
+ else if (pp->cast_flags) {
+ ip->dstadr = NSRCADR(&pp->dstadr->sin);
+ if (!ip->dstadr)
+ ip->dstadr = NSRCADR(&pp->dstadr->bcast);
+ }
+ }
+ } else
+ ip->dstadr = 0;
- ip->srcadr = GET_INADDR(pp->srcadr);
+ ip->srcadr = NSRCADR(&pp->srcadr);
if (client_v6_capable)
ip->v6_flag = 0;
} else {
if (pp->dstadr)
- ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
- GET_INADDR6(pp->dstadr->bcast):
- GET_INADDR6(pp->dstadr->sin);
+ ip->dstadr6 =
+ (MDF_BCAST == pp->cast_flags)
+ ? SOCK_ADDR6(&pp->dstadr->bcast)
+ : SOCK_ADDR6(&pp->dstadr->sin);
else
memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
-
- ip->srcadr6 = GET_INADDR6(pp->srcadr);
+
+ ip->srcadr6 = SOCK_ADDR6(&pp->srcadr);
ip->v6_flag = 1;
}
ip->srcport = NSRCPORT(&pp->srcadr);
@@ -1029,8 +1036,6 @@ peer_stats (
ip->flags |= INFO_FLAG_CONFIG;
if (pp->flags & FLAG_REFCLOCK)
ip->flags |= INFO_FLAG_REFCLOCK;
- if (pp->flags & FLAG_AUTHENABLE)
- ip->flags |= INFO_FLAG_AUTHENABLE;
if (pp->flags & FLAG_PREFER)
ip->flags |= INFO_FLAG_PREFER;
if (pp->flags & FLAG_BURST)
@@ -1064,7 +1069,7 @@ peer_stats (
*/
static void
sys_info(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1074,13 +1079,13 @@ sys_info(
is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
v6sizeof(struct info_sys));
- if (sys_peer != 0) {
- if (sys_peer->srcadr.ss_family == AF_INET) {
- is->peer = GET_INADDR(sys_peer->srcadr);
+ if (sys_peer) {
+ if (IS_IPV4(&sys_peer->srcadr)) {
+ is->peer = NSRCADR(&sys_peer->srcadr);
if (client_v6_capable)
is->v6_flag = 0;
} else if (client_v6_capable) {
- is->peer6 = GET_INADDR6(sys_peer->srcadr);
+ is->peer6 = SOCK_ADDR6(&sys_peer->srcadr);
is->v6_flag = 1;
}
is->peer_mode = sys_peer->hmode;
@@ -1096,7 +1101,7 @@ sys_info(
is->stratum = sys_stratum;
is->precision = sys_precision;
is->rootdelay = htonl(DTOFP(sys_rootdelay));
- is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
+ is->rootdispersion = htonl(DTOUFP(sys_rootdisp));
is->frequency = htonl(DTOFP(sys_jitter));
is->stability = htonl(DTOUFP(clock_stability));
is->refid = sys_refid;
@@ -1125,7 +1130,6 @@ sys_info(
is->flags |= INFO_FLAG_FILEGEN;
is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
HTONL_UF(sys_authdelay.l_f, &is->authdelay);
-
(void) more_pkt();
flush_pkt();
}
@@ -1136,7 +1140,7 @@ sys_info(
*/
static void
sys_stats(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1151,9 +1155,9 @@ sys_stats(
ss->timeup = htonl((u_int32)current_time);
ss->timereset = htonl((u_int32)(current_time - sys_stattime));
ss->denied = htonl((u_int32)sys_restricted);
- ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt);
- ss->newversionpkt = htonl((u_int32)sys_newversionpkt);
- ss->unknownversion = htonl((u_int32)sys_unknownversion);
+ ss->oldversionpkt = htonl((u_int32)sys_oldversion);
+ ss->newversionpkt = htonl((u_int32)sys_newversion);
+ ss->unknownversion = htonl((u_int32)sys_declined);
ss->badlength = htonl((u_int32)sys_badlength);
ss->processed = htonl((u_int32)sys_processed);
ss->badauth = htonl((u_int32)sys_badauth);
@@ -1169,7 +1173,7 @@ sys_stats(
*/
static void
mem_stats(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1215,7 +1219,7 @@ mem_stats(
*/
static void
io_stats(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1253,26 +1257,21 @@ io_stats(
*/
static void
timer_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
+ sockaddr_u * srcadr,
+ struct interface * inter,
+ struct req_pkt * inpkt
)
{
- register struct info_timer_stats *ts;
+ struct info_timer_stats * ts;
+ u_long sincereset;
- /*
- * Importations from the timer module
- */
- extern u_long timer_timereset;
- extern u_long timer_overflows;
- extern u_long timer_xmtcalls;
+ ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter,
+ inpkt, sizeof(*ts));
- ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_timer_stats));
-
- ts->timereset = htonl((u_int32)(current_time - timer_timereset));
- ts->alarms = htonl((u_int32)alarm_overflow);
- ts->overflows = htonl((u_int32)timer_overflows);
+ sincereset = current_time - timer_timereset;
+ ts->timereset = htonl((u_int32)sincereset);
+ ts->alarms = ts->timereset;
+ ts->overflows = htonl((u_int32)alarm_overflow);
ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
(void) more_pkt();
@@ -1285,7 +1284,7 @@ timer_stats(
*/
static void
loop_info(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1299,7 +1298,7 @@ loop_info(
extern double last_offset;
extern double drift_comp;
extern int tc_counter;
- extern u_long sys_clocktime;
+ extern u_long sys_epoch;
li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_loop));
@@ -1309,7 +1308,7 @@ loop_info(
DTOLFP(drift_comp * 1e6, &ltmp);
HTONL_FP(&ltmp, &li->drift_comp);
li->compliance = htonl((u_int32)(tc_counter));
- li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime));
+ li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch));
(void) more_pkt();
flush_pkt();
@@ -1321,7 +1320,7 @@ loop_info(
*/
static void
do_conf(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1331,8 +1330,7 @@ do_conf(
u_int fl;
struct conf_peer *cp;
struct conf_peer temp_cp;
- struct sockaddr_storage peeraddr;
- struct sockaddr_in tmp_clock;
+ sockaddr_u peeraddr;
/*
* Do a check of everything to see that it looks
@@ -1343,6 +1341,8 @@ do_conf(
cp = (struct conf_peer *)inpkt->data;
memset(&temp_cp, 0, sizeof(struct conf_peer));
memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
+
+#if 0 /* paranoid checking - these are done in newpeer() */
fl = 0;
while (items-- > 0 && !fl) {
if (((temp_cp.version) > NTP_VERSION)
@@ -1352,9 +1352,9 @@ do_conf(
&& temp_cp.hmode != MODE_CLIENT
&& temp_cp.hmode != MODE_BROADCAST)
fl = 1;
- if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
- | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY))
- fl = 1;
+ if (temp_cp.flags & ~(CONF_FLAG_PREFER | CONF_FLAG_BURST |
+ CONF_FLAG_IBURST | CONF_FLAG_SKEY))
+ fl = 1;
cp = (struct conf_peer *)
((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
@@ -1363,6 +1363,7 @@ do_conf(
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
+#endif /* end paranoid checking */
/*
* Looks okay, try it out
@@ -1373,43 +1374,38 @@ do_conf(
while (items-- > 0) {
memset(&temp_cp, 0, sizeof(struct conf_peer));
memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage));
+ ZERO_SOCK(&peeraddr);
fl = 0;
- if (temp_cp.flags & CONF_FLAG_AUTHENABLE)
- fl |= FLAG_AUTHENABLE;
if (temp_cp.flags & CONF_FLAG_PREFER)
fl |= FLAG_PREFER;
if (temp_cp.flags & CONF_FLAG_BURST)
fl |= FLAG_BURST;
if (temp_cp.flags & CONF_FLAG_IBURST)
fl |= FLAG_IBURST;
+#ifdef OPENSSL
if (temp_cp.flags & CONF_FLAG_SKEY)
fl |= FLAG_SKEY;
-
+#endif /* OPENSSL */
if (client_v6_capable && temp_cp.v6_flag != 0) {
- peeraddr.ss_family = AF_INET6;
- GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
+ AF(&peeraddr) = AF_INET6;
+ SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
} else {
- peeraddr.ss_family = AF_INET;
- GET_INADDR(peeraddr) = temp_cp.peeraddr;
+ AF(&peeraddr) = AF_INET;
+ NSRCADR(&peeraddr) = temp_cp.peeraddr;
/*
* Make sure the address is valid
*/
- tmp_clock = *CAST_V4(peeraddr);
- if (
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&tmp_clock) &&
-#endif
- ISBADADR(&tmp_clock)) {
+ if (!ISREFCLOCKADR(&peeraddr) &&
+ ISBADADR(&peeraddr)) {
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
}
NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
+#ifdef ISC_PLATFORM_HAVESALEN
+ peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
#endif
/* XXX W2DO? minpoll/maxpoll arguments ??? */
@@ -1451,7 +1447,7 @@ do_conf(
*/
static void
dns_a(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1480,16 +1476,8 @@ dns_a(
/*
* 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
+ if (!ISREFCLOCKADR(&peeraddr) && ISBADADR(&peeraddr)) {
+ msyslog(LOG_ERR, "dns_a: !ISREFCLOCKADR && ISBADADR");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1519,7 +1507,7 @@ dns_a(
msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
dp->hostname,
- stoa((struct sockaddr_storage *)&peeraddr), associd,
+ stoa((sockaddr_u *)&peeraddr), associd,
bogon);
if (bogon) {
@@ -1546,7 +1534,7 @@ dns_a(
*/
static void
do_unconf(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1555,7 +1543,7 @@ do_unconf(
struct conf_unpeer temp_cp;
register int items;
register struct peer *peer;
- struct sockaddr_storage peeraddr;
+ sockaddr_u peeraddr;
int bad, found;
/*
@@ -1570,36 +1558,35 @@ do_unconf(
bad = 0;
while (items-- > 0 && !bad) {
memset(&temp_cp, 0, sizeof(temp_cp));
- memset(&peeraddr, 0, sizeof(peeraddr));
+ ZERO_SOCK(&peeraddr);
memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- if (client_v6_capable && temp_cp.v6_flag != 0) {
- peeraddr.ss_family = AF_INET6;
- GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
+ if (client_v6_capable && temp_cp.v6_flag) {
+ AF(&peeraddr) = AF_INET6;
+ SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
} else {
- peeraddr.ss_family = AF_INET;
- GET_INADDR(peeraddr) = temp_cp.peeraddr;
+ AF(&peeraddr) = AF_INET;
+ NSRCADR(&peeraddr) = temp_cp.peeraddr;
}
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
+ SET_PORT(&peeraddr, NTP_PORT);
+#ifdef ISC_PLATFORM_HAVESALEN
+ peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
#endif
found = 0;
- peer = (struct peer *)0;
-#ifdef DEBUG
- if (debug)
- printf("searching for %s\n", stoa(&peeraddr));
-#endif
+ peer = NULL;
+
+ DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
+
while (!found) {
- peer = findexistingpeer(&peeraddr, peer, -1);
- if (peer == (struct peer *)0)
- break;
+ peer = findexistingpeer(&peeraddr, peer, -1, 0);
+ if (!peer)
+ break;
if (peer->flags & FLAG_CONFIG)
- found = 1;
+ found = 1;
}
if (!found)
- bad = 1;
+ bad = 1;
cp = (struct conf_unpeer *)
- ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
+ ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
if (bad) {
@@ -1613,24 +1600,40 @@ do_unconf(
items = INFO_NITEMS(inpkt->err_nitems);
cp = (struct conf_unpeer *)inpkt->data;
+
while (items-- > 0) {
memset(&temp_cp, 0, sizeof(temp_cp));
memset(&peeraddr, 0, sizeof(peeraddr));
memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- if (client_v6_capable && temp_cp.v6_flag != 0) {
- peeraddr.ss_family = AF_INET6;
- GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
+ if (client_v6_capable && temp_cp.v6_flag) {
+ AF(&peeraddr) = AF_INET6;
+ SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
} else {
- peeraddr.ss_family = AF_INET;
- GET_INADDR(peeraddr) = temp_cp.peeraddr;
+ AF(&peeraddr) = AF_INET;
+ NSRCADR(&peeraddr) = temp_cp.peeraddr;
}
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
+ SET_PORT(&peeraddr, NTP_PORT);
+#ifdef ISC_PLATFORM_HAVESALEN
+ peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
#endif
- peer_unconfig(&peeraddr, (struct interface *)0, -1);
+ found = 0;
+ peer = NULL;
+
+ while (!found) {
+ peer = findexistingpeer(&peeraddr, peer, -1, 0);
+ if (!peer)
+ break;
+ if (peer->flags & FLAG_CONFIG)
+ found = 1;
+ }
+ NTP_INSIST(found);
+ NTP_INSIST(peer);
+
+ peer_clear(peer, "GONE");
+ unpeer(peer);
+
cp = (struct conf_unpeer *)
- ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
+ ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
req_ack(srcadr, inter, inpkt, INFO_OKAY);
@@ -1642,7 +1645,7 @@ do_unconf(
*/
static void
set_sys_flag(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1656,7 +1659,7 @@ set_sys_flag(
*/
static void
clr_sys_flag(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1670,13 +1673,14 @@ clr_sys_flag(
*/
static void
setclr_flags(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
u_long set
)
{
- register u_int flags;
+ struct conf_sys_flags *sf;
+ u_int32 flags;
int prev_kern_enable;
prev_kern_enable = kern_enable;
@@ -1686,8 +1690,8 @@ setclr_flags(
return;
}
- flags = ((struct conf_sys_flags *)inpkt->data)->flags;
- flags = ntohl(flags);
+ sf = (struct conf_sys_flags *)inpkt->data;
+ flags = ntohl(sf->flags);
if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
@@ -1726,60 +1730,95 @@ setclr_flags(
loop_config(LOOP_DRIFTCOMP, drift_comp);
}
+/*
+ * list_restrict4 - recursive helper for list_restrict dumps IPv4
+ * restriction list in reverse order.
+ */
+static void
+list_restrict4(
+ restrict_u * res,
+ struct info_restrict ** ppir
+ )
+{
+ struct info_restrict * pir;
+
+ if (res->link != NULL)
+ list_restrict4(res->link, ppir);
+
+ pir = *ppir;
+ pir->addr = htonl(res->u.v4.addr);
+ if (client_v6_capable)
+ pir->v6_flag = 0;
+ pir->mask = htonl(res->u.v4.mask);
+ pir->count = htonl(res->count);
+ pir->flags = htons(res->flags);
+ pir->mflags = htons(res->mflags);
+ *ppir = (struct info_restrict *)more_pkt();
+}
+
+
+/*
+ * list_restrict6 - recursive helper for list_restrict dumps IPv6
+ * restriction list in reverse order.
+ */
+static void
+list_restrict6(
+ restrict_u * res,
+ struct info_restrict ** ppir
+ )
+{
+ struct info_restrict * pir;
+
+ if (res->link != NULL)
+ list_restrict6(res->link, ppir);
+
+ pir = *ppir;
+ pir->addr6 = res->u.v6.addr;
+ pir->mask6 = res->u.v6.mask;
+ pir->v6_flag = 1;
+ pir->count = htonl(res->count);
+ pir->flags = htons(res->flags);
+ pir->mflags = htons(res->mflags);
+ *ppir = (struct info_restrict *)more_pkt();
+}
+
/*
* list_restrict - return the restrict list
*/
static void
list_restrict(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
- register struct info_restrict *ir;
- register struct restrictlist *rl;
- register struct restrictlist6 *rl6;
+ struct info_restrict *ir;
-#ifdef DEBUG
- if (debug > 2)
- printf("wants restrict list summary\n");
-#endif
+ DPRINTF(3, ("wants restrict list summary\n"));
ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
v6sizeof(struct info_restrict));
- for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
- ir->addr = htonl(rl->addr);
- if (client_v6_capable)
- ir->v6_flag = 0;
- ir->mask = htonl(rl->mask);
- ir->count = htonl((u_int32)rl->count);
- ir->flags = htons(rl->flags);
- ir->mflags = htons(rl->mflags);
- ir = (struct info_restrict *)more_pkt();
- }
+ /*
+ * The restriction lists are kept sorted in the reverse order
+ * than they were originally. To preserve the output semantics,
+ * dump each list in reverse order. A recursive helper function
+ * achieves that.
+ */
+ list_restrict4(restrictlist4, &ir);
if (client_v6_capable)
- for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) {
- ir->addr6 = rl6->addr6;
- ir->mask6 = rl6->mask6;
- ir->v6_flag = 1;
- ir->count = htonl((u_int32)rl6->count);
- ir->flags = htons(rl6->flags);
- ir->mflags = htons(rl6->mflags);
- ir = (struct info_restrict *)more_pkt();
- }
+ list_restrict6(restrictlist6, &ir);
flush_pkt();
}
-
/*
* do_resaddflags - add flags to a restrict entry (or create one)
*/
static void
do_resaddflags(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1794,7 +1833,7 @@ do_resaddflags(
*/
static void
do_ressubflags(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1808,7 +1847,7 @@ do_ressubflags(
*/
static void
do_unrestrict(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1817,15 +1856,12 @@ do_unrestrict(
}
-
-
-
/*
* do_restrict - do the dirty stuff of dealing with restrictions
*/
static void
do_restrict(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
int op
@@ -1833,8 +1869,8 @@ do_restrict(
{
register struct conf_restrict *cr;
register int items;
- struct sockaddr_storage matchaddr;
- struct sockaddr_storage matchmask;
+ sockaddr_u matchaddr;
+ sockaddr_u matchmask;
int bad;
/*
@@ -1876,20 +1912,20 @@ do_restrict(
*/
items = INFO_NITEMS(inpkt->err_nitems);
cr = (struct conf_restrict *)inpkt->data;
- memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage));
- memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage));
+ ZERO_SOCK(&matchaddr);
+ ZERO_SOCK(&matchmask);
while (items-- > 0) {
- if (client_v6_capable && cr->v6_flag != 0) {
- GET_INADDR6(matchaddr) = cr->addr6;
- GET_INADDR6(matchmask) = cr->mask6;
- matchaddr.ss_family = AF_INET6;
- matchmask.ss_family = AF_INET6;
+ if (client_v6_capable && cr->v6_flag) {
+ AF(&matchaddr) = AF_INET6;
+ AF(&matchmask) = AF_INET6;
+ SOCK_ADDR6(&matchaddr) = cr->addr6;
+ SOCK_ADDR6(&matchmask) = cr->mask6;
} else {
- GET_INADDR(matchaddr) = cr->addr;
- GET_INADDR(matchmask) = cr->mask;
- matchaddr.ss_family = AF_INET;
- matchmask.ss_family = AF_INET;
+ AF(&matchaddr) = AF_INET;
+ AF(&matchmask) = AF_INET;
+ NSRCADR(&matchaddr) = cr->addr;
+ NSRCADR(&matchmask) = cr->mask;
}
hack_restrict(op, &matchaddr, &matchmask, cr->mflags,
cr->flags);
@@ -1905,7 +1941,7 @@ do_restrict(
*/
static void
mon_getlist_0(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1927,17 +1963,18 @@ mon_getlist_0(
v6sizeof(struct info_monitor));
for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
md = md->mru_next) {
- im->lasttime = htonl((u_int32)md->avg_interval);
+ im->lasttime = htonl((u_int32)((current_time -
+ md->firsttime) / md->count));
im->firsttime = htonl((u_int32)(current_time - md->lasttime));
- im->lastdrop = htonl((u_int32)md->drop_count);
+ im->restr = htonl((u_int32)md->flags);
im->count = htonl((u_int32)(md->count));
- if (md->rmtadr.ss_family == AF_INET6) {
+ if (IS_IPV6(&md->rmtadr)) {
if (!client_v6_capable)
continue;
- im->addr6 = GET_INADDR6(md->rmtadr);
+ im->addr6 = SOCK_ADDR6(&md->rmtadr);
im->v6_flag = 1;
} else {
- im->addr = GET_INADDR(md->rmtadr);
+ im->addr = NSRCADR(&md->rmtadr);
if (client_v6_capable)
im->v6_flag = 0;
}
@@ -1954,7 +1991,7 @@ mon_getlist_0(
*/
static void
mon_getlist_1(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1972,27 +2009,29 @@ mon_getlist_1(
v6sizeof(struct info_monitor_1));
for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
md = md->mru_next) {
- im->lasttime = htonl((u_int32)md->avg_interval);
+ im->lasttime = htonl((u_int32)((current_time -
+ md->firsttime) / md->count));
im->firsttime = htonl((u_int32)(current_time - md->lasttime));
- im->lastdrop = htonl((u_int32)md->drop_count);
+ im->restr = htonl((u_int32)md->flags);
im->count = htonl((u_int32)md->count);
- if (md->rmtadr.ss_family == AF_INET6) {
+ if (IS_IPV6(&md->rmtadr)) {
if (!client_v6_capable)
continue;
- im->addr6 = GET_INADDR6(md->rmtadr);
+ im->addr6 = SOCK_ADDR6(&md->rmtadr);
im->v6_flag = 1;
- im->daddr6 = GET_INADDR6(md->interface->sin);
+ im->daddr6 = SOCK_ADDR6(&md->interface->sin);
} else {
- im->addr = GET_INADDR(md->rmtadr);
+ im->addr = NSRCADR(&md->rmtadr);
if (client_v6_capable)
im->v6_flag = 0;
- im->daddr = (md->cast_flags == MDF_BCAST)
- ? GET_INADDR(md->interface->bcast)
- : (md->cast_flags
- ? (GET_INADDR(md->interface->sin)
- ? GET_INADDR(md->interface->sin)
- : GET_INADDR(md->interface->bcast))
- : 4);
+ if (MDF_BCAST == md->cast_flags)
+ im->daddr = NSRCADR(&md->interface->bcast);
+ else if (md->cast_flags) {
+ im->daddr = NSRCADR(&md->interface->sin);
+ if (!im->daddr)
+ im->daddr = NSRCADR(&md->interface->bcast);
+ } else
+ im->daddr = 4;
}
im->flags = htonl(md->cast_flags);
im->port = md->rmtport;
@@ -2008,7 +2047,7 @@ mon_getlist_1(
*/
struct reset_entry {
int flag; /* flag this corresponds to */
- void (*handler) P((void)); /* routine to handle request */
+ void (*handler) (void); /* routine to handle request */
};
struct reset_entry reset_entries[] = {
@@ -2027,11 +2066,12 @@ struct reset_entry reset_entries[] = {
*/
static void
reset_stats(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
+ struct reset_flags *rflags;
u_long flags;
struct reset_entry *rent;
@@ -2041,9 +2081,9 @@ reset_stats(
return;
}
- flags = ((struct reset_flags *)inpkt->data)->flags;
- flags = ntohl(flags);
-
+ rflags = (struct reset_flags *)inpkt->data;
+ flags = ntohl(rflags->flags);
+
if (flags & ~RESET_ALLFLAGS) {
msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
flags & ~RESET_ALLFLAGS);
@@ -2053,7 +2093,7 @@ reset_stats(
for (rent = reset_entries; rent->flag != 0; rent++) {
if (flags & rent->flag)
- (rent->handler)();
+ (*rent->handler)();
}
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -2064,15 +2104,15 @@ reset_stats(
*/
static void
reset_peer(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
- register struct conf_unpeer *cp;
- register int items;
- register struct peer *peer;
- struct sockaddr_storage peeraddr;
+ struct conf_unpeer *cp;
+ int items;
+ struct peer *peer;
+ sockaddr_u peeraddr;
int bad;
/*
@@ -2085,21 +2125,21 @@ reset_peer(
bad = 0;
while (items-- > 0 && !bad) {
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (client_v6_capable && cp->v6_flag != 0) {
- GET_INADDR6(peeraddr) = cp->peeraddr6;
- peeraddr.ss_family = AF_INET6;
+ ZERO_SOCK(&peeraddr);
+ if (client_v6_capable && cp->v6_flag) {
+ AF(&peeraddr) = AF_INET6;
+ SOCK_ADDR6(&peeraddr) = cp->peeraddr6;
} else {
- GET_INADDR(peeraddr) = cp->peeraddr;
- peeraddr.ss_family = AF_INET;
+ AF(&peeraddr) = AF_INET;
+ NSRCADR(&peeraddr) = cp->peeraddr;
}
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
+
+#ifdef ISC_PLATFORM_HAVESALEN
+ peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
#endif
- peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
- if (peer == (struct peer *)0)
- bad++;
+ peer = findexistingpeer(&peeraddr, NULL, -1, 0);
+ if (NULL == peer)
+ bad++;
cp = (struct conf_unpeer *)((char *)cp +
INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
@@ -2116,21 +2156,22 @@ reset_peer(
items = INFO_NITEMS(inpkt->err_nitems);
cp = (struct conf_unpeer *)inpkt->data;
while (items-- > 0) {
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (client_v6_capable && cp->v6_flag != 0) {
- GET_INADDR6(peeraddr) = cp->peeraddr6;
- peeraddr.ss_family = AF_INET6;
+ ZERO_SOCK(&peeraddr);
+ if (client_v6_capable && cp->v6_flag) {
+ AF(&peeraddr) = AF_INET6;
+ SOCK_ADDR6(&peeraddr) = cp->peeraddr6;
} else {
- GET_INADDR(peeraddr) = cp->peeraddr;
- peeraddr.ss_family = AF_INET;
+ AF(&peeraddr) = AF_INET;
+ NSRCADR(&peeraddr) = cp->peeraddr;
}
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
+ SET_PORT(&peeraddr, 123);
+#ifdef ISC_PLATFORM_HAVESALEN
+ peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
#endif
- peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
- while (peer != 0) {
+ peer = findexistingpeer(&peeraddr, NULL, -1, 0);
+ while (peer != NULL) {
peer_reset(peer);
- peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1);
+ peer = findexistingpeer(&peeraddr, peer, -1, 0);
}
cp = (struct conf_unpeer *)((char *)cp +
INFO_ITEMSIZE(inpkt->mbz_itemsize));
@@ -2145,7 +2186,7 @@ reset_peer(
*/
static void
do_key_reread(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2160,7 +2201,7 @@ do_key_reread(
*/
static void
trust_key(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2174,7 +2215,7 @@ trust_key(
*/
static void
untrust_key(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2188,7 +2229,7 @@ untrust_key(
*/
static void
do_trustkey(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
u_long trust
@@ -2213,7 +2254,7 @@ do_trustkey(
*/
static void
get_auth_info(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2281,7 +2322,7 @@ reset_auth_stats(void)
*/
static void
req_get_traps(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2306,21 +2347,21 @@ req_get_traps(
for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
if (tr->tr_flags & TRAP_INUSE) {
- if (tr->tr_addr.ss_family == AF_INET) {
+ if (IS_IPV4(&tr->tr_addr)) {
if (tr->tr_localaddr == any_interface)
it->local_address = 0;
else
it->local_address
- = GET_INADDR(tr->tr_localaddr->sin);
- it->trap_address = GET_INADDR(tr->tr_addr);
+ = NSRCADR(&tr->tr_localaddr->sin);
+ it->trap_address = NSRCADR(&tr->tr_addr);
if (client_v6_capable)
it->v6_flag = 0;
} else {
if (!client_v6_capable)
continue;
it->local_address6
- = GET_INADDR6(tr->tr_localaddr->sin);
- it->trap_address6 = GET_INADDR6(tr->tr_addr);
+ = SOCK_ADDR6(&tr->tr_localaddr->sin);
+ it->trap_address6 = SOCK_ADDR6(&tr->tr_addr);
it->v6_flag = 1;
}
it->trap_port = NSRCPORT(&tr->tr_addr);
@@ -2341,7 +2382,7 @@ req_get_traps(
*/
static void
req_set_trap(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2356,7 +2397,7 @@ req_set_trap(
*/
static void
req_clr_trap(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2371,7 +2412,7 @@ req_clr_trap(
*/
static void
do_setclr_trap(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
int set
@@ -2380,14 +2421,14 @@ do_setclr_trap(
register struct conf_trap *ct;
register struct interface *linter;
int res;
- struct sockaddr_storage laddr;
+ sockaddr_u laddr;
/*
- * Prepare sockaddr_storage structure
+ * Prepare sockaddr
*/
- memset((char *)&laddr, 0, sizeof laddr);
- laddr.ss_family = srcadr->ss_family;
- NSRCPORT(&laddr) = ntohs(NTP_PORT);
+ ZERO_SOCK(&laddr);
+ AF(&laddr) = AF(srcadr);
+ SET_PORT(&laddr, NTP_PORT);
/*
* Restrict ourselves to one item only. This eliminates
@@ -2406,25 +2447,25 @@ do_setclr_trap(
if (ct->local_address == 0) {
linter = any_interface;
} else {
- if (laddr.ss_family == AF_INET)
- GET_INADDR(laddr) = ct->local_address;
+ if (IS_IPV4(&laddr))
+ NSRCADR(&laddr) = ct->local_address;
else
- GET_INADDR6(laddr) = ct->local_address6;
+ SOCK_ADDR6(&laddr) = ct->local_address6;
linter = findinterface(&laddr);
- if (linter == NULL) {
+ if (NULL == linter) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
}
- if (laddr.ss_family == AF_INET)
- GET_INADDR(laddr) = ct->trap_address;
+ if (IS_IPV4(&laddr))
+ NSRCADR(&laddr) = ct->trap_address;
else
- GET_INADDR6(laddr) = ct->trap_address6;
- if (ct->trap_port != 0)
- NSRCPORT(&laddr) = ct->trap_port;
+ SOCK_ADDR6(&laddr) = ct->trap_address6;
+ if (ct->trap_port)
+ NSRCPORT(&laddr) = ct->trap_port;
else
- NSRCPORT(&laddr) = htons(TRAPPORT);
+ SET_PORT(&laddr, TRAPPORT);
if (set) {
res = ctlsettrap(&laddr, linter, 0,
@@ -2448,12 +2489,12 @@ do_setclr_trap(
*/
static void
set_request_keyid(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
- keyid_t keyid;
+ keyid_t *pkeyid;
/*
* Restrict ourselves to one item only.
@@ -2464,8 +2505,8 @@ set_request_keyid(
return;
}
- keyid = ntohl(*((u_int32 *)(inpkt->data)));
- info_auth_keyid = keyid;
+ pkeyid = (keyid_t *)inpkt->data;
+ info_auth_keyid = ntohl(*pkeyid);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -2476,12 +2517,12 @@ set_request_keyid(
*/
static void
set_control_keyid(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
- keyid_t keyid;
+ keyid_t *pkeyid;
extern keyid_t ctl_auth_keyid;
/*
@@ -2493,8 +2534,8 @@ set_control_keyid(
return;
}
- keyid = ntohl(*((u_int32 *)(inpkt->data)));
- ctl_auth_keyid = keyid;
+ pkeyid = (keyid_t *)inpkt->data;
+ ctl_auth_keyid = ntohl(*pkeyid);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -2505,7 +2546,7 @@ set_control_keyid(
*/
static void
get_ctl_stats(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2561,7 +2602,7 @@ get_ctl_stats(
*/
static void
get_kernel_info(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2616,7 +2657,7 @@ get_kernel_info(
*/
static void
get_clock_info(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2625,16 +2666,15 @@ get_clock_info(
register u_int32 *clkaddr;
register int items;
struct refclockstat clock_stat;
- struct sockaddr_storage addr;
- struct sockaddr_in tmp_clock;
+ sockaddr_u addr;
l_fp ltmp;
- memset((char *)&addr, 0, sizeof addr);
- addr.ss_family = AF_INET;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
+ ZERO_SOCK(&addr);
+ AF(&addr) = AF_INET;
+#ifdef ISC_PLATFORM_HAVESALEN
+ addr.sa.sa_len = SOCKLEN(&addr);
#endif
- NSRCPORT(&addr) = htons(NTP_PORT);
+ SET_PORT(&addr, NTP_PORT);
items = INFO_NITEMS(inpkt->err_nitems);
clkaddr = (u_int32 *) inpkt->data;
@@ -2642,19 +2682,18 @@ get_clock_info(
sizeof(struct info_clock));
while (items-- > 0) {
- tmp_clock.sin_addr.s_addr = *clkaddr++;
- CAST_V4(addr)->sin_addr = tmp_clock.sin_addr;
- if (!ISREFCLOCKADR(&tmp_clock) ||
- findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
+ NSRCADR(&addr) = *clkaddr++;
+ if (!ISREFCLOCKADR(&addr) ||
+ findexistingpeer(&addr, NULL, -1, 0) == NULL) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&addr, (struct refclockstat *)0, &clock_stat);
+ refclock_control(&addr, NULL, &clock_stat);
- ic->clockadr = tmp_clock.sin_addr.s_addr;
+ ic->clockadr = NSRCADR(&addr);
ic->type = clock_stat.type;
ic->flags = clock_stat.flags;
ic->lastevent = clock_stat.lastevent;
@@ -2669,7 +2708,7 @@ get_clock_info(
DTOLFP(clock_stat.fudgetime2, &ltmp);
HTONL_FP(&ltmp, &ic->fudgetime2);
ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
- ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2);
+ ic->fudgeval2 = htonl(clock_stat.fudgeval2);
free_varlist(clock_stat.kv_list);
@@ -2685,7 +2724,7 @@ get_clock_info(
*/
static void
set_clock_fudge(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2693,25 +2732,23 @@ set_clock_fudge(
register struct conf_fudge *cf;
register int items;
struct refclockstat clock_stat;
- struct sockaddr_storage addr;
- struct sockaddr_in tmp_clock;
+ sockaddr_u addr;
l_fp ltmp;
- memset((char *)&addr, 0, sizeof addr);
+ ZERO_SOCK(&addr);
memset((char *)&clock_stat, 0, sizeof clock_stat);
items = INFO_NITEMS(inpkt->err_nitems);
cf = (struct conf_fudge *) inpkt->data;
while (items-- > 0) {
- tmp_clock.sin_addr.s_addr = cf->clockadr;
- *CAST_V4(addr) = tmp_clock;
- addr.ss_family = AF_INET;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
+ AF(&addr) = AF_INET;
+ NSRCADR(&addr) = cf->clockadr;
+#ifdef ISC_PLATFORM_HAVESALEN
+ addr.sa.sa_len = SOCKLEN(&addr);
#endif
- NSRCPORT(&addr) = htons(NTP_PORT);
- if (!ISREFCLOCKADR(&tmp_clock) ||
- findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
+ SET_PORT(&addr, NTP_PORT);
+ if (!ISREFCLOCKADR(&addr) ||
+ findexistingpeer(&addr, NULL, -1, 0) == 0) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
@@ -2759,7 +2796,7 @@ set_clock_fudge(
*/
static void
get_clkbug_info(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2769,15 +2806,14 @@ get_clkbug_info(
register u_int32 *clkaddr;
register int items;
struct refclockbug bug;
- struct sockaddr_storage addr;
- struct sockaddr_in tmp_clock;
+ sockaddr_u addr;
- memset((char *)&addr, 0, sizeof addr);
- addr.ss_family = AF_INET;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
+ ZERO_SOCK(&addr);
+ AF(&addr) = AF_INET;
+#ifdef ISC_PLATFORM_HAVESALEN
+ addr.sa.sa_len = SOCKLEN(&addr);
#endif
- NSRCPORT(&addr) = htons(NTP_PORT);
+ SET_PORT(&addr, NTP_PORT);
items = INFO_NITEMS(inpkt->err_nitems);
clkaddr = (u_int32 *) inpkt->data;
@@ -2785,10 +2821,9 @@ get_clkbug_info(
sizeof(struct info_clkbug));
while (items-- > 0) {
- tmp_clock.sin_addr.s_addr = *clkaddr++;
- GET_INADDR(addr) = tmp_clock.sin_addr.s_addr;
- if (!ISREFCLOCKADR(&tmp_clock) ||
- findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
+ NSRCADR(&addr) = *clkaddr++;
+ if (!ISREFCLOCKADR(&addr) ||
+ findexistingpeer(&addr, NULL, -1, 0) == 0) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
@@ -2800,7 +2835,7 @@ get_clkbug_info(
return;
}
- ic->clockadr = tmp_clock.sin_addr.s_addr;
+ ic->clockadr = NSRCADR(&addr);
i = bug.nvalues;
if (i > NUMCBUGVALUES)
i = NUMCBUGVALUES;
@@ -2832,39 +2867,40 @@ fill_info_if_stats(void *data, interface_info_t *interface_info)
{
struct info_if_stats **ifsp = (struct info_if_stats **)data;
struct info_if_stats *ifs = *ifsp;
- struct interface *interface = interface_info->interface;
+ endpt *ep = interface_info->ep;
- memset((char*)ifs, 0, sizeof(*ifs));
+ memset(ifs, 0, sizeof(*ifs));
- if (interface->sin.ss_family == AF_INET6) {
+ if (IS_IPV6(&ep->sin)) {
if (!client_v6_capable) {
return;
}
ifs->v6_flag = 1;
- memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr));
- memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr));
- memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr));
+ ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin);
+ ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast);
+ ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask);
} else {
ifs->v6_flag = 0;
- memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr));
- memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr));
- memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr));
+ ifs->unaddr.addr = SOCK_ADDR4(&ep->sin);
+ ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast);
+ ifs->unmask.addr = SOCK_ADDR4(&ep->mask);
}
ifs->v6_flag = htonl(ifs->v6_flag);
- strcpy(ifs->name, interface->name);
- ifs->family = htons(interface->family);
- ifs->flags = htonl(interface->flags);
- ifs->last_ttl = htonl(interface->last_ttl);
- ifs->num_mcast = htonl(interface->num_mcast);
- ifs->received = htonl(interface->received);
- ifs->sent = htonl(interface->sent);
- ifs->notsent = htonl(interface->notsent);
- ifs->scopeid = htonl(interface->scopeid);
- ifs->ifindex = htonl(interface->ifindex);
- ifs->ifnum = htonl(interface->ifnum);
- ifs->uptime = htonl(current_time - interface->starttime);
- ifs->ignore_packets = interface->ignore_packets;
- ifs->peercnt = htonl(interface->peercnt);
+ strncpy(ifs->name, ep->name, sizeof(ifs->name));
+ ifs->family = htons(ep->family);
+ ifs->flags = htonl(ep->flags);
+ ifs->last_ttl = htonl(ep->last_ttl);
+ ifs->num_mcast = htonl(ep->num_mcast);
+ ifs->received = htonl(ep->received);
+ ifs->sent = htonl(ep->sent);
+ ifs->notsent = htonl(ep->notsent);
+ ifs->ifindex = htonl(ep->ifindex);
+ /* scope no longer in struct interface, in in6_addr typically */
+ ifs->scopeid = ifs->ifindex;
+ ifs->ifnum = htonl(ep->ifnum);
+ ifs->uptime = htonl(current_time - ep->starttime);
+ ifs->ignore_packets = ep->ignore_packets;
+ ifs->peercnt = htonl(ep->peercnt);
ifs->action = interface_info->action;
*ifsp = (struct info_if_stats *)more_pkt();
@@ -2875,7 +2911,7 @@ fill_info_if_stats(void *data, interface_info_t *interface_info)
*/
static void
get_if_stats(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2894,7 +2930,7 @@ get_if_stats(
static void
do_if_reload(
- struct sockaddr_storage *srcadr,
+ sockaddr_u *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
diff --git a/ntpd/ntp_restrict.c b/ntpd/ntp_restrict.c
index 473e2ce81d4a..e087b6ce441a 100644
--- a/ntpd/ntp_restrict.c
+++ b/ntpd/ntp_restrict.c
@@ -10,7 +10,9 @@
#include "ntpd.h"
#include "ntp_if.h"
+#include "ntp_lists.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
/*
* This code keeps a simple address-and-mask list of hosts we want
@@ -41,65 +43,75 @@
* addresses. This is not protocol-independant but for now I can't
* find a way to respect this. We'll check this later... JFB 07/2001
*/
-#define SET_IPV6_ADDR_MASK(dst, src, msk) \
- do { \
- int idx; \
- for (idx = 0; idx < 16; idx++) { \
- (dst)->s6_addr[idx] = \
- (u_char) ((src)->s6_addr[idx] & (msk)->s6_addr[idx]); \
- } \
+#define MASK_IPV6_ADDR(dst, src, msk) \
+ do { \
+ int idx; \
+ for (idx = 0; idx < COUNTOF((dst)->s6_addr); idx++) { \
+ (dst)->s6_addr[idx] = (src)->s6_addr[idx] \
+ & (msk)->s6_addr[idx]; \
+ } \
} while (0)
/*
- * Memory allocation parameters. We allocate INITRESLIST entries
- * initially, and add INCRESLIST entries to the free list whenever
- * we run out.
+ * We allocate INC_RESLIST{4|6} entries to the free list whenever empty.
+ * Auto-tune these to be just less than 1KB (leaving at least 16 bytes
+ * for allocator overhead).
*/
-#define INITRESLIST 10
-#define INCRESLIST 5
-
-#define RES_AVG 8. /* interpacket averaging factor */
+#define INC_RESLIST4 ((1024 - 16) / V4_SIZEOF_RESTRICT_U)
+#define INC_RESLIST6 ((1024 - 16) / V6_SIZEOF_RESTRICT_U)
/*
* The restriction list
*/
-struct restrictlist *restrictlist;
-struct restrictlist6 *restrictlist6;
-static int restrictcount; /* count of entries in the res list */
-static int restrictcount6; /* count of entries in the res list 2*/
+restrict_u *restrictlist4;
+restrict_u *restrictlist6;
+static int restrictcount; /* count in the restrict lists */
/*
* The free list and associated counters. Also some uninteresting
* stat counters.
*/
-static struct restrictlist *resfree;
-static struct restrictlist6 *resfree6;
-static int numresfree; /* number of structures on free list */
-static int numresfree6; /* number of structures on free list 2 */
+static restrict_u *resfree4; /* available entries (free list) */
+static restrict_u *resfree6;
-static u_long res_calls;
-static u_long res_found;
-static u_long res_not_found;
+static u_long res_calls;
+static u_long res_found;
+static u_long res_not_found;
/*
- * Parameters of the RES_LIMITED restriction option.
+ * Count number of restriction entries referring to RES_LIMITED, to
+ * control implicit activation/deactivation of the MRU monlist.
*/
-u_long res_avg_interval = 5; /* min average interpacket interval */
-u_long res_min_interval = 1; /* min interpacket interval */
+static u_long res_limited_refcnt;
/*
- * Count number of restriction entries referring to RES_LIMITED controls
- * activation/deactivation of monitoring (with respect to RES_LIMITED
- * control)
+ * Our default entries.
*/
-static u_long res_limited_refcnt;
-static u_long res_limited_refcnt6;
+static restrict_u restrict_def4;
+static restrict_u restrict_def6;
+
+/*
+ * "restrict source ..." enabled knob and restriction bits.
+ */
+static int restrict_source_enabled;
+static u_short restrict_source_flags;
+static u_short restrict_source_mflags;
/*
- * Our initial allocation of lists entries.
+ * private functions
*/
-static struct restrictlist resinit[INITRESLIST];
-static struct restrictlist6 resinit6[INITRESLIST];
+static restrict_u * alloc_res4(void);
+static restrict_u * alloc_res6(void);
+static void free_res(restrict_u *, int);
+static void inc_res_limited(void);
+static void dec_res_limited(void);
+static restrict_u * match_restrict4_addr(u_int32, u_short);
+static restrict_u * match_restrict6_addr(const struct in6_addr *,
+ u_short);
+static restrict_u * match_restrict_entry(const restrict_u *, int);
+static int res_sorts_before4(restrict_u *, restrict_u *);
+static int res_sorts_before6(restrict_u *, restrict_u *);
+
/*
* init_restrict - initialize the restriction data structures
@@ -107,103 +119,323 @@ static struct restrictlist6 resinit6[INITRESLIST];
void
init_restrict(void)
{
- register int i;
-
/*
- * Zero the list and put all but one on the free list
+ * The restriction lists begin with a default entry with address
+ * and mask 0, which will match any entry. The lists are kept
+ * sorted by descending address followed by descending mask:
+ *
+ * address mask
+ * 192.168.0.0 255.255.255.0 kod limited noquery nopeer
+ * 192.168.0.0 255.255.0.0 kod limited
+ * 0.0.0.0 0.0.0.0 kod limited noquery
+ *
+ * The first entry which matches an address is used. With the
+ * example restrictions above, 192.168.0.0/24 matches the first
+ * entry, the rest of 192.168.0.0/16 matches the second, and
+ * everything else matches the third (default).
+ *
+ * Note this achieves the same result a little more efficiently
+ * than the documented behavior, which is to keep the lists
+ * sorted by ascending address followed by ascending mask, with
+ * the _last_ matching entry used.
+ *
+ * An additional wrinkle is we may have multiple entries with
+ * the same address and mask but differing match flags (mflags).
+ * At present there is only one, RESM_NTPONLY. Entries with
+ * RESM_NTPONLY are sorted earlier so they take precedence over
+ * any otherwise similar entry without. Again, this is the same
+ * behavior as but reversed implementation compared to the docs.
+ *
*/
- resfree = NULL;
- memset((char *)resinit, 0, sizeof resinit);
- resfree6 = NULL;
- memset((char *)resinit6, 0, sizeof resinit6);
- for (i = 1; i < INITRESLIST; i++) {
- resinit[i].next = resfree;
- resinit6[i].next = resfree6;
- resfree = &resinit[i];
- resfree6 = &resinit6[i];
+ LINK_SLIST(restrictlist4, &restrict_def4, link);
+ LINK_SLIST(restrictlist6, &restrict_def6, link);
+ restrictcount = 2;
+}
+
+
+static restrict_u *
+alloc_res4(void)
+{
+ const size_t cb = V4_SIZEOF_RESTRICT_U;
+ const size_t count = INC_RESLIST4;
+ restrict_u * rl;
+ restrict_u * res;
+ int i;
+
+ UNLINK_HEAD_SLIST(res, resfree4, link);
+ if (res != NULL)
+ return res;
+
+ rl = emalloc(count * cb);
+ memset(rl, 0, count * cb);
+ /* link all but the first onto free list */
+ res = (void *)((char *)rl + (count - 1) * cb);
+ for (i = count - 1; i > 0; i--) {
+ LINK_SLIST(resfree4, res, link);
+ res = (void *)((char *)res - cb);
}
- numresfree = INITRESLIST-1;
- numresfree6 = INITRESLIST-1;
+ NTP_INSIST(rl == res);
+ /* allocate the first */
+ return res;
+}
- /*
- * Put the remaining item at the head of the list as our default
- * entry. Everything in here should be zero for now.
- */
- resinit[0].addr = htonl(INADDR_ANY);
- resinit[0].mask = 0;
- memset(&resinit6[0].addr6, 0, sizeof(struct in6_addr));
- memset(&resinit6[0].mask6, 0, sizeof(struct in6_addr));
- restrictlist = &resinit[0];
- restrictlist6 = &resinit6[0];
- restrictcount = 1;
- restrictcount = 2;
- /*
- * fix up stat counters
- */
- res_calls = 0;
- res_found = 0;
- res_not_found = 0;
+static restrict_u *
+alloc_res6(void)
+{
+ const size_t cb = V6_SIZEOF_RESTRICT_U;
+ const size_t count = INC_RESLIST6;
+ restrict_u * rl;
+ restrict_u * res;
+ int i;
+
+ UNLINK_HEAD_SLIST(res, resfree6, link);
+ if (res != NULL)
+ return res;
+
+ rl = emalloc(count * cb);
+ memset(rl, 0, count * cb);
+ /* link all but the first onto free list */
+ res = (void *)((char *)rl + (count - 1) * cb);
+ for (i = count - 1; i > 0; i--) {
+ LINK_SLIST(resfree6, res, link);
+ res = (void *)((char *)res - cb);
+ }
+ NTP_INSIST(rl == res);
+ /* allocate the first */
+ return res;
+}
- /*
- * set default values for RES_LIMIT functionality
- */
- res_limited_refcnt = 0;
- res_limited_refcnt6 = 0;
+
+static void
+free_res(
+ restrict_u * res,
+ int v6
+ )
+{
+ restrict_u ** plisthead;
+ restrict_u * unlinked;
+
+ restrictcount--;
+ if (RES_LIMITED && res->flags)
+ dec_res_limited();
+
+ if (v6)
+ plisthead = &restrictlist6;
+ else
+ plisthead = &restrictlist4;
+ UNLINK_SLIST(unlinked, *plisthead, res, link, restrict_u);
+ NTP_INSIST(unlinked == res);
+
+ if (v6) {
+ memset(res, 0, V6_SIZEOF_RESTRICT_U);
+ plisthead = &resfree6;
+ } else {
+ memset(res, 0, V4_SIZEOF_RESTRICT_U);
+ plisthead = &resfree4;
+ }
+ LINK_SLIST(*plisthead, res, link);
+}
+
+
+static void
+inc_res_limited(void)
+{
+ if (!res_limited_refcnt)
+ mon_start(MON_RES);
+ res_limited_refcnt++;
+}
+
+
+static void
+dec_res_limited(void)
+{
+ res_limited_refcnt--;
+ if (!res_limited_refcnt)
+ mon_stop(MON_RES);
+}
+
+
+static restrict_u *
+match_restrict4_addr(
+ u_int32 addr,
+ u_short port
+ )
+{
+ restrict_u * res;
+ restrict_u * next;
+
+ for (res = restrictlist4; res != NULL; res = next) {
+ next = res->link;
+ if (res->u.v4.addr == (addr & res->u.v4.mask)
+ && (!(RESM_NTPONLY & res->mflags)
+ || NTP_PORT == port))
+ break;
+ }
+ return res;
+}
+
+
+static restrict_u *
+match_restrict6_addr(
+ const struct in6_addr * addr,
+ u_short port
+ )
+{
+ restrict_u * res;
+ restrict_u * next;
+ struct in6_addr masked;
+
+ for (res = restrictlist6; res != NULL; res = next) {
+ next = res->link;
+ NTP_INSIST(next != res);
+ MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask);
+ if (ADDR6_EQ(&masked, &res->u.v6.addr)
+ && (!(RESM_NTPONLY & res->mflags)
+ || NTP_PORT == port))
+ break;
+ }
+ return res;
+}
+
+
+/*
+ * match_restrict_entry - find an exact match on a restrict list.
+ *
+ * Exact match is addr, mask, and mflags all equal.
+ * In order to use more common code for IPv4 and IPv6, this routine
+ * requires the caller to populate a restrict_u with mflags and either
+ * the v4 or v6 address and mask as appropriate. Other fields in the
+ * input restrict_u are ignored.
+ */
+static restrict_u *
+match_restrict_entry(
+ const restrict_u * pmatch,
+ int v6
+ )
+{
+ restrict_u *res;
+ restrict_u *rlist;
+ size_t cb;
+
+ if (v6) {
+ rlist = restrictlist6;
+ cb = sizeof(pmatch->u.v6);
+ } else {
+ rlist = restrictlist4;
+ cb = sizeof(pmatch->u.v4);
+ }
+
+ for (res = rlist; res != NULL; res = res->link)
+ if (res->mflags == pmatch->mflags &&
+ !memcmp(&res->u, &pmatch->u, cb))
+ break;
+ return res;
+}
+
+
+/*
+ * res_sorts_before4 - compare two restrict4 entries
+ *
+ * Returns nonzero if r1 sorts before r2. We sort by descending
+ * address, then descending mask, then descending mflags, so sorting
+ * before means having a higher value.
+ */
+static int
+res_sorts_before4(
+ restrict_u *r1,
+ restrict_u *r2
+ )
+{
+ int r1_before_r2;
+
+ if (r1->u.v4.addr > r2->u.v4.addr)
+ r1_before_r2 = 1;
+ else if (r1->u.v4.addr < r2->u.v4.addr)
+ r1_before_r2 = 0;
+ else if (r1->u.v4.mask > r2->u.v4.mask)
+ r1_before_r2 = 1;
+ else if (r1->u.v4.mask < r2->u.v4.mask)
+ r1_before_r2 = 0;
+ else if (r1->mflags > r2->mflags)
+ r1_before_r2 = 1;
+ else
+ r1_before_r2 = 0;
+
+ return r1_before_r2;
+}
+
+
+/*
+ * res_sorts_before6 - compare two restrict6 entries
+ *
+ * Returns nonzero if r1 sorts before r2. We sort by descending
+ * address, then descending mask, then descending mflags, so sorting
+ * before means having a higher value.
+ */
+static int
+res_sorts_before6(
+ restrict_u *r1,
+ restrict_u *r2
+ )
+{
+ int r1_before_r2;
+ int cmp;
+
+ cmp = ADDR6_CMP(&r1->u.v6.addr, &r2->u.v6.addr);
+ if (cmp > 0) /* r1->addr > r2->addr */
+ r1_before_r2 = 1;
+ else if (cmp < 0) /* r2->addr > r1->addr */
+ r1_before_r2 = 0;
+ else {
+ cmp = ADDR6_CMP(&r1->u.v6.mask, &r2->u.v6.mask);
+ if (cmp > 0) /* r1->mask > r2->mask*/
+ r1_before_r2 = 1;
+ else if (cmp < 0) /* r2->mask > r1->mask */
+ r1_before_r2 = 0;
+ else if (r1->mflags > r2->mflags)
+ r1_before_r2 = 1;
+ else
+ r1_before_r2 = 0;
+ }
+
+ return r1_before_r2;
}
/*
* restrictions - return restrictions for this host
*/
-int
+u_short
restrictions(
- struct sockaddr_storage *srcadr,
- int at_listhead
+ sockaddr_u *srcadr
)
{
- struct restrictlist *rl;
- struct restrictlist *match = NULL;
- struct restrictlist6 *rl6;
- struct restrictlist6 *match6 = NULL;
- struct in6_addr hostaddr6;
- struct in6_addr hostservaddr6;
- u_int32 hostaddr;
- int flags = 0;
- int isntpport;
+ restrict_u *match;
+ struct in6_addr *pin6;
+ u_short flags;
res_calls++;
- if (srcadr->ss_family == AF_INET) {
- /*
- * We need the host address in host order. Also need to
- * know whether this is from the ntp port or not.
- */
- hostaddr = SRCADR(srcadr);
- isntpport = (SRCPORT(srcadr) == NTP_PORT);
-
+ flags = 0;
+ /* IPv4 source address */
+ if (IS_IPV4(srcadr)) {
/*
* Ignore any packets with a multicast source address
* (this should be done early in the receive process,
- * later!)
+ * not later!)
*/
if (IN_CLASSD(SRCADR(srcadr)))
return (int)RES_IGNORE;
+ match = match_restrict4_addr(SRCADR(srcadr),
+ SRCPORT(srcadr));
+ match->count++;
/*
- * Set match to first entry, which is default entry.
- * Work our way down from there.
+ * res_not_found counts only use of the final default
+ * entry, not any "restrict default ntpport ...", which
+ * would be just before the final default.
*/
- match = restrictlist;
- for (rl = match->next; rl != NULL && rl->addr <= hostaddr;
- rl = rl->next)
- if ((hostaddr & rl->mask) == rl->addr) {
- if ((rl->mflags & RESM_NTPONLY) &&
- !isntpport)
- continue;
- match = rl;
- }
- match->count++;
- if (match == restrictlist)
+ if (&restrict_def4 == match)
res_not_found++;
else
res_found++;
@@ -211,77 +443,24 @@ restrictions(
}
/* IPv6 source address */
- if (srcadr->ss_family == AF_INET6) {
- /*
- * Need to know whether this is from the ntp port or
- * not.
- */
- hostaddr6 = GET_INADDR6(*srcadr);
- isntpport = (ntohs((
- (struct sockaddr_in6 *)srcadr)->sin6_port) ==
- NTP_PORT);
+ if (IS_IPV6(srcadr)) {
+ pin6 = PSOCK_ADDR6(srcadr);
/*
* Ignore any packets with a multicast source address
* (this should be done early in the receive process,
- * later!)
+ * not later!)
*/
- if (IN6_IS_ADDR_MULTICAST(&hostaddr6))
+ if (IN6_IS_ADDR_MULTICAST(pin6))
return (int)RES_IGNORE;
- /*
- * Set match to first entry, which is default entry.
- * Work our way down from there.
- */
- match6 = restrictlist6;
- for (rl6 = match6->next; rl6 != NULL &&
- (memcmp(&(rl6->addr6), &hostaddr6,
- sizeof(hostaddr6)) <= 0); rl6 = rl6->next) {
- SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6,
- &rl6->mask6);
- if (memcmp(&hostservaddr6, &(rl6->addr6),
- sizeof(hostservaddr6)) == 0) {
- if ((rl6->mflags & RESM_NTPONLY) &&
- !isntpport)
- continue;
- match6 = rl6;
- }
- }
- match6->count++;
- if (match6 == restrictlist6)
+ match = match_restrict6_addr(pin6, SRCPORT(srcadr));
+ match->count++;
+ if (&restrict_def6 == match)
res_not_found++;
else
res_found++;
- flags = match6->flags;
- }
-
- /*
- * The following implements a generalized call gap facility.
- * Douse the RES_LIMITED bit only if the interval since the last
- * packet is greater than res_min_interval and the average is
- * greater thatn res_avg_interval.
- */
- if (!at_listhead || mon_enabled == MON_OFF) {
- flags &= ~RES_LIMITED;
- } else {
- struct mon_data *md;
-
- /*
- * At this poin the most recent arrival is first in the
- * MRU list. Let the first 10 packets in for free until
- * the average stabilizes.
- */
- md = mon_mru_list.mru_next;
- if (md->avg_interval == 0)
- md->avg_interval = md->drop_count;
- else
- md->avg_interval += (md->drop_count -
- md->avg_interval) / RES_AVG;
- if (md->count < 10 || (md->drop_count >
- res_min_interval && md->avg_interval >
- res_avg_interval))
- flags &= ~RES_LIMITED;
- md->drop_count = flags;
+ flags = match->flags;
}
return (flags);
}
@@ -292,316 +471,130 @@ restrictions(
*/
void
hack_restrict(
- int op,
- struct sockaddr_storage *resaddr,
- struct sockaddr_storage *resmask,
- int mflags,
- int flags
+ int op,
+ sockaddr_u * resaddr,
+ sockaddr_u * resmask,
+ u_short mflags,
+ u_short flags
)
{
- register u_int32 addr = 0;
- register u_int32 mask = 0;
- struct in6_addr addr6;
- struct in6_addr mask6;
- register struct restrictlist *rl = NULL;
- register struct restrictlist *rlprev = NULL;
- register struct restrictlist6 *rl6 = NULL;
- register struct restrictlist6 *rlprev6 = NULL;
- int i, addr_cmp, mask_cmp;
- memset(&addr6, 0, sizeof(struct in6_addr));
- memset(&mask6, 0, sizeof(struct in6_addr));
-
- if (resaddr->ss_family == AF_INET) {
+ int v6;
+ restrict_u match;
+ restrict_u * res;
+ restrict_u ** plisthead;
+
+ DPRINTF(1, ("restrict: op %d addr %s mask %s mflags %08x flags %08x\n",
+ op, stoa(resaddr), stoa(resmask), mflags, flags));
+
+ if (NULL == resaddr) {
+ NTP_REQUIRE(NULL == resmask);
+ NTP_REQUIRE(RESTRICT_FLAGS == op);
+ restrict_source_flags = flags;
+ restrict_source_mflags = mflags;
+ restrict_source_enabled = 1;
+ return;
+ }
+
+ memset(&match, 0, sizeof(match));
+ /* silence VC9 potentially uninit warnings */
+ res = NULL;
+ v6 = 0;
+
+ if (IS_IPV4(resaddr)) {
+ v6 = 0;
/*
- * Get address and mask in host byte order
+ * Get address and mask in host byte order for easy
+ * comparison as u_int32
*/
- addr = SRCADR(resaddr);
- mask = SRCADR(resmask);
- addr &= mask; /* make sure low bits zero */
+ match.u.v4.addr = SRCADR(resaddr);
+ match.u.v4.mask = SRCADR(resmask);
+ match.u.v4.addr &= match.u.v4.mask;
+ } else if (IS_IPV6(resaddr)) {
+ v6 = 1;
/*
- * If this is the default address, point at first on
- * list. Else go searching for it.
+ * Get address and mask in network byte order for easy
+ * comparison as byte sequences (e.g. memcmp())
*/
- if (addr == 0) {
- rlprev = NULL;
- rl = restrictlist;
- } else {
- rlprev = restrictlist;
- rl = rlprev->next;
- while (rl != NULL) {
- if (rl->addr > addr) {
- rl = NULL;
- break;
- } else if (rl->addr == addr) {
- if (rl->mask == mask) {
- if ((mflags &
- RESM_NTPONLY) ==
- (rl->mflags &
- RESM_NTPONLY))
- break;
-
- if (!(mflags &
- RESM_NTPONLY)) {
- rl = NULL;
- break;
- }
- } else if (rl->mask > mask) {
- rl = NULL;
- break;
- }
- }
- rlprev = rl;
- rl = rl->next;
- }
- }
- }
+ match.u.v6.mask = SOCK_ADDR6(resmask);
+ MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr),
+ &match.u.v6.mask);
- if (resaddr->ss_family == AF_INET6) {
- mask6 = GET_INADDR6(*resmask);
- SET_IPV6_ADDR_MASK(&addr6,
- &GET_INADDR6(*resaddr), &mask6);
- if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
- rlprev6 = NULL;
- rl6 = restrictlist6;
- } else {
- rlprev6 = restrictlist6;
- rl6 = rlprev6->next;
- while (rl6 != NULL) {
- addr_cmp = memcmp(&rl6->addr6, &addr6,
- sizeof(addr6));
- if (addr_cmp > 0) {
- rl6 = NULL;
- break;
- } else if (addr_cmp == 0) {
- mask_cmp = memcmp(&rl6->mask6,
- &mask6, sizeof(mask6));
- if (mask_cmp == 0) {
- if ((mflags &
- RESM_NTPONLY) ==
- (rl6->mflags &
- RESM_NTPONLY))
- break;
-
- if (!(mflags &
- RESM_NTPONLY)) {
- rl6 = NULL;
- break;
- }
- } else if (mask_cmp > 0) {
- rl6 = NULL;
- break;
- }
- }
- rlprev6 = rl6;
- rl6 = rl6->next;
- }
- }
- }
+ } else /* not IPv4 nor IPv6 */
+ NTP_REQUIRE(0);
- /*
- * In case the above wasn't clear :-), either rl now points
- * at the entry this call refers to, or rl is zero and rlprev
- * points to the entry prior to where this one should go in
- * the sort.
- */
+ match.flags = flags;
+ match.mflags = mflags;
+ res = match_restrict_entry(&match, v6);
- /*
- * Switch based on operation
- */
- if (resaddr->ss_family == AF_INET) {
- switch (op) {
- case RESTRICT_FLAGS:
- /*
- * Here we add bits to the flags. If this is a
- * new restriction add it.
- */
- if (rl == NULL) {
- if (resfree == NULL) {
- rl = (struct restrictlist *)
- emalloc(INCRESLIST *
- sizeof(struct
- restrictlist));
- memset((char *)rl, 0,
- INCRESLIST * sizeof(struct
- restrictlist));
- for (i = 0; i < INCRESLIST; i++) {
- rl->next = resfree;
- resfree = rl;
- rl++;
- }
- numresfree = INCRESLIST;
- }
-
- rl = resfree;
- resfree = rl->next;
- numresfree--;
-
- rl->addr = addr;
- rl->mask = mask;
- rl->mflags = (u_short)mflags;
-
- if (rlprev == NULL) {
- rl->next = restrictlist;
- restrictlist = rl;
- } else {
- rl->next = rlprev->next;
- rlprev->next = rl;
- }
- restrictcount++;
- }
- if ((rl->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt++;
- mon_start(MON_RES);
- }
- rl->flags |= (u_short)flags;
- break;
+ switch (op) {
- case RESTRICT_UNFLAG:
- /*
- * Remove some bits from the flags. If we didn't
- * find this one, just return.
- */
- if (rl != NULL) {
- if ((rl->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt--;
- if (res_limited_refcnt == 0)
- mon_stop(MON_RES);
- }
- rl->flags &= (u_short)~flags;
- }
- break;
-
- case RESTRICT_REMOVE:
- case RESTRICT_REMOVEIF:
- /*
- * Remove an entry from the table entirely if we
- * found one. Don't remove the default entry and
- * don't remove an interface entry.
- */
- if (rl != NULL
- && rl->addr != htonl(INADDR_ANY)
- && !(rl->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
- if (rlprev != NULL) {
- rlprev->next = rl->next;
- } else {
- restrictlist = rl->next;
- }
- restrictcount--;
- if (rl->flags & RES_LIMITED) {
- res_limited_refcnt--;
- if (res_limited_refcnt == 0)
- mon_stop(MON_RES);
- }
- memset((char *)rl, 0,
- sizeof(struct restrictlist));
-
- rl->next = resfree;
- resfree = rl;
- numresfree++;
+ case RESTRICT_FLAGS:
+ /*
+ * Here we add bits to the flags. If this is a
+ * new restriction add it.
+ */
+ if (NULL == res) {
+ if (v6) {
+ res = alloc_res6();
+ memcpy(res, &match,
+ V6_SIZEOF_RESTRICT_U);
+ plisthead = &restrictlist6;
+ } else {
+ res = alloc_res4();
+ memcpy(res, &match,
+ V4_SIZEOF_RESTRICT_U);
+ plisthead = &restrictlist4;
}
- break;
-
- default:
- break;
+ LINK_SORT_SLIST(
+ *plisthead, res,
+ (v6)
+ ? res_sorts_before6(res, L_S_S_CUR())
+ : res_sorts_before4(res, L_S_S_CUR()),
+ link, restrict_u);
+ restrictcount++;
+ if (RES_LIMITED & flags)
+ inc_res_limited();
+ } else {
+ if ((RES_LIMITED & flags) &&
+ !(RES_LIMITED & res->flags))
+ inc_res_limited();
+ res->flags |= flags;
}
- } else if (resaddr->ss_family == AF_INET6) {
- switch (op) {
- case RESTRICT_FLAGS:
- /*
- * Here we add bits to the flags. If this is a
- * new restriction add it.
- */
- if (rl6 == NULL) {
- if (resfree6 == NULL) {
- rl6 = (struct
- restrictlist6 *)emalloc(
- INCRESLIST * sizeof(struct
- restrictlist6));
- memset((char *)rl6, 0,
- INCRESLIST * sizeof(struct
- restrictlist6));
-
- for (i = 0; i < INCRESLIST;
- i++) {
- rl6->next = resfree6;
- resfree6 = rl6;
- rl6++;
- }
- numresfree6 = INCRESLIST;
- }
- rl6 = resfree6;
- resfree6 = rl6->next;
- numresfree6--;
- rl6->addr6 = addr6;
- rl6->mask6 = mask6;
- rl6->mflags = (u_short)mflags;
- if (rlprev6 != NULL) {
- rl6->next = rlprev6->next;
- rlprev6->next = rl6;
- } else {
- rl6->next = restrictlist6;
- restrictlist6 = rl6;
- }
- restrictcount6++;
- }
- if ((rl6->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt6++;
- mon_start(MON_RES);
- }
- rl6->flags |= (u_short)flags;
- break;
-
- case RESTRICT_UNFLAG:
- /*
- * Remove some bits from the flags. If we didn't
- * find this one, just return.
- */
- if (rl6 != NULL) {
- if ((rl6->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt6--;
- if (res_limited_refcnt6 == 0)
- mon_stop(MON_RES);
- }
- rl6->flags &= (u_short)~flags;
- }
- break;
-
- case RESTRICT_REMOVE:
- case RESTRICT_REMOVEIF:
- /*
- * Remove an entry from the table entirely if we
- * found one. Don't remove the default entry and
- * don't remove an interface entry.
- */
- if (rl6 != NULL &&
- !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6)
- && !(rl6->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
- if (rlprev6 != NULL) {
- rlprev6->next = rl6->next;
- } else {
- restrictlist6 = rl6->next;
- }
- restrictcount6--;
- if (rl6->flags & RES_LIMITED) {
- res_limited_refcnt6--;
- if (res_limited_refcnt6 == 0)
- mon_stop(MON_RES);
- }
- memset((char *)rl6, 0,
- sizeof(struct restrictlist6));
- rl6->next = resfree6;
- resfree6 = rl6;
- numresfree6++;
- }
- break;
+ break;
- default:
- break;
+ case RESTRICT_UNFLAG:
+ /*
+ * Remove some bits from the flags. If we didn't
+ * find this one, just return.
+ */
+ if (res != NULL) {
+ if ((RES_LIMITED & res->flags)
+ && (RES_LIMITED & flags))
+ dec_res_limited();
+ res->flags &= ~flags;
}
+ break;
+
+ case RESTRICT_REMOVE:
+ case RESTRICT_REMOVEIF:
+ /*
+ * Remove an entry from the table entirely if we
+ * found one. Don't remove the default entry and
+ * don't remove an interface entry.
+ */
+ if (res != NULL
+ && (RESTRICT_REMOVEIF == op
+ || !(RESM_INTERFACE & res->mflags))
+ && res != &restrict_def4
+ && res != &restrict_def6)
+ free_res(res, v6);
+ break;
+
+ default: /* unknown op */
+ NTP_INSIST(0);
+ break;
}
+
}
+
diff --git a/ntpd/ntp_scanner.c b/ntpd/ntp_scanner.c
new file mode 100644
index 000000000000..d3c9f826f8f9
--- /dev/null
+++ b/ntpd/ntp_scanner.c
@@ -0,0 +1,659 @@
+
+/* ntp_scanner.c
+ *
+ * The source code for a simple lexical analyzer.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Copyright (c) 2006
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "ntp_config.h"
+#include "ntpsim.h"
+#include "ntp_scanner.h"
+#include "ntp_parser.h"
+#include "ntp_debug.h"
+
+/* ntp_keyword.h declares finite state machine and token text */
+#include "ntp_keyword.h"
+
+
+
+/* SCANNER GLOBAL VARIABLES
+ * ------------------------
+ */
+
+#define MAX_LEXEME (1024 + 1) /* The maximum size of a lexeme */
+char yytext[MAX_LEXEME]; /* Buffer for storing the input text/lexeme */
+extern int input_from_file;
+
+
+
+
+/* CONSTANTS
+ * ---------
+ */
+
+
+/* SCANNER GLOBAL VARIABLES
+ * ------------------------
+ */
+const char special_chars[] = "{}(),;|=";
+
+
+/* FUNCTIONS
+ * ---------
+ */
+
+int get_next_char(void);
+static int is_keyword(char *lexeme, follby *pfollowedby);
+
+
+
+/*
+ * keyword() - Return the keyword associated with token T_ identifier.
+ * See also token_name() for the string-ized T_ identifier.
+ * Example: keyword(T_Server) returns "server"
+ * token_name(T_Server) returns "T_Server"
+ */
+const char *
+keyword(
+ int token
+ )
+{
+ int i;
+ const char *text;
+
+ i = token - LOWEST_KEYWORD_ID;
+
+ if (i >= 0 && i < COUNTOF(keyword_text))
+ text = keyword_text[i];
+ else
+ text = NULL;
+
+ return (text != NULL)
+ ? text
+ : "(keyword not found)";
+}
+
+
+/* FILE INTERFACE
+ * --------------
+ * We define a couple of wrapper functions around the standard C fgetc
+ * and ungetc functions in order to include positional bookkeeping
+ */
+
+struct FILE_INFO *
+F_OPEN(
+ const char *path,
+ const char *mode
+ )
+{
+ struct FILE_INFO *my_info;
+
+ my_info = emalloc(sizeof *my_info);
+
+ my_info->line_no = 1;
+ my_info->col_no = 0;
+ my_info->prev_line_col_no = 0;
+ my_info->prev_token_col_no = 0;
+ my_info->fname = path;
+
+ my_info->fd = fopen(path, mode);
+ if (NULL == my_info->fd) {
+ free(my_info);
+ return NULL;
+ }
+ return my_info;
+}
+
+int
+FGETC(
+ struct FILE_INFO *stream
+ )
+{
+ int ch = fgetc(stream->fd);
+
+ ++stream->col_no;
+ if (ch == '\n') {
+ stream->prev_line_col_no = stream->col_no;
+ ++stream->line_no;
+ stream->col_no = 1;
+ }
+ return ch;
+}
+
+/* BUGS: 1. Function will fail on more than one line of pushback
+ * 2. No error checking is done to see if ungetc fails
+ * SK: I don't think its worth fixing these bugs for our purposes ;-)
+ */
+int
+UNGETC(
+ int ch,
+ struct FILE_INFO *stream
+ )
+{
+ if (ch == '\n') {
+ stream->col_no = stream->prev_line_col_no;
+ stream->prev_line_col_no = -1;
+ --stream->line_no;
+ }
+ --stream->col_no;
+ return ungetc(ch, stream->fd);
+}
+
+int
+FCLOSE(
+ struct FILE_INFO *stream
+ )
+{
+ int ret_val = fclose(stream->fd);
+
+ if (!ret_val)
+ free(stream);
+ return ret_val;
+}
+
+/* STREAM INTERFACE
+ * ----------------
+ * Provide a wrapper for the stream functions so that the
+ * stream can either read from a file or from a character
+ * array.
+ * NOTE: This is not very efficient for reading from character
+ * arrays, but needed to allow remote configuration where the
+ * configuration command is provided through ntpq.
+ *
+ * The behavior of there two functions is determined by the
+ * input_from_file flag.
+ */
+
+int
+get_next_char(
+ void
+ )
+{
+ char ch;
+
+ if (input_from_file)
+ return FGETC(ip_file);
+ else {
+ if (remote_config.buffer[remote_config.pos] == '\0')
+ return EOF;
+ else {
+ ip_file->col_no++;
+ ch = remote_config.buffer[remote_config.pos++];
+ if (ch == '\n') {
+ ip_file->prev_line_col_no = ip_file->col_no;
+ ++ip_file->line_no;
+ ip_file->col_no = 1;
+ }
+ return ch;
+ }
+ }
+}
+
+void
+push_back_char(
+ int ch
+ )
+{
+ if (input_from_file)
+ UNGETC(ch, ip_file);
+ else {
+ if (ch == '\n') {
+ ip_file->col_no = ip_file->prev_line_col_no;
+ ip_file->prev_line_col_no = -1;
+ --ip_file->line_no;
+ }
+ --ip_file->col_no;
+
+ remote_config.pos--;
+ }
+}
+
+
+
+/* STATE MACHINES
+ * --------------
+ */
+
+/* Keywords */
+static int
+is_keyword(
+ char *lexeme,
+ follby *pfollowedby
+ )
+{
+ follby fb;
+ int curr_s; /* current state index */
+ int token;
+ int i;
+
+ curr_s = SCANNER_INIT_S;
+ token = 0;
+
+ for (i = 0; lexeme[i]; i++) {
+ while (curr_s && (lexeme[i] != SS_CH(sst[curr_s])))
+ curr_s = SS_OTHER_N(sst[curr_s]);
+
+ if (curr_s && (lexeme[i] == SS_CH(sst[curr_s]))) {
+ if ('\0' == lexeme[i + 1]
+ && FOLLBY_NON_ACCEPTING
+ != SS_FB(sst[curr_s])) {
+ fb = SS_FB(sst[curr_s]);
+ *pfollowedby = fb;
+ token = curr_s;
+ break;
+ }
+ curr_s = SS_MATCH_N(sst[curr_s]);
+ } else
+ break;
+ }
+
+ return token;
+}
+
+
+/* Integer */
+static int
+is_integer(
+ char *lexeme
+ )
+{
+ int i = 0;
+
+ /* Allow a leading minus sign */
+ if (lexeme[i] == '-')
+ ++i;
+
+ /* Check that all the remaining characters are digits */
+ for (; lexeme[i]; ++i) {
+ if (!isdigit(lexeme[i]))
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Double */
+static int
+is_double(
+ char *lexeme
+ )
+{
+ u_int num_digits = 0; /* Number of digits read */
+ u_int i;
+
+ i = 0;
+
+ /* Check for an optional '+' or '-' */
+ if ('+' == lexeme[i] || '-' == lexeme[i])
+ i++;
+
+ /* Read the integer part */
+ for (; lexeme[i] && isdigit(lexeme[i]); i++)
+ num_digits++;
+
+ /* Check for the required decimal point */
+ if ('.' == lexeme[i])
+ i++;
+ else
+ return 0;
+
+ /* Check for any digits after the decimal point */
+ for (; lexeme[i] && isdigit(lexeme[i]); i++)
+ num_digits++;
+
+ /*
+ * The number of digits in both the decimal part and the
+ * fraction part must not be zero at this point
+ */
+ if (!num_digits)
+ return 0;
+
+ /* Check if we are done */
+ if (!lexeme[i])
+ return 1;
+
+ /* There is still more input, read the exponent */
+ if ('e' == tolower(lexeme[i]))
+ i++;
+ else
+ return 0;
+
+ /* Read an optional Sign */
+ if ('+' == lexeme[i] || '-' == lexeme[i])
+ i++;
+
+ /* Now read the exponent part */
+ while (lexeme[i] && isdigit(lexeme[i]))
+ i++;
+
+ /* Check if we are done */
+ if (!lexeme[i])
+ return 1;
+ else
+ return 0;
+}
+
+
+/* is_special() - Test whether a character is a token */
+static inline int
+is_special(
+ int ch
+ )
+{
+ return (int)strchr(special_chars, ch);
+}
+
+
+static int
+is_EOC(
+ int ch
+ )
+{
+ if ((old_config_style && (ch == '\n')) ||
+ (!old_config_style && (ch == ';')))
+ return 1;
+ return 0;
+}
+
+
+char *
+quote_if_needed(char *str)
+{
+ char *ret;
+ size_t len;
+ size_t octets;
+
+ len = strlen(str);
+ octets = len + 2 + 1;
+ ret = emalloc(octets);
+ if ('"' != str[0]
+ && (strcspn(str, special_chars) < len
+ || strchr(str, ' ') != NULL)) {
+ snprintf(ret, octets, "\"%s\"", str);
+ } else
+ strncpy(ret, str, octets);
+
+ return ret;
+}
+
+
+static int
+create_string_token(
+ char *lexeme
+ )
+{
+ char *pch;
+
+ /*
+ * ignore end of line whitespace
+ */
+ pch = lexeme;
+ while (*pch && isspace(*pch))
+ pch++;
+
+ if (!*pch) {
+ yylval.Integer = T_EOC;
+ return yylval.Integer;
+ }
+
+ yylval.String = estrdup(lexeme);
+ return T_String;
+}
+
+
+/*
+ * yylex() - function that does the actual scanning.
+ * Bison expects this function to be called yylex and for it to take no
+ * input and return an int.
+ * Conceptually yylex "returns" yylval as well as the actual return
+ * value representing the token or type.
+ */
+int
+yylex(
+ void
+ )
+{
+ int i, instring = 0;
+ int yylval_was_set = 0;
+ int token; /* The return value/the recognized token */
+ int ch;
+ static follby followedby = FOLLBY_TOKEN;
+
+ do {
+ /* Ignore whitespace at the beginning */
+ while (EOF != (ch = get_next_char()) &&
+ isspace(ch) &&
+ !is_EOC(ch))
+ ; /* Null Statement */
+
+ if (EOF == ch) {
+
+ if (!input_from_file || !curr_include_level)
+ return 0;
+
+ FCLOSE(fp[curr_include_level]);
+ ip_file = fp[--curr_include_level];
+ token = T_EOC;
+ goto normal_return;
+
+ } else if (is_EOC(ch)) {
+
+ /* end FOLLBY_STRINGS_TO_EOC effect */
+ followedby = FOLLBY_TOKEN;
+ token = T_EOC;
+ goto normal_return;
+
+ } else if (is_special(ch) && FOLLBY_TOKEN == followedby) {
+ /* special chars are their own token values */
+ token = ch;
+ /*
+ * '=' implies a single string following as in:
+ * setvar Owner = "The Boss" default
+ * This could alternatively be handled by
+ * removing '=' from special_chars and adding
+ * it to the keyword table.
+ */
+ if ('=' == ch)
+ followedby = FOLLBY_STRING;
+ yytext[0] = (char)ch;
+ yytext[1] = '\0';
+ goto normal_return;
+ } else
+ push_back_char(ch);
+
+ /* save the position of start of the token */
+ ip_file->prev_token_line_no = ip_file->line_no;
+ ip_file->prev_token_col_no = ip_file->col_no;
+
+ /* Read in the lexeme */
+ i = 0;
+ while (EOF != (ch = get_next_char())) {
+
+ yytext[i] = (char)ch;
+
+ /* Break on whitespace or a special character */
+ if (isspace(ch) || is_EOC(ch)
+ || '"' == ch
+ || (FOLLBY_TOKEN == followedby
+ && is_special(ch)))
+ break;
+
+ /* Read the rest of the line on reading a start
+ of comment character */
+ if ('#' == ch) {
+ while (EOF != (ch = get_next_char())
+ && '\n' != ch)
+ ; /* Null Statement */
+ break;
+ }
+
+ i++;
+ if (i >= COUNTOF(yytext))
+ goto lex_too_long;
+ }
+ /* Pick up all of the string inside between " marks, to
+ * end of line. If we make it to EOL without a
+ * terminating " assume it for them.
+ *
+ * XXX - HMS: I'm not sure we want to assume the closing "
+ */
+ if ('"' == ch) {
+ instring = 1;
+ while (EOF != (ch = get_next_char()) &&
+ ch != '"' && ch != '\n') {
+ yytext[i++] = (char)ch;
+ if (i >= COUNTOF(yytext))
+ goto lex_too_long;
+ }
+ /*
+ * yytext[i] will be pushed back as not part of
+ * this lexeme, but any closing quote should
+ * not be pushed back, so we read another char.
+ */
+ if ('"' == ch)
+ ch = get_next_char();
+ }
+ /* Pushback the last character read that is not a part
+ * of this lexeme.
+ * If the last character read was an EOF, pushback a
+ * newline character. This is to prevent a parse error
+ * when there is no newline at the end of a file.
+ */
+ if (EOF == ch)
+ push_back_char('\n');
+ else
+ push_back_char(ch);
+ yytext[i] = '\0';
+ } while (i == 0);
+
+ /* Now return the desired token */
+
+ /* First make sure that the parser is *not* expecting a string
+ * as the next token (based on the previous token that was
+ * returned) and that we haven't read a string.
+ */
+
+ if (followedby == FOLLBY_TOKEN && !instring) {
+ token = is_keyword(yytext, &followedby);
+ if (token)
+ goto normal_return;
+ else if (is_integer(yytext)) {
+ yylval_was_set = 1;
+ errno = 0;
+ if ((yylval.Integer = strtol(yytext, NULL, 10)) == 0
+ && ((errno == EINVAL) || (errno == ERANGE))) {
+ msyslog(LOG_ERR,
+ "Integer cannot be represented: %s",
+ yytext);
+ exit(1);
+ } else {
+ token = T_Integer;
+ goto normal_return;
+ }
+ }
+ else if (is_double(yytext)) {
+ yylval_was_set = 1;
+ errno = 0;
+ if ((yylval.Double = atof(yytext)) == 0 && errno == ERANGE) {
+ msyslog(LOG_ERR,
+ "Double too large to represent: %s",
+ yytext);
+ exit(1);
+ } else {
+ token = T_Double;
+ goto normal_return;
+ }
+ } else {
+ /* Default: Everything is a string */
+ yylval_was_set = 1;
+ token = create_string_token(yytext);
+ goto normal_return;
+ }
+ }
+
+ /*
+ * Either followedby is not FOLLBY_TOKEN or this lexeme is part
+ * of a string. Hence, we need to return T_String.
+ *
+ * _Except_ we might have a -4 or -6 flag on a an association
+ * configuration line (server, peer, pool, etc.).
+ *
+ * This is a terrible hack, but the grammar is ambiguous so we
+ * don't have a choice. [SK]
+ *
+ * The ambiguity is in the keyword scanner, not ntp_parser.y.
+ * We do not require server addresses be quoted in ntp.conf,
+ * complicating the scanner's job. To avoid trying (and
+ * failing) to match an IP address or DNS name to a keyword,
+ * the association keywords use FOLLBY_STRING in the keyword
+ * table, which tells the scanner to force the next token to be
+ * a T_String, so it does not try to match a keyword but rather
+ * expects a string when -4/-6 modifiers to server, peer, etc.
+ * are encountered.
+ * restrict -4 and restrict -6 parsing works correctly without
+ * this hack, as restrict uses FOLLBY_TOKEN. [DH]
+ */
+ if ('-' == yytext[0]) {
+ if ('4' == yytext[1]) {
+ token = T_Ipv4_flag;
+ goto normal_return;
+ } else if ('6' == yytext[1]) {
+ token = T_Ipv6_flag;
+ goto normal_return;
+ }
+ }
+
+ instring = 0;
+ if (FOLLBY_STRING == followedby)
+ followedby = FOLLBY_TOKEN;
+
+ yylval_was_set = 1;
+ token = create_string_token(yytext);
+
+normal_return:
+ if (T_EOC == token)
+ DPRINTF(4,("\t<end of command>\n"));
+ else
+ DPRINTF(4, ("yylex: lexeme '%s' -> %s\n", yytext,
+ token_name(token)));
+
+ if (!yylval_was_set)
+ yylval.Integer = token;
+
+ return token;
+
+lex_too_long:
+ yytext[min(sizeof(yytext) - 1, 50)] = 0;
+ msyslog(LOG_ERR,
+ "configuration item on line %d longer than limit of %lu, began with '%s'",
+ ip_file->line_no, (u_long)(sizeof(yytext) - 1), yytext);
+
+ /*
+ * If we hit the length limit reading the startup configuration
+ * file, abort.
+ */
+ if (input_from_file)
+ exit(sizeof(yytext) - 1);
+
+ /*
+ * If it's runtime configuration via ntpq :config treat it as
+ * if the configuration text ended before the too-long lexeme,
+ * hostname, or string.
+ */
+ yylval.Integer = 0;
+ return 0;
+}
diff --git a/ntpd/ntp_scanner.h b/ntpd/ntp_scanner.h
new file mode 100644
index 000000000000..907d7c0ff5c2
--- /dev/null
+++ b/ntpd/ntp_scanner.h
@@ -0,0 +1,132 @@
+/* ntp_scanner.h
+ *
+ * The header file for a simple lexical analyzer.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Copyright (c) 2006
+ */
+
+#ifndef NTP_SCANNER_H
+#define NTP_SCANNER_H
+
+/*
+ * ntp.conf syntax is slightly irregular in that some tokens such as
+ * hostnames do not require quoting even if they might otherwise be
+ * recognized as T_ terminal tokens. This hand-crafted lexical scanner
+ * uses a "followed by" value associated with each keyword to indicate
+ * normal scanning of the next token, forced scanning of the next token
+ * alone as a T_String, or forced scanning of all tokens to the end of
+ * the command as T_String.
+ * In the past the identifiers for this functionality ended in _ARG:
+ *
+ * NO_ARG -> FOLLBY_TOKEN
+ * SINGLE_ARG -> FOLLBY_STRING
+ * MULTIPLE_ARG -> FOLLBY_STRINGS_TO_EOC
+ *
+ * Note that some tokens use FOLLBY_TOKEN even though they sometimes
+ * are followed by strings. FOLLBY_STRING is used only when needed to
+ * avoid the keyword scanner matching a token where a string is needed.
+ *
+ * FOLLBY_NON_ACCEPT is an overloading of this field to distinguish
+ * non-accepting states (where the state number does not match a T_
+ * value).
+ */
+typedef enum {
+ FOLLBY_TOKEN = 0,
+ FOLLBY_STRING,
+ FOLLBY_STRINGS_TO_EOC,
+ FOLLBY_NON_ACCEPTING
+} follby;
+
+#define MAXLINE 1024 /* maximum length of line */
+#define MAXINCLUDELEVEL 5 /* maximum include file levels */
+
+/* STRUCTURES
+ * ----------
+ */
+
+/*
+ * Define a structure to hold the FSA for the keywords.
+ * The structure is actually a trie.
+ *
+ * To save space, a single u_int32 encodes four fields, and a fifth
+ * (the token completed for terminal states) is implied by the index of
+ * the rule within the scan state array, taking advantage of the fact
+ * there are more scan states than the highest T_ token number.
+ *
+ * The lowest 8 bits hold the character the state matches on.
+ * Bits 8 and 9 hold the followedby value (0 - 3). For non-accepting
+ * states (which do not match a completed token) the followedby
+ * value 3 (FOLLBY_NONACCEPTING) denotes that fact. For accepting
+ * states, values 0 - 2 control whether the scanner forces the
+ * following token(s) to strings.
+ * Bits 10 through 20 hold the next state to check not matching
+ * this state's character.
+ * Bits 21 through 31 hold the next state to check matching the char.
+ */
+
+#define S_ST(ch, fb, match_n, other_n) ( \
+ (u_char)((ch) & 0xff) | \
+ ((u_int32)(fb) << 8) | \
+ ((u_int32)(match_n) << 10) | \
+ ((u_int32)(other_n) << 21) \
+)
+
+#define SS_CH(ss) ((char)(u_char)((ss) & 0xff))
+#define SS_FB(ss) (((u_int)(ss) >> 8) & 0x3)
+#define SS_MATCH_N(ss) (((u_int)(ss) >> 10) & 0x7ff)
+#define SS_OTHER_N(ss) (((u_int)(ss) >> 21) & 0x7ff)
+
+typedef u_int32 scan_state;
+
+
+/* Structure to hold a filename, file pointer and positional info */
+struct FILE_INFO {
+ const char * fname; /* Path to the file */
+ FILE * fd; /* File Descriptor */
+ int line_no; /* Line Number */
+ int col_no; /* Column Number */
+ int prev_line_col_no; /* Col No on the
+ previous line when a
+ '\n' was seen */
+ int prev_token_line_no; /* Line at start of
+ token */
+ int prev_token_col_no; /* Col No at start of
+ token */
+ int err_line_no;
+ int err_col_no;
+};
+
+
+/* SCANNER GLOBAL VARIABLES
+ * ------------------------
+ */
+extern struct config_tree cfgt; /* Parser output stored here */
+extern int curr_include_level; /* The current include level */
+
+extern struct FILE_INFO *ip_file; /* Pointer to the configuration file stream */
+
+/* VARIOUS EXTERNAL DECLARATIONS
+ * -----------------------------
+ */
+extern int old_config_style;
+extern int input_from_file;
+extern struct FILE_INFO *fp[];
+
+/* VARIOUS SUBROUTINE DECLARATIONS
+ * -------------------------------
+ */
+extern const char *keyword(int token);
+extern char *quote_if_needed(char *str);
+int yylex(void);
+
+struct FILE_INFO *F_OPEN(const char *path, const char *mode);
+int FGETC(struct FILE_INFO *stream);
+int UNGETC(int ch, struct FILE_INFO *stream);
+int FCLOSE(struct FILE_INFO *stream);
+
+void push_back_char(int ch);
+
+#endif /* NTP_SCANNER_H */
diff --git a/ntpd/ntp_signd.c b/ntpd/ntp_signd.c
new file mode 100644
index 000000000000..3beb03be5a69
--- /dev/null
+++ b/ntpd/ntp_signd.c
@@ -0,0 +1,239 @@
+/* Copyright 2008, Red Hat, Inc.
+ Copyright 2008, Andrew Tridgell.
+ Licenced under the same terms as NTP itself.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_NTP_SIGND
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_stdlib.h"
+#include "ntp_unixtime.h"
+#include "ntp_control.h"
+#include "ntp_string.h"
+
+#include <stdio.h>
+#include <stddef.h>
+#ifdef HAVE_LIBSCF_H
+#include <libscf.h>
+#include <unistd.h>
+#endif /* HAVE_LIBSCF_H */
+
+#include <sys/un.h>
+
+/* socket routines by tridge - from junkcode.samba.org */
+
+/*
+ connect to a unix domain socket
+*/
+static int
+ux_socket_connect(const char *name)
+{
+ int fd;
+ struct sockaddr_un addr;
+ if (!name) {
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1) {
+ return -1;
+ }
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+
+/*
+ keep writing until its all sent
+*/
+static int
+write_all(int fd, const void *buf, size_t len)
+{
+ size_t total = 0;
+ while (len) {
+ int n = write(fd, buf, len);
+ if (n <= 0) return total;
+ buf = n + (char *)buf;
+ len -= n;
+ total += n;
+ }
+ return total;
+}
+
+/*
+ keep reading until its all read
+*/
+static int
+read_all(int fd, void *buf, size_t len)
+{
+ size_t total = 0;
+ while (len) {
+ int n = read(fd, buf, len);
+ if (n <= 0) return total;
+ buf = n + (char *)buf;
+ len -= n;
+ total += n;
+ }
+ return total;
+}
+
+/*
+ send a packet in length prefix format
+*/
+static int
+send_packet(int fd, const char *buf, uint32_t len)
+{
+ uint32_t net_len = htonl(len);
+ if (write_all(fd, &net_len, sizeof(net_len)) != sizeof(net_len)) return -1;
+ if (write_all(fd, buf, len) != len) return -1;
+ return 0;
+}
+
+/*
+ receive a packet in length prefix format
+*/
+static int
+recv_packet(int fd, char **buf, uint32_t *len)
+{
+ if (read_all(fd, len, sizeof(*len)) != sizeof(*len)) return -1;
+ *len = ntohl(*len);
+ (*buf) = emalloc(*len);
+ if (read_all(fd, *buf, *len) != *len) {
+ free(*buf);
+ return -1;
+ }
+ return 0;
+}
+
+void
+send_via_ntp_signd(
+ struct recvbuf *rbufp, /* receive packet pointer */
+ int xmode,
+ keyid_t xkeyid,
+ int flags,
+ struct pkt *xpkt
+ )
+{
+
+ /* We are here because it was detected that the client
+ * sent an all-zero signature, and we therefore know
+ * it's windows trying to talk to an AD server
+ *
+ * Because we don't want to dive into Samba's secrets
+ * database just to find the long-term kerberos key
+ * that is re-used as the NTP key, we instead hand the
+ * packet over to Samba to sign, and return to us.
+ *
+ * The signing method Samba will use is described by
+ * Microsoft in MS-SNTP, found here:
+ * http://msdn.microsoft.com/en-us/library/cc212930.aspx
+ */
+
+ int fd, sendlen;
+ struct samba_key_in {
+ uint32_t version;
+ uint32_t op;
+ uint32_t packet_id;
+ uint32_t key_id_le;
+ struct pkt pkt;
+ } samba_pkt;
+
+ struct samba_key_out {
+ uint32_t version;
+ uint32_t op;
+ uint32_t packet_id;
+ struct pkt pkt;
+ } samba_reply;
+
+ char full_socket[256];
+
+ char *reply = NULL;
+ uint32_t reply_len;
+
+ memset(&samba_pkt, 0, sizeof(samba_pkt));
+ samba_pkt.op = 0; /* Sign message */
+ /* This will be echoed into the reply - a different
+ * impelementation might want multiple packets
+ * awaiting signing */
+
+ samba_pkt.packet_id = 1;
+
+ /* Swap the byte order back - it's actually little
+ * endian on the wire, but it was read above as
+ * network byte order */
+ samba_pkt.key_id_le = htonl(xkeyid);
+ samba_pkt.pkt = *xpkt;
+
+ snprintf(full_socket, sizeof(full_socket), "%s/socket", ntp_signd_socket);
+
+ fd = ux_socket_connect(full_socket);
+ /* Only continue with this if we can talk to Samba */
+ if (fd != -1) {
+ /* Send old packet to Samba, expect response */
+ /* Packet to Samba is quite simple:
+ All values BIG endian except key ID as noted
+ [packet size as BE] - 4 bytes
+ [protocol version (0)] - 4 bytes
+ [packet ID] - 4 bytes
+ [operation (sign message=0)] - 4 bytes
+ [key id] - LITTLE endian (as on wire) - 4 bytes
+ [message to sign] - as marshalled, without signature
+ */
+
+ if (send_packet(fd, (char *)&samba_pkt, offsetof(struct samba_key_in, pkt) + LEN_PKT_NOMAC) != 0) {
+ /* Huh? could not talk to Samba... */
+ close(fd);
+ return;
+ }
+
+ if (recv_packet(fd, &reply, &reply_len) != 0) {
+ if (reply) {
+ free(reply);
+ }
+ close(fd);
+ return;
+ }
+ /* Return packet is also simple:
+ [packet size] - network byte order - 4 bytes
+ [protocol version (0)] network byte order - - 4 bytes
+ [operation (signed success=3, failure=4)] network byte order - - 4 byte
+ (optional) [signed message] - as provided before, with signature appended
+ */
+
+ if (reply_len <= sizeof(samba_reply)) {
+ memcpy(&samba_reply, reply, reply_len);
+ if (ntohl(samba_reply.op) == 3 && reply_len > offsetof(struct samba_key_out, pkt)) {
+ sendlen = reply_len - offsetof(struct samba_key_out, pkt);
+ xpkt = &samba_reply.pkt;
+ sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, xpkt, sendlen);
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "transmit ntp_signd packet: at %ld %s->%s mode %d keyid %08x len %d\n",
+ current_time, ntoa(&rbufp->dstadr->sin),
+ ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen);
+#endif
+ }
+ }
+
+ if (reply) {
+ free(reply);
+ }
+ close(fd);
+
+ }
+}
+#endif
diff --git a/ntpd/ntp_timer.c b/ntpd/ntp_timer.c
index 812206ad2627..3c2c832b1986 100644
--- a/ntpd/ntp_timer.c
+++ b/ntpd/ntp_timer.c
@@ -23,6 +23,14 @@
# include "ntp_timer.h"
#endif
+#ifdef KERNEL_PLL
+#include "ntp_syscall.h"
+#endif /* KERNEL_PLL */
+
+#ifdef OPENSSL
+#include <openssl/rand.h>
+#endif /* OPENSSL */
+
/*
* These routines provide support for the event timer. The timer is
* implemented by an interrupt routine which sets a flag once every
@@ -33,25 +41,27 @@
* dispatched to the transmit procedure. Finally, we call the hourly
* procedure to do cleanup and print a message.
*/
-
volatile int interface_interval = 300; /* update interface every 5 minutes as default */
/*
- * Alarm flag. The mainline code imports this.
+ * Alarm flag. The mainline code imports this.
*/
volatile int alarm_flag;
/*
- * The counters
+ * The counters and timeouts
*/
-static u_long adjust_timer; /* second timer */
-static u_long keys_timer; /* minute timer */
-static u_long stats_timer; /* stats timer */
-static u_long huffpuff_timer; /* huff-n'-puff timer */
-static u_long interface_timer; /* interface update timer */
+static u_long interface_timer; /* interface update timer */
+static u_long adjust_timer; /* second timer */
+static u_long stats_timer; /* stats timer */
+static u_long huffpuff_timer; /* huff-n'-puff timer */
+u_long leapsec; /* leapseconds countdown */
+l_fp sys_time; /* current system time */
#ifdef OPENSSL
-static u_long revoke_timer; /* keys revoke timer */
-u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
+static u_long revoke_timer; /* keys revoke timer */
+static u_long keys_timer; /* session key timer */
+u_long sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
+u_long sys_automax = NTP_AUTOMAX; /* key list timeout (log2 s) */
#endif /* OPENSSL */
/*
@@ -60,9 +70,10 @@ u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
volatile u_long alarm_overflow;
#define MINUTE 60
-#define HOUR (60*60)
+#define HOUR (60 * MINUTE)
+#define DAY (24 * HOUR)
-u_long current_time;
+u_long current_time; /* seconds since startup */
/*
* Stats. Number of overflows and number of calls to transmit().
@@ -79,7 +90,7 @@ static int vmsinc[2]; /* timer increment */
#if defined SYS_WINNT
static HANDLE WaitableTimerHandle = NULL;
#else
-static RETSIGTYPE alarming P((int));
+static RETSIGTYPE alarming (int);
#endif /* SYS_WINNT */
#if !defined(VMS)
@@ -140,11 +151,6 @@ reinit_timer(void)
void
init_timer(void)
{
-# if defined SYS_WINNT & !defined(SYS_CYGWIN32)
- HANDLE hToken = INVALID_HANDLE_VALUE;
- TOKEN_PRIVILEGES tkp;
-# endif /* SYS_WINNT */
-
/*
* Initialize...
*/
@@ -199,28 +205,6 @@ init_timer(void)
sys$setimr(0, &vmstimer, alarming, alarming, 0);
# endif /* VMS */
#else /* SYS_WINNT */
- _tzset();
-
- /*
- * Get privileges needed for fiddling with the clock
- */
-
- /* get the current process token handle */
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
- msyslog(LOG_ERR, "OpenProcessToken failed: %m");
- exit(1);
- }
- /* get the LUID for system-time privilege. */
- LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
- tkp.PrivilegeCount = 1; /* one privilege to set */
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- /* get set-time privilege for this process. */
- AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
- /* cannot test return value of AdjustTokenPrivileges. */
- if (GetLastError() != ERROR_SUCCESS) {
- msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
- }
-
/*
* Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
* Under Windows/NT,
@@ -253,26 +237,25 @@ get_timer_handle(void)
#endif
/*
- * timer - dispatch anyone who needs to be
+ * timer - event timer
*/
void
timer(void)
{
register struct peer *peer, *next_peer;
-#ifdef OPENSSL
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
-#endif /* OPENSSL */
- u_int n;
-
- current_time += (1<<EVENT_TIMEOUT);
+ u_int n;
/*
- * Adjustment timeout first.
+ * The basic timerevent is one second. This is used to adjust
+ * the system clock in time and frequency, implement the
+ * kiss-o'-deatch function and implement the association
+ * polling function..
*/
+ current_time++;
+ get_systime(&sys_time);
if (adjust_timer <= current_time) {
adjust_timer += 1;
adj_host_clock();
- kod_proto();
#ifdef REFCLOCK
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
@@ -285,15 +268,25 @@ timer(void)
}
/*
- * Now dispatch any peers whose event timer has expired. Be careful
- * here, since the peer structure might go away as the result of
- * the call.
+ * Now dispatch any peers whose event timer has expired. Be
+ * careful here, since the peer structure might go away as the
+ * result of the call.
*/
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
- if (peer->action && peer->nextaction <= current_time)
- peer->action(peer);
+ if (peer->action && peer->nextaction <=
+ current_time)
+ peer->action(peer);
+
+ /*
+ * Restrain the non-burst packet rate not more
+ * than one packet every 16 seconds. This is
+ * usually tripped using iburst and minpoll of
+ * 128 s or less.
+ */
+ if (peer->throttle > 0)
+ peer->throttle--;
if (peer->nextdate <= current_time) {
#ifdef REFCLOCK
if (peer->flags & FLAG_REFCLOCK)
@@ -308,15 +301,61 @@ timer(void)
}
/*
- * Garbage collect expired keys.
+ * Orphan mode is active when enabled and when no servers less
+ * than the orphan stratum are available. A server with no other
+ * synchronization source is an orphan. It shows offset zero and
+ * reference ID the loopback address.
*/
- if (keys_timer <= current_time) {
- keys_timer += MINUTE;
- auth_agekeys();
+ if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) {
+ if (sys_leap == LEAP_NOTINSYNC) {
+ sys_leap = LEAP_NOWARNING;
+#ifdef OPENSSL
+ if (crypto_flags)
+ crypto_update();
+#endif /* OPENSSL */
+ }
+ sys_stratum = (u_char)sys_orphan;
+ if (sys_stratum > 1)
+ sys_refid = htonl(LOOPBACKADR);
+ else
+ memcpy(&sys_refid, "LOOP", 4);
+ sys_offset = 0;
+ sys_rootdelay = 0;
+ sys_rootdisp = 0;
}
/*
- * Huff-n'-puff filter
+ * Leapseconds. If a leap is pending, decrement the time
+ * remaining. If less than one day remains, set the leap bits.
+ * When no time remains, clear the leap bits and increment the
+ * TAI. If kernel suppport is not available, do the leap
+ * crudely. Note a leap cannot be pending unless the clock is
+ * set.
+ */
+ if (leapsec > 0) {
+ leapsec--;
+ if (leapsec == 0) {
+ sys_leap = LEAP_NOWARNING;
+ sys_tai = leap_tai;
+#ifdef KERNEL_PLL
+ if (!(pll_control && kern_enable))
+ step_systime(-1.0);
+#else /* KERNEL_PLL */
+#ifndef SYS_WINNT /* WinNT port has its own leap second handling */
+ step_systime(-1.0);
+#endif /* SYS_WINNT */
+#endif /* KERNEL_PLL */
+ report_event(EVNT_LEAP, NULL, NULL);
+ } else {
+ if (leapsec < DAY)
+ sys_leap = LEAP_ADDSECOND;
+ if (leap_tai > 0)
+ sys_tai = leap_tai - 1;
+ }
+ }
+
+ /*
+ * Update huff-n'-puff filter.
*/
if (huffpuff_timer <= current_time) {
huffpuff_timer += HUFFPUFF;
@@ -325,37 +364,44 @@ timer(void)
#ifdef OPENSSL
/*
- * Garbage collect old keys and generate new private value
+ * Garbage collect expired keys.
*/
- if (revoke_timer <= current_time) {
- revoke_timer += RANDPOLL(sys_revoke);
- expire_all();
- sprintf(statstr, "refresh ts %u", ntohl(hostval.tstamp));
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("timer: %s\n", statstr);
-#endif
+ if (keys_timer <= current_time) {
+ keys_timer += 1 << sys_automax;
+ auth_agekeys();
+ }
+
+ /*
+ * Garbage collect key list and generate new private value. The
+ * timer runs only after initial synchronization and fires about
+ * once per day.
+ */
+ if (revoke_timer <= current_time && sys_leap !=
+ LEAP_NOTINSYNC) {
+ revoke_timer += 1 << sys_revoke;
+ RAND_bytes((u_char *)&sys_private, 4);
}
#endif /* OPENSSL */
/*
- * interface update timer
+ * Interface update timer
*/
if (interface_interval && interface_timer <= current_time) {
- timer_interfacetimeout(current_time + interface_interval);
- DPRINTF(1, ("timer: interface update\n"));
+ timer_interfacetimeout(current_time +
+ interface_interval);
+ DPRINTF(2, ("timer: interface update\n"));
interface_update(NULL, NULL);
}
/*
- * Finally, periodically write stats.
+ * Finally, write hourly stats.
*/
if (stats_timer <= current_time) {
- if (stats_timer != 0)
- write_stats();
- stats_timer += stats_write_period;
+ stats_timer += HOUR;
+ write_stats();
+ if (sys_tai != 0 && sys_time.l_ui > leap_expire)
+ report_event(EVNT_LEAPVAL, NULL, NULL);
}
}
diff --git a/ntpd/ntp_util.c b/ntpd/ntp_util.c
index 91ff8a64f76d..8bc95d619a56 100644
--- a/ntpd/ntp_util.c
+++ b/ntpd/ntp_util.c
@@ -1,7 +1,6 @@
/*
* ntp_util.c - stuff I didn't have any other place for
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -12,6 +11,7 @@
#include "ntp_filegen.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
#include <stdio.h>
#include <ctype.h>
@@ -38,24 +38,29 @@
#endif /* VMS */
/*
- * This contains odds and ends. Right now the only thing you'll find
- * in here is the hourly stats printer and some code to support
- * rereading the keys file, but I may eventually put other things in
- * here such as code to do something with the leap bits.
+ * Defines used by the leapseconds stuff
*/
+#define MAX_TAI 100 /* max TAI offset (s) */
+#define L_DAY 86400UL /* seconds per day */
+#define L_YEAR (L_DAY * 365) /* days per year */
+#define L_LYEAR (L_YEAR + L_DAY) /* days per leap year */
+#define L_4YEAR (L_LYEAR + 3 * L_YEAR) /* days per leap cycle */
+#define L_CENT (L_4YEAR * 25) /* days per century */
+
/*
- * Name of the keys file
+ * This contains odds and ends, including the hourly stats, various
+ * configuration items, leapseconds stuff, etc.
*/
-static char *key_file_name;
-
/*
- * The name of the drift_comp file and the temporary.
+ * File names
*/
-static char *stats_drift_file;
-static char *stats_temp_file;
-int stats_write_period = 3600; /* # of seconds between writes. */
-double stats_write_tolerance = 0;
-static double prev_drift_comp = 99999.;
+static char *key_file_name; /* keys file name */
+char *leapseconds_file_name; /* leapseconds file name */
+char *stats_drift_file; /* frequency file name */
+static char *stats_temp_file; /* temp frequency file name */
+double wander_resid; /* wander threshold */
+double wander_threshold = 1e-7; /* initial wander threshold */
+int drift_file_sw; /* clock update switch */
/*
* Statistics file stuff
@@ -64,7 +69,7 @@ static double prev_drift_comp = 99999.;
# ifndef SYS_WINNT
# define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */
# else
-# define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
+# define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
# endif /* SYS_WINNT */
#endif
@@ -72,13 +77,6 @@ static double prev_drift_comp = 99999.;
# define MAXPATHLEN 256
#endif
-static char statsdir[MAXPATHLEN] = NTP_VAR;
-
-static FILEGEN peerstats;
-static FILEGEN loopstats;
-static FILEGEN clockstats;
-static FILEGEN rawstats;
-static FILEGEN sysstats;
#ifdef DEBUG_TIMING
static FILEGEN timingstats;
#endif
@@ -86,6 +84,14 @@ static FILEGEN timingstats;
static FILEGEN cryptostats;
#endif /* OPENSSL */
+static char statsdir[MAXPATHLEN] = NTP_VAR;
+static FILEGEN peerstats;
+static FILEGEN loopstats;
+static FILEGEN clockstats;
+static FILEGEN rawstats;
+static FILEGEN sysstats;
+static FILEGEN protostats;
+
/*
* This controls whether stats are written to the fileset. Provided
* so that ntpdc can turn off stats when the file system fills up.
@@ -95,35 +101,87 @@ int stats_control;
/*
* Initial frequency offset later passed to the loopfilter.
*/
-double old_drift;
+double old_drift = 1e9; /* current frequency */
+static double prev_drift_comp; /* last frequency update */
/*
- * init_util - initialize the utilities
+ * Static prototypes
*/
-void
-init_util(void)
-{
- stats_drift_file = 0;
- stats_temp_file = 0;
- key_file_name = 0;
+static int leap_file(FILE *);
+static void record_sys_stats(void);
- filegen_register(&statsdir[0], "peerstats", &peerstats);
+/*
+ * Prototypes
+ */
+#ifdef DEBUG
+void uninit_util(void);
+#endif
- filegen_register(&statsdir[0], "loopstats", &loopstats);
- filegen_register(&statsdir[0], "clockstats", &clockstats);
+/*
+ * uninit_util - free memory allocated by init_util
+ */
+#ifdef DEBUG
+void
+uninit_util(void)
+{
+#if defined(_MSC_VER) && defined (_DEBUG)
+ _CrtCheckMemory();
+#endif
+ if (stats_drift_file) {
+ free(stats_drift_file);
+ free(stats_temp_file);
+ stats_drift_file = NULL;
+ stats_temp_file = NULL;
+ }
+ if (key_file_name) {
+ free(key_file_name);
+ key_file_name = NULL;
+ }
+ filegen_unregister("peerstats");
+ filegen_unregister("loopstats");
+ filegen_unregister("clockstats");
+ filegen_unregister("rawstats");
+ filegen_unregister("sysstats");
+ filegen_unregister("protostats");
+#ifdef OPENSSL
+ filegen_unregister("cryptostats");
+#endif /* OPENSSL */
+#ifdef DEBUG_TIMING
+ filegen_unregister("timingstats");
+#endif /* DEBUG_TIMING */
- filegen_register(&statsdir[0], "rawstats", &rawstats);
+#if defined(_MSC_VER) && defined (_DEBUG)
+ _CrtCheckMemory();
+#endif
+}
+#endif /* DEBUG */
- filegen_register(&statsdir[0], "sysstats", &sysstats);
+/*
+ * init_util - initialize the utilities (ntpd included)
+ */
+void
+init_util(void)
+{
+ stats_drift_file = NULL;
+ stats_temp_file = NULL;
+ key_file_name = NULL;
+ filegen_register(statsdir, "peerstats", &peerstats);
+ filegen_register(statsdir, "loopstats", &loopstats);
+ filegen_register(statsdir, "clockstats", &clockstats);
+ filegen_register(statsdir, "rawstats", &rawstats);
+ filegen_register(statsdir, "sysstats", &sysstats);
+ filegen_register(statsdir, "protostats", &protostats);
#ifdef OPENSSL
- filegen_register(&statsdir[0], "cryptostats", &cryptostats);
+ filegen_register(statsdir, "cryptostats", &cryptostats);
#endif /* OPENSSL */
-
#ifdef DEBUG_TIMING
- filegen_register(&statsdir[0], "timingstats", &timingstats);
-#endif
+ filegen_register(statsdir, "timingstats", &timingstats);
+#endif /* DEBUG_TIMING */
+#ifdef DEBUG
+ atexit(uninit_util);
+#endif /* DEBUG */
}
@@ -133,17 +191,17 @@ init_util(void)
void
write_stats(void)
{
- FILE *fp;
-
+ FILE *fp;
+ double ftemp;
#ifdef DOSYNCTODR
struct timeval tv;
#if !defined(VMS)
- int prio_set;
+ int prio_set;
#endif
#ifdef HAVE_GETCLOCK
struct timespec ts;
#endif
- int o_prio;
+ int o_prio;
/*
* Sometimes having a Sun can be a drag.
@@ -168,7 +226,8 @@ write_stats(void)
*/
#if !defined(VMS)
- /* (prr) getpriority returns -1 on error, but -1 is also a valid
+ /*
+ * (prr) getpriority returns -1 on error, but -1 is also a valid
* return value (!), so instead we have to zero errno before the
* call and check it for non-zero afterwards.
*/
@@ -198,63 +257,87 @@ write_stats(void)
#else /* not HAVE_GETCLOCK */
GETTIMEOFDAY(&tv,(struct timezone *)NULL);
#endif /* not HAVE_GETCLOCK */
- if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0) {
+ if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0)
msyslog(LOG_ERR, "can't sync battery time: %m");
- }
#if !defined(VMS)
if (prio_set)
setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */
#endif /* VMS */
#endif /* DOSYNCTODR */
-
- NLOG(NLOG_SYSSTATIST)
- msyslog(LOG_INFO,
- "offset %.6f sec freq %.3f ppm error %.6f poll %d",
- last_offset, drift_comp * 1e6, sys_jitter,
- sys_poll);
-
-
record_sys_stats();
- if ((u_long)(fabs(prev_drift_comp - drift_comp) * 1e9) <=
- (u_long)(fabs(stats_write_tolerance * drift_comp) * 1e9)) {
- return;
- }
+ ftemp = fabs(prev_drift_comp - drift_comp);
prev_drift_comp = drift_comp;
- if (stats_drift_file != 0) {
- if ((fp = fopen(stats_temp_file, "w")) == NULL) {
- msyslog(LOG_ERR, "can't open %s: %m",
- stats_temp_file);
- return;
- }
- fprintf(fp, "%.3f\n", drift_comp * 1e6);
- (void)fclose(fp);
- /* atomic */
+ if (ftemp > clock_phi)
+ return;
+
+ if (stats_drift_file != 0 && drift_file_sw) {
+
+ /*
+ * When the frequency file is written, initialize the
+ * wander threshold to a configured initial value.
+ * Thereafter reduce it by a factor of 0.5. When it
+ * drops below the frequency wander, write the frequency
+ * file. This adapts to the prevailing wander yet
+ * minimizes the file writes.
+ */
+ drift_file_sw = FALSE;
+ wander_resid *= 0.5;
+#ifdef DEBUG
+ if (debug)
+ printf("write_stats: wander %.6lf thresh %.6lf, freq %.6lf\n",
+ clock_stability * 1e6, wander_resid * 1e6,
+ drift_comp * 1e6);
+#endif
+ if (sys_leap != LEAP_NOTINSYNC && clock_stability >
+ wander_resid) {
+ wander_resid = wander_threshold;
+ if ((fp = fopen(stats_temp_file, "w")) == NULL)
+ {
+ msyslog(LOG_ERR,
+ "frequency file %s: %m",
+ stats_temp_file);
+ return;
+ }
+ fprintf(fp, "%.3f\n", drift_comp * 1e6);
+ (void)fclose(fp);
+ /* atomic */
#ifdef SYS_WINNT
- (void) _unlink(stats_drift_file); /* rename semantics differ under NT */
+ if (_unlink(stats_drift_file)) /* rename semantics differ under NT */
+ msyslog(LOG_WARNING,
+ "Unable to remove prior drift file %s, %m",
+ stats_drift_file);
#endif /* SYS_WINNT */
#ifndef NO_RENAME
- (void) rename(stats_temp_file, stats_drift_file);
+ if (rename(stats_temp_file, stats_drift_file))
+ msyslog(LOG_WARNING,
+ "Unable to rename temp drift file %s to %s, %m",
+ stats_temp_file, stats_drift_file);
#else
- /* we have no rename NFS of ftp in use */
- if ((fp = fopen(stats_drift_file, "w")) == NULL) {
- msyslog(LOG_ERR, "can't open %s: %m",
- stats_drift_file);
- return;
- }
-
+ /* we have no rename NFS of ftp in use */
+ if ((fp = fopen(stats_drift_file, "w")) ==
+ NULL) {
+ msyslog(LOG_ERR,
+ "frequency file %s: %m",
+ stats_drift_file);
+ return;
+ }
#endif
#if defined(VMS)
- /* PURGE */
- {
- $DESCRIPTOR(oldvers,";-1");
- struct dsc$descriptor driftdsc = {
- strlen(stats_drift_file),0,0,stats_drift_file };
-
- while(lib$delete_file(&oldvers,&driftdsc) & 1) ;
- }
+ /* PURGE */
+ {
+ $DESCRIPTOR(oldvers,";-1");
+ struct dsc$descriptor driftdsc = {
+ strlen(stats_drift_file), 0, 0,
+ stats_drift_file };
+ while(lib$delete_file(&oldvers,
+ &driftdsc) & 1);
+ }
#endif
+ } else {
+ /* XXX: Log a message at INFO level */
+ }
}
}
@@ -268,9 +351,16 @@ stats_config(
const char *invalue /* only one type so far */
)
{
- FILE *fp;
+ FILE *fp;
const char *value;
- int len;
+ int len;
+ char tbuf[80];
+ char str1[20], str2[20];
+#ifndef VMS
+ const char temp_ext[] = ".TEMP";
+#else
+ const char temp_ext[] = "-TEMP";
+#endif
/*
* Expand environment strings under Windows NT, since the
@@ -284,20 +374,27 @@ stats_config(
case STATS_FREQ_FILE:
strcpy(parameter,"STATS_FREQ_FILE");
break;
+
+ case STATS_LEAP_FILE:
+ strcpy(parameter,"STATS_LEAP_FILE");
+ break;
+
case STATS_STATSDIR:
strcpy(parameter,"STATS_STATSDIR");
break;
+
case STATS_PID_FILE:
strcpy(parameter,"STATS_PID_FILE");
break;
+
default:
strcpy(parameter,"UNKNOWN");
break;
}
value = invalue;
-
msyslog(LOG_ERR,
- "ExpandEnvironmentStrings(%s) failed: %m\n", parameter);
+ "ExpandEnvironmentStrings(%s) failed: %m\n",
+ parameter);
} else {
value = newvalue;
}
@@ -306,67 +403,77 @@ stats_config(
#endif /* SYS_WINNT */
switch(item) {
- case STATS_FREQ_FILE:
- if (stats_drift_file != 0) {
- (void) free(stats_drift_file);
- (void) free(stats_temp_file);
- stats_drift_file = 0;
- stats_temp_file = 0;
- }
- if (value == 0 || (len = strlen(value)) == 0)
- break;
+ /*
+ * Open and read frequency file.
+ */
+ case STATS_FREQ_FILE:
+ if (!value || (len = strlen(value)) == 0)
+ break;
- stats_drift_file = (char*)emalloc((u_int)(len + 1));
-#if !defined(VMS)
- stats_temp_file = (char*)emalloc((u_int)(len +
- sizeof(".TEMP")));
-#else
- stats_temp_file = (char*)emalloc((u_int)(len +
- sizeof("-TEMP")));
-#endif /* VMS */
- memmove(stats_drift_file, value, (unsigned)(len+1));
- memmove(stats_temp_file, value, (unsigned)len);
-#if !defined(VMS)
- memmove(stats_temp_file + len, ".TEMP",
- sizeof(".TEMP"));
-#else
- memmove(stats_temp_file + len, "-TEMP",
- sizeof("-TEMP"));
-#endif /* VMS */
+ stats_drift_file = erealloc(stats_drift_file, len + 1);
+ stats_temp_file = erealloc(stats_temp_file,
+ len + sizeof(".TEMP"));
+
+ memcpy(stats_drift_file, value, (unsigned)(len+1));
+ memcpy(stats_temp_file, value, (unsigned)len);
+ memcpy(stats_temp_file + len, temp_ext,
+ sizeof(temp_ext));
/*
* Open drift file and read frequency. If the file is
* missing or contains errors, tell the loop to reset.
*/
- if ((fp = fopen(stats_drift_file, "r")) == NULL) {
- old_drift = 1e9;
+ if ((fp = fopen(stats_drift_file, "r")) == NULL)
break;
- }
+
if (fscanf(fp, "%lf", &old_drift) != 1) {
- msyslog(LOG_ERR, "Frequency format error in %s",
- stats_drift_file);
- old_drift = 1e9;
+ msyslog(LOG_ERR,
+ "format error frequency file %s",
+ stats_drift_file);
fclose(fp);
break;
+
}
fclose(fp);
- prev_drift_comp = old_drift / 1e6;
- msyslog(LOG_INFO,
- "frequency initialized %.3f PPM from %s",
- old_drift, stats_drift_file);
+ old_drift /= 1e6;
+ prev_drift_comp = old_drift;
break;
-
- case STATS_STATSDIR:
+
+ /*
+ * Specify statistics directory.
+ */
+ case STATS_STATSDIR:
+
+ /*
+ * HMS: the following test is insufficient:
+ * - value may be missing the DIR_SEP
+ * - we still need the filename after it
+ */
if (strlen(value) >= sizeof(statsdir)) {
msyslog(LOG_ERR,
- "value for statsdir too long (>%d, sigh)",
- (int)sizeof(statsdir)-1);
+ "statsdir too long (>%d, sigh)",
+ (int)sizeof(statsdir) - 1);
} else {
l_fp now;
+ int add_dir_sep;
+ int value_l = strlen(value);
+
+ /* Add a DIR_SEP unless we already have one. */
+ if (value_l == 0)
+ add_dir_sep = 0;
+ else
+ add_dir_sep = (DIR_SEP !=
+ value[value_l - 1]);
+
+ if (add_dir_sep)
+ snprintf(statsdir, sizeof(statsdir),
+ "%s%c", value, DIR_SEP);
+ else
+ snprintf(statsdir, sizeof(statsdir),
+ "%s", value);
get_systime(&now);
- strcpy(statsdir,value);
if(peerstats.prefix == &statsdir[0] &&
peerstats.fp != NULL) {
fclose(peerstats.fp);
@@ -397,6 +504,12 @@ stats_config(
sysstats.fp = NULL;
filegen_setup(&sysstats, now.l_ui);
}
+ if(protostats.prefix == &statsdir[0] &&
+ protostats.fp != NULL) {
+ fclose(protostats.fp);
+ protostats.fp = NULL;
+ filegen_setup(&protostats, now.l_ui);
+ }
#ifdef OPENSSL
if(cryptostats.prefix == &statsdir[0] &&
cryptostats.fp != NULL) {
@@ -405,45 +518,83 @@ stats_config(
filegen_setup(&cryptostats, now.l_ui);
}
#endif /* OPENSSL */
+#ifdef DEBUG_TIMING
+ if(timingstats.prefix == &statsdir[0] &&
+ timingstats.fp != NULL) {
+ fclose(timingstats.fp);
+ timingstats.fp = NULL;
+ filegen_setup(&timingstats, now.l_ui);
+ }
+#endif /* DEBUG_TIMING */
}
break;
- case STATS_PID_FILE:
+ /*
+ * Open pid file.
+ */
+ case STATS_PID_FILE:
if ((fp = fopen(value, "w")) == NULL) {
- msyslog(LOG_ERR, "Can't open %s: %m", value);
+ msyslog(LOG_ERR, "pid file %s: %m",
+ value);
break;
}
- fprintf(fp, "%d", (int) getpid());
+ fprintf(fp, "%d", (int)getpid());
fclose(fp);;
break;
- default:
+ /*
+ * Read leapseconds file.
+ */
+ case STATS_LEAP_FILE:
+ if ((fp = fopen(value, "r")) == NULL) {
+ msyslog(LOG_ERR, "leapseconds file %s: %m",
+ value);
+ break;
+ }
+
+ if (leap_file(fp) < 0) {
+ msyslog(LOG_ERR,
+ "format error leapseconds file %s",
+ value);
+ } else {
+ strcpy(str1, fstostr(leap_sec));
+ strcpy(str2, fstostr(leap_expire));
+ snprintf(tbuf, sizeof(tbuf),
+ "%d leap %s expire %s", leap_tai, str1,
+ str2);
+ report_event(EVNT_TAI, NULL, tbuf);
+ }
+ fclose(fp);
+ break;
+
+ default:
/* oh well */
break;
}
}
+
/*
* record_peer_stats - write peer statistics to file
*
* file format:
- * day (mjd)
+ * day (MJD)
* time (s past UTC midnight)
- * peer (ip address)
- * peer status word (hex)
- * peer offset (s)
- * peer delay (s)
- * peer error bound (s)
- * peer error (s)
+ * IP address
+ * status word (hex)
+ * offset
+ * delay
+ * dispersion
+ * jitter
*/
void
record_peer_stats(
- struct sockaddr_storage *addr,
+ sockaddr_u *addr,
int status,
- double offset,
- double delay,
- double dispersion,
- double skew
+ double offset, /* offset */
+ double delay, /* delay */
+ double dispersion, /* dispersion */
+ double jitter /* jitter */
)
{
l_fp now;
@@ -458,29 +609,32 @@ record_peer_stats(
now.l_ui %= 86400;
if (peerstats.fp != NULL) {
fprintf(peerstats.fp,
- "%lu %s %s %x %.9f %.9f %.9f %.9f\n",
- day, ulfptoa(&now, 3), stoa(addr), status, offset,
- delay, dispersion, skew);
+ "%lu %s %s %x %.9f %.9f %.9f %.9f\n", day,
+ ulfptoa(&now, 3), stoa(addr), status, offset,
+ delay, dispersion, jitter);
fflush(peerstats.fp);
}
}
+
/*
* record_loop_stats - write loop filter statistics to file
*
* file format:
- * day (mjd)
+ * day (MJD)
* time (s past midnight)
- * offset (s)
- * frequency (approx ppm)
- * time constant (log base 2)
+ * offset
+ * frequency (PPM)
+ * jitter
+ * wnder (PPM)
+ * time constant (log2)
*/
void
record_loop_stats(
- double offset,
- double freq,
- double jitter,
- double stability,
+ double offset, /* offset */
+ double freq, /* frequency (PPM) */
+ double jitter, /* jitter */
+ double wander, /* wander (PPM) */
int spoll
)
{
@@ -497,24 +651,25 @@ record_loop_stats(
if (loopstats.fp != NULL) {
fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n",
day, ulfptoa(&now, 3), offset, freq * 1e6, jitter,
- stability * 1e6, spoll);
+ wander * 1e6, spoll);
fflush(loopstats.fp);
}
}
+
/*
* record_clock_stats - write clock statistics to file
*
* file format:
- * day (mjd)
+ * day (MJD)
* time (s past midnight)
- * peer (ip address)
+ * IP address
* text message
*/
void
record_clock_stats(
- struct sockaddr_storage *addr,
- const char *text
+ sockaddr_u *addr,
+ const char *text /* timecode string */
)
{
l_fp now;
@@ -528,30 +683,31 @@ record_clock_stats(
day = now.l_ui / 86400 + MJD_1900;
now.l_ui %= 86400;
if (clockstats.fp != NULL) {
- fprintf(clockstats.fp, "%lu %s %s %s\n",
- day, ulfptoa(&now, 3), stoa(addr), text);
+ fprintf(clockstats.fp, "%lu %s %s %s\n", day,
+ ulfptoa(&now, 3), stoa(addr), text);
fflush(clockstats.fp);
}
}
+
/*
* record_raw_stats - write raw timestamps to file
*
- *
* file format
+ * day (MJD)
* time (s past midnight)
* peer ip address
- * local ip address
+ * IP address
* t1 t2 t3 t4 timestamps
*/
void
record_raw_stats(
- struct sockaddr_storage *srcadr,
- struct sockaddr_storage *dstadr,
- l_fp *t1,
- l_fp *t2,
- l_fp *t3,
- l_fp *t4
+ sockaddr_u *srcadr,
+ sockaddr_u *dstadr,
+ l_fp *t1, /* originate timestamp */
+ l_fp *t2, /* receive timestamp */
+ l_fp *t3, /* transmit timestamp */
+ l_fp *t4 /* destination timestamp */
)
{
l_fp now;
@@ -565,10 +721,10 @@ record_raw_stats(
day = now.l_ui / 86400 + MJD_1900;
now.l_ui %= 86400;
if (rawstats.fp != NULL) {
- fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n",
- day, ulfptoa(&now, 3), stoa(srcadr), dstadr ? stoa(dstadr) : "-",
- ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9),
- ulfptoa(t4, 9));
+ fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n", day,
+ ulfptoa(&now, 3), stoa(srcadr), dstadr ?
+ stoa(dstadr) : "-", ulfptoa(t1, 9), ulfptoa(t2, 9),
+ ulfptoa(t3, 9), ulfptoa(t4, 9));
fflush(rawstats.fp);
}
}
@@ -578,17 +734,19 @@ record_raw_stats(
* record_sys_stats - write system statistics to file
*
* file format
+ * day (MJD)
* time (s past midnight)
- * time since startup (hr)
+ * time since reset
* packets recieved
- * packets processed
+ * packets for this host
* current version
- * previous version
- * bad version
+ * old version
* access denied
* bad length or format
* bad authentication
+ * declined
* rate exceeded
+ * KoD sent
*/
void
record_sys_stats(void)
@@ -604,19 +762,50 @@ record_sys_stats(void)
day = now.l_ui / 86400 + MJD_1900;
now.l_ui %= 86400;
if (sysstats.fp != NULL) {
- fprintf(sysstats.fp,
- "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
- day, ulfptoa(&now, 3), sys_stattime / 3600,
- sys_received, sys_processed, sys_newversionpkt,
- sys_oldversionpkt, sys_unknownversion,
- sys_restricted, sys_badlength, sys_badauth,
- sys_limitrejected);
+ fprintf(sysstats.fp,
+ "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ day, ulfptoa(&now, 3), current_time - sys_stattime,
+ sys_received, sys_processed, sys_newversion,
+ sys_oldversion, sys_restricted, sys_badlength,
+ sys_badauth, sys_declined, sys_limitrejected,
+ sys_kodsent);
fflush(sysstats.fp);
proto_clr_stats();
}
}
+/*
+ * record_proto_stats - write system statistics to file
+ *
+ * file format
+ * day (MJD)
+ * time (s past midnight)
+ * text message
+ */
+void
+record_proto_stats(
+ char *str /* text string */
+ )
+{
+ l_fp now;
+ u_long day;
+
+ if (!stats_control)
+ return;
+
+ get_systime(&now);
+ filegen_setup(&protostats, now.l_ui);
+ day = now.l_ui / 86400 + MJD_1900;
+ now.l_ui %= 86400;
+ if (protostats.fp != NULL) {
+ fprintf(protostats.fp, "%lu %s %s\n", day,
+ ulfptoa(&now, 3), str);
+ fflush(protostats.fp);
+ }
+}
+
+
#ifdef OPENSSL
/*
* record_crypto_stats - write crypto statistics to file
@@ -624,13 +813,13 @@ record_sys_stats(void)
* file format:
* day (mjd)
* time (s past midnight)
- * peer (ip address)
+ * peer ip address
* text message
*/
void
record_crypto_stats(
- struct sockaddr_storage *addr,
- const char *text
+ sockaddr_u *addr,
+ const char *text /* text message */
)
{
l_fp now;
@@ -645,7 +834,7 @@ record_crypto_stats(
now.l_ui %= 86400;
if (cryptostats.fp != NULL) {
if (addr == NULL)
- fprintf(cryptostats.fp, "%lu %s %s\n",
+ fprintf(cryptostats.fp, "%lu %s 0.0.0.0 %s\n",
day, ulfptoa(&now, 3), text);
else
fprintf(cryptostats.fp, "%lu %s %s %s\n",
@@ -655,9 +844,10 @@ record_crypto_stats(
}
#endif /* OPENSSL */
+
#ifdef DEBUG_TIMING
/*
- * record_crypto_stats - write crypto statistics to file
+ * record_timing_stats - write timing statistics to file
*
* file format:
* day (mjd)
@@ -666,7 +856,7 @@ record_crypto_stats(
*/
void
record_timing_stats(
- const char *text
+ const char *text /* text message */
)
{
static unsigned int flshcnt;
@@ -681,13 +871,140 @@ record_timing_stats(
day = now.l_ui / 86400 + MJD_1900;
now.l_ui %= 86400;
if (timingstats.fp != NULL) {
- fprintf(timingstats.fp, "%lu %s %s\n",
- day, lfptoa(&now, 3), text);
+ fprintf(timingstats.fp, "%lu %s %s\n", day, lfptoa(&now,
+ 3), text);
if (++flshcnt % 100 == 0)
fflush(timingstats.fp);
}
}
#endif
+
+
+/*
+ * leap_file - read leapseconds file
+ *
+ * Read the ERTS leapsecond file in NIST text format and extract the
+ * NTP seconds of the latest leap and TAI offset after the leap.
+ */
+static int
+leap_file(
+ FILE *fp /* file handle */
+ )
+{
+ char buf[NTP_MAXSTRLEN]; /* file line buffer */
+ u_long leap; /* NTP time at leap */
+ u_long expire; /* NTP time when file expires */
+ int offset; /* TAI offset at leap (s) */
+ int i;
+
+ /*
+ * Read and parse the leapseconds file. Empty lines and comments
+ * are ignored. A line beginning with #@ contains the file
+ * expiration time in NTP seconds. Other lines begin with two
+ * integers followed by junk or comments. The first integer is
+ * the NTP seconds at the leap, the second is the TAI offset
+ * after the leap.
+ */
+ offset = 0;
+ leap = 0;
+ expire = 0;
+ i = 10;
+ while (fgets(buf, NTP_MAXSTRLEN - 1, fp) != NULL) {
+ if (strlen(buf) < 1)
+ continue;
+
+ if (buf[0] == '#') {
+ if (strlen(buf) < 3)
+ continue;
+
+ /*
+ * Note the '@' flag was used only in the 2006
+ * table; previious to that the flag was '$'.
+ */
+ if (buf[1] == '@' || buf[1] == '$') {
+ if (sscanf(&buf[2], "%lu", &expire) !=
+ 1)
+ return (-1);
+
+ continue;
+ }
+ }
+ if (sscanf(buf, "%lu %d", &leap, &offset) == 2) {
+
+ /*
+ * Valid offsets must increase by one for each
+ * leap.
+ */
+ if (i++ != offset)
+ return (-1);
+ }
+ }
+
+ /*
+ * There must be at least one leap.
+ */
+ if (i == 10)
+ return (-1);
+
+ leap_tai = offset;
+ leap_sec = leap;
+ leap_expire = expire;
+ return (0);
+}
+
+
+/*
+ * leap_month - returns seconds until the end of the month.
+ */
+u_long
+leap_month(
+ u_long sec /* current NTP second */
+ )
+{
+ u_long ltemp;
+ u_long *ptr;
+ u_long year[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
+ 31};
+ u_long lyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30,
+ 31};
+
+ /*
+ * Find current leap cycle.
+ */
+ ltemp = sec;
+ while (ltemp >= L_CENT)
+ ltemp -= L_CENT;
+ while (ltemp >= L_4YEAR)
+ ltemp -= L_4YEAR;
+
+ /*
+ * We are within four years of the target. If in leap year, use
+ * leap year month table; otherwise, use year month table.
+ */
+ if (ltemp < L_LYEAR) {
+ ptr = lyear;
+ } else {
+ ptr = year;
+ ltemp -= L_LYEAR;
+ while (ltemp >= L_YEAR)
+ ltemp -= L_YEAR;
+ }
+
+ /*
+ * We are within one year of the target. Find the month of the
+ * leap.
+ */
+ while (ltemp >= *ptr * L_DAY)
+ ltemp -= *ptr++ * L_DAY;
+
+ /*
+ * The result is the number of seconds until the end of the
+ * month when the leap is to occur.
+ */
+ return (*ptr * L_DAY - ltemp - L_DAY);
+}
+
+
/*
* getauthkeys - read the authentication keys from the specified file
*/
@@ -699,30 +1016,21 @@ getauthkeys(
int len;
len = strlen(keyfile);
- if (len == 0)
+ if (!len)
return;
- if (key_file_name != 0) {
- if (len > (int)strlen(key_file_name)) {
- (void) free(key_file_name);
- key_file_name = 0;
- }
- }
-
- if (key_file_name == 0) {
#ifndef SYS_WINNT
- key_file_name = (char*)emalloc((u_int) (len + 1));
+ key_file_name = erealloc(key_file_name, len + 1);
+ memmove(key_file_name, keyfile, len + 1);
#else
- key_file_name = (char*)emalloc((u_int) (MAXPATHLEN));
-#endif
- }
-#ifndef SYS_WINNT
- memmove(key_file_name, keyfile, (unsigned)(len+1));
-#else
- if (!ExpandEnvironmentStrings(keyfile, key_file_name, MAXPATHLEN))
- {
+ key_file_name = erealloc(key_file_name, _MAX_PATH);
+ if (len + 1 > _MAX_PATH)
+ return;
+ if (!ExpandEnvironmentStrings(keyfile, key_file_name,
+ _MAX_PATH)) {
msyslog(LOG_ERR,
- "ExpandEnvironmentStrings(KEY_FILE) failed: %m\n");
+ "ExpandEnvironmentStrings(KEY_FILE) failed: %m");
+ strncpy(key_file_name, keyfile, _MAX_PATH);
}
#endif /* SYS_WINNT */
@@ -736,58 +1044,58 @@ getauthkeys(
void
rereadkeys(void)
{
- if (key_file_name != 0)
- authreadkeys(key_file_name);
+ if (NULL != key_file_name)
+ authreadkeys(key_file_name);
}
+
/*
- * sock_hash - hash an sockaddr_storage structure
+ * sock_hash - hash a sockaddr_u structure
*/
-int
+u_short
sock_hash(
- struct sockaddr_storage *addr
+ sockaddr_u *addr
)
{
- int hashVal;
- int i;
- int len;
- char *ch;
-
+ u_int hashVal;
+ u_int j;
+ size_t len;
+ u_char *pch;
hashVal = 0;
len = 0;
+
/*
* We can't just hash the whole thing because there are hidden
* fields in sockaddr_in6 that might be filled in by recvfrom(),
* so just use the family, port and address.
*/
- ch = (char *)&addr->ss_family;
- hashVal = 37 * hashVal + (int)*ch;
- if (sizeof(addr->ss_family) > 1) {
- ch++;
- hashVal = 37 * hashVal + (int)*ch;
+ pch = (u_char *)&AF(addr);
+ hashVal = 37 * hashVal + *pch;
+ if (sizeof(AF(addr)) > 1) {
+ pch++;
+ hashVal = 37 * hashVal + *pch;
}
- switch(addr->ss_family) {
+ switch(AF(addr)) {
case AF_INET:
- ch = (char *)&((struct sockaddr_in *)addr)->sin_addr;
- len = sizeof(struct in_addr);
+ pch = (u_char *)&SOCK_ADDR4(addr);
+ len = sizeof(SOCK_ADDR4(addr));
break;
+
case AF_INET6:
- ch = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
- len = sizeof(struct in6_addr);
+ pch = (u_char *)&SOCK_ADDR6(addr);
+ len = sizeof(SOCK_ADDR6(addr));
break;
}
- for (i = 0; i < len ; i++)
- hashVal = 37 * hashVal + (int)*(ch + i);
-
- hashVal = hashVal % 128; /* % MON_HASH_SIZE hardcoded */
+ for (j = 0; j < len ; j++)
+ hashVal = 37 * hashVal + pch[j];
- if (hashVal < 0)
- hashVal += 128;
+ hashVal = hashVal & NTP_HASH_MASK;
- return hashVal;
+ return (u_short)hashVal;
}
+
#if notyet
/*
* ntp_exit - document explicitly that ntpd has exited
@@ -795,7 +1103,31 @@ sock_hash(
void
ntp_exit(int retval)
{
- msyslog(LOG_ERR, "EXITING with return code %d", retval);
- exit(retval);
+ msyslog(LOG_ERR, "EXITING with return code %d", retval);
+ exit(retval);
}
#endif
+
+/*
+ * fstostr - prettyprint NTP seconds
+ */
+char * fstostr(
+ time_t ntp_stamp
+ )
+{
+ static char str[20];
+ struct tm * tm;
+ time_t unix_stamp;
+
+ unix_stamp = ntp_stamp - JAN_1970;
+ tm = gmtime(&unix_stamp);
+ if (NULL != tm)
+ snprintf(str, sizeof(str),
+ "%04d%02d%02d%02d%02d",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min);
+ else
+ strcpy(str, "gmtime() error");
+
+ return str;
+}
diff --git a/ntpd/ntpd-opts.c b/ntpd/ntpd-opts.c
index 4d23d6674276..d5989bffde0f 100644
--- a/ntpd/ntpd-opts.c
+++ b/ntpd/ntpd-opts.c
@@ -1,31 +1,31 @@
/*
* EDIT THIS FILE WITH CAUTION (ntpd-opts.c)
*
- * It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:10 AM EST
+ * It has been AutoGen-ed December 24, 2011 at 06:34:01 PM by AutoGen 5.12
* From the definitions ntpd-opts.def
* and the template file options
*
- * Generated from AutoOpts 29:0:4 templates.
- */
-
-/*
- * This file was produced by an AutoOpts template. AutoOpts is a
- * copyrighted work. This source file is not encumbered by AutoOpts
- * licensing, but is provided under the licensing terms chosen by the
- * ntpd author or copyright holder. AutoOpts is licensed under
- * the terms of the LGPL. The redistributable library (``libopts'') is
- * licensed under the terms of either the LGPL or, at the users discretion,
- * the BSD license. See the AutoOpts and/or libopts sources for details.
+ * Generated from AutoOpts 35:0:10 templates.
*
- * This source file is copyrighted and licensed under the following terms:
+ * AutoOpts is a copyrighted work. This source file is not encumbered
+ * by AutoOpts licensing, but is provided under the licensing terms chosen
+ * by the ntpd author or copyright holder. AutoOpts is
+ * licensed under the terms of the LGPL. The redistributable library
+ * (``libopts'') is licensed under the terms of either the LGPL or, at the
+ * users discretion, the BSD license. See the AutoOpts and/or libopts sources
+ * for details.
*
- * ntpd copyright 1970-2009 David L. Mills and/or others - all rights reserved
+ * This source file is copyrighted and licensed under the following terms:
*
- * see html/copyright.html
+ * see html/copyright.html
+ *
*/
+#include <sys/types.h>
#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
#define OPTION_CODE_COMPILE 1
#include "ntpd-opts.h"
@@ -33,19 +33,23 @@
#ifdef __cplusplus
extern "C" {
#endif
-tSCC zCopyright[] =
- "ntpd copyright (c) 1970-2009 David L. Mills and/or others, all rights reserved";
-tSCC zCopyrightNotice[] =
-
-/* extracted from ../include/copyright.def near line 8 */
-"see html/copyright.html";
+extern FILE * option_usage_fp;
+
+/* TRANSLATORS: choose the translation for option names wisely because you
+ cannot ever change your mind. */
+static char const zCopyright[38] =
+"ntpd 4.2.6p5\n\
+see html/copyright.html\n";
+static char const zLicenseDescrip[25] =
+"see html/copyright.html\n";
+
extern tUsageProc optionUsage;
/*
* global included definitions
*/
#ifdef __windows
- extern int atoi(const char*);
+ extern int atoi(const char *);
#else
# include <stdlib.h>
#endif
@@ -53,38 +57,41 @@ extern tUsageProc optionUsage;
#ifndef NULL
# define NULL 0
#endif
-#ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-#endif
-#ifndef EXIT_FAILURE
-# define EXIT_FAILURE 1
-#endif
+
/*
- * Ipv4 option description:
+ * Ipv4 option description with
+ * "Must also have options" and "Incompatible options":
*/
-tSCC zIpv4Text[] =
+static char const zIpv4Text[] =
"Force IPv4 DNS name resolution";
-tSCC zIpv4_NAME[] = "IPV4";
-tSCC zIpv4_Name[] = "ipv4";
+static char const zIpv4_NAME[] = "IPV4";
+static char const zIpv4_Name[] = "ipv4";
+static const int
+ aIpv4CantList[] = {
+ INDEX_OPT_IPV6, NO_EQUIVALENT };
#define IPV4_FLAGS (OPTST_DISABLED)
/*
- * Ipv6 option description:
+ * Ipv6 option description with
+ * "Must also have options" and "Incompatible options":
*/
-tSCC zIpv6Text[] =
+static char const zIpv6Text[] =
"Force IPv6 DNS name resolution";
-tSCC zIpv6_NAME[] = "IPV6";
-tSCC zIpv6_Name[] = "ipv6";
+static char const zIpv6_NAME[] = "IPV6";
+static char const zIpv6_Name[] = "ipv6";
+static const int
+ aIpv6CantList[] = {
+ INDEX_OPT_IPV4, NO_EQUIVALENT };
#define IPV6_FLAGS (OPTST_DISABLED)
/*
* Authreq option description with
* "Must also have options" and "Incompatible options":
*/
-tSCC zAuthreqText[] =
+static char const zAuthreqText[] =
"Require crypto authentication";
-tSCC zAuthreq_NAME[] = "AUTHREQ";
-tSCC zAuthreq_Name[] = "authreq";
+static char const zAuthreq_NAME[] = "AUTHREQ";
+static char const zAuthreq_Name[] = "authreq";
static const int
aAuthreqCantList[] = {
INDEX_OPT_AUTHNOREQ, NO_EQUIVALENT };
@@ -94,10 +101,10 @@ static const int
* Authnoreq option description with
* "Must also have options" and "Incompatible options":
*/
-tSCC zAuthnoreqText[] =
+static char const zAuthnoreqText[] =
"Do not require crypto authentication";
-tSCC zAuthnoreq_NAME[] = "AUTHNOREQ";
-tSCC zAuthnoreq_Name[] = "authnoreq";
+static char const zAuthnoreq_NAME[] = "AUTHNOREQ";
+static char const zAuthnoreq_Name[] = "authnoreq";
static const int
aAuthnoreqCantList[] = {
INDEX_OPT_AUTHREQ, NO_EQUIVALENT };
@@ -106,19 +113,19 @@ static const int
/*
* Bcastsync option description:
*/
-tSCC zBcastsyncText[] =
+static char const zBcastsyncText[] =
"Allow us to sync to broadcast servers";
-tSCC zBcastsync_NAME[] = "BCASTSYNC";
-tSCC zBcastsync_Name[] = "bcastsync";
+static char const zBcastsync_NAME[] = "BCASTSYNC";
+static char const zBcastsync_Name[] = "bcastsync";
#define BCASTSYNC_FLAGS (OPTST_DISABLED)
/*
* Configfile option description:
*/
-tSCC zConfigfileText[] =
+static char const zConfigfileText[] =
"configuration file name";
-tSCC zConfigfile_NAME[] = "CONFIGFILE";
-tSCC zConfigfile_Name[] = "configfile";
+static char const zConfigfile_NAME[] = "CONFIGFILE";
+static char const zConfigfile_Name[] = "configfile";
#define CONFIGFILE_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
@@ -126,262 +133,340 @@ tSCC zConfigfile_Name[] = "configfile";
* Debug_Level option description:
*/
#ifdef DEBUG
-tSCC zDebug_LevelText[] =
+static char const zDebug_LevelText[] =
"Increase output debug message level";
-tSCC zDebug_Level_NAME[] = "DEBUG_LEVEL";
-tSCC zDebug_Level_Name[] = "debug-level";
+static char const zDebug_Level_NAME[] = "DEBUG_LEVEL";
+static char const zDebug_Level_Name[] = "debug-level";
#define DEBUG_LEVEL_FLAGS (OPTST_DISABLED)
#else /* disable Debug_Level */
-#define VALUE_OPT_DEBUG_LEVEL NO_EQUIVALENT
#define DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
-#define zDebug_LevelText NULL
#define zDebug_Level_NAME NULL
-#define zDebug_Level_Name NULL
+static char const zDebug_Level_Name[] = "debug-level";
+static char const zDebug_LevelText[] = "this package was built using 'configure --disable--debug'";
#endif /* DEBUG */
/*
* Set_Debug_Level option description:
*/
#ifdef DEBUG
-tSCC zSet_Debug_LevelText[] =
+static char const zSet_Debug_LevelText[] =
"Set the output debug message level";
-tSCC zSet_Debug_Level_NAME[] = "SET_DEBUG_LEVEL";
-tSCC zSet_Debug_Level_Name[] = "set-debug-level";
+static char const zSet_Debug_Level_NAME[] = "SET_DEBUG_LEVEL";
+static char const zSet_Debug_Level_Name[] = "set-debug-level";
#define SET_DEBUG_LEVEL_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
#else /* disable Set_Debug_Level */
-#define VALUE_OPT_SET_DEBUG_LEVEL NO_EQUIVALENT
#define SET_DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
-#define zSet_Debug_LevelText NULL
#define zSet_Debug_Level_NAME NULL
-#define zSet_Debug_Level_Name NULL
+static char const zSet_Debug_Level_Name[] = "set-debug-level";
+static char const zSet_Debug_LevelText[] = "this package was built using 'configure --disable--debug'";
#endif /* DEBUG */
/*
* Driftfile option description:
*/
-tSCC zDriftfileText[] =
+static char const zDriftfileText[] =
"frequency drift file name";
-tSCC zDriftfile_NAME[] = "DRIFTFILE";
-tSCC zDriftfile_Name[] = "driftfile";
+static char const zDriftfile_NAME[] = "DRIFTFILE";
+static char const zDriftfile_Name[] = "driftfile";
#define DRIFTFILE_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Panicgate option description:
*/
-tSCC zPanicgateText[] =
+static char const zPanicgateText[] =
"Allow the first adjustment to be Big";
-tSCC zPanicgate_NAME[] = "PANICGATE";
-tSCC zPanicgate_Name[] = "panicgate";
+static char const zPanicgate_NAME[] = "PANICGATE";
+static char const zPanicgate_Name[] = "panicgate";
#define PANICGATE_FLAGS (OPTST_DISABLED)
/*
* Jaildir option description:
*/
-tSCC zJaildirText[] =
+#ifdef HAVE_DROPROOT
+static char const zJaildirText[] =
"Jail directory";
-tSCC zJaildir_NAME[] = "JAILDIR";
-tSCC zJaildir_Name[] = "jaildir";
+static char const zJaildir_NAME[] = "JAILDIR";
+static char const zJaildir_Name[] = "jaildir";
#define JAILDIR_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+#else /* disable Jaildir */
+#define JAILDIR_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zJaildir_NAME NULL
+static char const zJaildir_Name[] = "jaildir";
+static char const zJaildirText[] = "built without --enable-clockctl or --enable-linuxcaps";
+#endif /* HAVE_DROPROOT */
+
/*
* Interface option description:
*/
-tSCC zInterfaceText[] =
- "Listen on interface";
-tSCC zInterface_NAME[] = "INTERFACE";
-tSCC zInterface_Name[] = "interface";
+static char const zInterfaceText[] =
+ "Listen on an interface name or address";
+static char const zInterface_NAME[] = "INTERFACE";
+static char const zInterface_Name[] = "interface";
#define INTERFACE_FLAGS (OPTST_DISABLED | OPTST_STACKED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Keyfile option description:
*/
-tSCC zKeyfileText[] =
+static char const zKeyfileText[] =
"path to symmetric keys";
-tSCC zKeyfile_NAME[] = "KEYFILE";
-tSCC zKeyfile_Name[] = "keyfile";
+static char const zKeyfile_NAME[] = "KEYFILE";
+static char const zKeyfile_Name[] = "keyfile";
#define KEYFILE_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Logfile option description:
*/
-tSCC zLogfileText[] =
+static char const zLogfileText[] =
"path to the log file";
-tSCC zLogfile_NAME[] = "LOGFILE";
-tSCC zLogfile_Name[] = "logfile";
+static char const zLogfile_NAME[] = "LOGFILE";
+static char const zLogfile_Name[] = "logfile";
#define LOGFILE_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Novirtualips option description:
*/
-tSCC zNovirtualipsText[] =
- "Do not listen to virtual IPs";
-tSCC zNovirtualips_NAME[] = "NOVIRTUALIPS";
-tSCC zNovirtualips_Name[] = "novirtualips";
+static char const zNovirtualipsText[] =
+ "Do not listen to virtual interfaces";
+static char const zNovirtualips_NAME[] = "NOVIRTUALIPS";
+static char const zNovirtualips_Name[] = "novirtualips";
#define NOVIRTUALIPS_FLAGS (OPTST_DISABLED)
/*
* Modifymmtimer option description:
*/
#ifdef SYS_WINNT
-tSCC zModifymmtimerText[] =
+static char const zModifymmtimerText[] =
"Modify Multimedia Timer (Windows only)";
-tSCC zModifymmtimer_NAME[] = "MODIFYMMTIMER";
-tSCC zModifymmtimer_Name[] = "modifymmtimer";
+static char const zModifymmtimer_NAME[] = "MODIFYMMTIMER";
+static char const zModifymmtimer_Name[] = "modifymmtimer";
#define MODIFYMMTIMER_FLAGS (OPTST_DISABLED)
#else /* disable Modifymmtimer */
-#define VALUE_OPT_MODIFYMMTIMER NO_EQUIVALENT
#define MODIFYMMTIMER_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
-#define zModifymmtimerText NULL
#define zModifymmtimer_NAME NULL
+#define zModifymmtimerText NULL
#define zModifymmtimer_Name NULL
#endif /* SYS_WINNT */
/*
* Nofork option description:
*/
-tSCC zNoforkText[] =
+static char const zNoforkText[] =
"Do not fork";
-tSCC zNofork_NAME[] = "NOFORK";
-tSCC zNofork_Name[] = "nofork";
+static char const zNofork_NAME[] = "NOFORK";
+static char const zNofork_Name[] = "nofork";
#define NOFORK_FLAGS (OPTST_DISABLED)
/*
* Nice option description:
*/
-tSCC zNiceText[] =
+static char const zNiceText[] =
"Run at high priority";
-tSCC zNice_NAME[] = "NICE";
-tSCC zNice_Name[] = "nice";
+static char const zNice_NAME[] = "NICE";
+static char const zNice_Name[] = "nice";
#define NICE_FLAGS (OPTST_DISABLED)
/*
* Pidfile option description:
*/
-tSCC zPidfileText[] =
+static char const zPidfileText[] =
"path to the PID file";
-tSCC zPidfile_NAME[] = "PIDFILE";
-tSCC zPidfile_Name[] = "pidfile";
+static char const zPidfile_NAME[] = "PIDFILE";
+static char const zPidfile_Name[] = "pidfile";
#define PIDFILE_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Priority option description:
*/
-tSCC zPriorityText[] =
+static char const zPriorityText[] =
"Process priority";
-tSCC zPriority_NAME[] = "PRIORITY";
-tSCC zPriority_Name[] = "priority";
+static char const zPriority_NAME[] = "PRIORITY";
+static char const zPriority_Name[] = "priority";
#define PRIORITY_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
/*
* Quit option description:
*/
-tSCC zQuitText[] =
+static char const zQuitText[] =
"Set the time and quit";
-tSCC zQuit_NAME[] = "QUIT";
-tSCC zQuit_Name[] = "quit";
+static char const zQuit_NAME[] = "QUIT";
+static char const zQuit_Name[] = "quit";
#define QUIT_FLAGS (OPTST_DISABLED)
/*
* Propagationdelay option description:
*/
-tSCC zPropagationdelayText[] =
+static char const zPropagationdelayText[] =
"Broadcast/propagation delay";
-tSCC zPropagationdelay_NAME[] = "PROPAGATIONDELAY";
-tSCC zPropagationdelay_Name[] = "propagationdelay";
+static char const zPropagationdelay_NAME[] = "PROPAGATIONDELAY";
+static char const zPropagationdelay_Name[] = "propagationdelay";
#define PROPAGATIONDELAY_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
- * Updateinterval option description:
+ * Saveconfigquit option description:
*/
-tSCC zUpdateintervalText[] =
- "interval in seconds between scans for new or dropped interfaces";
-tSCC zUpdateinterval_NAME[] = "UPDATEINTERVAL";
-tSCC zUpdateinterval_Name[] = "updateinterval";
-#define UPDATEINTERVAL_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+#ifdef SAVECONFIG
+static char const zSaveconfigquitText[] =
+ "Save parsed configuration and quit";
+static char const zSaveconfigquit_NAME[] = "SAVECONFIGQUIT";
+static char const zSaveconfigquit_Name[] = "saveconfigquit";
+#define SAVECONFIGQUIT_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else /* disable Saveconfigquit */
+#define SAVECONFIGQUIT_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zSaveconfigquit_NAME NULL
+#define zSaveconfigquitText NULL
+#define zSaveconfigquit_Name NULL
+#endif /* SAVECONFIG */
/*
* Statsdir option description:
*/
-tSCC zStatsdirText[] =
+static char const zStatsdirText[] =
"Statistics file location";
-tSCC zStatsdir_NAME[] = "STATSDIR";
-tSCC zStatsdir_Name[] = "statsdir";
+static char const zStatsdir_NAME[] = "STATSDIR";
+static char const zStatsdir_Name[] = "statsdir";
#define STATSDIR_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Trustedkey option description:
*/
-tSCC zTrustedkeyText[] =
+static char const zTrustedkeyText[] =
"Trusted key number";
-tSCC zTrustedkey_NAME[] = "TRUSTEDKEY";
-tSCC zTrustedkey_Name[] = "trustedkey";
+static char const zTrustedkey_NAME[] = "TRUSTEDKEY";
+static char const zTrustedkey_Name[] = "trustedkey";
#define TRUSTEDKEY_FLAGS (OPTST_DISABLED | OPTST_STACKED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* User option description:
*/
-tSCC zUserText[] =
+#ifdef HAVE_DROPROOT
+static char const zUserText[] =
"Run as userid (or userid:groupid)";
-tSCC zUser_NAME[] = "USER";
-tSCC zUser_Name[] = "user";
+static char const zUser_NAME[] = "USER";
+static char const zUser_Name[] = "user";
#define USER_FLAGS (OPTST_DISABLED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+#else /* disable User */
+#define USER_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zUser_NAME NULL
+static char const zUser_Name[] = "user";
+static char const zUserText[] = "built without --enable-clockctl or --enable-linuxcaps";
+#endif /* HAVE_DROPROOT */
+
+/*
+ * Updateinterval option description:
+ */
+static char const zUpdateintervalText[] =
+ "interval in seconds between scans for new or dropped interfaces";
+static char const zUpdateinterval_NAME[] = "UPDATEINTERVAL";
+static char const zUpdateinterval_Name[] = "updateinterval";
+#define UPDATEINTERVAL_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
/*
* Var option description:
*/
-tSCC zVarText[] =
+static char const zVarText[] =
"make ARG an ntp variable (RW)";
-tSCC zVar_NAME[] = "VAR";
-tSCC zVar_Name[] = "var";
+static char const zVar_NAME[] = "VAR";
+static char const zVar_Name[] = "var";
#define VAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Dvar option description:
*/
-tSCC zDvarText[] =
+static char const zDvarText[] =
"make ARG an ntp variable (RW|DEF)";
-tSCC zDvar_NAME[] = "DVAR";
-tSCC zDvar_Name[] = "dvar";
+static char const zDvar_NAME[] = "DVAR";
+static char const zDvar_Name[] = "dvar";
#define DVAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
| OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
/*
* Slew option description:
*/
-tSCC zSlewText[] =
+static char const zSlewText[] =
"Slew up to 600 seconds";
-tSCC zSlew_NAME[] = "SLEW";
-tSCC zSlew_Name[] = "slew";
+static char const zSlew_NAME[] = "SLEW";
+static char const zSlew_Name[] = "slew";
#define SLEW_FLAGS (OPTST_DISABLED)
/*
- * Help/More_Help/Version option descriptions:
+ * Usepcc option description:
+ */
+#ifdef SYS_WINNT
+static char const zUsepccText[] =
+ "Use CPU cycle counter (Windows only)";
+static char const zUsepcc_NAME[] = "USEPCC";
+static char const zUsepcc_Name[] = "usepcc";
+#define USEPCC_FLAGS (OPTST_DISABLED)
+
+#else /* disable Usepcc */
+#define USEPCC_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zUsepcc_NAME NULL
+#define zUsepccText NULL
+#define zUsepcc_Name NULL
+#endif /* SYS_WINNT */
+
+/*
+ * Pccfreq option description:
*/
-tSCC zHelpText[] = "Display usage information and exit";
-tSCC zHelp_Name[] = "help";
+#ifdef SYS_WINNT
+static char const zPccfreqText[] =
+ "Force CPU cycle counter use (Windows only)";
+static char const zPccfreq_NAME[] = "PCCFREQ";
+static char const zPccfreq_Name[] = "pccfreq";
+#define PCCFREQ_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else /* disable Pccfreq */
+#define PCCFREQ_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zPccfreq_NAME NULL
+#define zPccfreqText NULL
+#define zPccfreq_Name NULL
+#endif /* SYS_WINNT */
-tSCC zMore_HelpText[] = "Extended usage information passed thru pager";
-tSCC zMore_Help_Name[] = "more-help";
+/*
+ * Help/More_Help/Version option descriptions:
+ */
+static char const zHelpText[] = "Display extended usage information and exit";
+static char const zHelp_Name[] = "help";
+#ifdef HAVE_WORKING_FORK
+#define OPTST_MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
+static char const zMore_Help_Name[] = "more-help";
+static char const zMore_HelpText[] = "Extended usage information passed thru pager";
+#else
+#define OPTST_MORE_HELP_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zMore_Help_Name NULL
+#define zMore_HelpText NULL
+#endif
+#ifdef NO_OPTIONAL_OPT_ARGS
+# define OPTST_VERSION_FLAGS OPTST_IMM | OPTST_NO_INIT
+#else
+# define OPTST_VERSION_FLAGS OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
+ OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT
+#endif
-tSCC zVersionText[] = "Output version information and exit";
-tSCC zVersion_Name[] = "version";
+static char const zVersionText[] = "Output version information and exit";
+static char const zVersion_Name[] = "version";
/*
* Declare option callback procedures
*/
@@ -395,9 +480,6 @@ tSCC zVersion_Name[] = "version";
* Under test, omit argument processing, or call optionStackArg,
* if multiple copies are allowed.
*/
-extern tOptProc
- optionNumericVal, optionPagedUsage, optionStackArg,
- optionVersionStderr;
static tOptProc
doUsageOpt;
@@ -412,7 +494,10 @@ static tOptProc
* When not under test, there are different procs to use
*/
extern tOptProc
- optionNumericVal, optionPagedUsage, optionPrintVersion, optionStackArg;
+ optionBooleanVal, optionNestedVal, optionNumericVal,
+ optionPagedUsage, optionPrintVersion, optionResetOpt,
+ optionStackArg, optionTimeDate, optionTimeVal,
+ optionUnstackArg, optionVersionStderr;
static tOptProc
doUsageOpt;
@@ -433,27 +518,27 @@ static tOptProc
*
* Define the Ntpd Option Descriptions.
*/
-static tOptDesc optDesc[ OPTION_CT ] = {
+static tOptDesc optDesc[OPTION_CT] = {
{ /* entry idx, value */ 0, VALUE_OPT_IPV4,
- /* equiv idx, value */ NO_EQUIVALENT, 0,
+ /* equiv idx, value */ 0, VALUE_OPT_IPV4,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, 1, 0,
/* opt state flags */ IPV4_FLAGS, 0,
/* last opt argumnt */ { NULL },
/* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
+ /* must/cannot opts */ NULL, aIpv4CantList,
/* option proc */ NULL,
/* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
/* disablement strs */ NULL, NULL },
{ /* entry idx, value */ 1, VALUE_OPT_IPV6,
- /* equiv idx, value */ NOLIMIT, NOLIMIT,
- /* equivalenced to */ INDEX_OPT_IPV4,
+ /* equiv idx, value */ 1, VALUE_OPT_IPV6,
+ /* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, 1, 0,
/* opt state flags */ IPV6_FLAGS, 0,
/* last opt argumnt */ { NULL },
/* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
+ /* must/cannot opts */ NULL, aIpv6CantList,
/* option proc */ NULL,
/* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
/* disablement strs */ NULL, NULL },
@@ -545,7 +630,7 @@ static tOptDesc optDesc[ OPTION_CT ] = {
{ /* entry idx, value */ 9, VALUE_OPT_PANICGATE,
/* equiv idx, value */ 9, VALUE_OPT_PANICGATE,
/* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
/* opt state flags */ PANICGATE_FLAGS, 0,
/* last opt argumnt */ { NULL },
/* arg list/cookie */ NULL,
@@ -698,16 +783,16 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* desc, NAME, name */ zPropagationdelayText, zPropagationdelay_NAME, zPropagationdelay_Name,
/* disablement strs */ NULL, NULL },
- { /* entry idx, value */ 22, VALUE_OPT_UPDATEINTERVAL,
- /* equiv idx, value */ 22, VALUE_OPT_UPDATEINTERVAL,
+ { /* entry idx, value */ 22, VALUE_OPT_SAVECONFIGQUIT,
+ /* equiv idx, value */ 22, VALUE_OPT_SAVECONFIGQUIT,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ UPDATEINTERVAL_FLAGS, 0,
+ /* opt state flags */ SAVECONFIGQUIT_FLAGS, 0,
/* last opt argumnt */ { NULL },
/* arg list/cookie */ NULL,
/* must/cannot opts */ NULL, NULL,
- /* option proc */ optionNumericVal,
- /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zSaveconfigquitText, zSaveconfigquit_NAME, zSaveconfigquit_Name,
/* disablement strs */ NULL, NULL },
{ /* entry idx, value */ 23, VALUE_OPT_STATSDIR,
@@ -746,8 +831,20 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* desc, NAME, name */ zUserText, zUser_NAME, zUser_Name,
/* disablement strs */ NULL, NULL },
- { /* entry idx, value */ 26, VALUE_OPT_VAR,
- /* equiv idx, value */ 26, VALUE_OPT_VAR,
+ { /* entry idx, value */ 26, VALUE_OPT_UPDATEINTERVAL,
+ /* equiv idx, value */ 26, VALUE_OPT_UPDATEINTERVAL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ UPDATEINTERVAL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionNumericVal,
+ /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 27, VALUE_OPT_VAR,
+ /* equiv idx, value */ 27, VALUE_OPT_VAR,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, NOLIMIT, 0,
/* opt state flags */ VAR_FLAGS, 0,
@@ -758,8 +855,8 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* desc, NAME, name */ zVarText, zVar_NAME, zVar_Name,
/* disablement strs */ NULL, NULL },
- { /* entry idx, value */ 27, VALUE_OPT_DVAR,
- /* equiv idx, value */ 27, VALUE_OPT_DVAR,
+ { /* entry idx, value */ 28, VALUE_OPT_DVAR,
+ /* equiv idx, value */ 28, VALUE_OPT_DVAR,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, NOLIMIT, 0,
/* opt state flags */ DVAR_FLAGS, 0,
@@ -770,8 +867,8 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
/* disablement strs */ NULL, NULL },
- { /* entry idx, value */ 28, VALUE_OPT_SLEW,
- /* equiv idx, value */ 28, VALUE_OPT_SLEW,
+ { /* entry idx, value */ 29, VALUE_OPT_SLEW,
+ /* equiv idx, value */ 29, VALUE_OPT_SLEW,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, 1, 0,
/* opt state flags */ SLEW_FLAGS, 0,
@@ -782,18 +879,35 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
/* disablement strs */ NULL, NULL },
-#ifdef NO_OPTIONAL_OPT_ARGS
-# define VERSION_OPT_FLAGS OPTST_IMM | OPTST_NO_INIT
-#else
-# define VERSION_OPT_FLAGS OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
- OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT
-#endif
+ { /* entry idx, value */ 30, VALUE_OPT_USEPCC,
+ /* equiv idx, value */ 30, VALUE_OPT_USEPCC,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ USEPCC_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zUsepccText, zUsepcc_NAME, zUsepcc_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 31, VALUE_OPT_PCCFREQ,
+ /* equiv idx, value */ 31, VALUE_OPT_PCCFREQ,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PCCFREQ_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPccfreqText, zPccfreq_NAME, zPccfreq_Name,
+ /* disablement strs */ NULL, NULL },
{ /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
/* equiv idx value */ NO_EQUIVALENT, 0,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ VERSION_OPT_FLAGS, 0,
+ /* opt state flags */ OPTST_VERSION_FLAGS, 0,
/* last opt argumnt */ { NULL },
/* arg list/cookie */ NULL,
/* must/cannot opts */ NULL, NULL,
@@ -801,7 +915,6 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
/* disablement strs */ NULL, NULL },
-#undef VERSION_OPT_FLAGS
{ /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
@@ -820,7 +933,7 @@ static tOptDesc optDesc[ OPTION_CT ] = {
/* equiv idx value */ NO_EQUIVALENT, 0,
/* equivalenced to */ NO_EQUIVALENT,
/* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
+ /* opt state flags */ OPTST_MORE_HELP_FLAGS, 0,
/* last opt argumnt */ { NULL },
/* arg list/cookie */ NULL,
/* must/cannot opts */ NULL, NULL,
@@ -833,18 +946,18 @@ static tOptDesc optDesc[ OPTION_CT ] = {
*
* Define the Ntpd Option Environment
*/
-tSCC zPROGNAME[] = "NTPD";
-tSCC zUsageTitle[] =
-"ntpd - NTP daemon program - Ver. 4.2.4p8\n\
+static char const zPROGNAME[5] = "NTPD";
+static char const zUsageTitle[99] =
+"ntpd - NTP daemon program - Ver. 4.2.6p5\n\
USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
#define zRcName NULL
#define apzHomeList NULL
-tSCC zBugsAddr[] = "http://bugs.ntp.org, bugs@ntp.org";
+static char const zBugsAddr[34] = "http://bugs.ntp.org, bugs@ntp.org";
#define zExplain NULL
-tSCC zDetail[] = "\n\n";
-tSCC zFullVersion[] = NTPD_FULL_VERSION;
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/optcode.tpl near line 408 */
+static char const zDetail[7] = "\n\n";
+static char const zFullVersion[] = NTPD_FULL_VERSION;
+/* extracted from optcode.tlib near line 515 */
#if defined(ENABLE_NLS)
# define OPTPROC_BASE OPTPROC_TRANSLATE
@@ -854,6 +967,29 @@ tSCC zFullVersion[] = NTPD_FULL_VERSION;
# define translate_option_strings NULL
#endif /* ENABLE_NLS */
+
+#define ntpd_full_usage NULL
+#define ntpd_short_usage NULL
+#ifndef PKGDATADIR
+# define PKGDATADIR ""
+#endif
+
+#ifndef WITH_PACKAGER
+# define ntpd_packager_info NULL
+#else
+static char const ntpd_packager_info[] =
+ "Packaged by " WITH_PACKAGER
+
+# ifdef WITH_PACKAGER_VERSION
+ " ("WITH_PACKAGER_VERSION")"
+# endif
+
+# ifdef WITH_PACKAGER_BUG_REPORTS
+ "\nReport ntpd bugs to " WITH_PACKAGER_BUG_REPORTS
+# endif
+ "\n";
+#endif
+
tOptions ntpdOptions = {
OPTIONS_STRUCT_VERSION,
0, NULL, /* original argc + argv */
@@ -863,74 +999,75 @@ tOptions ntpdOptions = {
+ OPTPROC_LONGOPT
+ OPTPROC_NO_REQ_OPT
+ OPTPROC_ENVIRON
- + OPTPROC_NO_ARGS ),
+ + OPTPROC_NO_ARGS
+ + OPTPROC_MISUSE ),
0, NULL, /* current option index, current option */
NULL, NULL, zPROGNAME,
- zRcName, zCopyright, zCopyrightNotice,
+ zRcName, zCopyright, zLicenseDescrip,
zFullVersion, apzHomeList, zUsageTitle,
zExplain, zDetail, optDesc,
zBugsAddr, /* address to send bugs to */
NULL, NULL, /* extensions/saved state */
- optionUsage, /* usage procedure */
+ optionUsage, /* usage procedure */
translate_option_strings, /* translation procedure */
/*
* Indexes to special options
*/
- { INDEX_OPT_MORE_HELP,
- 0 /* no option state saving */,
- NO_EQUIVALENT /* index of '-#' option */,
+ { INDEX_OPT_MORE_HELP, /* more-help option index */
+ NO_EQUIVALENT, /* save option index */
+ NO_EQUIVALENT, /* '-#' option index */
NO_EQUIVALENT /* index of default opt */
},
- 32 /* full option count */, 29 /* user option count */
+ 35 /* full option count */, 32 /* user option count */,
+ ntpd_full_usage, ntpd_short_usage,
+ NULL, NULL,
+ PKGDATADIR, ntpd_packager_info
};
/*
* Create the static procedure(s) declared above.
*/
static void
-doUsageOpt(
- tOptions* pOptions,
- tOptDesc* pOptDesc )
+doUsageOpt(tOptions * pOptions, tOptDesc * pOptDesc)
{
- USAGE( EXIT_SUCCESS );
+ (void)pOptions;
+ USAGE(NTPD_EXIT_SUCCESS);
}
#if ! defined(TEST_NTPD_OPTS)
-/* * * * * * *
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* For the set-debug-level option, when DEBUG is #define-d.
*/
#ifdef DEBUG
static void
-doOptSet_Debug_Level(
- tOptions* pOptions,
- tOptDesc* pOptDesc )
+doOptSet_Debug_Level(tOptions* pOptions, tOptDesc* pOptDesc)
{
- /* extracted from ../include/debug-opt.def, line 29 */
+ /* extracted from ntpdbase-opts.def, line 100 */
DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
}
#endif /* defined DEBUG */
-
#endif /* defined(TEST_NTPD_OPTS) */
-
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/optmain.tpl near line 92 */
+/* extracted from optmain.tlib near line 128 */
#if defined(TEST_NTPD_OPTS) /* TEST MAIN PROCEDURE: */
+extern void optionPutShell(tOptions*);
+
int
-main( int argc, char** argv )
+main(int argc, char ** argv)
{
- int res = EXIT_SUCCESS;
- (void)optionProcess( &ntpdOptions, argc, argv );
- {
- void optionPutShell( tOptions* );
- optionPutShell( &ntpdOptions );
- }
+ int res = NTPD_EXIT_SUCCESS;
+ (void)optionProcess(&ntpdOptions, argc, argv);
+ optionPutShell(&ntpdOptions);
+ res = ferror(stdout);
+ if (res != 0)
+ fputs("output error writing to stdout\n", stderr);
return res;
}
#endif /* defined TEST_NTPD_OPTS */
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/optcode.tpl near line 514 */
+/* extracted from optcode.tlib near line 666 */
#if ENABLE_NLS
#include <stdio.h>
@@ -939,11 +1076,11 @@ main( int argc, char** argv )
#include <unistd.h>
#include <autoopts/usage-txt.h>
-static char* AO_gettext( char const* pz );
+static char* AO_gettext(char const* pz);
static void coerce_it(void** s);
static char*
-AO_gettext( char const* pz )
+AO_gettext(char const* pz)
{
char* pzRes;
if (pz == NULL)
@@ -951,66 +1088,68 @@ AO_gettext( char const* pz )
pzRes = _(pz);
if (pzRes == pz)
return pzRes;
- pzRes = strdup( pzRes );
+ pzRes = strdup(pzRes);
if (pzRes == NULL) {
- fputs( _("No memory for duping translated strings\n"), stderr );
- exit( EXIT_FAILURE );
+ fputs(_("No memory for duping translated strings\n"), stderr);
+ exit(NTPD_EXIT_FAILURE);
}
return pzRes;
}
-static void coerce_it(void** s) { *s = AO_gettext(*s); }
-#define COERSION(_f) \
- coerce_it((void*)&(ntpdOptions._f))
+static void coerce_it(void** s) { *s = AO_gettext(*s);
+}
/*
* This invokes the translation code (e.g. gettext(3)).
*/
static void
-translate_option_strings( void )
+translate_option_strings(void)
{
+ tOptions * const pOpt = &ntpdOptions;
+
/*
* Guard against re-translation. It won't work. The strings will have
* been changed by the first pass through this code. One shot only.
*/
- if (option_usage_text.field_ct == 0)
- return;
- /*
- * Do the translations. The first pointer follows the field count field.
- * The field count field is the size of a pointer.
- */
- {
- char** ppz = (char**)(void*)&(option_usage_text);
- int ix = option_usage_text.field_ct;
+ if (option_usage_text.field_ct != 0) {
+ /*
+ * Do the translations. The first pointer follows the field count
+ * field. The field count field is the size of a pointer.
+ */
+ tOptDesc * pOD = pOpt->pOptDesc;
+ char ** ppz = (char**)(void*)&(option_usage_text);
+ int ix = option_usage_text.field_ct;
do {
ppz++;
*ppz = AO_gettext(*ppz);
} while (--ix > 0);
+
+ coerce_it((void*)&(pOpt->pzCopyright));
+ coerce_it((void*)&(pOpt->pzCopyNotice));
+ coerce_it((void*)&(pOpt->pzFullVersion));
+ coerce_it((void*)&(pOpt->pzUsageTitle));
+ coerce_it((void*)&(pOpt->pzExplain));
+ coerce_it((void*)&(pOpt->pzDetail));
+ coerce_it((void*)&(pOpt->pzPackager));
+ option_usage_text.field_ct = 0;
+
+ for (ix = pOpt->optCt; ix > 0; ix--, pOD++)
+ coerce_it((void*)&(pOD->pzText));
}
- option_usage_text.field_ct = 0;
-
- {
- tOptDesc* pOD = ntpdOptions.pOptDesc;
- int ix = ntpdOptions.optCt;
-
- for (;;) {
- pOD->pzText = AO_gettext(pOD->pzText);
- pOD->pz_NAME = AO_gettext(pOD->pz_NAME);
- pOD->pz_Name = AO_gettext(pOD->pz_Name);
- pOD->pz_DisableName = AO_gettext(pOD->pz_DisableName);
- pOD->pz_DisablePfx = AO_gettext(pOD->pz_DisablePfx);
- if (--ix <= 0)
- break;
- pOD++;
+
+ if ((pOpt->fOptSet & OPTPROC_NXLAT_OPT_CFG) == 0) {
+ tOptDesc * pOD = pOpt->pOptDesc;
+ int ix;
+
+ for (ix = pOpt->optCt; ix > 0; ix--, pOD++) {
+ coerce_it((void*)&(pOD->pz_Name));
+ coerce_it((void*)&(pOD->pz_DisableName));
+ coerce_it((void*)&(pOD->pz_DisablePfx));
}
+ /* prevent re-translation */
+ ntpdOptions.fOptSet |= OPTPROC_NXLAT_OPT_CFG | OPTPROC_NXLAT_OPT;
}
- COERSION(pzCopyright);
- COERSION(pzCopyNotice);
- COERSION(pzFullVersion);
- COERSION(pzUsageTitle);
- COERSION(pzExplain);
- COERSION(pzDetail);
}
#endif /* ENABLE_NLS */
diff --git a/ntpd/ntpd-opts.h b/ntpd/ntpd-opts.h
index 0347f333aa83..4036432e14a3 100644
--- a/ntpd/ntpd-opts.h
+++ b/ntpd/ntpd-opts.h
@@ -1,27 +1,24 @@
/*
* EDIT THIS FILE WITH CAUTION (ntpd-opts.h)
*
- * It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:09 AM EST
+ * It has been AutoGen-ed December 24, 2011 at 06:34:00 PM by AutoGen 5.12
* From the definitions ntpd-opts.def
* and the template file options
*
- * Generated from AutoOpts 29:0:4 templates.
- */
-
-/*
- * This file was produced by an AutoOpts template. AutoOpts is a
- * copyrighted work. This header file is not encumbered by AutoOpts
- * licensing, but is provided under the licensing terms chosen by the
- * ntpd author or copyright holder. AutoOpts is licensed under
- * the terms of the LGPL. The redistributable library (``libopts'') is
- * licensed under the terms of either the LGPL or, at the users discretion,
- * the BSD license. See the AutoOpts and/or libopts sources for details.
+ * Generated from AutoOpts 35:0:10 templates.
*
- * This source file is copyrighted and licensed under the following terms:
+ * AutoOpts is a copyrighted work. This header file is not encumbered
+ * by AutoOpts licensing, but is provided under the licensing terms chosen
+ * by the ntpd author or copyright holder. AutoOpts is
+ * licensed under the terms of the LGPL. The redistributable library
+ * (``libopts'') is licensed under the terms of either the LGPL or, at the
+ * users discretion, the BSD license. See the AutoOpts and/or libopts sources
+ * for details.
*
- * ntpd copyright 1970-2009 David L. Mills and/or others - all rights reserved
+ * This source file is copyrighted and licensed under the following terms:
*
- * see html/copyright.html
+ * see html/copyright.html
+ *
*/
/*
* This file contains the programmatic interface to the Automated
@@ -30,7 +27,7 @@
* "AutoOpts" chapter. Please refer to that doc for usage help.
*/
#ifndef AUTOOPTS_NTPD_OPTS_H_GUARD
-#define AUTOOPTS_NTPD_OPTS_H_GUARD
+#define AUTOOPTS_NTPD_OPTS_H_GUARD 1
#include "config.h"
#include <autoopts/options.h>
@@ -41,7 +38,7 @@
* tolerable version is at least as old as what was current when the header
* template was released.
*/
-#define AO_TEMPLATE_VERSION 118784
+#define AO_TEMPLATE_VERSION 143360
#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
|| (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
# error option template version mismatches autoopts/options.h header
@@ -52,48 +49,51 @@
* Enumeration of each option:
*/
typedef enum {
- INDEX_OPT_IPV4 = 0,
- INDEX_OPT_IPV6 = 1,
- INDEX_OPT_AUTHREQ = 2,
- INDEX_OPT_AUTHNOREQ = 3,
- INDEX_OPT_BCASTSYNC = 4,
- INDEX_OPT_CONFIGFILE = 5,
- INDEX_OPT_DEBUG_LEVEL = 6,
- INDEX_OPT_SET_DEBUG_LEVEL = 7,
- INDEX_OPT_DRIFTFILE = 8,
- INDEX_OPT_PANICGATE = 9,
- INDEX_OPT_JAILDIR = 10,
- INDEX_OPT_INTERFACE = 11,
- INDEX_OPT_KEYFILE = 12,
- INDEX_OPT_LOGFILE = 13,
- INDEX_OPT_NOVIRTUALIPS = 14,
- INDEX_OPT_MODIFYMMTIMER = 15,
- INDEX_OPT_NOFORK = 16,
- INDEX_OPT_NICE = 17,
- INDEX_OPT_PIDFILE = 18,
- INDEX_OPT_PRIORITY = 19,
- INDEX_OPT_QUIT = 20,
- INDEX_OPT_PROPAGATIONDELAY = 21,
- INDEX_OPT_UPDATEINTERVAL = 22,
- INDEX_OPT_STATSDIR = 23,
- INDEX_OPT_TRUSTEDKEY = 24,
- INDEX_OPT_USER = 25,
- INDEX_OPT_VAR = 26,
- INDEX_OPT_DVAR = 27,
- INDEX_OPT_SLEW = 28,
- INDEX_OPT_VERSION = 29,
- INDEX_OPT_HELP = 30,
- INDEX_OPT_MORE_HELP = 31
+ INDEX_OPT_IPV4 = 0,
+ INDEX_OPT_IPV6 = 1,
+ INDEX_OPT_AUTHREQ = 2,
+ INDEX_OPT_AUTHNOREQ = 3,
+ INDEX_OPT_BCASTSYNC = 4,
+ INDEX_OPT_CONFIGFILE = 5,
+ INDEX_OPT_DEBUG_LEVEL = 6,
+ INDEX_OPT_SET_DEBUG_LEVEL = 7,
+ INDEX_OPT_DRIFTFILE = 8,
+ INDEX_OPT_PANICGATE = 9,
+ INDEX_OPT_JAILDIR = 10,
+ INDEX_OPT_INTERFACE = 11,
+ INDEX_OPT_KEYFILE = 12,
+ INDEX_OPT_LOGFILE = 13,
+ INDEX_OPT_NOVIRTUALIPS = 14,
+ INDEX_OPT_MODIFYMMTIMER = 15,
+ INDEX_OPT_NOFORK = 16,
+ INDEX_OPT_NICE = 17,
+ INDEX_OPT_PIDFILE = 18,
+ INDEX_OPT_PRIORITY = 19,
+ INDEX_OPT_QUIT = 20,
+ INDEX_OPT_PROPAGATIONDELAY = 21,
+ INDEX_OPT_SAVECONFIGQUIT = 22,
+ INDEX_OPT_STATSDIR = 23,
+ INDEX_OPT_TRUSTEDKEY = 24,
+ INDEX_OPT_USER = 25,
+ INDEX_OPT_UPDATEINTERVAL = 26,
+ INDEX_OPT_VAR = 27,
+ INDEX_OPT_DVAR = 28,
+ INDEX_OPT_SLEW = 29,
+ INDEX_OPT_USEPCC = 30,
+ INDEX_OPT_PCCFREQ = 31,
+ INDEX_OPT_VERSION = 32,
+ INDEX_OPT_HELP = 33,
+ INDEX_OPT_MORE_HELP = 34
} teOptIndex;
-#define OPTION_CT 32
-#define NTPD_VERSION "4.2.4p8"
-#define NTPD_FULL_VERSION "ntpd - NTP daemon program - Ver. 4.2.4p8"
+#define OPTION_CT 35
+#define NTPD_VERSION "4.2.6p5"
+#define NTPD_FULL_VERSION "ntpd 4.2.6p5"
/*
* Interface defines for all options. Replace "n" with the UPPER_CASED
* option name (as in the teOptIndex enumeration above).
- * e.g. HAVE_OPT( IPV4 )
+ * e.g. HAVE_OPT(IPV4)
*/
#define DESC(n) (ntpdOptions.pOptDesc[INDEX_OPT_## n])
#define HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
@@ -107,10 +107,18 @@ typedef enum {
#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
#define CLEAR_OPT(n) STMTS( \
DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \
- if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+ if ((DESC(n).fOptState & OPTST_INITENABLED) == 0) \
DESC(n).fOptState |= OPTST_DISABLED; \
DESC(n).optCookie = NULL )
+/* * * * * *
+ *
+ * Enumeration of ntpd exit codes
+ */
+typedef enum {
+ NTPD_EXIT_SUCCESS = 0,
+ NTPD_EXIT_FAILURE = 1
+} ntpd_exit_code_t;
/*
* Make sure there are no #define name conflicts with the option names
*/
@@ -203,9 +211,9 @@ typedef enum {
# warning undefining PROPAGATIONDELAY due to option name conflict
# undef PROPAGATIONDELAY
# endif
-# ifdef UPDATEINTERVAL
-# warning undefining UPDATEINTERVAL due to option name conflict
-# undef UPDATEINTERVAL
+# ifdef SAVECONFIGQUIT
+# warning undefining SAVECONFIGQUIT due to option name conflict
+# undef SAVECONFIGQUIT
# endif
# ifdef STATSDIR
# warning undefining STATSDIR due to option name conflict
@@ -219,6 +227,10 @@ typedef enum {
# warning undefining USER due to option name conflict
# undef USER
# endif
+# ifdef UPDATEINTERVAL
+# warning undefining UPDATEINTERVAL due to option name conflict
+# undef UPDATEINTERVAL
+# endif
# ifdef VAR
# warning undefining VAR due to option name conflict
# undef VAR
@@ -231,6 +243,14 @@ typedef enum {
# warning undefining SLEW due to option name conflict
# undef SLEW
# endif
+# ifdef USEPCC
+# warning undefining USEPCC due to option name conflict
+# undef USEPCC
+# endif
+# ifdef PCCFREQ
+# warning undefining PCCFREQ due to option name conflict
+# undef PCCFREQ
+# endif
#else /* NO_OPTION_NAME_WARNINGS */
# undef IPV4
# undef IPV6
@@ -254,32 +274,30 @@ typedef enum {
# undef PRIORITY
# undef QUIT
# undef PROPAGATIONDELAY
-# undef UPDATEINTERVAL
+# undef SAVECONFIGQUIT
# undef STATSDIR
# undef TRUSTEDKEY
# undef USER
+# undef UPDATEINTERVAL
# undef VAR
# undef DVAR
# undef SLEW
+# undef USEPCC
+# undef PCCFREQ
#endif /* NO_OPTION_NAME_WARNINGS */
-/*
+/* * * * * *
+ *
* Interface defines for specific options.
*/
#define VALUE_OPT_IPV4 '4'
-#define WHICH_OPT_IPV4 (DESC(IPV4).optActualValue)
-#define WHICH_IDX_IPV4 (DESC(IPV4).optActualIndex)
#define VALUE_OPT_IPV6 '6'
#define VALUE_OPT_AUTHREQ 'a'
#define VALUE_OPT_AUTHNOREQ 'A'
#define VALUE_OPT_BCASTSYNC 'b'
#define VALUE_OPT_CONFIGFILE 'c'
-#ifdef DEBUG
#define VALUE_OPT_DEBUG_LEVEL 'd'
-#endif /* DEBUG */
-#ifdef DEBUG
#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
-#endif /* DEBUG */
#define VALUE_OPT_DRIFTFILE 'f'
#define VALUE_OPT_PANICGATE 'g'
#define VALUE_OPT_JAILDIR 'i'
@@ -287,62 +305,83 @@ typedef enum {
#define VALUE_OPT_KEYFILE 'k'
#define VALUE_OPT_LOGFILE 'l'
#define VALUE_OPT_NOVIRTUALIPS 'L'
-#ifdef SYS_WINNT
#define VALUE_OPT_MODIFYMMTIMER 'M'
-#endif /* SYS_WINNT */
#define VALUE_OPT_NOFORK 'n'
#define VALUE_OPT_NICE 'N'
#define VALUE_OPT_PIDFILE 'p'
#define VALUE_OPT_PRIORITY 'P'
+
#define OPT_VALUE_PRIORITY (DESC(PRIORITY).optArg.argInt)
#define VALUE_OPT_QUIT 'q'
#define VALUE_OPT_PROPAGATIONDELAY 'r'
-#define VALUE_OPT_UPDATEINTERVAL 'U'
-#define OPT_VALUE_UPDATEINTERVAL (DESC(UPDATEINTERVAL).optArg.argInt)
+#define VALUE_OPT_SAVECONFIGQUIT 22
#define VALUE_OPT_STATSDIR 's'
#define VALUE_OPT_TRUSTEDKEY 't'
#define VALUE_OPT_USER 'u'
-#define VALUE_OPT_VAR 'v'
-#define VALUE_OPT_DVAR 'V'
-#define VALUE_OPT_SLEW 'x'
+#define VALUE_OPT_UPDATEINTERVAL 'U'
-#define VALUE_OPT_VERSION 'v'
+#define OPT_VALUE_UPDATEINTERVAL (DESC(UPDATEINTERVAL).optArg.argInt)
+#define VALUE_OPT_VAR 27
+#define VALUE_OPT_DVAR 28
+#define VALUE_OPT_SLEW 'x'
+#define VALUE_OPT_USEPCC 30
+#define VALUE_OPT_PCCFREQ 31
#define VALUE_OPT_HELP '?'
#define VALUE_OPT_MORE_HELP '!'
+#define VALUE_OPT_VERSION INDEX_OPT_VERSION
/*
* Interface defines not associated with particular options
*/
-#define ERRSKIP_OPTERR STMTS( ntpdOptions.fOptSet &= ~OPTPROC_ERRSTOP )
-#define ERRSTOP_OPTERR STMTS( ntpdOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define ERRSKIP_OPTERR STMTS(ntpdOptions.fOptSet &= ~OPTPROC_ERRSTOP)
+#define ERRSTOP_OPTERR STMTS(ntpdOptions.fOptSet |= OPTPROC_ERRSTOP)
#define RESTART_OPT(n) STMTS( \
ntpdOptions.curOptIdx = (n); \
- ntpdOptions.pzCurOpt = NULL )
+ ntpdOptions.pzCurOpt = NULL)
#define START_OPT RESTART_OPT(1)
-#define USAGE(c) (*ntpdOptions.pUsageProc)( &ntpdOptions, c )
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/opthead.tpl near line 360 */
+#define USAGE(c) (*ntpdOptions.pUsageProc)(&ntpdOptions, c)
+/* extracted from opthead.tlib near line 451 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
/* * * * * *
*
* Declare the ntpd option descriptor.
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
+extern tOptions ntpdOptions;
-extern tOptions ntpdOptions;
+#if defined(ENABLE_NLS)
+# ifndef _
+# include <stdio.h>
+static inline char* aoGetsText(char const* pz) {
+ if (pz == NULL) return NULL;
+ return (char*)gettext(pz);
+}
+# define _(s) aoGetsText(s)
+# endif /* _() */
-#ifndef _
-# if ENABLE_NLS
-# include <stdio.h>
- static inline char* aoGetsText( char const* pz ) {
- if (pz == NULL) return NULL;
- return (char*)gettext( pz );
- }
-# define _(s) aoGetsText(s)
-# else /* ENABLE_NLS */
-# define _(s) s
-# endif /* ENABLE_NLS */
-#endif
+# define OPT_NO_XLAT_CFG_NAMES STMTS(ntpdOptions.fOptSet |= \
+ OPTPROC_NXLAT_OPT_CFG;)
+# define OPT_NO_XLAT_OPT_NAMES STMTS(ntpdOptions.fOptSet |= \
+ OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG;)
+
+# define OPT_XLAT_CFG_NAMES STMTS(ntpdOptions.fOptSet &= \
+ ~(OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG);)
+# define OPT_XLAT_OPT_NAMES STMTS(ntpdOptions.fOptSet &= \
+ ~OPTPROC_NXLAT_OPT;)
+
+#else /* ENABLE_NLS */
+# define OPT_NO_XLAT_CFG_NAMES
+# define OPT_NO_XLAT_OPT_NAMES
+
+# define OPT_XLAT_CFG_NAMES
+# define OPT_XLAT_OPT_NAMES
+
+# ifndef _
+# define _(_s) _s
+# endif
+#endif /* ENABLE_NLS */
#ifdef __cplusplus
}
diff --git a/ntpd/ntpd-opts.texi b/ntpd/ntpd-opts.texi
index 04912945b240..7ea8f3bfea5b 100644
--- a/ntpd/ntpd-opts.texi
+++ b/ntpd/ntpd-opts.texi
@@ -6,7 +6,7 @@
#
# EDIT THIS FILE WITH CAUTION (ntpd-opts.texi)
#
-# It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:12 AM EST
+# It has been AutoGen-ed December 24, 2011 at 06:34:12 PM by AutoGen 5.12
# From the definitions ntpd-opts.def
# and the template file aginfo.tpl
@end ignore
@@ -15,41 +15,44 @@ This program has no explanation.
This section was generated by @strong{AutoGen},
-the aginfo template and the option descriptions for the @command{ntpd} program. It documents the ntpd usage text and option meanings.
+the aginfo template and the option descriptions for the @command{ntpd} program. It documents the @command{ntpd} usage text and option meanings.
This software is released under a specialized copyright license.
@menu
* ntpd usage:: ntpd usage help (-?)
-* ntpd authnoreq:: authnoreq option (-A)
-* ntpd authreq:: authreq option (-a)
-* ntpd bcastsync:: bcastsync option (-b)
-* ntpd configfile:: configfile option (-c)
-* ntpd debug-level:: debug-level option (-d)
-* ntpd driftfile:: driftfile option (-f)
-* ntpd dvar:: dvar option (-V)
-* ntpd interface:: interface option (-I)
-* ntpd ipv4:: ipv4 option (-4)
-* ntpd ipv6:: ipv6 option (-6)
-* ntpd jaildir:: jaildir option (-i)
-* ntpd keyfile:: keyfile option (-k)
-* ntpd logfile:: logfile option (-l)
-* ntpd modifymmtimer:: modifymmtimer option (-M)
-* ntpd nice:: nice option (-N)
-* ntpd nofork:: nofork option (-n)
-* ntpd novirtualips:: novirtualips option (-L)
-* ntpd panicgate:: panicgate option (-g)
-* ntpd pidfile:: pidfile option (-p)
-* ntpd priority:: priority option (-P)
-* ntpd propagationdelay:: propagationdelay option (-r)
-* ntpd quit:: quit option (-q)
-* ntpd set-debug-level:: set-debug-level option (-D)
-* ntpd slew:: slew option (-x)
-* ntpd statsdir:: statsdir option (-s)
-* ntpd trustedkey:: trustedkey option (-t)
-* ntpd updateinterval:: updateinterval option (-U)
-* ntpd user:: user option (-u)
-* ntpd var:: var option (-v)
+* ntpd authnoreq:: authnoreq option (-A)
+* ntpd authreq:: authreq option (-a)
+* ntpd bcastsync:: bcastsync option (-b)
+* ntpd configfile:: configfile option (-c)
+* ntpd debug-level:: debug-level option (-d)
+* ntpd driftfile:: driftfile option (-f)
+* ntpd dvar:: dvar option
+* ntpd interface:: interface option (-I)
+* ntpd ipv4:: ipv4 option (-4)
+* ntpd ipv6:: ipv6 option (-6)
+* ntpd jaildir:: jaildir option (-i)
+* ntpd keyfile:: keyfile option (-k)
+* ntpd logfile:: logfile option (-l)
+* ntpd modifymmtimer:: modifymmtimer option (-M)
+* ntpd nice:: nice option (-N)
+* ntpd nofork:: nofork option (-n)
+* ntpd novirtualips:: novirtualips option (-L)
+* ntpd panicgate:: panicgate option (-g)
+* ntpd pccfreq:: pccfreq option
+* ntpd pidfile:: pidfile option (-p)
+* ntpd priority:: priority option (-P)
+* ntpd propagationdelay:: propagationdelay option (-r)
+* ntpd quit:: quit option (-q)
+* ntpd saveconfigquit:: saveconfigquit option
+* ntpd set-debug-level:: set-debug-level option (-D)
+* ntpd slew:: slew option (-x)
+* ntpd statsdir:: statsdir option (-s)
+* ntpd trustedkey:: trustedkey option (-t)
+* ntpd updateinterval:: updateinterval option (-U)
+* ntpd usepcc:: usepcc option
+* ntpd user:: user option (-u)
+* ntpd var:: var option
@end menu
@node ntpd usage
@@ -60,7 +63,7 @@ This is the automatically generated usage text for ntpd:
@exampleindent 0
@example
-ntpd - NTP daemon program - Ver. 4.2.5p247-RC
+ntpd - NTP daemon program - Ver. 4.2.6p5
USAGE: ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
Flg Arg Option-Name Description
-4 no ipv4 Force IPv4 DNS name resolution
@@ -111,8 +114,8 @@ USAGE: ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
-? no help Display extended usage information and exit
-! no more-help Extended usage information passed thru pager
-Options are specified by doubled hyphens and their name
-or by a single hyphen and the flag character.
+Options are specified by doubled hyphens and their name or by a single
+hyphen and the flag character.
The following option preset mechanisms are supported:
- examining environment variables named NTPD_*
@@ -123,35 +126,22 @@ please send bug reports to: http://bugs.ntp.org, bugs@@ntp.org
@end example
@exampleindent 4
-@node ntpd ipv4
-@subsection ipv4 option (-4)
-@cindex ntpd-ipv4
-
-This is the ``force ipv4 dns name resolution'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-is a member of the ipv4 class of options.
-@end itemize
-
-Force DNS resolution of following host names on the command line
-to the IPv4 namespace.
-
-@node ntpd ipv6
-@subsection ipv6 option (-6)
-@cindex ntpd-ipv6
+@node ntpd authnoreq
+@subsection authnoreq option (-A)
+@cindex ntpd-authnoreq
-This is the ``force ipv6 dns name resolution'' option.
+This is the ``do not require crypto authentication'' option.
This option has some usage constraints. It:
@itemize @bullet
@item
-is a member of the ipv4 class of options.
+must not appear in combination with any of the following options:
+authreq.
@end itemize
-Force DNS resolution of following host names on the command line
-to the IPv6 namespace.
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
@node ntpd authreq
@subsection authreq option (-a)
@@ -170,23 +160,6 @@ Require cryptographic authentication for broadcast client,
multicast client and symmetric passive associations.
This is the default.
-@node ntpd authnoreq
-@subsection authnoreq option (-A)
-@cindex ntpd-authnoreq
-
-This is the ``do not require crypto authentication'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-must not appear in combination with any of the following options:
-authreq.
-@end itemize
-
-Do not require cryptographic authentication for broadcast client,
-multicast client and symmetric passive associations.
-This is almost never a good idea.
-
@node ntpd bcastsync
@subsection bcastsync option (-b)
@cindex ntpd-bcastsync
@@ -219,23 +192,6 @@ must be compiled in by defining @code{DEBUG} during the compilation.
Increase the debugging message output level.
-@node ntpd set-debug-level
-@subsection set-debug-level option (-D)
-@cindex ntpd-set-debug-level
-
-This is the ``set the output debug message level'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@item
-must be compiled in by defining @code{DEBUG} during the compilation.
-@end itemize
-
-Set the output debugging level. Can be supplied multiple times,
-but each overrides the previous value(s).
-
@node ntpd driftfile
@subsection driftfile option (-f)
@cindex ntpd-driftfile
@@ -250,42 +206,25 @@ configuration specification in the
/etc/ntp.conf
file.
-@node ntpd panicgate
-@subsection panicgate option (-g)
-@cindex ntpd-panicgate
+@node ntpd dvar
+@subsection dvar option
+@cindex ntpd-dvar
-This is the ``allow the first adjustment to be big'' option.
-Normally,
-ntpd
-exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
-ntpd
-will exit with a message to the system log. This option can be used with the
--q
-and
--x
-options.
-See the
-tinker
-configuration file directive for other options.
+This is the ``make arg an ntp variable (rw|def)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
-@node ntpd jaildir
-@subsection jaildir option (-i)
-@cindex ntpd-jaildir
-This is the ``jail directory'' option.
-Chroot the server to the directory
-jaildir
-.
-This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
-You may need to also specify a
--u
-option.
@node ntpd interface
@subsection interface option (-I)
@cindex ntpd-interface
-This is the ``listen on interface'' option.
+This is the ``listen on an interface name or address'' option.
This option has some usage constraints. It:
@itemize @bullet
@@ -293,7 +232,70 @@ This option has some usage constraints. It:
may appear an unlimited number of times.
@end itemize
+Open the network address given, or all the addresses associated with the
+given interface name. This option may appear multiple times. This option
+also implies not opening other addresses, except wildcard and localhost.
+This option is deprecated. Please consider using the configuration file
+interface command, which is more versatile.
+
+@node ntpd ipv4
+@subsection ipv4 option (-4)
+@cindex ntpd-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+ipv6.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpd ipv6
+@subsection ipv6 option (-6)
+@cindex ntpd-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+ipv4.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpd jaildir
+@subsection jaildir option (-i)
+@cindex ntpd-jaildir
+
+This is the ``jail directory'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{HAVE_DROPROOT} during the compilation.
+@end itemize
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup.
+You may need to also specify a
+-u
+option.
+This option is only available if the OS supports adjusting the clock
+without full root privileges.
+This option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
@node ntpd keyfile
@subsection keyfile option (-k)
@@ -318,13 +320,6 @@ This is the same operation as the
logfile logfile
configuration file directive.
-@node ntpd novirtualips
-@subsection novirtualips option (-L)
-@cindex ntpd-novirtualips
-
-This is the ``do not listen to virtual ips'' option.
-Do not listen to virtual IPs. The default is to listen.
-
@node ntpd modifymmtimer
@subsection modifymmtimer option (-M)
@cindex ntpd-modifymmtimer
@@ -337,7 +332,18 @@ This option has some usage constraints. It:
must be compiled in by defining @code{SYS_WINNT} during the compilation.
@end itemize
-Set the Windows Multimedia Timer to highest resolution.
+Set the Windows Multimedia Timer to highest resolution. This
+ensures the resolution does not change while ntpd is running,
+avoiding timekeeping glitches associated with changes.
+
+@node ntpd nice
+@subsection nice option (-N)
+@cindex ntpd-nice
+
+This is the ``run at high priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
@node ntpd nofork
@subsection nofork option (-n)
@@ -346,14 +352,56 @@ Set the Windows Multimedia Timer to highest resolution.
This is the ``do not fork'' option.
-@node ntpd nice
-@subsection nice option (-N)
-@cindex ntpd-nice
+@node ntpd novirtualips
+@subsection novirtualips option (-L)
+@cindex ntpd-novirtualips
-This is the ``run at high priority'' option.
-To the extent permitted by the operating system, run
+This is the ``do not listen to virtual interfaces'' option.
+Do not listen to virtual interfaces, defined as those with
+names containing a colon. This option is deprecated. Please
+consider using the configuration file interface command, which
+is more versatile.
+
+@node ntpd panicgate
+@subsection panicgate option (-g)
+@cindex ntpd-panicgate
+
+This is the ``allow the first adjustment to be big'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Normally,
ntpd
-at the highest priority.
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+
+@node ntpd pccfreq
+@subsection pccfreq option
+@cindex ntpd-pccfreq
+
+This is the ``force cpu cycle counter use (windows only)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{SYS_WINNT} during the compilation.
+@end itemize
+
+Force substitution the CPU counter for QueryPerformanceCounter.
+The CPU counter (RDTSC on x86) is used unconditionally with the
+given frequency (in Hz).
@node ntpd pidfile
@subsection pidfile option (-p)
@@ -378,6 +426,13 @@ at the specified
sched_setscheduler(SCHED_FIFO)
priority.
+@node ntpd propagationdelay
+@subsection propagationdelay option (-r)
+@cindex ntpd-propagationdelay
+
+This is the ``broadcast/propagation delay'' option.
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+
@node ntpd quit
@subsection quit option (-q)
@cindex ntpd-quit
@@ -394,22 +449,57 @@ and
options can be used with this option.
Note: The kernel time discipline is disabled with this option.
-@node ntpd propagationdelay
-@subsection propagationdelay option (-r)
-@cindex ntpd-propagationdelay
+@node ntpd saveconfigquit
+@subsection saveconfigquit option
+@cindex ntpd-saveconfigquit
-This is the ``broadcast/propagation delay'' option.
-Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+This is the ``save parsed configuration and quit'' option.
-@node ntpd updateinterval
-@subsection updateinterval option (-U)
-@cindex ntpd-updateinterval
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{SAVECONFIG} during the compilation.
+@end itemize
-This is the ``interval in seconds between scans for new or dropped interfaces'' option.
-Give the time in seconds between two scans for new or dropped interfaces.
-For systems with routing socket support the scans will be performed shortly after the interface change
-has been detected by the system.
-Use 0 to disable scanning.
+Cause ntpd to parse its startup configuration file and save an
+equivalent to the given filename and exit. This option was
+designed for automated testing.
+
+@node ntpd set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpd-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@item
+must be compiled in by defining @code{DEBUG} during the compilation.
+@end itemize
+
+Set the output debugging level. Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpd slew
+@subsection slew option (-x)
+@cindex ntpd-slew
+
+This is the ``slew up to 600 seconds'' option.
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
@node ntpd statsdir
@subsection statsdir option (-s)
@@ -435,21 +525,56 @@ may appear an unlimited number of times.
Add a key number to the trusted key list.
+@node ntpd updateinterval
+@subsection updateinterval option (-U)
+@cindex ntpd-updateinterval
+
+This is the ``interval in seconds between scans for new or dropped interfaces'' option.
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+
+@node ntpd usepcc
+@subsection usepcc option
+@cindex ntpd-usepcc
+
+This is the ``use cpu cycle counter (windows only)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{SYS_WINNT} during the compilation.
+@end itemize
+
+Attempt to substitute the CPU counter for QueryPerformanceCounter.
+The CPU counter and QueryPerformanceCounter are compared, and if
+they have the same frequency, the CPU counter (RDTSC on x86) is
+used directly, saving the overhead of a system call.
+
@node ntpd user
@subsection user option (-u)
@cindex ntpd-user
This is the ``run as userid (or userid:groupid)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{HAVE_DROPROOT} during the compilation.
+@end itemize
+
Specify a user, and optionally a group, to switch to.
-This option is only available if the OS supports to run the server without full root privileges.
-Currently, this option is supported under NetBSD (configure with
+This option is only available if the OS supports adjusting the clock
+without full root privileges.
+This option is supported under NetBSD (configure with
--enable-clockctl
) and Linux (configure with
--enable-linuxcaps
).
@node ntpd var
-@subsection var option (-v)
+@subsection var option
@cindex ntpd-var
This is the ``make arg an ntp variable (rw)'' option.
@@ -459,38 +584,3 @@ This option has some usage constraints. It:
@item
may appear an unlimited number of times.
@end itemize
-
-
-
-@node ntpd dvar
-@subsection dvar option (-V)
-@cindex ntpd-dvar
-
-This is the ``make arg an ntp variable (rw|def)'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@end itemize
-
-
-
-@node ntpd slew
-@subsection slew option (-x)
-@cindex ntpd-slew
-
-This is the ``slew up to 600 seconds'' option.
-Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
-This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
-Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
-Thus, an adjustment as much as 600 s will take almost 14 days to complete.
-This option can be used with the
--g
-and
--q
-options.
-See the
-tinker
-configuration file directive for other options.
-Note: The kernel time discipline is disabled with this option.
diff --git a/ntpd/ntpd.1 b/ntpd/ntpd.1
index ec0a0ed75fa6..baa7b8b9e291 100644
--- a/ntpd/ntpd.1
+++ b/ntpd/ntpd.1
@@ -1,7 +1,7 @@
-.TH NTPD 1 2009-12-08 "( 4.2.4p8)" "Programmer's Manual"
+.TH NTPD 1 2011-12-24 "( 4.2.6p5)" "Programmer's Manual"
.\" EDIT THIS FILE WITH CAUTION (ntpd.1)
.\"
-.\" It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:11 AM EST
+.\" It has been AutoGen-ed December 24, 2011 at 06:34:12 PM by AutoGen 5.12
.\" From the definitions ntpd-opts.def
.\" and the template file agman1.tpl
.\"
@@ -14,20 +14,22 @@ ntpd \- NTP daemon program
.PP
All arguments must be options.
.SH "DESCRIPTION"
-This manual page documents, briefly, the \fBntpd\fP command.
+This manual page briefly documents the \fBntpd\fP command.
.SH OPTIONS
.TP
.BR \-4 ", " \--ipv4
Force IPv4 DNS name resolution.
-This option is a member of the ipv4 class of options.
+This option must not appear in combination with any of the following options:
+ipv6.
.sp
Force DNS resolution of following host names on the command line
to the IPv4 namespace.
.TP
.BR \-6 ", " \--ipv6
Force IPv6 DNS name resolution.
-This option is a member of the ipv4 class of options.
+This option must not appear in combination with any of the following options:
+ipv4.
.sp
Force DNS resolution of following host names on the command line
to the IPv6 namespace.
@@ -89,6 +91,7 @@ file.
.TP
.BR \-g ", " \--panicgate
Allow the first adjustment to be Big.
+This option may appear an unlimited number of times.
.sp
Normally,
ntpd
@@ -109,16 +112,27 @@ Jail directory.
Chroot the server to the directory
jaildir
.
-This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+This option also implies that the server attempts to drop root privileges at startup.
You may need to also specify a
-u
option.
+This option is only available if the OS supports adjusting the clock
+without full root privileges.
+This option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
.TP
.BR \-I " \fIiface\fP, " \--interface "=" \fIiface\fP
-Listen on interface.
+Listen on an interface name or address.
This option may appear an unlimited number of times.
.sp
-
+Open the network address given, or all the addresses associated with the
+given interface name. This option may appear multiple times. This option
+also implies not opening other addresses, except wildcard and localhost.
+This option is deprecated. Please consider using the configuration file
+interface command, which is more versatile.
.TP
.BR \-k " \fIstring\fP, " \--keyfile "=" \fIstring\fP
path to symmetric keys.
@@ -140,14 +154,19 @@ logfile logfile
configuration file directive.
.TP
.BR \-L ", " \--novirtualips
-Do not listen to virtual IPs.
+Do not listen to virtual interfaces.
.sp
-Do not listen to virtual IPs. The default is to listen.
+Do not listen to virtual interfaces, defined as those with
+names containing a colon. This option is deprecated. Please
+consider using the configuration file interface command, which
+is more versatile.
.TP
.BR \-M ", " \--modifymmtimer
Modify Multimedia Timer (Windows only).
.sp
-Set the Windows Multimedia Timer to highest resolution.
+Set the Windows Multimedia Timer to highest resolution. This
+ensures the resolution does not change while ntpd is running,
+avoiding timekeeping glitches associated with changes.
.TP
.BR \-n ", " \--nofork
Do not fork.
@@ -200,14 +219,12 @@ Broadcast/propagation delay.
.sp
Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
.TP
-.BR \-U " \fInumber\fP, " \--updateinterval "=" \fInumber\fP
-interval in seconds between scans for new or dropped interfaces.
-This option takes an integer number as its argument.
+.BR \--saveconfigquit "=\fIstring\fP"
+Save parsed configuration and quit.
.sp
-Give the time in seconds between two scans for new or dropped interfaces.
-For systems with routing socket support the scans will be performed shortly after the interface change
-has been detected by the system.
-Use 0 to disable scanning.
+Cause ntpd to parse its startup configuration file and save an
+equivalent to the given filename and exit. This option was
+designed for automated testing.
.TP
.BR \-s " \fIstring\fP, " \--statsdir "=" \fIstring\fP
Statistics file location.
@@ -227,20 +244,30 @@ Add a key number to the trusted key list.
Run as userid (or userid:groupid).
.sp
Specify a user, and optionally a group, to switch to.
-This option is only available if the OS supports to run the server without full root privileges.
-Currently, this option is supported under NetBSD (configure with
+This option is only available if the OS supports adjusting the clock
+without full root privileges.
+This option is supported under NetBSD (configure with
--enable-clockctl
) and Linux (configure with
--enable-linuxcaps
).
.TP
-.BR \-v " \fInvar\fP, " \--var "=" \fInvar\fP
+.BR \-U " \fInumber\fP, " \--updateinterval "=" \fInumber\fP
+interval in seconds between scans for new or dropped interfaces.
+This option takes an integer number as its argument.
+.sp
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+.TP
+.BR \--var "=\fInvar\fP"
make ARG an ntp variable (RW).
This option may appear an unlimited number of times.
.sp
.TP
-.BR \-V " \fIndvar\fP, " \--dvar "=" \fIndvar\fP
+.BR \--dvar "=\fIndvar\fP"
make ARG an ntp variable (RW|DEF).
This option may appear an unlimited number of times.
.sp
@@ -263,13 +290,28 @@ tinker
configuration file directive for other options.
Note: The kernel time discipline is disabled with this option.
.TP
+.BR \--usepcc
+Use CPU cycle counter (Windows only).
+.sp
+Attempt to substitute the CPU counter for QueryPerformanceCounter.
+The CPU counter and QueryPerformanceCounter are compared, and if
+they have the same frequency, the CPU counter (RDTSC on x86) is
+used directly, saving the overhead of a system call.
+.TP
+.BR \--pccfreq "=\fIstring\fP"
+Force CPU cycle counter use (Windows only).
+.sp
+Force substitution the CPU counter for QueryPerformanceCounter.
+The CPU counter (RDTSC on x86) is used unconditionally with the
+given frequency (in Hz).
+.TP
.BR \-? , " \--help"
-Display usage information and exit.
+Display extended usage information and exit.
.TP
.BR \-! , " \--more-help"
Extended usage information passed thru pager.
.TP
-.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+.BR \- " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
Output version of program and exit. The default mode is `v', a simple
version. The `c' mode will print copyright information and `n' will
print the full copyright notice.
@@ -279,7 +321,7 @@ by loading values from environment variables named:
.nf
\fBNTPD_<option-name>\fP or \fBNTPD\fP
.fi
-.aj
+.ad
.SH AUTHOR
David L. Mills and/or others
.br
@@ -289,6 +331,7 @@ Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org
.nf
.na
see html/copyright.html
+
.fi
.ad
.PP
diff --git a/ntpd/ntpd.c b/ntpd/ntpd.c
index 02a5198b087f..b2884de0fe6c 100644
--- a/ntpd/ntpd.c
+++ b/ntpd/ntpd.c
@@ -12,13 +12,19 @@
#include "ntp_stdlib.h"
#include <ntp_random.h>
+#include "ntp_syslog.h"
+#include "isc/assertions.h"
+#include "isc/error.h"
+#include "isc/strerror.h"
+#include "isc/formatcheck.h"
+
#ifdef SIM
# include "ntpsim.h"
-# include "ntpdsim-opts.h"
-#else
-# include "ntpd-opts.h"
#endif
+#include "ntp_libopts.h"
+#include "ntpd-opts.h"
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -78,8 +84,8 @@
# include <apollo/base.h>
#endif /* SYS_DOMAINOS */
-#include "recvbuff.h"
-#include "ntp_cmdargs.h"
+#include "recvbuff.h"
+#include "ntp_cmdargs.h"
#if 0 /* HMS: I don't think we need this. 961223 */
#ifdef LOCK_PROCESS
@@ -119,10 +125,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 */
#ifdef HAVE_DNSREGISTRATION
@@ -155,16 +161,26 @@ const char *specific_interface = NULL; /* interface name or IP address to
*/
int nofork = 0; /* Fork by default */
+#ifdef HAVE_DNSREGISTRATION
+/*
+ * mDNS registration flag. If set, we attempt to register with the mDNS system, but only
+ * after we have synched the first time. If the attempt fails, then try again once per
+ * minute for up to 5 times. After all, we may be starting before mDNS.
+ */
+int mdnsreg = 1;
+int mdnstries = 5;
+#endif /* HAVE_DNSREGISTRATION */
+
#ifdef HAVE_DROPROOT
int droproot = 0;
char *user = NULL; /* User to switch to */
char *group = NULL; /* group to switch to */
-char *chrootdir = NULL; /* directory to chroot to */
+const char *chrootdir = NULL; /* directory to chroot to */
int sw_uid;
int sw_gid;
-char *endp;
+char *endp;
struct group *gr;
-struct passwd *pw;
+struct passwd *pw;
#endif /* HAVE_DROPROOT */
/*
@@ -186,33 +202,45 @@ int was_alarmed;
/*
* We put this here, since the argument profile is syscall-specific
*/
-extern int syscall P((int, ...));
+extern int syscall (int, ...);
#endif /* DECL_SYSCALL */
#ifdef SIGDIE2
-static RETSIGTYPE finish P((int));
+static RETSIGTYPE finish (int);
#endif /* SIGDIE2 */
#ifdef DEBUG
#ifndef SYS_WINNT
-static RETSIGTYPE moredebug P((int));
-static RETSIGTYPE lessdebug P((int));
+static RETSIGTYPE moredebug (int);
+static RETSIGTYPE lessdebug (int);
#endif
#else /* not DEBUG */
-static RETSIGTYPE no_debug P((int));
+static RETSIGTYPE no_debug (int);
#endif /* not DEBUG */
-int ntpdmain P((int, char **));
-static void set_process_priority P((void));
-static void init_logging P((char const *));
-static void setup_logfile P((void));
+int ntpdmain (int, char **);
+static void set_process_priority (void);
+void init_logging (char const *, int);
+void setup_logfile (void);
+static void process_commandline_opts(int *, char ***);
+
+static void assertion_failed (const char *file, int line,
+ isc_assertiontype_t type, const char *cond);
+static void library_fatal_error (const char *file, int line,
+ const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
+static void library_unexpected_error(const char *file, int line,
+ const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
+
/*
* Initialize the logging
*/
void
-init_logging(char const *name)
+init_logging(
+ char const *name,
+ int log_version
+ )
{
const char *cp;
@@ -243,17 +271,19 @@ init_logging(char const *name)
# endif /* DEBUG */
setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
# endif /* LOG_DAEMON */
-#endif /* !SYS_WINNT && !VMS */
+#endif /* !VMS */
- NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
+ if (log_version)
+ NLOG(NLOG_SYSINFO) /* 'if' clause for syslog */
msyslog(LOG_NOTICE, "%s", Version);
}
/*
- * See if we should redirect the logfile
+ * Redirect logging to a file if requested with -l.
+ * The ntp.conf logfile directive does not use this code, see
+ * config_vars() in ntp_config.c.
*/
-
void
setup_logfile(
void
@@ -286,6 +316,21 @@ setup_logfile(
}
}
+
+static void
+process_commandline_opts(
+ int *pargc,
+ char ***pargv
+ )
+{
+ int optct;
+
+ optct = ntpOptionProcess(&ntpdOptions, *pargc, *pargv);
+ *pargc -= optct;
+ *pargv += optct;
+}
+
+
#ifdef SIM
int
main(
@@ -293,6 +338,8 @@ main(
char *argv[]
)
{
+ process_commandline_opts(&argc, &argv);
+
return ntpsim(argc, argv);
}
#else /* SIM */
@@ -316,10 +363,10 @@ main(
/*
* OK. AIX is different than solaris in how it implements plock().
* If you do NOT adjust the stack limit, you will get the MAXIMUM
- * stack size allocated and PINNED with you program. To check the
- * value, use ulimit -a.
+ * stack size allocated and PINNED with you program. To check the
+ * value, use ulimit -a.
*
- * To fix this, we create an automatic variable and set our stack limit
+ * To fix this, we create an automatic variable and set our stack limit
* to that PLUS 32KB of extra space (we need some headroom).
*
* This subroutine gets the stack address.
@@ -363,10 +410,6 @@ set_process_priority(void)
priority_done);
#endif /* DEBUG */
-#ifdef SYS_WINNT
- priority_done += NT_set_process_priority();
-#endif
-
#if defined(HAVE_SCHED_SETSCHEDULER)
if (!priority_done) {
extern int config_priority_override, config_priority;
@@ -453,24 +496,9 @@ ntpdmain(
#endif
progname = argv[0];
-
initializing = 1; /* mark that we are initializing */
-
- {
- int optct = optionProcess(
-#ifdef SIM
- &ntpdsimOptions
-#else
- &ntpdOptions
-#endif
- , argc, argv);
- argc -= optct;
- argv += optct;
- }
-
- /* HMS: is this lame? Should we process -l first? */
-
- init_logging(progname); /* Open the log file */
+ process_commandline_opts(&argc, &argv);
+ init_logging(progname, 1); /* Open the log file */
#ifdef HAVE_UMASK
{
@@ -489,32 +517,24 @@ ntpdmain(
uid_t uid;
uid = getuid();
- if (uid)
- {
+ if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
- printf("must be run as root, not uid %ld", (long)uid);
+ printf("must be run as root, not uid %ld\n", (long)uid);
exit(1);
}
}
#endif
-#ifdef OPENSSL
- if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
- msyslog(LOG_ERR,
- "ntpd: OpenSSL version mismatch. Built against %lx, you have %lx\n",
- OPENSSL_VERSION_NUMBER, SSLeay());
- exit(1);
- }
-#endif
-
/* getstartup(argc, argv); / * startup configuration, may set debug */
#ifdef DEBUG
debug = DESC(DEBUG_LEVEL).optOccCt;
- if (debug)
- printf("%s\n", Version);
+ DPRINTF(1, ("%s\n", Version));
#endif
+ /* honor -l/--logfile option to log to a file */
+ setup_logfile();
+
/*
* Enable the Multi-Media Timer for Windows?
*/
@@ -523,24 +543,32 @@ ntpdmain(
set_mm_timer(MM_TIMER_HIRES);
#endif
- if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ))
+ if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT )
+#ifdef DEBUG
+ || debug
+#endif
+ || HAVE_OPT( SAVECONFIGQUIT ))
nofork = 1;
if (HAVE_OPT( NOVIRTUALIPS ))
listen_to_virtual_ips = 0;
+ /*
+ * --interface, listen on specified interfaces
+ */
if (HAVE_OPT( INTERFACE )) {
-#if 0
- int ifacect = STACKCT_OPT( INTERFACE );
- char** ifaces = STACKLST_OPT( INTERFACE );
+ int ifacect = STACKCT_OPT( INTERFACE );
+ const char** ifaces = STACKLST_OPT( INTERFACE );
+ sockaddr_u addr;
- /* malloc space for the array of names */
while (ifacect-- > 0) {
- next_iface = *ifaces++;
+ add_nic_rule(
+ is_ip_address(*ifaces, &addr)
+ ? MATCH_IFADDR
+ : MATCH_IFNAME,
+ *ifaces, -1, ACTION_LISTEN);
+ ifaces++;
}
-#else
- specific_interface = OPT_ARG( INTERFACE );
-#endif
}
if (HAVE_OPT( NICE ))
@@ -556,13 +584,11 @@ ntpdmain(
#ifdef SYS_WINNT
/*
- * Initialize the time structures and variables
+ * Start interpolation thread, must occur before first
+ * get_systime()
*/
init_winnt_time();
#endif
-
- setup_logfile();
-
/*
* Initialize random generator and public key pair
*/
@@ -570,25 +596,22 @@ ntpdmain(
ntp_srandom((int)(now.l_i * now.l_uf));
-#ifdef HAVE_DNSREGISTRATION
- /* HMS: does this have to happen this early? */
- msyslog(LOG_INFO, "Attemping to register mDNS");
- if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
- msyslog(LOG_ERR, "Unable to register mDNS");
- }
-#endif
-
#if !defined(VMS)
# ifndef NODETACH
/*
* Detach us from the terminal. May need an #ifndef GIZMO.
*/
- if (
-# ifdef DEBUG
- !debug &&
-# endif /* DEBUG */
- !nofork)
- {
+ if (!nofork) {
+
+ /*
+ * Install trap handlers to log errors and assertion
+ * failures. Default handlers print to stderr which
+ * doesn't work if detached.
+ */
+ isc_assertion_setcallback(assertion_failed);
+ isc_error_setfatal(library_fatal_error);
+ isc_error_setunexpected(library_unexpected_error);
+
# ifndef SYS_WINNT
# ifdef HAVE_DAEMON
daemon(0, 0);
@@ -600,8 +623,11 @@ ntpdmain(
#if !defined(F_CLOSEM)
u_long s;
int max_fd;
-#endif /* not F_CLOSEM */
-
+#endif /* !FCLOSEM */
+ if (syslog_file != NULL) {
+ fclose(syslog_file);
+ syslog_file = NULL;
+ }
#if defined(F_CLOSEM)
/*
* From 'Writing Reliable AIX Daemons,' SG24-4946-00,
@@ -623,6 +649,11 @@ ntpdmain(
(void) open("/", 0);
(void) dup2(0, 1);
(void) dup2(0, 2);
+
+ init_logging(progname, 0);
+ /* we lost our logfile (if any) daemonizing */
+ setup_logfile();
+
#ifdef SYS_DOMAINOS
{
uid_$t puid;
@@ -674,8 +705,6 @@ ntpdmain(
# endif /* NODETACH */
#endif /* VMS */
- setup_logfile(); /* We lost any redirect when we daemonized */
-
#ifdef SCO5_CLOCK
/*
* SCO OpenServer's system clock offers much more precise timekeeping
@@ -724,7 +753,7 @@ ntpdmain(
*/
rl.rlim_cur = rl.rlim_max = 32*1024*1024;
if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
- msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
+ msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
}
# endif /* RLIMIT_MEMLOCK */
}
@@ -738,7 +767,7 @@ ntpdmain(
# ifdef HAVE_PLOCK
# ifdef PROCLOCK
# ifdef _AIX
- /*
+ /*
* set the stack limit for AIX for plock().
* see get_aix_stack() for more info.
*/
@@ -831,13 +860,9 @@ ntpdmain(
* Get the configuration. This is done in a separate module
* since this will definitely be different for the gizmo board.
*/
-
getconfig(argc, argv);
-
- loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
-#ifdef OPENSSL
- crypto_setup();
-#endif /* OPENSSL */
+ report_event(EVNT_SYSRESTART, NULL, NULL);
+ loop_config(LOOP_DRIFTCOMP, old_drift);
initializing = 0;
#ifdef HAVE_DROPROOT
@@ -846,30 +871,48 @@ ntpdmain(
#ifdef HAVE_LINUX_CAPABILITIES
/* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
- if( prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1 ) {
+ if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) {
msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
exit(-1);
}
#else
/* we need a user to switch to */
- if( user == NULL ) {
+ if (user == NULL) {
msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
exit(-1);
}
#endif /* HAVE_LINUX_CAPABILITIES */
-
+
if (user != NULL) {
if (isdigit((unsigned char)*user)) {
sw_uid = (uid_t)strtoul(user, &endp, 0);
- if (*endp != '\0')
+ if (*endp != '\0')
goto getuser;
+
+ if ((pw = getpwuid(sw_uid)) != NULL) {
+ user = strdup(pw->pw_name);
+ if (NULL == user) {
+ msyslog(LOG_ERR, "strdup() failed: %m");
+ exit (-1);
+ }
+ sw_gid = pw->pw_gid;
+ } else {
+ errno = 0;
+ msyslog(LOG_ERR, "Cannot find user ID %s", user);
+ exit (-1);
+ }
+
} else {
-getuser:
+getuser:
+ errno = 0;
if ((pw = getpwnam(user)) != NULL) {
sw_uid = pw->pw_uid;
+ sw_gid = pw->pw_gid;
} else {
- errno = 0;
- msyslog(LOG_ERR, "Cannot find user `%s'", user);
+ if (errno)
+ msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
+ else
+ msyslog(LOG_ERR, "Cannot find user `%s'", user);
exit (-1);
}
}
@@ -877,10 +920,10 @@ getuser:
if (group != NULL) {
if (isdigit((unsigned char)*group)) {
sw_gid = (gid_t)strtoul(group, &endp, 0);
- if (*endp != '\0')
+ if (*endp != '\0')
goto getgroup;
} else {
-getgroup:
+getgroup:
if ((gr = getgrnam(group)) != NULL) {
sw_gid = gr->gr_gid;
} else {
@@ -890,17 +933,25 @@ getgroup:
}
}
}
-
- if( chrootdir ) {
+
+ if (chrootdir ) {
/* make sure cwd is inside the jail: */
- if( chdir(chrootdir) ) {
+ if (chdir(chrootdir)) {
msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
exit (-1);
}
- if( chroot(chrootdir) ) {
+ if (chroot(chrootdir)) {
msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
exit (-1);
}
+ if (chdir("/")) {
+ msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m");
+ exit (-1);
+ }
+ }
+ if (user && initgroups(user, sw_gid)) {
+ msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
+ exit (-1);
}
if (group && setgid(sw_gid)) {
msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
@@ -918,7 +969,7 @@ getgroup:
msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
exit (-1);
}
-
+
#ifndef HAVE_LINUX_CAPABILITIES
/*
* for now assume that the privilege to bind to privileged ports
@@ -941,9 +992,9 @@ getgroup:
* cap_net_bind_service if doing dynamic interface tracking.
*/
cap_t caps;
- char *captext = interface_interval ?
- "cap_sys_time,cap_net_bind_service=ipe" :
- "cap_sys_time=ipe";
+ char *captext = (interface_interval)
+ ? "cap_sys_time,cap_net_bind_service=ipe"
+ : "cap_sys_time=ipe";
if( ! ( caps = cap_from_text( captext ) ) ) {
msyslog( LOG_ERR, "cap_from_text() failed: %m" );
exit(-1);
@@ -958,11 +1009,6 @@ getgroup:
} /* if( droproot ) */
#endif /* HAVE_DROPROOT */
-
- /*
- * Report that we're up to any trappers
- */
- report_event(EVNT_SYSRESTART, (struct peer *)0);
/*
* Use select() on all on all input fd's for unlimited
@@ -989,7 +1035,7 @@ getgroup:
was_alarmed = 0;
for (;;)
{
-# if !defined(HAVE_SIGNALED_IO)
+# if !defined(HAVE_SIGNALED_IO)
extern fd_set activefds;
extern int maxactivefd;
@@ -997,7 +1043,7 @@ getgroup:
int nfound;
# endif
- if (alarm_flag) /* alarmed? */
+ if (alarm_flag) /* alarmed? */
{
was_alarmed = 1;
alarm_flag = 0;
@@ -1032,16 +1078,16 @@ getgroup:
(void)input_handler(&ts);
}
else if (nfound == -1 && errno != EINTR)
- netsyslog(LOG_ERR, "select() error: %m");
+ msyslog(LOG_ERR, "select() error: %m");
# ifdef DEBUG
else if (debug > 5)
- netsyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
+ msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
# endif /* DEBUG */
# else /* HAVE_SIGNALED_IO */
-
+
wait_for_signal();
# endif /* HAVE_SIGNALED_IO */
- if (alarm_flag) /* alarmed? */
+ if (alarm_flag) /* alarmed? */
{
was_alarmed = 1;
alarm_flag = 0;
@@ -1057,17 +1103,17 @@ getgroup:
*/
timer();
was_alarmed = 0;
- BLOCK_IO_AND_ALARM();
+ BLOCK_IO_AND_ALARM();
}
-#endif /* HAVE_IO_COMPLETION_PORT */
+#endif /* ! HAVE_IO_COMPLETION_PORT */
#ifdef DEBUG_TIMING
{
l_fp pts;
l_fp tsa, tsb;
int bufcount = 0;
-
+
get_systime(&pts);
tsa = pts;
#endif
@@ -1124,6 +1170,25 @@ getgroup:
/*
* Go around again
*/
+
+#ifdef HAVE_DNSREGISTRATION
+ if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) {
+ mdnsreg = current_time;
+ msyslog(LOG_INFO, "Attempting to register mDNS");
+ if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL,
+ htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
+ if (!--mdnstries) {
+ msyslog(LOG_ERR, "Unable to register mDNS, giving up.");
+ } else {
+ msyslog(LOG_INFO, "Unable to register mDNS, will try later.");
+ }
+ } else {
+ msyslog(LOG_INFO, "mDNS service registered.");
+ mdnsreg = 0;
+ }
+ }
+#endif /* HAVE_DNSREGISTRATION */
+
}
UNBLOCK_IO_AND_ALARM();
return 1;
@@ -1139,30 +1204,95 @@ finish(
int sig
)
{
-
msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
- write_stats();
#ifdef HAVE_DNSREGISTRATION
if (mdns != NULL)
- DNSServiceRefDeallocate(mdns);
+ DNSServiceRefDeallocate(mdns);
#endif
-
- switch (sig)
- {
+ switch (sig) {
# ifdef SIGBUS
- case SIGBUS:
+ case SIGBUS:
printf("\nfinish(SIGBUS)\n");
exit(0);
# endif
- case 0: /* Should never happen... */
+ case 0: /* Should never happen... */
return;
- default:
+
+ default:
exit(0);
}
}
#endif /* SIGDIE2 */
+/* assertion_failed
+ * Redirect trap messages from ISC libraries to syslog.
+ * This code was cloned and simplified from BIND.
+ */
+
+/*
+ * assertion_failed - Handle assertion failures.
+ */
+
+static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond)
+{
+ isc_assertion_setcallback(NULL); /* Avoid recursion */
+
+ msyslog(LOG_ERR, "%s:%d: %s(%s) failed",
+ file, line, isc_assertion_typetotext(type), cond);
+ msyslog(LOG_ERR, "exiting (due to assertion failure)");
+
+ abort();
+}
+
+/*
+ * library_fatal_error - Handle fatal errors from our libraries.
+ */
+
+static void
+library_fatal_error(const char *file, int line, const char *format,
+ va_list args)
+{
+ char errbuf[256];
+
+ isc_error_setfatal(NULL); /* Avoid recursion */
+
+ msyslog(LOG_ERR, "%s:%d: fatal error:", file, line);
+ vsnprintf(errbuf, sizeof(errbuf), format, args);
+ msyslog(LOG_ERR, errbuf);
+ msyslog(LOG_ERR, "exiting (due to fatal error in library)");
+
+ abort();
+}
+
+/*
+ * library_unexpected_error - Handle non fatal errors from our libraries.
+ */
+#define MAX_UNEXPECTED_ERRORS 100
+int unexpected_error_cnt = 0;
+static void
+library_unexpected_error(const char *file, int line, const char *format,
+ va_list args)
+{
+ char errbuf[256];
+
+ if (unexpected_error_cnt >= MAX_UNEXPECTED_ERRORS)
+ return; /* avoid clutter in log */
+
+ msyslog(LOG_ERR, "%s:%d: unexpected error:", file, line);
+ vsnprintf(errbuf, sizeof(errbuf), format, args);
+ msyslog(LOG_ERR, errbuf);
+
+ if (++unexpected_error_cnt == MAX_UNEXPECTED_ERRORS)
+ {
+ msyslog(LOG_ERR, "Too many errors. Shutting up.");
+ }
+
+}
+
+
#ifdef DEBUG
#ifndef SYS_WINNT
/*
diff --git a/ntpd/ntpdbase-opts.def b/ntpd/ntpdbase-opts.def
index 852af456857f..586a33e055dc 100644
--- a/ntpd/ntpdbase-opts.def
+++ b/ntpd/ntpdbase-opts.def
@@ -1,11 +1,19 @@
#include autogen-version.def
+include = <<- _EOF_
+ #ifdef __windows
+ extern int atoi(const char *);
+ #else
+ # include <stdlib.h>
+ #endif
+ _EOF_;
+
test-main;
flag = {
name = ipv4;
value = 4;
- equivalence = ipv4;
+ flags-cant = ipv6;
descrip = "Force IPv4 DNS name resolution";
doc = <<- _EndOfDoc_
Force DNS resolution of following host names on the command line
@@ -16,7 +24,7 @@ flag = {
flag = {
name = ipv6;
value = 6;
- equivalence = ipv4;
+ flags-cant = ipv4;
descrip = "Force IPv6 DNS name resolution";
doc = <<- _EndOfDoc_
Force DNS resolution of following host names on the command line
@@ -56,17 +64,6 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
-flag = {
- name = simbroadcastdelay;
- value = B;
- arg-type = string;
- descrip = "Simulator broadcast delay";
- doc = <<- _EndOfDoc_
- _EndOfDoc_;
-};
-#endif
-
flag = {
name = configfile;
value = c;
@@ -79,18 +76,33 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
flag = {
- name = phasenoise;
- value = C;
- arg-type = string;
- descrip = "Phase noise level";
+ name = debug-level;
+ value = d;
+ max = NOLIMIT;
+ ifdef = DEBUG;
+ nopreset;
+ descrip = "Increase output debug message level";
+ omitted-usage = "this package was built using 'configure --disable--debug'";
doc = <<- _EndOfDoc_
+ Increase the debugging message output level.
_EndOfDoc_;
};
-#endif
-#include debug-opt.def
+flag = {
+ name = set-debug-level;
+ value = D;
+ arg-type = string;
+ max = NOLIMIT;
+ ifdef = DEBUG;
+ descrip = "Set the output debug message level";
+ omitted-usage = "this package was built using 'configure --disable--debug'";
+ flag-code = 'DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );';
+ doc = <<- _EndOfDoc_
+ Set the output debugging level. Can be supplied multiple times,
+ but each overrides the previous value(s).
+ _EndOfDoc_;
+};
flag = {
name = driftfile;
@@ -112,6 +124,7 @@ flag = {
flag = {
name = panicgate;
value = g;
+ max = NOLIMIT;
descrip = "Allow the first adjustment to be Big";
doc = <<- _EndOfDoc_
Normally,
@@ -129,30 +142,28 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
-flag = {
- name = simslew;
- value = H;
- arg-type = string;
- descrip = "Simuator slew";
- doc = <<- _EndOfDoc_
- _EndOfDoc_;
-};
-#endif
-
flag = {
+ ifdef = HAVE_DROPROOT;
name = jaildir;
value = i;
arg-type = string;
descrip = "Jail directory";
+ omitted-usage = "built without --enable-clockctl or --enable-linuxcaps";
doc = <<- _EndOfDoc_
Chroot the server to the directory
jaildir
.
- This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+ This option also implies that the server attempts to drop root privileges at startup.
You may need to also specify a
-u
option.
+ This option is only available if the OS supports adjusting the clock
+ without full root privileges.
+ This option is supported under NetBSD (configure with
+ --enable-clockctl
+ ) and Linux (configure with
+ --enable-linuxcaps
+ ).
_EndOfDoc_;
};
@@ -160,11 +171,16 @@ flag = {
name = interface;
value = I;
arg-type = string;
- descrip = "Listen on interface";
+ descrip = "Listen on an interface name or address";
max = NOLIMIT;
arg-name = iface;
stack-arg;
doc = <<- _EndOfDoc_
+ Open the network address given, or all the addresses associated with the
+ given interface name. This option may appear multiple times. This option
+ also implies not opening other addresses, except wildcard and localhost.
+ This option is deprecated. Please consider using the configuration file
+ interface command, which is more versatile.
_EndOfDoc_;
};
@@ -200,9 +216,12 @@ flag = {
flag = {
name = novirtualips;
value = L;
- descrip = "Do not listen to virtual IPs";
+ descrip = "Do not listen to virtual interfaces";
doc = <<- _EndOfDoc_
- Do not listen to virtual IPs. The default is to listen.
+ Do not listen to virtual interfaces, defined as those with
+ names containing a colon. This option is deprecated. Please
+ consider using the configuration file interface command, which
+ is more versatile.
_EndOfDoc_;
};
@@ -212,7 +231,9 @@ flag = {
value = M;
descrip = "Modify Multimedia Timer (Windows only)";
doc = <<- _EndOfDoc_
- Set the Windows Multimedia Timer to highest resolution.
+ Set the Windows Multimedia Timer to highest resolution. This
+ ensures the resolution does not change while ntpd is running,
+ avoiding timekeeping glitches associated with changes.
_EndOfDoc_;
};
@@ -235,17 +256,6 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
-flag = {
- name = servertime;
- value = O;
- arg-type = string;
- descrip = "Server time";
- doc = <<- _EndOfDoc_
- _EndOfDoc_;
-};
-#endif
-
flag = {
name = pidfile;
value = p;
@@ -304,15 +314,14 @@ flag = {
};
flag = {
- name = updateinterval;
- value = U;
- arg-type = number;
- descrip = "interval in seconds between scans for new or dropped interfaces";
+ ifdef = SAVECONFIG;
+ name = saveconfigquit;
+ arg-type = string;
+ descrip = "Save parsed configuration and quit";
doc = <<- _EndOfDoc_
- Give the time in seconds between two scans for new or dropped interfaces.
- For systems with routing socket support the scans will be performed shortly after the interface change
- has been detected by the system.
- Use 0 to disable scanning.
+ Cause ntpd to parse its startup configuration file and save an
+ equivalent to the given filename and exit. This option was
+ designed for automated testing.
_EndOfDoc_;
};
@@ -329,17 +338,6 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
-flag = {
- name = endsimtime;
- value = S;
- arg-type = string;
- descrip = "Simulation end time";
- doc = <<- _EndOfDoc_
- _EndOfDoc_;
-};
-#endif
-
flag = {
name = trustedkey;
value = t;
@@ -353,37 +351,18 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
-flag = {
- name = freqerr;
- value = T;
- arg-type = string;
- descrip = "Simulation frequency error";
- doc = <<- _EndOfDoc_
- _EndOfDoc_;
-};
-#endif
-
-#ifdef SIM
-flag = {
- name = walknoise;
- value = W;
- arg-type = string;
- descrip = "Simulation random walk noise";
- doc = <<- _EndOfDoc_
- _EndOfDoc_;
-};
-#endif
-
flag = {
+ ifdef = HAVE_DROPROOT;
name = user;
value = u;
arg-type = string;
descrip = "Run as userid (or userid:groupid)";
+ omitted-usage = "built without --enable-clockctl or --enable-linuxcaps";
doc = <<- _EndOfDoc_
Specify a user, and optionally a group, to switch to.
- This option is only available if the OS supports to run the server without full root privileges.
- Currently, this option is supported under NetBSD (configure with
+ This option is only available if the OS supports adjusting the clock
+ without full root privileges.
+ This option is supported under NetBSD (configure with
--enable-clockctl
) and Linux (configure with
--enable-linuxcaps
@@ -392,8 +371,21 @@ flag = {
};
flag = {
+ name = updateinterval;
+ value = U;
+ arg-type = number;
+ descrip = "interval in seconds between scans for new or dropped interfaces";
+ doc = <<- _EndOfDoc_
+ Give the time in seconds between two scans for new or dropped interfaces.
+ For systems with routing socket support the scans will be performed shortly after the interface change
+ has been detected by the system.
+ Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+ _EndOfDoc_;
+};
+
+flag = {
name = var;
- value = v;
+/* value = v; Bug 817 */
arg-type = string;
descrip = "make ARG an ntp variable (RW)";
max = NOLIMIT;
@@ -405,7 +397,7 @@ flag = {
flag = {
name = dvar;
- value = V;
+/* value = V; Bug 817 */
arg-type = string;
descrip = "make ARG an ntp variable (RW|DEF)";
max = NOLIMIT;
@@ -436,24 +428,26 @@ flag = {
_EndOfDoc_;
};
-#ifdef SIM
flag = {
- name = ndelay;
- value = Y;
- arg-type = string;
- descrip = "Simulation network delay";
+ ifdef = SYS_WINNT;
+ name = usepcc;
+ descrip = "Use CPU cycle counter (Windows only)";
doc = <<- _EndOfDoc_
+ Attempt to substitute the CPU counter for QueryPerformanceCounter.
+ The CPU counter and QueryPerformanceCounter are compared, and if
+ they have the same frequency, the CPU counter (RDTSC on x86) is
+ used directly, saving the overhead of a system call.
_EndOfDoc_;
};
-#endif
-#ifdef SIM
flag = {
- name = pdelay;
- value = Z;
+ ifdef = SYS_WINNT;
+ name = pccfreq;
arg-type = string;
- descrip = "Simulation processing delay";
+ descrip = "Force CPU cycle counter use (Windows only)";
doc = <<- _EndOfDoc_
+ Force substitution the CPU counter for QueryPerformanceCounter.
+ The CPU counter (RDTSC on x86) is used unconditionally with the
+ given frequency (in Hz).
_EndOfDoc_;
};
-#endif
diff --git a/ntpd/ntpdsim-opts.c b/ntpd/ntpdsim-opts.c
deleted file mode 100644
index d9ef1b22e057..000000000000
--- a/ntpd/ntpdsim-opts.c
+++ /dev/null
@@ -1,1262 +0,0 @@
-/*
- * EDIT THIS FILE WITH CAUTION (ntpdsim-opts.c)
- *
- * It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:13 AM EST
- * From the definitions ntpdsim-opts.def
- * and the template file options
- *
- * Generated from AutoOpts 29:0:4 templates.
- */
-
-/*
- * This file was produced by an AutoOpts template. AutoOpts is a
- * copyrighted work. This source file is not encumbered by AutoOpts
- * licensing, but is provided under the licensing terms chosen by the
- * ntpdsim author or copyright holder. AutoOpts is licensed under
- * the terms of the LGPL. The redistributable library (``libopts'') is
- * licensed under the terms of either the LGPL or, at the users discretion,
- * the BSD license. See the AutoOpts and/or libopts sources for details.
- *
- * This source file is copyrighted and licensed under the following terms:
- *
- * ntpdsim copyright 1970-2009 David L. Mills and/or others - all rights reserved
- *
- * see html/copyright.html
- */
-
-
-#include <limits.h>
-
-#define OPTION_CODE_COMPILE 1
-#include "ntpdsim-opts.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-tSCC zCopyright[] =
- "ntpdsim copyright (c) 1970-2009 David L. Mills and/or others, all rights reserved";
-tSCC zCopyrightNotice[] =
-
-/* extracted from ../include/copyright.def near line 8 */
-"see html/copyright.html";
-extern tUsageProc optionUsage;
-
-/*
- * global included definitions
- */
-#ifdef __windows
- extern int atoi(const char*);
-#else
-# include <stdlib.h>
-#endif
-
-#ifndef NULL
-# define NULL 0
-#endif
-#ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-#endif
-#ifndef EXIT_FAILURE
-# define EXIT_FAILURE 1
-#endif
-/*
- * Ipv4 option description:
- */
-tSCC zIpv4Text[] =
- "Force IPv4 DNS name resolution";
-tSCC zIpv4_NAME[] = "IPV4";
-tSCC zIpv4_Name[] = "ipv4";
-#define IPV4_FLAGS (OPTST_DISABLED)
-
-/*
- * Ipv6 option description:
- */
-tSCC zIpv6Text[] =
- "Force IPv6 DNS name resolution";
-tSCC zIpv6_NAME[] = "IPV6";
-tSCC zIpv6_Name[] = "ipv6";
-#define IPV6_FLAGS (OPTST_DISABLED)
-
-/*
- * Authreq option description with
- * "Must also have options" and "Incompatible options":
- */
-tSCC zAuthreqText[] =
- "Require crypto authentication";
-tSCC zAuthreq_NAME[] = "AUTHREQ";
-tSCC zAuthreq_Name[] = "authreq";
-static const int
- aAuthreqCantList[] = {
- INDEX_OPT_AUTHNOREQ, NO_EQUIVALENT };
-#define AUTHREQ_FLAGS (OPTST_DISABLED)
-
-/*
- * Authnoreq option description with
- * "Must also have options" and "Incompatible options":
- */
-tSCC zAuthnoreqText[] =
- "Do not require crypto authentication";
-tSCC zAuthnoreq_NAME[] = "AUTHNOREQ";
-tSCC zAuthnoreq_Name[] = "authnoreq";
-static const int
- aAuthnoreqCantList[] = {
- INDEX_OPT_AUTHREQ, NO_EQUIVALENT };
-#define AUTHNOREQ_FLAGS (OPTST_DISABLED)
-
-/*
- * Bcastsync option description:
- */
-tSCC zBcastsyncText[] =
- "Allow us to sync to broadcast servers";
-tSCC zBcastsync_NAME[] = "BCASTSYNC";
-tSCC zBcastsync_Name[] = "bcastsync";
-#define BCASTSYNC_FLAGS (OPTST_DISABLED)
-
-/*
- * Simbroadcastdelay option description:
- */
-tSCC zSimbroadcastdelayText[] =
- "Simulator broadcast delay";
-tSCC zSimbroadcastdelay_NAME[] = "SIMBROADCASTDELAY";
-tSCC zSimbroadcastdelay_Name[] = "simbroadcastdelay";
-#define SIMBROADCASTDELAY_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Configfile option description:
- */
-tSCC zConfigfileText[] =
- "configuration file name";
-tSCC zConfigfile_NAME[] = "CONFIGFILE";
-tSCC zConfigfile_Name[] = "configfile";
-#define CONFIGFILE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Phasenoise option description:
- */
-tSCC zPhasenoiseText[] =
- "Phase noise level";
-tSCC zPhasenoise_NAME[] = "PHASENOISE";
-tSCC zPhasenoise_Name[] = "phasenoise";
-#define PHASENOISE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Debug_Level option description:
- */
-#ifdef DEBUG
-tSCC zDebug_LevelText[] =
- "Increase output debug message level";
-tSCC zDebug_Level_NAME[] = "DEBUG_LEVEL";
-tSCC zDebug_Level_Name[] = "debug-level";
-#define DEBUG_LEVEL_FLAGS (OPTST_DISABLED)
-
-#else /* disable Debug_Level */
-#define VALUE_OPT_DEBUG_LEVEL NO_EQUIVALENT
-#define DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
-#define zDebug_LevelText NULL
-#define zDebug_Level_NAME NULL
-#define zDebug_Level_Name NULL
-#endif /* DEBUG */
-
-/*
- * Set_Debug_Level option description:
- */
-#ifdef DEBUG
-tSCC zSet_Debug_LevelText[] =
- "Set the output debug message level";
-tSCC zSet_Debug_Level_NAME[] = "SET_DEBUG_LEVEL";
-tSCC zSet_Debug_Level_Name[] = "set-debug-level";
-#define SET_DEBUG_LEVEL_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-#else /* disable Set_Debug_Level */
-#define VALUE_OPT_SET_DEBUG_LEVEL NO_EQUIVALENT
-#define SET_DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
-#define zSet_Debug_LevelText NULL
-#define zSet_Debug_Level_NAME NULL
-#define zSet_Debug_Level_Name NULL
-#endif /* DEBUG */
-
-/*
- * Driftfile option description:
- */
-tSCC zDriftfileText[] =
- "frequency drift file name";
-tSCC zDriftfile_NAME[] = "DRIFTFILE";
-tSCC zDriftfile_Name[] = "driftfile";
-#define DRIFTFILE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Panicgate option description:
- */
-tSCC zPanicgateText[] =
- "Allow the first adjustment to be Big";
-tSCC zPanicgate_NAME[] = "PANICGATE";
-tSCC zPanicgate_Name[] = "panicgate";
-#define PANICGATE_FLAGS (OPTST_DISABLED)
-
-/*
- * Simslew option description:
- */
-tSCC zSimslewText[] =
- "Simuator slew";
-tSCC zSimslew_NAME[] = "SIMSLEW";
-tSCC zSimslew_Name[] = "simslew";
-#define SIMSLEW_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Jaildir option description:
- */
-tSCC zJaildirText[] =
- "Jail directory";
-tSCC zJaildir_NAME[] = "JAILDIR";
-tSCC zJaildir_Name[] = "jaildir";
-#define JAILDIR_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Interface option description:
- */
-tSCC zInterfaceText[] =
- "Listen on interface";
-tSCC zInterface_NAME[] = "INTERFACE";
-tSCC zInterface_Name[] = "interface";
-#define INTERFACE_FLAGS (OPTST_DISABLED | OPTST_STACKED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Keyfile option description:
- */
-tSCC zKeyfileText[] =
- "path to symmetric keys";
-tSCC zKeyfile_NAME[] = "KEYFILE";
-tSCC zKeyfile_Name[] = "keyfile";
-#define KEYFILE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Logfile option description:
- */
-tSCC zLogfileText[] =
- "path to the log file";
-tSCC zLogfile_NAME[] = "LOGFILE";
-tSCC zLogfile_Name[] = "logfile";
-#define LOGFILE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Novirtualips option description:
- */
-tSCC zNovirtualipsText[] =
- "Do not listen to virtual IPs";
-tSCC zNovirtualips_NAME[] = "NOVIRTUALIPS";
-tSCC zNovirtualips_Name[] = "novirtualips";
-#define NOVIRTUALIPS_FLAGS (OPTST_DISABLED)
-
-/*
- * Modifymmtimer option description:
- */
-#ifdef SYS_WINNT
-tSCC zModifymmtimerText[] =
- "Modify Multimedia Timer (Windows only)";
-tSCC zModifymmtimer_NAME[] = "MODIFYMMTIMER";
-tSCC zModifymmtimer_Name[] = "modifymmtimer";
-#define MODIFYMMTIMER_FLAGS (OPTST_DISABLED)
-
-#else /* disable Modifymmtimer */
-#define VALUE_OPT_MODIFYMMTIMER NO_EQUIVALENT
-#define MODIFYMMTIMER_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
-#define zModifymmtimerText NULL
-#define zModifymmtimer_NAME NULL
-#define zModifymmtimer_Name NULL
-#endif /* SYS_WINNT */
-
-/*
- * Nofork option description:
- */
-tSCC zNoforkText[] =
- "Do not fork";
-tSCC zNofork_NAME[] = "NOFORK";
-tSCC zNofork_Name[] = "nofork";
-#define NOFORK_FLAGS (OPTST_DISABLED)
-
-/*
- * Nice option description:
- */
-tSCC zNiceText[] =
- "Run at high priority";
-tSCC zNice_NAME[] = "NICE";
-tSCC zNice_Name[] = "nice";
-#define NICE_FLAGS (OPTST_DISABLED)
-
-/*
- * Servertime option description:
- */
-tSCC zServertimeText[] =
- "Server time";
-tSCC zServertime_NAME[] = "SERVERTIME";
-tSCC zServertime_Name[] = "servertime";
-#define SERVERTIME_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Pidfile option description:
- */
-tSCC zPidfileText[] =
- "path to the PID file";
-tSCC zPidfile_NAME[] = "PIDFILE";
-tSCC zPidfile_Name[] = "pidfile";
-#define PIDFILE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Priority option description:
- */
-tSCC zPriorityText[] =
- "Process priority";
-tSCC zPriority_NAME[] = "PRIORITY";
-tSCC zPriority_Name[] = "priority";
-#define PRIORITY_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
-
-/*
- * Quit option description:
- */
-tSCC zQuitText[] =
- "Set the time and quit";
-tSCC zQuit_NAME[] = "QUIT";
-tSCC zQuit_Name[] = "quit";
-#define QUIT_FLAGS (OPTST_DISABLED)
-
-/*
- * Propagationdelay option description:
- */
-tSCC zPropagationdelayText[] =
- "Broadcast/propagation delay";
-tSCC zPropagationdelay_NAME[] = "PROPAGATIONDELAY";
-tSCC zPropagationdelay_Name[] = "propagationdelay";
-#define PROPAGATIONDELAY_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Updateinterval option description:
- */
-tSCC zUpdateintervalText[] =
- "interval in seconds between scans for new or dropped interfaces";
-tSCC zUpdateinterval_NAME[] = "UPDATEINTERVAL";
-tSCC zUpdateinterval_Name[] = "updateinterval";
-#define UPDATEINTERVAL_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
-
-/*
- * Statsdir option description:
- */
-tSCC zStatsdirText[] =
- "Statistics file location";
-tSCC zStatsdir_NAME[] = "STATSDIR";
-tSCC zStatsdir_Name[] = "statsdir";
-#define STATSDIR_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Endsimtime option description:
- */
-tSCC zEndsimtimeText[] =
- "Simulation end time";
-tSCC zEndsimtime_NAME[] = "ENDSIMTIME";
-tSCC zEndsimtime_Name[] = "endsimtime";
-#define ENDSIMTIME_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Trustedkey option description:
- */
-tSCC zTrustedkeyText[] =
- "Trusted key number";
-tSCC zTrustedkey_NAME[] = "TRUSTEDKEY";
-tSCC zTrustedkey_Name[] = "trustedkey";
-#define TRUSTEDKEY_FLAGS (OPTST_DISABLED | OPTST_STACKED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Freqerr option description:
- */
-tSCC zFreqerrText[] =
- "Simulation frequency error";
-tSCC zFreqerr_NAME[] = "FREQERR";
-tSCC zFreqerr_Name[] = "freqerr";
-#define FREQERR_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Walknoise option description:
- */
-tSCC zWalknoiseText[] =
- "Simulation random walk noise";
-tSCC zWalknoise_NAME[] = "WALKNOISE";
-tSCC zWalknoise_Name[] = "walknoise";
-#define WALKNOISE_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * User option description:
- */
-tSCC zUserText[] =
- "Run as userid (or userid:groupid)";
-tSCC zUser_NAME[] = "USER";
-tSCC zUser_Name[] = "user";
-#define USER_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Var option description:
- */
-tSCC zVarText[] =
- "make ARG an ntp variable (RW)";
-tSCC zVar_NAME[] = "VAR";
-tSCC zVar_Name[] = "var";
-#define VAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Dvar option description:
- */
-tSCC zDvarText[] =
- "make ARG an ntp variable (RW|DEF)";
-tSCC zDvar_NAME[] = "DVAR";
-tSCC zDvar_Name[] = "dvar";
-#define DVAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Slew option description:
- */
-tSCC zSlewText[] =
- "Slew up to 600 seconds";
-tSCC zSlew_NAME[] = "SLEW";
-tSCC zSlew_Name[] = "slew";
-#define SLEW_FLAGS (OPTST_DISABLED)
-
-/*
- * Ndelay option description:
- */
-tSCC zNdelayText[] =
- "Simulation network delay";
-tSCC zNdelay_NAME[] = "NDELAY";
-tSCC zNdelay_Name[] = "ndelay";
-#define NDELAY_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Pdelay option description:
- */
-tSCC zPdelayText[] =
- "Simulation processing delay";
-tSCC zPdelay_NAME[] = "PDELAY";
-tSCC zPdelay_Name[] = "pdelay";
-#define PDELAY_FLAGS (OPTST_DISABLED \
- | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
-
-/*
- * Help/More_Help/Version option descriptions:
- */
-tSCC zHelpText[] = "Display usage information and exit";
-tSCC zHelp_Name[] = "help";
-
-tSCC zMore_HelpText[] = "Extended usage information passed thru pager";
-tSCC zMore_Help_Name[] = "more-help";
-
-tSCC zVersionText[] = "Output version information and exit";
-tSCC zVersion_Name[] = "version";
-
-/*
- * Save/Load_Opts option description:
- */
-tSCC zSave_OptsText[] = "Save the option state to a config file";
-tSCC zSave_Opts_Name[] = "save-opts";
-
-tSCC zLoad_OptsText[] = "Load options from a config file";
-tSCC zLoad_Opts_NAME[] = "LOAD_OPTS";
-
-tSCC zNotLoad_Opts_Name[] = "no-load-opts";
-tSCC zNotLoad_Opts_Pfx[] = "no";
-#define zLoad_Opts_Name (zNotLoad_Opts_Name + 3)
-/*
- * Declare option callback procedures
- */
-#ifdef DEBUG
- static tOptProc doOptSet_Debug_Level;
-#else /* not DEBUG */
-# define doOptSet_Debug_Level NULL
-#endif /* def/not DEBUG */
-#if defined(TEST_NTPDSIM_OPTS)
-/*
- * Under test, omit argument processing, or call optionStackArg,
- * if multiple copies are allowed.
- */
-extern tOptProc
- optionNumericVal, optionPagedUsage, optionStackArg,
- optionVersionStderr;
-static tOptProc
- doUsageOpt;
-
-/*
- * #define map the "normal" callout procs to the test ones...
- */
-#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
-
-
-#else /* NOT defined TEST_NTPDSIM_OPTS */
-/*
- * When not under test, there are different procs to use
- */
-extern tOptProc
- optionNumericVal, optionPagedUsage, optionPrintVersion, optionStackArg;
-static tOptProc
- doUsageOpt;
-
-/*
- * #define map the "normal" callout procs
- */
-#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
-
-#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
-#endif /* defined(TEST_NTPDSIM_OPTS) */
-#ifdef TEST_NTPDSIM_OPTS
-# define DOVERPROC optionVersionStderr
-#else
-# define DOVERPROC optionPrintVersion
-#endif /* TEST_NTPDSIM_OPTS */
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Define the Ntpdsim Option Descriptions.
- */
-static tOptDesc optDesc[ OPTION_CT ] = {
- { /* entry idx, value */ 0, VALUE_OPT_IPV4,
- /* equiv idx, value */ NO_EQUIVALENT, 0,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ IPV4_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 1, VALUE_OPT_IPV6,
- /* equiv idx, value */ NOLIMIT, NOLIMIT,
- /* equivalenced to */ INDEX_OPT_IPV4,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ IPV6_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 2, VALUE_OPT_AUTHREQ,
- /* equiv idx, value */ 2, VALUE_OPT_AUTHREQ,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ AUTHREQ_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, aAuthreqCantList,
- /* option proc */ NULL,
- /* desc, NAME, name */ zAuthreqText, zAuthreq_NAME, zAuthreq_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 3, VALUE_OPT_AUTHNOREQ,
- /* equiv idx, value */ 3, VALUE_OPT_AUTHNOREQ,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ AUTHNOREQ_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, aAuthnoreqCantList,
- /* option proc */ NULL,
- /* desc, NAME, name */ zAuthnoreqText, zAuthnoreq_NAME, zAuthnoreq_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 4, VALUE_OPT_BCASTSYNC,
- /* equiv idx, value */ 4, VALUE_OPT_BCASTSYNC,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ BCASTSYNC_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zBcastsyncText, zBcastsync_NAME, zBcastsync_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 5, VALUE_OPT_SIMBROADCASTDELAY,
- /* equiv idx, value */ 5, VALUE_OPT_SIMBROADCASTDELAY,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ SIMBROADCASTDELAY_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zSimbroadcastdelayText, zSimbroadcastdelay_NAME, zSimbroadcastdelay_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 6, VALUE_OPT_CONFIGFILE,
- /* equiv idx, value */ 6, VALUE_OPT_CONFIGFILE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ CONFIGFILE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zConfigfileText, zConfigfile_NAME, zConfigfile_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 7, VALUE_OPT_PHASENOISE,
- /* equiv idx, value */ 7, VALUE_OPT_PHASENOISE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ PHASENOISE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zPhasenoiseText, zPhasenoise_NAME, zPhasenoise_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 8, VALUE_OPT_DEBUG_LEVEL,
- /* equiv idx, value */ 8, VALUE_OPT_DEBUG_LEVEL,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ DEBUG_LEVEL_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 9, VALUE_OPT_SET_DEBUG_LEVEL,
- /* equiv idx, value */ 9, VALUE_OPT_SET_DEBUG_LEVEL,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ SET_DEBUG_LEVEL_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ SET_DEBUG_LEVEL_OPT_PROC,
- /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 10, VALUE_OPT_DRIFTFILE,
- /* equiv idx, value */ 10, VALUE_OPT_DRIFTFILE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ DRIFTFILE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zDriftfileText, zDriftfile_NAME, zDriftfile_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 11, VALUE_OPT_PANICGATE,
- /* equiv idx, value */ 11, VALUE_OPT_PANICGATE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ PANICGATE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zPanicgateText, zPanicgate_NAME, zPanicgate_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 12, VALUE_OPT_SIMSLEW,
- /* equiv idx, value */ 12, VALUE_OPT_SIMSLEW,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ SIMSLEW_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zSimslewText, zSimslew_NAME, zSimslew_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 13, VALUE_OPT_JAILDIR,
- /* equiv idx, value */ 13, VALUE_OPT_JAILDIR,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ JAILDIR_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zJaildirText, zJaildir_NAME, zJaildir_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 14, VALUE_OPT_INTERFACE,
- /* equiv idx, value */ 14, VALUE_OPT_INTERFACE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ INTERFACE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionStackArg,
- /* desc, NAME, name */ zInterfaceText, zInterface_NAME, zInterface_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 15, VALUE_OPT_KEYFILE,
- /* equiv idx, value */ 15, VALUE_OPT_KEYFILE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ KEYFILE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zKeyfileText, zKeyfile_NAME, zKeyfile_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 16, VALUE_OPT_LOGFILE,
- /* equiv idx, value */ 16, VALUE_OPT_LOGFILE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ LOGFILE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zLogfileText, zLogfile_NAME, zLogfile_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 17, VALUE_OPT_NOVIRTUALIPS,
- /* equiv idx, value */ 17, VALUE_OPT_NOVIRTUALIPS,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ NOVIRTUALIPS_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zNovirtualipsText, zNovirtualips_NAME, zNovirtualips_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 18, VALUE_OPT_MODIFYMMTIMER,
- /* equiv idx, value */ 18, VALUE_OPT_MODIFYMMTIMER,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ MODIFYMMTIMER_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zModifymmtimerText, zModifymmtimer_NAME, zModifymmtimer_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 19, VALUE_OPT_NOFORK,
- /* equiv idx, value */ 19, VALUE_OPT_NOFORK,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ NOFORK_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zNoforkText, zNofork_NAME, zNofork_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 20, VALUE_OPT_NICE,
- /* equiv idx, value */ 20, VALUE_OPT_NICE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ NICE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zNiceText, zNice_NAME, zNice_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 21, VALUE_OPT_SERVERTIME,
- /* equiv idx, value */ 21, VALUE_OPT_SERVERTIME,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ SERVERTIME_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zServertimeText, zServertime_NAME, zServertime_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 22, VALUE_OPT_PIDFILE,
- /* equiv idx, value */ 22, VALUE_OPT_PIDFILE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ PIDFILE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zPidfileText, zPidfile_NAME, zPidfile_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 23, VALUE_OPT_PRIORITY,
- /* equiv idx, value */ 23, VALUE_OPT_PRIORITY,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ PRIORITY_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionNumericVal,
- /* desc, NAME, name */ zPriorityText, zPriority_NAME, zPriority_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 24, VALUE_OPT_QUIT,
- /* equiv idx, value */ 24, VALUE_OPT_QUIT,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ QUIT_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zQuitText, zQuit_NAME, zQuit_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 25, VALUE_OPT_PROPAGATIONDELAY,
- /* equiv idx, value */ 25, VALUE_OPT_PROPAGATIONDELAY,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ PROPAGATIONDELAY_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zPropagationdelayText, zPropagationdelay_NAME, zPropagationdelay_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 26, VALUE_OPT_UPDATEINTERVAL,
- /* equiv idx, value */ 26, VALUE_OPT_UPDATEINTERVAL,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ UPDATEINTERVAL_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionNumericVal,
- /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 27, VALUE_OPT_STATSDIR,
- /* equiv idx, value */ 27, VALUE_OPT_STATSDIR,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ STATSDIR_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zStatsdirText, zStatsdir_NAME, zStatsdir_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 28, VALUE_OPT_ENDSIMTIME,
- /* equiv idx, value */ 28, VALUE_OPT_ENDSIMTIME,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ ENDSIMTIME_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zEndsimtimeText, zEndsimtime_NAME, zEndsimtime_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 29, VALUE_OPT_TRUSTEDKEY,
- /* equiv idx, value */ 29, VALUE_OPT_TRUSTEDKEY,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ TRUSTEDKEY_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionStackArg,
- /* desc, NAME, name */ zTrustedkeyText, zTrustedkey_NAME, zTrustedkey_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 30, VALUE_OPT_FREQERR,
- /* equiv idx, value */ 30, VALUE_OPT_FREQERR,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ FREQERR_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zFreqerrText, zFreqerr_NAME, zFreqerr_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 31, VALUE_OPT_WALKNOISE,
- /* equiv idx, value */ 31, VALUE_OPT_WALKNOISE,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ WALKNOISE_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zWalknoiseText, zWalknoise_NAME, zWalknoise_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 32, VALUE_OPT_USER,
- /* equiv idx, value */ 32, VALUE_OPT_USER,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ USER_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zUserText, zUser_NAME, zUser_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 33, VALUE_OPT_VAR,
- /* equiv idx, value */ 33, VALUE_OPT_VAR,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ VAR_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionStackArg,
- /* desc, NAME, name */ zVarText, zVar_NAME, zVar_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 34, VALUE_OPT_DVAR,
- /* equiv idx, value */ 34, VALUE_OPT_DVAR,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ DVAR_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionStackArg,
- /* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 35, VALUE_OPT_SLEW,
- /* equiv idx, value */ 35, VALUE_OPT_SLEW,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ SLEW_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 36, VALUE_OPT_NDELAY,
- /* equiv idx, value */ 36, VALUE_OPT_NDELAY,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ NDELAY_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zNdelayText, zNdelay_NAME, zNdelay_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ 37, VALUE_OPT_PDELAY,
- /* equiv idx, value */ 37, VALUE_OPT_PDELAY,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ PDELAY_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zPdelayText, zPdelay_NAME, zPdelay_Name,
- /* disablement strs */ NULL, NULL },
-
-#ifdef NO_OPTIONAL_OPT_ARGS
-# define VERSION_OPT_FLAGS OPTST_IMM | OPTST_NO_INIT
-#else
-# define VERSION_OPT_FLAGS OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
- OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT
-#endif
-
- { /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
- /* equiv idx value */ NO_EQUIVALENT, 0,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ VERSION_OPT_FLAGS, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ DOVERPROC,
- /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
- /* disablement strs */ NULL, NULL },
-
-#undef VERSION_OPT_FLAGS
-
-
- { /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
- /* equiv idx value */ NO_EQUIVALENT, 0,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ doUsageOpt,
- /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
- /* equiv idx value */ NO_EQUIVALENT, 0,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionPagedUsage,
- /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
- /* equiv idx value */ NO_EQUIVALENT, 0,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, 1, 0,
- /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
- | OPTST_ARG_OPTIONAL | OPTST_NO_INIT, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ NULL,
- /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
- /* disablement strs */ NULL, NULL },
-
- { /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
- /* equiv idx value */ NO_EQUIVALENT, 0,
- /* equivalenced to */ NO_EQUIVALENT,
- /* min, max, act ct */ 0, NOLIMIT, 0,
- /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) \
- | OPTST_DISABLE_IMM, 0,
- /* last opt argumnt */ { NULL },
- /* arg list/cookie */ NULL,
- /* must/cannot opts */ NULL, NULL,
- /* option proc */ optionLoadOpt,
- /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
- /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
-};
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * Define the Ntpdsim Option Environment
- */
-tSCC zPROGNAME[] = "NTPDSIM";
-tSCC zUsageTitle[] =
-"ntpdsim - NTP daemon simulation program - Ver. 4.2.4p8\n\
-USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
-tSCC zRcName[] = ".ntprc";
-tSCC* apzHomeList[] = {
- "$HOME",
- ".",
- NULL };
-
-tSCC zBugsAddr[] = "http://bugs.ntp.org, bugs@ntp.org";
-#define zExplain NULL
-tSCC zDetail[] = "\n\n";
-tSCC zFullVersion[] = NTPDSIM_FULL_VERSION;
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/optcode.tpl near line 408 */
-
-#if defined(ENABLE_NLS)
-# define OPTPROC_BASE OPTPROC_TRANSLATE
- static tOptionXlateProc translate_option_strings;
-#else
-# define OPTPROC_BASE OPTPROC_NONE
-# define translate_option_strings NULL
-#endif /* ENABLE_NLS */
-
-tOptions ntpdsimOptions = {
- OPTIONS_STRUCT_VERSION,
- 0, NULL, /* original argc + argv */
- ( OPTPROC_BASE
- + OPTPROC_ERRSTOP
- + OPTPROC_SHORTOPT
- + OPTPROC_LONGOPT
- + OPTPROC_NO_REQ_OPT
- + OPTPROC_ENVIRON
- + OPTPROC_NO_ARGS
- + OPTPROC_HAS_IMMED ),
- 0, NULL, /* current option index, current option */
- NULL, NULL, zPROGNAME,
- zRcName, zCopyright, zCopyrightNotice,
- zFullVersion, apzHomeList, zUsageTitle,
- zExplain, zDetail, optDesc,
- zBugsAddr, /* address to send bugs to */
- NULL, NULL, /* extensions/saved state */
- optionUsage, /* usage procedure */
- translate_option_strings, /* translation procedure */
- /*
- * Indexes to special options
- */
- { INDEX_OPT_MORE_HELP,
- INDEX_OPT_SAVE_OPTS,
- NO_EQUIVALENT /* index of '-#' option */,
- NO_EQUIVALENT /* index of default opt */
- },
- 43 /* full option count */, 38 /* user option count */
-};
-
-/*
- * Create the static procedure(s) declared above.
- */
-static void
-doUsageOpt(
- tOptions* pOptions,
- tOptDesc* pOptDesc )
-{
- USAGE( EXIT_SUCCESS );
-}
-
-#if ! defined(TEST_NTPDSIM_OPTS)
-
-/* * * * * * *
- *
- * For the set-debug-level option, when DEBUG is #define-d.
- */
-#ifdef DEBUG
-static void
-doOptSet_Debug_Level(
- tOptions* pOptions,
- tOptDesc* pOptDesc )
-{
- /* extracted from ../include/debug-opt.def, line 29 */
-DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
-}
-#endif /* defined DEBUG */
-
-#endif /* defined(TEST_NTPDSIM_OPTS) */
-
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/optmain.tpl near line 92 */
-
-#if defined(TEST_NTPDSIM_OPTS) /* TEST MAIN PROCEDURE: */
-
-int
-main( int argc, char** argv )
-{
- int res = EXIT_SUCCESS;
- (void)optionProcess( &ntpdsimOptions, argc, argv );
- {
- void optionPutShell( tOptions* );
- optionPutShell( &ntpdsimOptions );
- }
- return res;
-}
-#endif /* defined TEST_NTPDSIM_OPTS */
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/optcode.tpl near line 514 */
-
-#if ENABLE_NLS
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <autoopts/usage-txt.h>
-
-static char* AO_gettext( char const* pz );
-static void coerce_it(void** s);
-
-static char*
-AO_gettext( char const* pz )
-{
- char* pzRes;
- if (pz == NULL)
- return NULL;
- pzRes = _(pz);
- if (pzRes == pz)
- return pzRes;
- pzRes = strdup( pzRes );
- if (pzRes == NULL) {
- fputs( _("No memory for duping translated strings\n"), stderr );
- exit( EXIT_FAILURE );
- }
- return pzRes;
-}
-
-static void coerce_it(void** s) { *s = AO_gettext(*s); }
-#define COERSION(_f) \
- coerce_it((void*)&(ntpdsimOptions._f))
-
-/*
- * This invokes the translation code (e.g. gettext(3)).
- */
-static void
-translate_option_strings( void )
-{
- /*
- * Guard against re-translation. It won't work. The strings will have
- * been changed by the first pass through this code. One shot only.
- */
- if (option_usage_text.field_ct == 0)
- return;
- /*
- * Do the translations. The first pointer follows the field count field.
- * The field count field is the size of a pointer.
- */
- {
- char** ppz = (char**)(void*)&(option_usage_text);
- int ix = option_usage_text.field_ct;
-
- do {
- ppz++;
- *ppz = AO_gettext(*ppz);
- } while (--ix > 0);
- }
- option_usage_text.field_ct = 0;
-
- {
- tOptDesc* pOD = ntpdsimOptions.pOptDesc;
- int ix = ntpdsimOptions.optCt;
-
- for (;;) {
- pOD->pzText = AO_gettext(pOD->pzText);
- pOD->pz_NAME = AO_gettext(pOD->pz_NAME);
- pOD->pz_Name = AO_gettext(pOD->pz_Name);
- pOD->pz_DisableName = AO_gettext(pOD->pz_DisableName);
- pOD->pz_DisablePfx = AO_gettext(pOD->pz_DisablePfx);
- if (--ix <= 0)
- break;
- pOD++;
- }
- }
- COERSION(pzCopyright);
- COERSION(pzCopyNotice);
- COERSION(pzFullVersion);
- COERSION(pzUsageTitle);
- COERSION(pzExplain);
- COERSION(pzDetail);
-}
-
-#endif /* ENABLE_NLS */
-
-#ifdef __cplusplus
-}
-#endif
-/* ntpdsim-opts.c ends here */
diff --git a/ntpd/ntpdsim-opts.def b/ntpd/ntpdsim-opts.def
deleted file mode 100644
index 093c325cf209..000000000000
--- a/ntpd/ntpdsim-opts.def
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -*- Mode: Text -*- */
-
-autogen definitions options;
-
-#include copyright.def
-#include homerc.def
-
-prog-name = "ntpdsim";
-prog-title = "NTP daemon simulation program";
-
-#define SIM
-#include ntpdbase-opts.def
-
-detail = <<- _END_DETAIL
- _END_DETAIL;
diff --git a/ntpd/ntpdsim-opts.h b/ntpd/ntpdsim-opts.h
deleted file mode 100644
index 3458bbfd0deb..000000000000
--- a/ntpd/ntpdsim-opts.h
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * EDIT THIS FILE WITH CAUTION (ntpdsim-opts.h)
- *
- * It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:12 AM EST
- * From the definitions ntpdsim-opts.def
- * and the template file options
- *
- * Generated from AutoOpts 29:0:4 templates.
- */
-
-/*
- * This file was produced by an AutoOpts template. AutoOpts is a
- * copyrighted work. This header file is not encumbered by AutoOpts
- * licensing, but is provided under the licensing terms chosen by the
- * ntpdsim author or copyright holder. AutoOpts is licensed under
- * the terms of the LGPL. The redistributable library (``libopts'') is
- * licensed under the terms of either the LGPL or, at the users discretion,
- * the BSD license. See the AutoOpts and/or libopts sources for details.
- *
- * This source file is copyrighted and licensed under the following terms:
- *
- * ntpdsim copyright 1970-2009 David L. Mills and/or others - all rights reserved
- *
- * see html/copyright.html
- */
-/*
- * This file contains the programmatic interface to the Automated
- * Options generated for the ntpdsim program.
- * These macros are documented in the AutoGen info file in the
- * "AutoOpts" chapter. Please refer to that doc for usage help.
- */
-#ifndef AUTOOPTS_NTPDSIM_OPTS_H_GUARD
-#define AUTOOPTS_NTPDSIM_OPTS_H_GUARD
-#include "config.h"
-#include <autoopts/options.h>
-
-/*
- * Ensure that the library used for compiling this generated header is at
- * least as new as the version current when the header template was released
- * (not counting patch version increments). Also ensure that the oldest
- * tolerable version is at least as old as what was current when the header
- * template was released.
- */
-#define AO_TEMPLATE_VERSION 118784
-#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
- || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
-# error option template version mismatches autoopts/options.h header
- Choke Me.
-#endif
-
-/*
- * Enumeration of each option:
- */
-typedef enum {
- INDEX_OPT_IPV4 = 0,
- INDEX_OPT_IPV6 = 1,
- INDEX_OPT_AUTHREQ = 2,
- INDEX_OPT_AUTHNOREQ = 3,
- INDEX_OPT_BCASTSYNC = 4,
- INDEX_OPT_SIMBROADCASTDELAY = 5,
- INDEX_OPT_CONFIGFILE = 6,
- INDEX_OPT_PHASENOISE = 7,
- INDEX_OPT_DEBUG_LEVEL = 8,
- INDEX_OPT_SET_DEBUG_LEVEL = 9,
- INDEX_OPT_DRIFTFILE = 10,
- INDEX_OPT_PANICGATE = 11,
- INDEX_OPT_SIMSLEW = 12,
- INDEX_OPT_JAILDIR = 13,
- INDEX_OPT_INTERFACE = 14,
- INDEX_OPT_KEYFILE = 15,
- INDEX_OPT_LOGFILE = 16,
- INDEX_OPT_NOVIRTUALIPS = 17,
- INDEX_OPT_MODIFYMMTIMER = 18,
- INDEX_OPT_NOFORK = 19,
- INDEX_OPT_NICE = 20,
- INDEX_OPT_SERVERTIME = 21,
- INDEX_OPT_PIDFILE = 22,
- INDEX_OPT_PRIORITY = 23,
- INDEX_OPT_QUIT = 24,
- INDEX_OPT_PROPAGATIONDELAY = 25,
- INDEX_OPT_UPDATEINTERVAL = 26,
- INDEX_OPT_STATSDIR = 27,
- INDEX_OPT_ENDSIMTIME = 28,
- INDEX_OPT_TRUSTEDKEY = 29,
- INDEX_OPT_FREQERR = 30,
- INDEX_OPT_WALKNOISE = 31,
- INDEX_OPT_USER = 32,
- INDEX_OPT_VAR = 33,
- INDEX_OPT_DVAR = 34,
- INDEX_OPT_SLEW = 35,
- INDEX_OPT_NDELAY = 36,
- INDEX_OPT_PDELAY = 37,
- INDEX_OPT_VERSION = 38,
- INDEX_OPT_HELP = 39,
- INDEX_OPT_MORE_HELP = 40,
- INDEX_OPT_SAVE_OPTS = 41,
- INDEX_OPT_LOAD_OPTS = 42
-} teOptIndex;
-
-#define OPTION_CT 43
-#define NTPDSIM_VERSION "4.2.4p8"
-#define NTPDSIM_FULL_VERSION "ntpdsim - NTP daemon simulation program - Ver. 4.2.4p8"
-
-/*
- * Interface defines for all options. Replace "n" with the UPPER_CASED
- * option name (as in the teOptIndex enumeration above).
- * e.g. HAVE_OPT( IPV4 )
- */
-#define DESC(n) (ntpdsimOptions.pOptDesc[INDEX_OPT_## n])
-#define HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
-#define OPT_ARG(n) (DESC(n).optArg.argString)
-#define STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
-#define COUNT_OPT(n) (DESC(n).optOccCt)
-#define ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
-#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
-#define ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
-#define STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
-#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
-#define CLEAR_OPT(n) STMTS( \
- DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \
- if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
- DESC(n).fOptState |= OPTST_DISABLED; \
- DESC(n).optCookie = NULL )
-
-/*
- * Make sure there are no #define name conflicts with the option names
- */
-#ifndef NO_OPTION_NAME_WARNINGS
-# ifdef IPV4
-# warning undefining IPV4 due to option name conflict
-# undef IPV4
-# endif
-# ifdef IPV6
-# warning undefining IPV6 due to option name conflict
-# undef IPV6
-# endif
-# ifdef AUTHREQ
-# warning undefining AUTHREQ due to option name conflict
-# undef AUTHREQ
-# endif
-# ifdef AUTHNOREQ
-# warning undefining AUTHNOREQ due to option name conflict
-# undef AUTHNOREQ
-# endif
-# ifdef BCASTSYNC
-# warning undefining BCASTSYNC due to option name conflict
-# undef BCASTSYNC
-# endif
-# ifdef SIMBROADCASTDELAY
-# warning undefining SIMBROADCASTDELAY due to option name conflict
-# undef SIMBROADCASTDELAY
-# endif
-# ifdef CONFIGFILE
-# warning undefining CONFIGFILE due to option name conflict
-# undef CONFIGFILE
-# endif
-# ifdef PHASENOISE
-# warning undefining PHASENOISE due to option name conflict
-# undef PHASENOISE
-# endif
-# ifdef DEBUG_LEVEL
-# warning undefining DEBUG_LEVEL due to option name conflict
-# undef DEBUG_LEVEL
-# endif
-# ifdef SET_DEBUG_LEVEL
-# warning undefining SET_DEBUG_LEVEL due to option name conflict
-# undef SET_DEBUG_LEVEL
-# endif
-# ifdef DRIFTFILE
-# warning undefining DRIFTFILE due to option name conflict
-# undef DRIFTFILE
-# endif
-# ifdef PANICGATE
-# warning undefining PANICGATE due to option name conflict
-# undef PANICGATE
-# endif
-# ifdef SIMSLEW
-# warning undefining SIMSLEW due to option name conflict
-# undef SIMSLEW
-# endif
-# ifdef JAILDIR
-# warning undefining JAILDIR due to option name conflict
-# undef JAILDIR
-# endif
-# ifdef INTERFACE
-# warning undefining INTERFACE due to option name conflict
-# undef INTERFACE
-# endif
-# ifdef KEYFILE
-# warning undefining KEYFILE due to option name conflict
-# undef KEYFILE
-# endif
-# ifdef LOGFILE
-# warning undefining LOGFILE due to option name conflict
-# undef LOGFILE
-# endif
-# ifdef NOVIRTUALIPS
-# warning undefining NOVIRTUALIPS due to option name conflict
-# undef NOVIRTUALIPS
-# endif
-# ifdef MODIFYMMTIMER
-# warning undefining MODIFYMMTIMER due to option name conflict
-# undef MODIFYMMTIMER
-# endif
-# ifdef NOFORK
-# warning undefining NOFORK due to option name conflict
-# undef NOFORK
-# endif
-# ifdef NICE
-# warning undefining NICE due to option name conflict
-# undef NICE
-# endif
-# ifdef SERVERTIME
-# warning undefining SERVERTIME due to option name conflict
-# undef SERVERTIME
-# endif
-# ifdef PIDFILE
-# warning undefining PIDFILE due to option name conflict
-# undef PIDFILE
-# endif
-# ifdef PRIORITY
-# warning undefining PRIORITY due to option name conflict
-# undef PRIORITY
-# endif
-# ifdef QUIT
-# warning undefining QUIT due to option name conflict
-# undef QUIT
-# endif
-# ifdef PROPAGATIONDELAY
-# warning undefining PROPAGATIONDELAY due to option name conflict
-# undef PROPAGATIONDELAY
-# endif
-# ifdef UPDATEINTERVAL
-# warning undefining UPDATEINTERVAL due to option name conflict
-# undef UPDATEINTERVAL
-# endif
-# ifdef STATSDIR
-# warning undefining STATSDIR due to option name conflict
-# undef STATSDIR
-# endif
-# ifdef ENDSIMTIME
-# warning undefining ENDSIMTIME due to option name conflict
-# undef ENDSIMTIME
-# endif
-# ifdef TRUSTEDKEY
-# warning undefining TRUSTEDKEY due to option name conflict
-# undef TRUSTEDKEY
-# endif
-# ifdef FREQERR
-# warning undefining FREQERR due to option name conflict
-# undef FREQERR
-# endif
-# ifdef WALKNOISE
-# warning undefining WALKNOISE due to option name conflict
-# undef WALKNOISE
-# endif
-# ifdef USER
-# warning undefining USER due to option name conflict
-# undef USER
-# endif
-# ifdef VAR
-# warning undefining VAR due to option name conflict
-# undef VAR
-# endif
-# ifdef DVAR
-# warning undefining DVAR due to option name conflict
-# undef DVAR
-# endif
-# ifdef SLEW
-# warning undefining SLEW due to option name conflict
-# undef SLEW
-# endif
-# ifdef NDELAY
-# warning undefining NDELAY due to option name conflict
-# undef NDELAY
-# endif
-# ifdef PDELAY
-# warning undefining PDELAY due to option name conflict
-# undef PDELAY
-# endif
-#else /* NO_OPTION_NAME_WARNINGS */
-# undef IPV4
-# undef IPV6
-# undef AUTHREQ
-# undef AUTHNOREQ
-# undef BCASTSYNC
-# undef SIMBROADCASTDELAY
-# undef CONFIGFILE
-# undef PHASENOISE
-# undef DEBUG_LEVEL
-# undef SET_DEBUG_LEVEL
-# undef DRIFTFILE
-# undef PANICGATE
-# undef SIMSLEW
-# undef JAILDIR
-# undef INTERFACE
-# undef KEYFILE
-# undef LOGFILE
-# undef NOVIRTUALIPS
-# undef MODIFYMMTIMER
-# undef NOFORK
-# undef NICE
-# undef SERVERTIME
-# undef PIDFILE
-# undef PRIORITY
-# undef QUIT
-# undef PROPAGATIONDELAY
-# undef UPDATEINTERVAL
-# undef STATSDIR
-# undef ENDSIMTIME
-# undef TRUSTEDKEY
-# undef FREQERR
-# undef WALKNOISE
-# undef USER
-# undef VAR
-# undef DVAR
-# undef SLEW
-# undef NDELAY
-# undef PDELAY
-#endif /* NO_OPTION_NAME_WARNINGS */
-
-/*
- * Interface defines for specific options.
- */
-#define VALUE_OPT_IPV4 '4'
-#define WHICH_OPT_IPV4 (DESC(IPV4).optActualValue)
-#define WHICH_IDX_IPV4 (DESC(IPV4).optActualIndex)
-#define VALUE_OPT_IPV6 '6'
-#define VALUE_OPT_AUTHREQ 'a'
-#define VALUE_OPT_AUTHNOREQ 'A'
-#define VALUE_OPT_BCASTSYNC 'b'
-#define VALUE_OPT_SIMBROADCASTDELAY 'B'
-#define VALUE_OPT_CONFIGFILE 'c'
-#define VALUE_OPT_PHASENOISE 'C'
-#ifdef DEBUG
-#define VALUE_OPT_DEBUG_LEVEL 'd'
-#endif /* DEBUG */
-#ifdef DEBUG
-#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
-#endif /* DEBUG */
-#define VALUE_OPT_DRIFTFILE 'f'
-#define VALUE_OPT_PANICGATE 'g'
-#define VALUE_OPT_SIMSLEW 'H'
-#define VALUE_OPT_JAILDIR 'i'
-#define VALUE_OPT_INTERFACE 'I'
-#define VALUE_OPT_KEYFILE 'k'
-#define VALUE_OPT_LOGFILE 'l'
-#define VALUE_OPT_NOVIRTUALIPS 'L'
-#ifdef SYS_WINNT
-#define VALUE_OPT_MODIFYMMTIMER 'M'
-#endif /* SYS_WINNT */
-#define VALUE_OPT_NOFORK 'n'
-#define VALUE_OPT_NICE 'N'
-#define VALUE_OPT_SERVERTIME 'O'
-#define VALUE_OPT_PIDFILE 'p'
-#define VALUE_OPT_PRIORITY 'P'
-#define OPT_VALUE_PRIORITY (DESC(PRIORITY).optArg.argInt)
-#define VALUE_OPT_QUIT 'q'
-#define VALUE_OPT_PROPAGATIONDELAY 'r'
-#define VALUE_OPT_UPDATEINTERVAL 'U'
-#define OPT_VALUE_UPDATEINTERVAL (DESC(UPDATEINTERVAL).optArg.argInt)
-#define VALUE_OPT_STATSDIR 's'
-#define VALUE_OPT_ENDSIMTIME 'S'
-#define VALUE_OPT_TRUSTEDKEY 't'
-#define VALUE_OPT_FREQERR 'T'
-#define VALUE_OPT_WALKNOISE 'W'
-#define VALUE_OPT_USER 'u'
-#define VALUE_OPT_VAR 'v'
-#define VALUE_OPT_DVAR 'V'
-#define VALUE_OPT_SLEW 'x'
-#define VALUE_OPT_NDELAY 'Y'
-#define VALUE_OPT_PDELAY 'Z'
-
-#define VALUE_OPT_VERSION 'v'
-#define VALUE_OPT_HELP '?'
-#define VALUE_OPT_MORE_HELP '!'
-#define VALUE_OPT_SAVE_OPTS '>'
-#define VALUE_OPT_LOAD_OPTS '<'
-#define SET_OPT_SAVE_OPTS(a) STMTS( \
- DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT_MASK; \
- DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
- DESC(SAVE_OPTS).optArg.argString = (char const*)(a) )
-/*
- * Interface defines not associated with particular options
- */
-#define ERRSKIP_OPTERR STMTS( ntpdsimOptions.fOptSet &= ~OPTPROC_ERRSTOP )
-#define ERRSTOP_OPTERR STMTS( ntpdsimOptions.fOptSet |= OPTPROC_ERRSTOP )
-#define RESTART_OPT(n) STMTS( \
- ntpdsimOptions.curOptIdx = (n); \
- ntpdsimOptions.pzCurOpt = NULL )
-#define START_OPT RESTART_OPT(1)
-#define USAGE(c) (*ntpdsimOptions.pUsageProc)( &ntpdsimOptions, c )
-/* extracted from /usr/local/gnu/autogen-5.9.1/share/autogen/opthead.tpl near line 360 */
-
-/* * * * * *
- *
- * Declare the ntpdsim option descriptor.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern tOptions ntpdsimOptions;
-
-#ifndef _
-# if ENABLE_NLS
-# include <stdio.h>
- static inline char* aoGetsText( char const* pz ) {
- if (pz == NULL) return NULL;
- return (char*)gettext( pz );
- }
-# define _(s) aoGetsText(s)
-# else /* ENABLE_NLS */
-# define _(s) s
-# endif /* ENABLE_NLS */
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* AUTOOPTS_NTPDSIM_OPTS_H_GUARD */
-/* ntpdsim-opts.h ends here */
diff --git a/ntpd/ntpdsim-opts.menu b/ntpd/ntpdsim-opts.menu
deleted file mode 100644
index c7874583d9ae..000000000000
--- a/ntpd/ntpdsim-opts.menu
+++ /dev/null
@@ -1 +0,0 @@
-* ntpdsim Invocation:: Invoking ntpdsim
diff --git a/ntpd/ntpdsim-opts.texi b/ntpd/ntpdsim-opts.texi
deleted file mode 100644
index ed522106276a..000000000000
--- a/ntpd/ntpdsim-opts.texi
+++ /dev/null
@@ -1,568 +0,0 @@
-@node ntpdsim Invocation
-@section Invoking ntpdsim
-@pindex ntpdsim
-@cindex NTP daemon simulation program
-@ignore
-#
-# EDIT THIS FILE WITH CAUTION (ntpdsim-opts.texi)
-#
-# It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:15 AM EST
-# From the definitions ntpdsim-opts.def
-# and the template file aginfo.tpl
-@end ignore
-This program has no explanation.
-
-
-
-This section was generated by @strong{AutoGen},
-the aginfo template and the option descriptions for the @command{ntpdsim} program. It documents the ntpdsim usage text and option meanings.
-
-This software is released under a specialized copyright license.
-
-@menu
-* ntpdsim usage:: ntpdsim usage help (-?)
-* ntpdsim authnoreq:: authnoreq option (-A)
-* ntpdsim authreq:: authreq option (-a)
-* ntpdsim bcastsync:: bcastsync option (-b)
-* ntpdsim configfile:: configfile option (-c)
-* ntpdsim debug-level:: debug-level option (-d)
-* ntpdsim driftfile:: driftfile option (-f)
-* ntpdsim dvar:: dvar option (-V)
-* ntpdsim endsimtime:: endsimtime option (-S)
-* ntpdsim freqerr:: freqerr option (-T)
-* ntpdsim interface:: interface option (-I)
-* ntpdsim ipv4:: ipv4 option (-4)
-* ntpdsim ipv6:: ipv6 option (-6)
-* ntpdsim jaildir:: jaildir option (-i)
-* ntpdsim keyfile:: keyfile option (-k)
-* ntpdsim logfile:: logfile option (-l)
-* ntpdsim modifymmtimer:: modifymmtimer option (-M)
-* ntpdsim ndelay:: ndelay option (-Y)
-* ntpdsim nice:: nice option (-N)
-* ntpdsim nofork:: nofork option (-n)
-* ntpdsim novirtualips:: novirtualips option (-L)
-* ntpdsim panicgate:: panicgate option (-g)
-* ntpdsim pdelay:: pdelay option (-Z)
-* ntpdsim phasenoise:: phasenoise option (-C)
-* ntpdsim pidfile:: pidfile option (-p)
-* ntpdsim priority:: priority option (-P)
-* ntpdsim propagationdelay:: propagationdelay option (-r)
-* ntpdsim quit:: quit option (-q)
-* ntpdsim servertime:: servertime option (-O)
-* ntpdsim set-debug-level:: set-debug-level option (-D)
-* ntpdsim simbroadcastdelay:: simbroadcastdelay option (-B)
-* ntpdsim simslew:: simslew option (-H)
-* ntpdsim slew:: slew option (-x)
-* ntpdsim statsdir:: statsdir option (-s)
-* ntpdsim trustedkey:: trustedkey option (-t)
-* ntpdsim updateinterval:: updateinterval option (-U)
-* ntpdsim user:: user option (-u)
-* ntpdsim var:: var option (-v)
-* ntpdsim walknoise:: walknoise option (-W)
-@end menu
-
-@node ntpdsim usage
-@subsection ntpdsim usage help (-?)
-@cindex ntpdsim usage
-
-This is the automatically generated usage text for ntpdsim:
-
-@exampleindent 0
-@example
-ntpd - NTP daemon program - Ver. 4.2.5p247-RC
-USAGE: ntpdsim [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
- Flg Arg Option-Name Description
- -4 no ipv4 Force IPv4 DNS name resolution
- - prohibits these options:
- ipv6
- -6 no ipv6 Force IPv6 DNS name resolution
- - prohibits these options:
- ipv4
- -a no authreq Require crypto authentication
- - prohibits these options:
- authnoreq
- -A no authnoreq Do not require crypto authentication
- - prohibits these options:
- authreq
- -b no bcastsync Allow us to sync to broadcast servers
- -c Str configfile configuration file name
- -d no debug-level Increase output debug message level
- - may appear multiple times
- -D Str set-debug-level Set the output debug message level
- - may appear multiple times
- -f Str driftfile frequency drift file name
- -g no panicgate Allow the first adjustment to be Big
- - may appear multiple times
- -i --- jaildir built without --enable-clockctl or --enable-linuxcaps
- -I Str interface Listen on an interface name or address
- - may appear multiple times
- -k Str keyfile path to symmetric keys
- -l Str logfile path to the log file
- -L no novirtualips Do not listen to virtual interfaces
- -n no nofork Do not fork
- -N no nice Run at high priority
- -p Str pidfile path to the PID file
- -P Num priority Process priority
- -q no quit Set the time and quit
- -r Str propagationdelay Broadcast/propagation delay
- Str saveconfigquit Save parsed configuration and quit
- -s Str statsdir Statistics file location
- -t Str trustedkey Trusted key number
- - may appear multiple times
- -u --- user built without --enable-clockctl or --enable-linuxcaps
- -U Num updateinterval interval in seconds between scans for new or dropped interfaces
- Str var make ARG an ntp variable (RW)
- - may appear multiple times
- Str dvar make ARG an ntp variable (RW|DEF)
- - may appear multiple times
- -x no slew Slew up to 600 seconds
- opt version Output version information and exit
- -? no help Display extended usage information and exit
- -! no more-help Extended usage information passed thru pager
-
-Options are specified by doubled hyphens and their name
-or by a single hyphen and the flag character.
-
-The following option preset mechanisms are supported:
- - examining environment variables named NTPD_*
-
-
-
-please send bug reports to: http://bugs.ntp.org, bugs@@ntp.org
-@end example
-@exampleindent 4
-
-@node ntpdsim ipv4
-@subsection ipv4 option (-4)
-@cindex ntpdsim-ipv4
-
-This is the ``force ipv4 dns name resolution'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-is a member of the ipv4 class of options.
-@end itemize
-
-Force DNS resolution of following host names on the command line
-to the IPv4 namespace.
-
-@node ntpdsim ipv6
-@subsection ipv6 option (-6)
-@cindex ntpdsim-ipv6
-
-This is the ``force ipv6 dns name resolution'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-is a member of the ipv4 class of options.
-@end itemize
-
-Force DNS resolution of following host names on the command line
-to the IPv6 namespace.
-
-@node ntpdsim authreq
-@subsection authreq option (-a)
-@cindex ntpdsim-authreq
-
-This is the ``require crypto authentication'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-must not appear in combination with any of the following options:
-authnoreq.
-@end itemize
-
-Require cryptographic authentication for broadcast client,
-multicast client and symmetric passive associations.
-This is the default.
-
-@node ntpdsim authnoreq
-@subsection authnoreq option (-A)
-@cindex ntpdsim-authnoreq
-
-This is the ``do not require crypto authentication'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-must not appear in combination with any of the following options:
-authreq.
-@end itemize
-
-Do not require cryptographic authentication for broadcast client,
-multicast client and symmetric passive associations.
-This is almost never a good idea.
-
-@node ntpdsim bcastsync
-@subsection bcastsync option (-b)
-@cindex ntpdsim-bcastsync
-
-This is the ``allow us to sync to broadcast servers'' option.
-
-
-@node ntpdsim simbroadcastdelay
-@subsection simbroadcastdelay option (-B)
-@cindex ntpdsim-simbroadcastdelay
-
-This is the ``simulator broadcast delay'' option.
-
-
-@node ntpdsim configfile
-@subsection configfile option (-c)
-@cindex ntpdsim-configfile
-
-This is the ``configuration file name'' option.
-The name and path of the configuration file,
-/etc/ntp.conf
-by default.
-
-@node ntpdsim phasenoise
-@subsection phasenoise option (-C)
-@cindex ntpdsim-phasenoise
-
-This is the ``phase noise level'' option.
-
-
-@node ntpdsim debug-level
-@subsection debug-level option (-d)
-@cindex ntpdsim-debug-level
-
-This is the ``increase output debug message level'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@item
-must be compiled in by defining @code{DEBUG} during the compilation.
-@end itemize
-
-Increase the debugging message output level.
-
-@node ntpdsim set-debug-level
-@subsection set-debug-level option (-D)
-@cindex ntpdsim-set-debug-level
-
-This is the ``set the output debug message level'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@item
-must be compiled in by defining @code{DEBUG} during the compilation.
-@end itemize
-
-Set the output debugging level. Can be supplied multiple times,
-but each overrides the previous value(s).
-
-@node ntpdsim driftfile
-@subsection driftfile option (-f)
-@cindex ntpdsim-driftfile
-
-This is the ``frequency drift file name'' option.
-The name and path of the frequency file,
-/etc/ntp.drift
-by default.
-This is the same operation as the
-driftfile driftfile
-configuration specification in the
-/etc/ntp.conf
-file.
-
-@node ntpdsim panicgate
-@subsection panicgate option (-g)
-@cindex ntpdsim-panicgate
-
-This is the ``allow the first adjustment to be big'' option.
-Normally,
-ntpd
-exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
-ntpd
-will exit with a message to the system log. This option can be used with the
--q
-and
--x
-options.
-See the
-tinker
-configuration file directive for other options.
-
-@node ntpdsim simslew
-@subsection simslew option (-H)
-@cindex ntpdsim-simslew
-
-This is the ``simuator slew'' option.
-
-
-@node ntpdsim jaildir
-@subsection jaildir option (-i)
-@cindex ntpdsim-jaildir
-
-This is the ``jail directory'' option.
-Chroot the server to the directory
-jaildir
-.
-This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
-You may need to also specify a
--u
-option.
-
-@node ntpdsim interface
-@subsection interface option (-I)
-@cindex ntpdsim-interface
-
-This is the ``listen on interface'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@end itemize
-
-
-
-@node ntpdsim keyfile
-@subsection keyfile option (-k)
-@cindex ntpdsim-keyfile
-
-This is the ``path to symmetric keys'' option.
-Specify the name and path of the symmetric key file.
-/etc/ntp.keys
-is the default.
-This is the same operation as the
-keys keyfile
-configuration file directive.
-
-@node ntpdsim logfile
-@subsection logfile option (-l)
-@cindex ntpdsim-logfile
-
-This is the ``path to the log file'' option.
-Specify the name and path of the log file.
-The default is the system log file.
-This is the same operation as the
-logfile logfile
-configuration file directive.
-
-@node ntpdsim novirtualips
-@subsection novirtualips option (-L)
-@cindex ntpdsim-novirtualips
-
-This is the ``do not listen to virtual ips'' option.
-Do not listen to virtual IPs. The default is to listen.
-
-@node ntpdsim modifymmtimer
-@subsection modifymmtimer option (-M)
-@cindex ntpdsim-modifymmtimer
-
-This is the ``modify multimedia timer (windows only)'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-must be compiled in by defining @code{SYS_WINNT} during the compilation.
-@end itemize
-
-Set the Windows Multimedia Timer to highest resolution.
-
-@node ntpdsim nofork
-@subsection nofork option (-n)
-@cindex ntpdsim-nofork
-
-This is the ``do not fork'' option.
-
-
-@node ntpdsim nice
-@subsection nice option (-N)
-@cindex ntpdsim-nice
-
-This is the ``run at high priority'' option.
-To the extent permitted by the operating system, run
-ntpd
-at the highest priority.
-
-@node ntpdsim servertime
-@subsection servertime option (-O)
-@cindex ntpdsim-servertime
-
-This is the ``server time'' option.
-
-
-@node ntpdsim pidfile
-@subsection pidfile option (-p)
-@cindex ntpdsim-pidfile
-
-This is the ``path to the pid file'' option.
-Specify the name and path of the file used to record
-ntpd's
-process ID.
-This is the same operation as the
-pidfile pidfile
-configuration file directive.
-
-@node ntpdsim priority
-@subsection priority option (-P)
-@cindex ntpdsim-priority
-
-This is the ``process priority'' option.
-To the extent permitted by the operating system, run
-ntpd
-at the specified
-sched_setscheduler(SCHED_FIFO)
-priority.
-
-@node ntpdsim quit
-@subsection quit option (-q)
-@cindex ntpdsim-quit
-
-This is the ``set the time and quit'' option.
-ntpd
-will exit just after the first time the clock is set. This behavior mimics that of the
-ntpdate
-program, which is to be retired.
-The
--g
-and
--x
-options can be used with this option.
-Note: The kernel time discipline is disabled with this option.
-
-@node ntpdsim propagationdelay
-@subsection propagationdelay option (-r)
-@cindex ntpdsim-propagationdelay
-
-This is the ``broadcast/propagation delay'' option.
-Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
-
-@node ntpdsim updateinterval
-@subsection updateinterval option (-U)
-@cindex ntpdsim-updateinterval
-
-This is the ``interval in seconds between scans for new or dropped interfaces'' option.
-Give the time in seconds between two scans for new or dropped interfaces.
-For systems with routing socket support the scans will be performed shortly after the interface change
-has been detected by the system.
-Use 0 to disable scanning.
-
-@node ntpdsim statsdir
-@subsection statsdir option (-s)
-@cindex ntpdsim-statsdir
-
-This is the ``statistics file location'' option.
-Specify the directory path for files created by the statistics facility.
-This is the same operation as the
-statsdir statsdir
-configuration file directive.
-
-@node ntpdsim endsimtime
-@subsection endsimtime option (-S)
-@cindex ntpdsim-endsimtime
-
-This is the ``simulation end time'' option.
-
-
-@node ntpdsim trustedkey
-@subsection trustedkey option (-t)
-@cindex ntpdsim-trustedkey
-
-This is the ``trusted key number'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@end itemize
-
-Add a key number to the trusted key list.
-
-@node ntpdsim freqerr
-@subsection freqerr option (-T)
-@cindex ntpdsim-freqerr
-
-This is the ``simulation frequency error'' option.
-
-
-@node ntpdsim walknoise
-@subsection walknoise option (-W)
-@cindex ntpdsim-walknoise
-
-This is the ``simulation random walk noise'' option.
-
-
-@node ntpdsim user
-@subsection user option (-u)
-@cindex ntpdsim-user
-
-This is the ``run as userid (or userid:groupid)'' option.
-Specify a user, and optionally a group, to switch to.
-This option is only available if the OS supports to run the server without full root privileges.
-Currently, this option is supported under NetBSD (configure with
---enable-clockctl
-) and Linux (configure with
---enable-linuxcaps
-).
-
-@node ntpdsim var
-@subsection var option (-v)
-@cindex ntpdsim-var
-
-This is the ``make arg an ntp variable (rw)'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@end itemize
-
-
-
-@node ntpdsim dvar
-@subsection dvar option (-V)
-@cindex ntpdsim-dvar
-
-This is the ``make arg an ntp variable (rw|def)'' option.
-
-This option has some usage constraints. It:
-@itemize @bullet
-@item
-may appear an unlimited number of times.
-@end itemize
-
-
-
-@node ntpdsim slew
-@subsection slew option (-x)
-@cindex ntpdsim-slew
-
-This is the ``slew up to 600 seconds'' option.
-Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
-This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
-Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
-Thus, an adjustment as much as 600 s will take almost 14 days to complete.
-This option can be used with the
--g
-and
--q
-options.
-See the
-tinker
-configuration file directive for other options.
-Note: The kernel time discipline is disabled with this option.
-
-@node ntpdsim ndelay
-@subsection ndelay option (-Y)
-@cindex ntpdsim-ndelay
-
-This is the ``simulation network delay'' option.
-
-
-@node ntpdsim pdelay
-@subsection pdelay option (-Z)
-@cindex ntpdsim-pdelay
-
-This is the ``simulation processing delay'' option.
-
diff --git a/ntpd/ntpdsim.1 b/ntpd/ntpdsim.1
deleted file mode 100644
index 202876418f25..000000000000
--- a/ntpd/ntpdsim.1
+++ /dev/null
@@ -1,357 +0,0 @@
-.TH NTPDSIM 1 2009-12-08 "( 4.2.4p8)" "Programmer's Manual"
-.\" EDIT THIS FILE WITH CAUTION (ntpdsim.1)
-.\"
-.\" It has been AutoGen-ed Tuesday December 8, 2009 at 08:13:14 AM EST
-.\" From the definitions ntpdsim-opts.def
-.\" and the template file agman1.tpl
-.\"
-.SH NAME
-ntpdsim \- NTP daemon simulation program
-.SH SYNOPSIS
-.B ntpdsim
-.\" Mixture of short (flag) options and long options
-.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \--\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
-.PP
-All arguments must be options.
-.SH "DESCRIPTION"
-This manual page documents, briefly, the \fBntpdsim\fP command.
-
-.SH OPTIONS
-.TP
-.BR \-4 ", " \--ipv4
-Force IPv4 DNS name resolution.
-This option is a member of the ipv4 class of options.
-.sp
-Force DNS resolution of following host names on the command line
-to the IPv4 namespace.
-.TP
-.BR \-6 ", " \--ipv6
-Force IPv6 DNS name resolution.
-This option is a member of the ipv4 class of options.
-.sp
-Force DNS resolution of following host names on the command line
-to the IPv6 namespace.
-.TP
-.BR \-a ", " \--authreq
-Require crypto authentication.
-This option must not appear in combination with any of the following options:
-authnoreq.
-.sp
-Require cryptographic authentication for broadcast client,
-multicast client and symmetric passive associations.
-This is the default.
-.TP
-.BR \-A ", " \--authnoreq
-Do not require crypto authentication.
-This option must not appear in combination with any of the following options:
-authreq.
-.sp
-Do not require cryptographic authentication for broadcast client,
-multicast client and symmetric passive associations.
-This is almost never a good idea.
-.TP
-.BR \-b ", " \--bcastsync
-Allow us to sync to broadcast servers.
-.sp
-
-.TP
-.BR \-B " \fIstring\fP, " \--simbroadcastdelay "=" \fIstring\fP
-Simulator broadcast delay.
-.sp
-
-.TP
-.BR \-c " \fIstring\fP, " \--configfile "=" \fIstring\fP
-configuration file name.
-.sp
-The name and path of the configuration file,
-/etc/ntp.conf
-by default.
-.TP
-.BR \-C " \fIstring\fP, " \--phasenoise "=" \fIstring\fP
-Phase noise level.
-.sp
-
-.TP
-.BR \-d ", " \--debug-level
-Increase output debug message level.
-This option may appear an unlimited number of times.
-.sp
-Increase the debugging message output level.
-.TP
-.BR \-D " \fIstring\fP, " \--set-debug-level "=" \fIstring\fP
-Set the output debug message level.
-This option may appear an unlimited number of times.
-.sp
-Set the output debugging level. Can be supplied multiple times,
-but each overrides the previous value(s).
-.TP
-.BR \-f " \fIstring\fP, " \--driftfile "=" \fIstring\fP
-frequency drift file name.
-.sp
-The name and path of the frequency file,
-/etc/ntp.drift
-by default.
-This is the same operation as the
-driftfile driftfile
-configuration specification in the
-/etc/ntp.conf
-file.
-.TP
-.BR \-g ", " \--panicgate
-Allow the first adjustment to be Big.
-.sp
-Normally,
-ntpd
-exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
-ntpd
-will exit with a message to the system log. This option can be used with the
--q
-and
--x
-options.
-See the
-tinker
-configuration file directive for other options.
-.TP
-.BR \-H " \fIstring\fP, " \--simslew "=" \fIstring\fP
-Simuator slew.
-.sp
-
-.TP
-.BR \-i " \fIstring\fP, " \--jaildir "=" \fIstring\fP
-Jail directory.
-.sp
-Chroot the server to the directory
-jaildir
-.
-This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
-You may need to also specify a
--u
-option.
-.TP
-.BR \-I " \fIiface\fP, " \--interface "=" \fIiface\fP
-Listen on interface.
-This option may appear an unlimited number of times.
-.sp
-
-.TP
-.BR \-k " \fIstring\fP, " \--keyfile "=" \fIstring\fP
-path to symmetric keys.
-.sp
-Specify the name and path of the symmetric key file.
-/etc/ntp.keys
-is the default.
-This is the same operation as the
-keys keyfile
-configuration file directive.
-.TP
-.BR \-l " \fIstring\fP, " \--logfile "=" \fIstring\fP
-path to the log file.
-.sp
-Specify the name and path of the log file.
-The default is the system log file.
-This is the same operation as the
-logfile logfile
-configuration file directive.
-.TP
-.BR \-L ", " \--novirtualips
-Do not listen to virtual IPs.
-.sp
-Do not listen to virtual IPs. The default is to listen.
-.TP
-.BR \-M ", " \--modifymmtimer
-Modify Multimedia Timer (Windows only).
-.sp
-Set the Windows Multimedia Timer to highest resolution.
-.TP
-.BR \-n ", " \--nofork
-Do not fork.
-.sp
-
-.TP
-.BR \-N ", " \--nice
-Run at high priority.
-.sp
-To the extent permitted by the operating system, run
-ntpd
-at the highest priority.
-.TP
-.BR \-O " \fIstring\fP, " \--servertime "=" \fIstring\fP
-Server time.
-.sp
-
-.TP
-.BR \-p " \fIstring\fP, " \--pidfile "=" \fIstring\fP
-path to the PID file.
-.sp
-Specify the name and path of the file used to record
-ntpd's
-process ID.
-This is the same operation as the
-pidfile pidfile
-configuration file directive.
-.TP
-.BR \-P " \fInumber\fP, " \--priority "=" \fInumber\fP
-Process priority.
-This option takes an integer number as its argument.
-.sp
-To the extent permitted by the operating system, run
-ntpd
-at the specified
-sched_setscheduler(SCHED_FIFO)
-priority.
-.TP
-.BR \-q ", " \--quit
-Set the time and quit.
-.sp
-ntpd
-will exit just after the first time the clock is set. This behavior mimics that of the
-ntpdate
-program, which is to be retired.
-The
--g
-and
--x
-options can be used with this option.
-Note: The kernel time discipline is disabled with this option.
-.TP
-.BR \-r " \fIstring\fP, " \--propagationdelay "=" \fIstring\fP
-Broadcast/propagation delay.
-.sp
-Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
-.TP
-.BR \-U " \fInumber\fP, " \--updateinterval "=" \fInumber\fP
-interval in seconds between scans for new or dropped interfaces.
-This option takes an integer number as its argument.
-.sp
-Give the time in seconds between two scans for new or dropped interfaces.
-For systems with routing socket support the scans will be performed shortly after the interface change
-has been detected by the system.
-Use 0 to disable scanning.
-.TP
-.BR \-s " \fIstring\fP, " \--statsdir "=" \fIstring\fP
-Statistics file location.
-.sp
-Specify the directory path for files created by the statistics facility.
-This is the same operation as the
-statsdir statsdir
-configuration file directive.
-.TP
-.BR \-S " \fIstring\fP, " \--endsimtime "=" \fIstring\fP
-Simulation end time.
-.sp
-
-.TP
-.BR \-t " \fItkey\fP, " \--trustedkey "=" \fItkey\fP
-Trusted key number.
-This option may appear an unlimited number of times.
-.sp
-Add a key number to the trusted key list.
-.TP
-.BR \-T " \fIstring\fP, " \--freqerr "=" \fIstring\fP
-Simulation frequency error.
-.sp
-
-.TP
-.BR \-W " \fIstring\fP, " \--walknoise "=" \fIstring\fP
-Simulation random walk noise.
-.sp
-
-.TP
-.BR \-u " \fIstring\fP, " \--user "=" \fIstring\fP
-Run as userid (or userid:groupid).
-.sp
-Specify a user, and optionally a group, to switch to.
-This option is only available if the OS supports to run the server without full root privileges.
-Currently, this option is supported under NetBSD (configure with
---enable-clockctl
-) and Linux (configure with
---enable-linuxcaps
-).
-.TP
-.BR \-v " \fInvar\fP, " \--var "=" \fInvar\fP
-make ARG an ntp variable (RW).
-This option may appear an unlimited number of times.
-.sp
-
-.TP
-.BR \-V " \fIndvar\fP, " \--dvar "=" \fIndvar\fP
-make ARG an ntp variable (RW|DEF).
-This option may appear an unlimited number of times.
-.sp
-
-.TP
-.BR \-x ", " \--slew
-Slew up to 600 seconds.
-.sp
-Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
-This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
-Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
-Thus, an adjustment as much as 600 s will take almost 14 days to complete.
-This option can be used with the
--g
-and
--q
-options.
-See the
-tinker
-configuration file directive for other options.
-Note: The kernel time discipline is disabled with this option.
-.TP
-.BR \-Y " \fIstring\fP, " \--ndelay "=" \fIstring\fP
-Simulation network delay.
-.sp
-
-.TP
-.BR \-Z " \fIstring\fP, " \--pdelay "=" \fIstring\fP
-Simulation processing delay.
-.sp
-
-.TP
-.BR \-? , " \--help"
-Display usage information and exit.
-.TP
-.BR \-! , " \--more-help"
-Extended usage information passed thru pager.
-.TP
-.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
-Save the option state to \fIrcfile\fP. The default is the \fIlast\fP
-configuration file listed in the \fBOPTION PRESETS\fP section, below.
-.TP
-.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " \--no-load-opts"
-Load options from \fIrcfile\fP.
-The \fIno-load-opts\fP form will disable the loading
-of earlier RC/INI files. \fI--no-load-opts\fP is handled early,
-out of order.
-.TP
-.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
-Output version of program and exit. The default mode is `v', a simple
-version. The `c' mode will print copyright information and `n' will
-print the full copyright notice.
-.SH OPTION PRESETS
-Any option that is not marked as \fInot presettable\fP may be preset
-by loading values from configuration ("RC" or ".INI") file(s) and values from
-environment variables named:
-.nf
- \fBNTPDSIM_<option-name>\fP or \fBNTPDSIM\fP
-.fi
-.aj
-The environmental presets take precedence (are processed later than)
-the configuration files.
-The \fIhomerc\fP files are "\fI$HOME\fP", and "\fI.\fP".
-If any of these are directories, then the file \fI.ntprc\fP
-is searched for within those directories.
-.SH AUTHOR
-David L. Mills and/or others
-.br
-Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org
-
-.PP
-.nf
-.na
-see html/copyright.html
-.fi
-.ad
-.PP
-This manual page was \fIAutoGen\fP-erated from the \fBntpdsim\fP
-option definitions.
diff --git a/ntpd/ntpsim.c b/ntpd/ntpsim.c
index d5ed587d562e..e7c0d9a583c9 100644
--- a/ntpd/ntpsim.c
+++ b/ntpd/ntpsim.c
@@ -1,371 +1,604 @@
-/*
- * NTP simulator engine - Harish Nair
- * University of Delaware, 2001
+/* ntpdsim.c
+ *
+ * The source code for the ntp discrete event simulator.
+ *
+ * Written By: Sachin Kamboj
+ * University of Delaware
+ * Newark, DE 19711
+ * Copyright (c) 2006
+ * (Some code shamelessly based on the original NTP discrete event simulator)
*/
+
+#ifdef SIM
#include "ntpd.h"
#include "ntpsim.h"
-#include "ntpdsim-opts.h"
+#include "ntp_data_structures.h"
-/*
- * Defines...
- */
-#define SIM_TIME 86400 /* end simulation time */
-#define NET_DLY .001 /* network delay */
-#define PROC_DLY .001 /* processing delay */
-#define BEEP_DLY 3600 /* beep interval (s) */
-#define SLEW 500e-6 /* correction rate (PPM) */
-/*
- * Function pointers
+/* Global Variable Definitions */
+
+sim_info simulation; /* Simulation Control Variables */
+local_clock_info simclock; /* Local Clock Variables */
+queue *event_queue; /* Event Queue */
+queue *recv_queue; /* Receive Queue */
+static double sys_residual = 0; /* adjustment residue (s) */
+
+void (*event_ptr[]) (Event *) = {
+ sim_event_beep, sim_update_clocks, sim_event_timer, sim_event_recv_packet
+}; /* Function pointer to the events */
+
+
+/* Define a function to compare two events to determine which one occurs first
*/
-void (*funcPtr[]) (Node *, Event) = {
- &ndbeep, &ndeclk, &ntptmr, &netpkt
-};
+int determine_event_ordering(Event *e1, Event *e2);
-/*
- * ntpsim - initialize global variables and event queue and start
+int determine_event_ordering(Event *e1, Event *e2)
+{
+ return (e1->time - e2->time);
+}
+
+/* Define a function to compare two received packets to determine which one
+ * is received first
*/
-int
-ntpsim(
- int argc,
- char *argv[]
- )
+int determine_recv_buf_ordering(struct recvbuf *b1, struct recvbuf *b2);
+
+int determine_recv_buf_ordering(struct recvbuf *b1, struct recvbuf *b2)
{
- Event e;
- double maxtime;
- struct timeval seed;
+ double recv_time1, recv_time2;
- /*
- * Initialize the global node
- */
- ntp_node.time = 0; /* simulation time */
- ntp_node.sim_time = SIM_TIME; /* end simulation time (-S) */
- ntp_node.ntp_time = 0; /* client disciplined time */
- ntp_node.adj = 0; /* remaining time correction */
- ntp_node.slew = SLEW; /* correction rate (-H) */
-
- ntp_node.clk_time = 0; /* server time (-O) */
- ntp_node.ferr = 0; /* frequency error (-T) */
- ntp_node.fnse = 0; /* random walk noise (-W) */
- ntp_node.ndly = NET_DLY; /* network delay (-Y) */
- ntp_node.snse = 0; /* phase noise (-C) */
- ntp_node.pdly = PROC_DLY; /* processing delay (-Z) */
- ntp_node.bdly = BEEP_DLY; /* beep interval (-B) */
-
- ntp_node.events = NULL;
- ntp_node.rbuflist = NULL;
-
- /*
- * Initialize ntp variables
- */
- initializing = 1;
- init_auth();
- init_util();
- init_restrict();
- init_mon();
- init_timer();
- init_lib();
- init_request();
- init_control();
- init_peer();
- init_proto();
- init_io();
- init_loopfilter();
- mon_start(MON_OFF);
-
- {
- int optct = optionProcess(&ntpdsimOptions, argc, argv);
- argc -= optct;
- argv += optct;
+ /* Simply convert the time received to double and subtract */
+ LFPTOD(&b1->recv_time, recv_time1);
+ LFPTOD(&b2->recv_time, recv_time2);
+ return ((int)(recv_time1 - recv_time2));
+}
+
+/* Define a function to create the server associations */
+void create_server_associations()
+{
+ int i;
+ for (i = 0;i < simulation.num_of_servers;++i) {
+ printf("%s\n", stoa(simulation.servers[i].addr));
+ if (peer_config(simulation.servers[i].addr,
+ ANY_INTERFACE_CHOOSE(simulation.servers[i].addr),
+ MODE_CLIENT,
+ NTP_VERSION,
+ NTP_MINDPOLL,
+ NTP_MAXDPOLL,
+ 0, /* peerflags */
+ 0, /* ttl */
+ 0, /* peerkey */
+ (u_char *)"*" /* peerkeystr */) == 0) {
+ fprintf(stderr, "ERROR!! Could not create association for: %s",
+ stoa(simulation.servers[i].addr));
}
+ }
+}
- getconfig(argc, argv);
- initializing = 0;
- loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
+/* Main Simulator Code */
- /*
- * Watch out here, we want the real time, not the silly stuff.
- */
- gettimeofday(&seed, NULL);
- ntp_srandom(seed.tv_usec);
+int ntpsim(int argc, char *argv[])
+{
+ Event *curr_event;
+ struct timeval seed;
+
+ /* Initialize the local Clock
+ */
+ simclock.local_time = 0;
+ simclock.adj = 0;
+ simclock.slew = 0;
+
+ /* Initialize the simulation
+ */
+ simulation.num_of_servers = 0;
+ simulation.beep_delay = BEEP_DLY;
+ simulation.sim_time = 0;
+ simulation.end_time = SIM_TIME;
+
+ /*
+ * Initialize ntp variables
+ */
+ initializing = 1;
+ init_auth();
+ init_util();
+ init_restrict();
+ init_mon();
+ init_timer();
+ init_lib();
+ init_request();
+ init_control();
+ init_peer();
+ init_proto();
+ init_io();
+ init_loopfilter();
+ mon_start(MON_OFF);
+
+ /* Call getconfig to parse the configuration file */
+ getconfig(argc, argv);
+ initializing = 0;
+ loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
+
+ /*
+ * Watch out here, we want the real time, not the silly stuff.
+ */
+ gettimeofday(&seed, NULL);
+ ntp_srandom(seed.tv_usec);
+
+
+ /* Initialize the event queue */
+ event_queue = create_priority_queue((int(*)(void *, void*))
+ determine_event_ordering);
+
+ /* Initialize the receive queue */
+ recv_queue = create_priority_queue((int(*)(void *, void*))
+ determine_recv_buf_ordering);
+
+ /* Push a beep and a timer on the event queue */
+ enqueue(event_queue, event(0, BEEP));
+ enqueue(event_queue, event(simulation.sim_time + 1.0, TIMER));
+ /*
+ * Pop the queue until nothing is left or time is exceeded
+ */
+ /* maxtime = simulation.sim_time + simulation.end_time;*/
+ while (simulation.sim_time <= simulation.end_time &&
+ (!empty(event_queue))) {
+ curr_event = dequeue(event_queue);
+ /* Update all the clocks to the time on the event */
+ sim_update_clocks(curr_event);
+
+ /* Execute the function associated with the event */
+ event_ptr[curr_event->function](curr_event);
+ free_node(curr_event);
+ }
+ return (0);
+}
- /*
- * Push a beep and timer interrupt on the queue
- */
- push(event(0, BEEP), &ntp_node.events);
- push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
- /*
- * Pop the queue until nothing is left or time is exceeded
- */
- maxtime = ntp_node.time + ntp_node.sim_time;
- while (ntp_node.time <= maxtime && ntp_node.events != NULL ) {
- e = pop(&ntp_node.events);
- ndeclk(&ntp_node, e);
- funcPtr[e.function](&ntp_node, e);
- }
- return (0);
-}
+/* Define a function to create an return an Event */
-/*
- * Return an event
- */
-Event
-event(
- double t,
- funcTkn f
- )
+Event *event(double t, funcTkn f)
{
- Event e;
+ Event *e;
- e.time = t;
- e.function = f;
- return (e);
+ if ((e = get_node(sizeof(*e))) == NULL)
+ abortsim("get_node failed in event");
+ e->time = t;
+ e->function = f;
+ return (e);
}
-/*
- * Create an event queue
+/* NTP SIMULATION FUNCTIONS */
+
+/* Define a function for processing a timer interrupt.
+ * On every timer interrupt, call the NTP timer to send packets and process
+ * the clock and then call the receive function to receive packets.
*/
-Queue
-queue(
- Event e,
- Queue q
- )
+void sim_event_timer(Event *e)
{
- Queue ret;
-
- if ((ret = (Queue)malloc(sizeof(struct List))) == NULL)
- abortsim("queue-malloc");
- ret->event = e;
- ret->next = q;
- return (ret);
+ struct recvbuf *rbuf;
+
+ /* Call the NTP timer.
+ * This will be responsible for actually "sending the packets."
+ * Since this is a simulation, the packets sent over the network
+ * will be processed by the simulate_server routine below.
+ */
+ timer();
+
+ /* Process received buffers */
+ while (!empty(recv_queue)) {
+ rbuf = (struct recvbuf *)dequeue(recv_queue);
+ (rbuf->receiver)(rbuf);
+ free_node(rbuf);
+ }
+
+ /* Arm the next timer interrupt. */
+ enqueue(event_queue,
+ event(simulation.sim_time + (1 << EVENT_TIMEOUT), TIMER));
}
-/*
- * Push an event into the event queue
+
+/* Define a function to simulate a server.
+ * This function processes the sent packet according to the server script,
+ * creates a reply packet and pushes the reply packet onto the event queue
*/
-void push(
- Event e,
- Queue *qp
- )
+int simulate_server(
+ sockaddr_u *serv_addr, /* Address of the server */
+ struct interface *inter, /* Interface on which the reply should
+ be inserted */
+ struct pkt *rpkt /* Packet sent to the server that
+ needs to be processed. */
+)
{
- Queue *tmp = qp;
+ struct pkt xpkt; /* Packet to be transmitted back
+ to the client */
+ struct recvbuf rbuf; /* Buffer for the received packet */
+ Event *e; /* Packet receive event */
+ server_info *server; /* Pointer to the server being simulated */
+ script_info *curr_script; /* Current script being processed */
+ int i;
+ double d1, d2, d3; /* Delays while the packet is enroute */
+ double t1, t2, t3, t4; /* The four timestamps in the packet */
+
+ memset(&xpkt, 0, sizeof(xpkt));
+ memset(&rbuf, 0, sizeof(rbuf));
+
+ /* Search for the server with the desired address */
+ server = NULL;
+ for (i = 0; i < simulation.num_of_servers; ++i) {
+ fprintf(stderr,"Checking address: %s\n", stoa(simulation.servers[i].addr));
+ if (memcmp(simulation.servers[i].addr, serv_addr,
+ sizeof(*serv_addr)) == 0) {
+ server = &simulation.servers[i];
+ break;
+ }
+ }
+
+ fprintf(stderr, "Received packet for: %s\n", stoa(serv_addr));
+ if (server == NULL)
+ abortsim("Server with specified address not found!!!");
+
+ /* Get the current script for the server */
+ curr_script = server->curr_script;
+
+ /* Create a server reply packet.
+ * Masquerade the reply as a stratum-1 server with a GPS clock
+ */
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
+ MODE_SERVER);
+ xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
+ memcpy(&xpkt.refid, "GPS", 4);
+ xpkt.ppoll = rpkt->ppoll;
+ xpkt.precision = rpkt->precision;
+ xpkt.rootdelay = 0;
+ xpkt.rootdisp = 0;
+
+ /* TIMESTAMP CALCULATIONS
+ t1 t4
+ \ /
+ d1 \ / d3
+ \ /
+ t2 ----------------- t3
+ d2
+ */
+ /* Compute the delays */
+ d1 = poisson(curr_script->prop_delay, curr_script->jitter);
+ d2 = poisson(curr_script->proc_delay, 0);
+ d3 = poisson(curr_script->prop_delay, curr_script->jitter);
+
+ /* Note: In the transmitted packet:
+ * 1. t1 and t4 are times in the client according to the local clock.
+ * 2. t2 and t3 are server times according to the simulated server.
+ * Compute t1, t2, t3 and t4
+ * Note: This function is called at time t1.
+ */
+
+ LFPTOD(&rpkt->xmt, t1);
+ t2 = server->server_time + d1;
+ t3 = server->server_time + d1 + d2;
+ t4 = t1 + d1 + d2 + d3;
+
+ /* Save the timestamps */
+ xpkt.org = rpkt->xmt;
+ DTOLFP(t2, &xpkt.rec);
+ DTOLFP(t3, &xpkt.xmt);
+ xpkt.reftime = xpkt.xmt;
+
+
+
+ /* Ok, we are done with the packet. Now initialize the receive buffer for
+ * the packet.
+ */
+ rbuf.receiver = receive; /* Function to call to process the packet */
+ rbuf.recv_length = LEN_PKT_NOMAC;
+ rbuf.recv_pkt = xpkt;
+ rbuf.used = 1;
+
+ memcpy(&rbuf.srcadr, serv_addr, sizeof(rbuf.srcadr));
+ memcpy(&rbuf.recv_srcadr, serv_addr, sizeof(rbuf.recv_srcadr));
+ if ((rbuf.dstadr = malloc(sizeof(*rbuf.dstadr))) == NULL)
+ abortsim("malloc failed in simulate_server");
+ memcpy(rbuf.dstadr, inter, sizeof(*rbuf.dstadr));
+ /* rbuf.link = NULL; */
+
+ /* Create a packet event and insert it onto the event_queue at the
+ * arrival time (t4) of the packet at the client
+ */
+ e = event(t4, PACKET);
+ e->rcv_buf = rbuf;
+ enqueue(event_queue, e);
+
+
+ /* Check if the time of the script has expired. If yes, delete the script.
+ * If not, re-enqueue the script onto the server script queue
+ */
+ if (curr_script->duration > simulation.sim_time &&
+ !empty(server->script)) {
+ printf("Hello\n");
+ /*
+ * For some reason freeing up the curr_script memory kills the
+ * simulation. Further debugging is needed to determine why.
+ * free_node(curr_script);
+ */
+ curr_script = dequeue(server->script);
+ }
- while (*tmp != NULL && ((*tmp)->event.time < e.time))
- tmp = &((*tmp)->next);
- *tmp = queue(e, (*tmp));
+ return (0);
}
-/*
- * Pop the first event from the event queue
+/* Define a function to update all the clocks
+ * Most of the code is modified from the systime.c file by Prof. Mills
*/
-Event
-pop(
- Queue *qp
- )
+
+void sim_update_clocks (Event *e)
{
- Event ret;
- Queue tmp;
-
- tmp = *qp;
- if (tmp == NULL)
- abortsim("pop - empty queue");
- ret = tmp->event;
- *qp = tmp->next;
- free(tmp);
- return (ret);
+ double time_gap;
+ double adj;
+ int i;
+
+ /* Compute the time between the last update event and this update */
+ time_gap = e->time - simulation.sim_time;
+
+ /* Advance the client clock */
+ simclock.local_time = e->time + time_gap;
+
+ /* Advance the simulation time */
+ simulation.sim_time = e->time;
+
+ /* Advance the server clocks adjusted for systematic and random frequency
+ * errors. The random error is a random walk computed as the
+ * integral of samples from a Gaussian distribution.
+ */
+ for (i = 0;i < simulation.num_of_servers; ++i) {
+ simulation.servers[i].curr_script->freq_offset +=
+ gauss(0, time_gap * simulation.servers[i].curr_script->wander);
+
+ simulation.servers[i].server_time += time_gap *
+ (1 + simulation.servers[i].curr_script->freq_offset);
+ }
+
+
+ /* Perform the adjtime() function. If the adjustment completed
+ * in the previous interval, amortize the entire amount; if not,
+ * carry the leftover to the next interval.
+ */
+
+ adj = time_gap * simclock.slew;
+ if (adj < fabs(simclock.adj)) {
+ if (simclock.adj < 0) {
+ simclock.adj += adj;
+ simclock.local_time -= adj;
+ }
+ else {
+ simclock.adj -= adj;
+ simclock.local_time += adj;
+ }
+ }
+ else {
+ simclock.local_time += simclock.adj;
+ simclock.adj = 0;
+ }
}
-/*
- * Update clocks
- */
-void
-ndeclk(
- Node *n,
- Event e
- )
+/* Define a function that processes a receive packet event.
+ * This function simply inserts the packet received onto the receive queue
+ */
+
+void sim_event_recv_packet(Event *e)
{
- node_clock(n, e.time);
+ struct recvbuf *rbuf;
+
+ /* Allocate a receive buffer and copy the packet to it */
+ if ((rbuf = get_node(sizeof(*rbuf))) == NULL)
+ abortsim("get_node failed in sim_event_recv_packet");
+ memcpy(rbuf, &e->rcv_buf, sizeof(*rbuf));
+
+ /* Store the local time in the received packet */
+ DTOLFP(simclock.local_time, &rbuf->recv_time);
+
+ /* Insert the packet received onto the receive queue */
+ enqueue(recv_queue, rbuf);
}
-/*
- * Timer interrupt. Eventually, this results in calling the
- * srvr_rplyi() routine below.
- */
-void
-ntptmr(
- Node *n,
- Event e
- )
-{
- struct recvbuf *rbuf;
- timer();
+/* Define a function to output simulation statistics on a beep event
+ */
- /*
- * Process buffers received. They had better be in order by
- * receive timestamp. Note that there are no additional buffers
- * in the current implementation of ntpsim.
- */
- while (n->rbuflist != NULL) {
- rbuf = n->rbuflist;
- n->rbuflist = NULL;
- (rbuf->receiver)(rbuf);
- free(rbuf);
+/*** TODO: Need to decide on how to output for multiple servers ***/
+void sim_event_beep(Event *e)
+{
+#if 0
+ static int first_time = 1;
+ char *dash = "-----------------";
+#endif
+
+ fprintf(stderr, "BEEP!!!\n");
+ enqueue(event_queue, event(e->time + simulation.beep_delay, BEEP));
+#if 0
+ if(simulation.beep_delay > 0) {
+ if (first_time) {
+ printf("\t%4c T %4c\t%4c T+ERR %3c\t%5cT+ERR+NTP\n",
+ ' ', ' ', ' ', ' ',' ');
+ printf("\t%s\t%s\t%s\n", dash, dash, dash);
+ first_time = 0;
+
+ printf("\t%16.6f\t%16.6f\t%16.6f\n",
+ n->time, n->clk_time, n->ntp_time);
+ return;
}
+ printf("\t%16.6f\t%16.6f\t%16.6f\n",
+ simclock.local_time,
+ n->time, n->clk_time, n->ntp_time);
+#endif
- /*
- * Arm the next timer interrupt.
- */
- push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
}
-/*
- * srvr_rply() - send packet
+/* Define a function to abort the simulation on an error and spit out an
+ * error message
*/
-int srvr_rply(
- Node *n,
- struct sockaddr_storage *dest,
- struct interface *inter, struct pkt *rpkt
- )
+
+void abortsim(char *errmsg)
{
- struct pkt xpkt;
- struct recvbuf rbuf;
- Event xvnt;
- double dtemp, etemp;
-
- /*
- * Insert packet header values. We make this look like a
- * stratum-1 server with a GPS clock, but nobody will ever
- * notice that.
- */
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
- MODE_SERVER);
- xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
- memcpy(&xpkt.refid, "GPS", 4);
- xpkt.ppoll = rpkt->ppoll;
- xpkt.precision = rpkt->precision;
- xpkt.rootdelay = 0;
- xpkt.rootdispersion = 0;
-
- /*
- * Insert the timestamps.
- */
- xpkt.org = rpkt->xmt;
- dtemp = poisson(n->ndly, n->snse); /* client->server delay */
- DTOLFP(dtemp + n->clk_time, &xpkt.rec);
- dtemp += poisson(n->pdly, 0); /* server delay */
- DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
- xpkt.reftime = xpkt.xmt;
- dtemp += poisson(n->ndly, n->snse); /* server->client delay */
-
- /*
- * Insert the I/O stuff.
- */
- rbuf.receiver = receive;
- get_systime(&rbuf.recv_time);
- rbuf.recv_length = LEN_PKT_NOMAC;
- rbuf.recv_pkt = xpkt;
- memcpy(&rbuf.srcadr, dest, sizeof(struct sockaddr_storage));
- memcpy(&rbuf.recv_srcadr, dest,
- sizeof(struct sockaddr_storage));
- if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
- abortsim("server-malloc");
- memcpy(rbuf.dstadr, inter, sizeof(struct interface));
-
- /*
- * Very carefully predict the time of arrival for the received
- * packet.
- */
- LFPTOD(&xpkt.org, etemp);
- etemp += dtemp;
- xvnt = event(etemp, PACKET);
- xvnt.rcv_buf = rbuf;
- push(xvnt, &n->events);
- return (0);
+ perror(errmsg);
+ exit(1);
}
+
+/* CODE ORIGINALLY IN libntp/systime.c
+ * -----------------------------------
+ * This code was a part of the original NTP simulator and originally
+ * had its home in the libntp/systime.c file.
+ *
+ * It has been shamelessly moved to here and has been modified for the
+ * purposes of the current simulator.
+ */
+
+
/*
- * netpkt() - receive packet
+ * get_systime - return the system time in NTP timestamp format
*/
void
-netpkt(
- Node *n,
- Event e
- )
+get_systime(
+ l_fp *now /* current system time in l_fp */ )
{
- struct recvbuf *rbuf;
- struct recvbuf *obuf;
-
- /*
- * Insert the packet on the receive queue and record the arrival
- * time.
- */
- if ((rbuf = malloc(sizeof(struct recvbuf))) == NULL)
- abortsim("ntprcv-malloc");
- memcpy(rbuf, &e.rcv_buf, sizeof(struct recvbuf));
- rbuf->receiver = receive;
- DTOLFP(n->ntp_time, &rbuf->recv_time);
- obuf = n->rbuflist;
-
- /*
- * In the present incarnation, no more than one buffer can be on
- * the queue;
- */
- if (obuf == NULL) {
- n->rbuflist = rbuf;
- }
+ /*
+ * To fool the code that determines the local clock precision,
+ * we advance the clock a minimum of 200 nanoseconds on every
+ * clock read. This is appropriate for a typical modern machine
+ * with nanosecond clocks. Note we make no attempt here to
+ * simulate reading error, since the error is so small. This may
+ * change when the need comes to implement picosecond clocks.
+ */
+ if (simclock.local_time == simclock.last_read_time)
+ simclock.local_time += 200e-9;
+
+ simclock.last_read_time = simclock.local_time;
+ DTOLFP(simclock.local_time, now);
+/* OLD Code
+ if (ntp_node.ntp_time == ntp_node.last_time)
+ ntp_node.ntp_time += 200e-9;
+ ntp_node.last_time = ntp_node.ntp_time;
+ DTOLFP(ntp_node.ntp_time, now);
+*/
}
-
-
+
+
/*
- * ndbeep() - progress indicator
+ * adj_systime - advance or retard the system clock exactly like the
+ * real thng.
*/
-void
-ndbeep(
- Node *n,
- Event e
- )
+int /* always succeeds */
+adj_systime(
+ double now /* time adjustment (s) */
+ )
{
- static int first_time = 1;
- char *dash = "-----------------";
-
- if(n->bdly > 0) {
- if (first_time) {
- printf(
- "\t%4c T %4c\t%4c T+ERR %3c\t%5cT+ERR+NTP\n", ' ', ' ', ' ', ' ',' ');
- printf("\t%s\t%s\t%s\n", dash, dash, dash);
- first_time = 0;
- push(event(n->bdly, BEEP), &n->events);
- push(event(n->sim_time, BEEP), &n->events);
- printf("\t%16.6f\t%16.6f\t%16.6f\n",
- n->time, n->clk_time, n->ntp_time);
- return;
- }
- printf("\t%16.6f\t%16.6f\t%16.6f\n",
- n->time, n->clk_time, n->ntp_time);
- push(event(e.time + n->bdly, BEEP), &n->events);
- }
+ struct timeval adjtv; /* new adjustment */
+ double dtemp;
+ long ticks;
+ int isneg = 0;
+
+ /*
+ * Most Unix adjtime() implementations adjust the system clock
+ * in microsecond quanta, but some adjust in 10-ms quanta. We
+ * carefully round the adjustment to the nearest quantum, then
+ * adjust in quanta and keep the residue for later.
+ */
+ dtemp = now + sys_residual;
+ if (dtemp < 0) {
+ isneg = 1;
+ dtemp = -dtemp;
+ }
+ adjtv.tv_sec = (long)dtemp;
+ dtemp -= adjtv.tv_sec;
+ ticks = (long)(dtemp / sys_tick + .5);
+ adjtv.tv_usec = (long)(ticks * sys_tick * 1e6);
+ dtemp -= adjtv.tv_usec / 1e6;
+ sys_residual = dtemp;
+
+ /*
+ * Convert to signed seconds and microseconds for the Unix
+ * adjtime() system call. Note we purposely lose the adjtime()
+ * leftover.
+ */
+ if (isneg) {
+ adjtv.tv_sec = -adjtv.tv_sec;
+ adjtv.tv_usec = -adjtv.tv_usec;
+ sys_residual = -sys_residual;
+ }
+ simclock.adj = now;
+/* ntp_node.adj = now; */
+ return (1);
+}
+
+
+/*
+ * step_systime - step the system clock. We are religious here.
+ */
+int /* always succeeds */
+step_systime(
+ double now /* step adjustment (s) */
+ )
+{
+#ifdef DEBUG
+ if (debug)
+ printf("step_systime: time %.6f adj %.6f\n",
+ simclock.local_time, now);
+#endif
+ simclock.local_time += now;
+ return (1);
+}
+
+/*
+ * gauss() - returns samples from a gaussion distribution
+ */
+double /* Gaussian sample */
+gauss(
+ double m, /* sample mean */
+ double s /* sample standard deviation (sigma) */
+ )
+{
+ double q1, q2;
+
+ /*
+ * Roll a sample from a Gaussian distribution with mean m and
+ * standard deviation s. For m = 0, s = 1, mean(y) = 0,
+ * std(y) = 1.
+ */
+ if (s == 0)
+ return (m);
+ while ((q1 = drand48()) == 0);
+ q2 = drand48();
+ return (m + s * sqrt(-2. * log(q1)) * cos(2. * PI * q2));
}
-
+
/*
- * Abort simulation
+ * poisson() - returns samples from a network delay distribution
*/
-void
-abortsim(
- char *errmsg
- )
+double /* delay sample (s) */
+poisson(
+ double m, /* fixed propagation delay (s) */
+ double s /* exponential parameter (mu) */
+ )
{
- perror(errmsg);
- exit(1);
+ double q1;
+
+ /*
+ * Roll a sample from a composite distribution with propagation
+ * delay m and exponential distribution time with parameter s.
+ * For m = 0, s = 1, mean(y) = std(y) = 1.
+ */
+ if (s == 0)
+ return (m);
+ while ((q1 = drand48()) == 0);
+ return (m - s * log(q1 * s));
}
+
+#endif
diff --git a/ntpd/refclock_acts.c b/ntpd/refclock_acts.c
index 57f2ca7c7ac3..be69ce6cd581 100644
--- a/ntpd/refclock_acts.c
+++ b/ntpd/refclock_acts.c
@@ -136,6 +136,7 @@
#define REFID "NONE" /* default reference ID */
#define MSGCNT 20 /* max message count */
#define SMAX 256 /* max clockstats line length */
+#define MAXPHONE 10 /* max number of phone numbers */
/*
* Calling program modes
@@ -210,15 +211,15 @@ struct actsunit {
/*
* Function prototypes
*/
-static int acts_start P((int, struct peer *));
-static void acts_shutdown P((int, struct peer *));
-static void acts_receive P((struct recvbuf *));
-static void acts_message P((struct peer *));
-static void acts_timecode P((struct peer *, char *));
-static void acts_poll P((int, struct peer *));
-static void acts_timeout P((struct peer *));
-static void acts_disc P((struct peer *));
-static void acts_timer P((int, struct peer *));
+static int acts_start (int, struct peer *);
+static void acts_shutdown (int, struct peer *);
+static void acts_receive (struct recvbuf *);
+static void acts_message (struct peer *);
+static void acts_timecode (struct peer *, char *);
+static void acts_poll (int, struct peer *);
+static void acts_timeout (struct peer *);
+static void acts_disc (struct peer *);
+static void acts_timer (int, struct peer *);
/*
* Transfer vector (conditional structure name)
@@ -233,8 +234,6 @@ struct refclock refclock_acts = {
acts_timer /* housekeeping timer */
};
-struct refclock refclock_ptb;
-
/*
* Initialize data for processing
*/
@@ -251,9 +250,6 @@ acts_start (
* Allocate and initialize unit structure
*/
up = emalloc(sizeof(struct actsunit));
- if (up == NULL)
- return (0);
-
memset(up, 0, sizeof(struct actsunit));
up->unit = unit;
pp = peer->procptr;
@@ -269,7 +265,6 @@ acts_start (
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
peer->sstclktype = CTL_SST_TS_TELEPHONE;
- peer->flags &= ~FLAG_FIXPOLL;
up->bufptr = pp->a_lastcode;
return (1);
}
@@ -362,21 +357,28 @@ acts_message(
/*
* What to do depends on the state and the first token in the
- * message. A NO token sends the message to the clockstats.
- */
+ * message. */
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
#ifdef DEBUG
ioctl(pp->io.fd, TIOCMGET, (char *)&modem);
- sprintf(tbuf, "acts: %04x (%d %d) %lu %s", modem, up->state,
- up->timer, strlen(pp->a_lastcode), pp->a_lastcode);
+ snprintf(tbuf, sizeof(tbuf), "acts: %04x (%d %d) %lu %s", modem,
+ up->state, up->timer, (u_long)strlen(pp->a_lastcode),
+ pp->a_lastcode);
if (debug)
printf("%s\n", tbuf);
#endif
+
+ /*
+ * Extract the first token in the line. A NO token sends the
+ * message to the clockstats.
+ */
strncpy(tbuf, pp->a_lastcode, SMAX);
strtok(tbuf, " ");
- if (strcmp(tbuf, "NO") == 0)
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ if (strcmp(tbuf, "NO") == 0) {
+ report_event(PEVNT_CLOCK, peer, pp->a_lastcode);
+ return;
+ }
switch(up->state) {
/*
@@ -401,7 +403,7 @@ acts_message(
* here is token CONNECT. Send the message to the clockstats.
*/
case S_CONNECT:
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ report_event(PEVNT_CLOCK, peer, pp->a_lastcode);
if (strcmp(tbuf, "CONNECT") != 0) {
acts_disc(peer);
return;
@@ -616,10 +618,8 @@ acts_timecode(
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
return;
- }
+ }
pp->lastref = pp->lastrec;
- if (peer->disp > MAXDISTANCE)
- refclock_receive(peer);
if (up->state != S_MSG) {
up->state = S_MSG;
up->timer = TIMECODE;
@@ -724,7 +724,7 @@ acts_timeout(
int fd;
char device[20];
char lockfile[128], pidbuf[8];
- char tbuf[BMAX];
+ char tbuf[SMAX];
/*
* The state machine is driven by messages from the modem, when
@@ -751,14 +751,16 @@ acts_timeout(
* file may not be removed.
*/
if (pp->sloppyclockflag & CLK_FLAG2) {
- sprintf(lockfile, LOCKFILE, up->unit);
+ snprintf(lockfile, sizeof(lockfile), LOCKFILE,
+ up->unit);
fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL,
0644);
if (fd < 0) {
msyslog(LOG_ERR, "acts: port busy");
return;
}
- sprintf(pidbuf, "%d\n", (u_int)getpid());
+ snprintf(pidbuf, sizeof(pidbuf), "%d\n",
+ (u_int)getpid());
write(fd, pidbuf, strlen(pidbuf));
close(fd);
}
@@ -767,10 +769,13 @@ acts_timeout(
* Open the device in raw mode and link the I/O.
*/
if (!pp->io.fd) {
- sprintf(device, DEVICE, up->unit);
+ snprintf(device, sizeof(device), DEVICE,
+ up->unit);
fd = refclock_open(device, SPEED232,
LDISC_ACTS | LDISC_RAW | LDISC_REMOTE);
if (fd == 0) {
+ msyslog(LOG_ERR,
+ "acts: open fails");
return;
}
pp->io.fd = fd;
@@ -825,9 +830,9 @@ acts_timeout(
* before hammering it with a dial command.
*/
case S_DTR:
- sprintf(tbuf, "DIAL #%d %s", up->retry,
+ snprintf(tbuf, sizeof(tbuf), "DIAL #%d %s", up->retry,
sys_phone[up->retry]);
- record_clock_stats(&peer->srcadr, tbuf);
+ report_event(PEVNT_CLOCK, peer, tbuf);
#ifdef DEBUG
if (debug)
printf("%s\n", tbuf);
@@ -866,7 +871,8 @@ acts_timeout(
io_closeclock(&pp->io);
close(pp->io.fd);
if (pp->sloppyclockflag & CLK_FLAG2) {
- sprintf(lockfile, LOCKFILE, up->unit);
+ snprintf(lockfile, sizeof(lockfile),
+ LOCKFILE, up->unit);
unlink(lockfile);
}
pp->io.fd = 0;
@@ -910,9 +916,9 @@ acts_disc (
/*
* We get here if the call terminated successfully or if an
- * error occured. If the median filter has something in it,feed
- * the data to the clock filter. If a modem port, drop DTR to
- * force command mode and send modem hangup.
+ * error occured. If the median filter has something in it,
+ * feed the data to the clock filter. If a modem port, drop DTR
+ * to force command mode and send modem hangup.
*/
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
@@ -925,7 +931,6 @@ acts_disc (
up->timer = SETUP;
up->state = S_CLOSE;
}
-
#else
int refclock_acts_bs;
#endif /* REFCLOCK */
diff --git a/ntpd/refclock_arbiter.c b/ntpd/refclock_arbiter.c
index 88a32250df3c..8e92c0fbffcf 100644
--- a/ntpd/refclock_arbiter.c
+++ b/ntpd/refclock_arbiter.c
@@ -17,6 +17,12 @@
#include <stdio.h>
#include <ctype.h>
+#ifdef SYS_WINNT
+extern int async_write(int, const void *, unsigned int);
+#undef write
+#define write(fd, data, octets) async_write(fd, data, octets)
+#endif
+
/*
* This driver supports the Arbiter 1088A/B Satellite Controlled Clock.
* The claimed accuracy of this clock is 100 ns relative to the PPS
@@ -97,6 +103,15 @@
#define MAXSTA 40 /* max length of status string */
#define MAXPOS 80 /* max length of position string */
+#ifdef PRE_NTP420
+#define MODE ttlmax
+#else
+#define MODE ttl
+#endif
+
+#define COMMAND_HALT_BCAST ( (peer->MODE % 2) ? "O0" : "B0" )
+#define COMMAND_START_BCAST ( (peer->MODE % 2) ? "O5" : "B5" )
+
/*
* ARB unit control structure
*/
@@ -111,10 +126,10 @@ struct arbunit {
/*
* Function prototypes
*/
-static int arb_start P((int, struct peer *));
-static void arb_shutdown P((int, struct peer *));
-static void arb_receive P((struct recvbuf *));
-static void arb_poll P((int, struct peer *));
+static int arb_start (int, struct peer *);
+static void arb_shutdown (int, struct peer *);
+static void arb_receive (struct recvbuf *);
+static void arb_poll (int, struct peer *);
/*
* Transfer vector
@@ -147,25 +162,23 @@ arb_start(
/*
* Open serial port. Use CLK line discipline, if available.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
return (0);
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct arbunit *)emalloc(sizeof(struct arbunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct arbunit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = arb_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -177,7 +190,17 @@ arb_start(
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
- write(pp->io.fd, "B0", 2);
+ if (peer->MODE > 1) {
+ msyslog(LOG_NOTICE, "ARBITER: Invalid mode %d", peer->MODE);
+ close(fd);
+ pp->io.fd = -1;
+ free(up);
+ return (0);
+ }
+#ifdef DEBUG
+ if(debug) { printf("arbiter: mode = %d.\n", peer->MODE); }
+#endif
+ write(pp->io.fd, COMMAND_HALT_BCAST, 2);
return (1);
}
@@ -196,8 +219,10 @@ arb_shutdown(
pp = peer->procptr;
up = (struct arbunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -268,7 +293,7 @@ arb_receive(
if (pp->sloppyclockflag & CLK_FLAG4)
write(pp->io.fd, "LA", 2);
else
- write(pp->io.fd, "B5", 2);
+ write(pp->io.fd, COMMAND_START_BCAST, 2);
return;
} else if (!strncmp(tbuf, "LA", 2)) {
@@ -296,7 +321,7 @@ arb_receive(
if (debug)
printf("arbiter: %s\n", up->latlon);
#endif
- write(pp->io.fd, "B5", 2);
+ write(pp->io.fd, COMMAND_START_BCAST, 2);
}
}
@@ -325,7 +350,7 @@ arb_receive(
&syncchar, &pp->year, &pp->day, &pp->hour,
&pp->minute, &pp->second) != 6) {
refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, "B0", 2);
+ write(pp->io.fd, COMMAND_HALT_BCAST, 2);
return;
}
@@ -375,13 +400,13 @@ arb_receive(
case 'F': /* clock failure */
pp->disp = MAXDISPERSE;
refclock_report(peer, CEVNT_FAULT);
- write(pp->io.fd, "B0", 2);
+ write(pp->io.fd, COMMAND_HALT_BCAST, 2);
return;
default:
pp->disp = MAXDISPERSE;
refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, "B0", 2);
+ write(pp->io.fd, COMMAND_HALT_BCAST, 2);
return;
}
if (syncchar != ' ')
@@ -398,9 +423,9 @@ arb_receive(
else if (peer->disp > MAXDISTANCE)
refclock_receive(peer);
- if (up->tcswitch >= MAXSTAGE) {
- write(pp->io.fd, "B0", 2);
- }
+ /* if (up->tcswitch >= MAXSTAGE) { */
+ write(pp->io.fd, COMMAND_HALT_BCAST, 2);
+ /* } */
}
diff --git a/ntpd/refclock_arc.c b/ntpd/refclock_arc.c
index af80621926cc..c6ac8c7ee74b 100644
--- a/ntpd/refclock_arc.c
+++ b/ntpd/refclock_arc.c
@@ -138,27 +138,27 @@ GENERAL
2) PRECISION should be -4/-5 (63ms/31ms) for the following reasons:
a) The ARC documentation claims the internal clock is (only)
- accurate to about 20ms relative to Rugby (plus there must be
- noticable drift and delay in the ms range due to transmission
- delays and changing atmospheric effects). This clock is not
- designed for ms accuracy as NTP has spoilt us all to expect.
+ accurate to about 20ms relative to Rugby (plus there must be
+ noticable drift and delay in the ms range due to transmission
+ delays and changing atmospheric effects). This clock is not
+ designed for ms accuracy as NTP has spoilt us all to expect.
b) The clock oscillator looks like a simple uncompensated quartz
- crystal of the sort used in digital watches (ie 32768Hz) which
- can have large temperature coefficients and drifts; it is not
- clear if this oscillator is properly disciplined to the MSF
- transmission, but as the default is to resync only once per
- *day*, we can imagine that it is not, and is free-running. We
- can minimise drift by resyncing more often (at the cost of
- reduced battery life), but drift/wander may still be
- significant.
+ crystal of the sort used in digital watches (ie 32768Hz) which
+ can have large temperature coefficients and drifts; it is not
+ clear if this oscillator is properly disciplined to the MSF
+ transmission, but as the default is to resync only once per
+ *day*, we can imagine that it is not, and is free-running. We
+ can minimise drift by resyncing more often (at the cost of
+ reduced battery life), but drift/wander may still be
+ significant.
c) Note that the bit time of 3.3ms adds to the potential error in
- the the clock timestamp, since the bit clock of the serial link
- may effectively be free-running with respect to the host clock
- and the MSF clock. Actually, the error is probably 1/16th of
- the above, since the input data is probably sampled at at least
- 16x the bit rate.
+ the the clock timestamp, since the bit clock of the serial link
+ may effectively be free-running with respect to the host clock
+ and the MSF clock. Actually, the error is probably 1/16th of
+ the above, since the input data is probably sampled at at least
+ 16x the bit rate.
By keeping the clock marked as not very precise, it will have a
fairly large dispersion, and thus will tend to be used as a
@@ -178,9 +178,9 @@ GENERAL
IN ANY CASE, BE SURE TO SET AN APPROPRIATE FUDGE FACTOR TO REMOVE
ANY RESIDUAL SKEW, eg:
- server 127.127.27.0 # ARCRON MSF radio clock unit 0.
- # Fudge timestamps by about 20ms.
- fudge 127.127.27.0 time1 0.020
+ server 127.127.27.0 # ARCRON MSF radio clock unit 0.
+ # Fudge timestamps by about 20ms.
+ fudge 127.127.27.0 time1 0.020
You will need to observe your system's behaviour, assuming you have
some other NTP source to compare it with, to work out what the
@@ -317,28 +317,28 @@ You have to wait for character echo + 10ms before sending next character.
/* 12. year tens */
/* 13. year units */
/* 14. BST/UTC status */
-/* bit 7 parity */
-/* bit 6 always 0 */
-/* bit 5 always 1 */
-/* bit 4 always 1 */
-/* bit 3 always 0 */
-/* bit 2 =1 if UTC is in effect, complementary to the BST bit */
-/* bit 1 =1 if BST is in effect, according to the BST bit */
-/* bit 0 BST/UTC change impending bit=1 in case of change impending */
+/* bit 7 parity */
+/* bit 6 always 0 */
+/* bit 5 always 1 */
+/* bit 4 always 1 */
+/* bit 3 always 0 */
+/* bit 2 =1 if UTC is in effect, complementary to the BST bit */
+/* bit 1 =1 if BST is in effect, according to the BST bit */
+/* bit 0 BST/UTC change impending bit=1 in case of change impending */
/* 15. status */
-/* bit 7 parity */
-/* bit 6 always 0 */
-/* bit 5 always 1 */
-/* bit 4 always 1 */
-/* bit 3 =1 if low battery is detected */
-/* bit 2 =1 if the very last reception attempt failed and a valid */
-/* time information already exists (bit0=1) */
-/* =0 if the last reception attempt was successful */
-/* bit 1 =1 if at least one reception since 2:30 am was successful */
-/* =0 if no reception attempt since 2:30 am was successful */
-/* bit 0 =1 if the RC Computer Clock contains valid time information */
-/* This bit is zero after reset and one after the first */
-/* successful reception attempt */
+/* bit 7 parity */
+/* bit 6 always 0 */
+/* bit 5 always 1 */
+/* bit 4 always 1 */
+/* bit 3 =1 if low battery is detected */
+/* bit 2 =1 if the very last reception attempt failed and a valid */
+/* time information already exists (bit0=1) */
+/* =0 if the last reception attempt was successful */
+/* bit 1 =1 if at least one reception since 2:30 am was successful */
+/* =0 if no reception attempt since 2:30 am was successful */
+/* bit 0 =1 if the RC Computer Clock contains valid time information */
+/* This bit is zero after reset and one after the first */
+/* successful reception attempt */
/* DHD note:
Also note g<cr> command which confirms that a resync is in progress, and
@@ -375,15 +375,15 @@ Also note h<cr> command which starts a resync to MSF signal.
/*
* Interface definitions
*/
-#define DEVICE "/dev/arc%d" /* Device name and unit. */
-#define SPEED B300 /* UART speed (300 baud) */
-#define PRECISION (-4) /* Precision (~63 ms). */
-#define HIGHPRECISION (-5) /* If things are going well... */
-#define REFID "MSFa" /* Reference ID. */
-#define REFID_MSF "MSF" /* Reference ID. */
-#define REFID_DCF77 "DCF" /* Reference ID. */
-#define REFID_WWVB "WWVB" /* Reference ID. */
-#define DESCRIPTION "ARCRON MSF/DCF/WWVB Receiver"
+#define DEVICE "/dev/arc%d" /* Device name and unit. */
+#define SPEED B300 /* UART speed (300 baud) */
+#define PRECISION (-4) /* Precision (~63 ms). */
+#define HIGHPRECISION (-5) /* If things are going well... */
+#define REFID "MSFa" /* Reference ID. */
+#define REFID_MSF "MSF" /* Reference ID. */
+#define REFID_DCF77 "DCF" /* Reference ID. */
+#define REFID_WWVB "WWVB" /* Reference ID. */
+#define DESCRIPTION "ARCRON MSF/DCF/WWVB Receiver"
#ifdef PRE_NTP420
#define MODE ttlmax
@@ -391,13 +391,13 @@ Also note h<cr> command which starts a resync to MSF signal.
#define MODE ttl
#endif
-#define LENARC 16 /* Format `o' timecode length. */
+#define LENARC 16 /* Format `o' timecode length. */
-#define BITSPERCHAR 11 /* Bits per character. */
-#define BITTIME 0x0DA740E /* Time for 1 bit at 300bps. */
-#define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */
-#define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */
-#define CHARTIME /* Time for char at 300bps. */ \
+#define BITSPERCHAR 11 /* Bits per character. */
+#define BITTIME 0x0DA740E /* Time for 1 bit at 300bps. */
+#define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */
+#define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */
+#define CHARTIME /* Time for char at 300bps. */ \
( (BITSPERCHAR == 11) ? CHARTIME11 : ( (BITSPERCHAR == 10) ? CHARTIME10 : \
(BITSPERCHAR * BITTIME) ) )
@@ -457,12 +457,12 @@ Also note h<cr> command which starts a resync to MSF signal.
#endif
};
-#define DEFAULT_RESYNC_TIME (57*60) /* Gap between resync attempts (s). */
-#define RETRY_RESYNC_TIME (27*60) /* Gap to emergency resync attempt. */
+#define DEFAULT_RESYNC_TIME (57*60) /* Gap between resync attempts (s). */
+#define RETRY_RESYNC_TIME (27*60) /* Gap to emergency resync attempt. */
#ifdef ARCRON_KEEN
-#define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */
+#define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */
#else
-#define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */
+#define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */
#endif
static const int moff[12] =
@@ -470,30 +470,30 @@ Also note h<cr> command which starts a resync to MSF signal.
/* Flags for a raw open() of the clock serial device. */
#ifdef O_NOCTTY /* Good, we can avoid tty becoming controlling tty. */
#define OPEN_FLAGS (O_RDWR | O_NOCTTY)
-#else /* Oh well, it may not matter... */
+#else /* Oh well, it may not matter... */
#define OPEN_FLAGS (O_RDWR)
#endif
/* Length of queue of command bytes to be sent. */
-#define CMDQUEUELEN 4 /* Enough for two cmds + each \r. */
+#define CMDQUEUELEN 4 /* Enough for two cmds + each \r. */
/* Queue tick time; interval in seconds between chars taken off queue. */
/* Must be >= 2 to allow o\r response to come back uninterrupted. */
-#define QUEUETICK 2 /* Allow o\r reply to finish. */
+#define QUEUETICK 2 /* Allow o\r reply to finish. */
/*
* ARC unit control structure
*/
struct arcunit {
- l_fp lastrec; /* Time tag for the receive time (system). */
- int status; /* Clock status. */
+ l_fp lastrec; /* Time tag for the receive time (system). */
+ int status; /* Clock status. */
- int quality; /* Quality of reception 0--5 for unit. */
+ int quality; /* Quality of reception 0--5 for unit. */
/* We may also use the values -1 or 6 internally. */
u_long quality_stamp; /* Next time to reset quality average. */
u_long next_resync; /* Next resync time (s) compared to current_time. */
- int resyncing; /* Resync in progress if true. */
+ int resyncing; /* Resync in progress if true. */
/* In the outgoing queue, cmdqueue[0] is next to be sent. */
char cmdqueue[CMDQUEUELEN+1]; /* Queue of outgoing commands + \0. */
@@ -527,11 +527,11 @@ static int possible_leap = 0; /* No resync required by default. */
#endif
#if 0
-static void dummy_event_handler P((struct peer *));
-static void arc_event_handler P((struct peer *));
+static void dummy_event_handler (struct peer *);
+static void arc_event_handler (struct peer *);
#endif /* 0 */
-#define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */
+#define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */
#define MIN_CLOCK_QUALITY 0 /* Min quality clock will return. */
#define MIN_CLOCK_QUALITY_OK 3 /* Min quality for OK reception. */
#define MAX_CLOCK_QUALITY 5 /* Max quality clock will return. */
@@ -539,22 +539,22 @@ static void arc_event_handler P((struct peer *));
/*
* Function prototypes
*/
-static int arc_start P((int, struct peer *));
-static void arc_shutdown P((int, struct peer *));
-static void arc_receive P((struct recvbuf *));
-static void arc_poll P((int, struct peer *));
+static int arc_start (int, struct peer *);
+static void arc_shutdown (int, struct peer *);
+static void arc_receive (struct recvbuf *);
+static void arc_poll (int, struct peer *);
/*
* Transfer vector
*/
struct refclock refclock_arc = {
- arc_start, /* start up driver */
- arc_shutdown, /* shut down driver */
- arc_poll, /* transmit poll message */
- noentry, /* not used (old arc_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old arc_buginfo) */
- NOFLAGS /* not used */
+ arc_start, /* start up driver */
+ arc_shutdown, /* shut down driver */
+ arc_poll, /* transmit poll message */
+ noentry, /* not used (old arc_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old arc_buginfo) */
+ NOFLAGS /* not used */
};
/* Queue us up for the next tick. */
@@ -591,7 +591,7 @@ arc_event_handler(
)
{
struct refclockproc *pp = peer->procptr;
- register struct arcunit *up = (struct arcunit *)pp->unitptr;
+ register struct arcunit *up = pp->unitptr;
int i;
char c;
#ifdef DEBUG
@@ -627,48 +627,49 @@ arc_start(
{
register struct arcunit *up;
struct refclockproc *pp;
+ int temp_fd;
int fd;
char device[20];
#ifdef HAVE_TERMIOS
struct termios arg;
#endif
- msyslog(LOG_NOTICE, "ARCRON: %s: opening unit %d", arc_version, unit);
-#ifdef DEBUG
- if(debug) {
- printf("arc: %s: attempt to open unit %d.\n", arc_version, unit);
- }
-#endif
-
- /* Prevent a ridiculous device number causing overflow of device[]. */
- if((unit < 0) || (unit > 255)) { return(0); }
+ msyslog(LOG_NOTICE, "MSF_ARCRON %s: opening unit %d",
+ arc_version, unit);
+ DPRINTF(1, ("arc: %s: attempt to open unit %d.\n", arc_version,
+ unit));
/*
* Open serial port. Use CLK line discipline, if available.
*/
- (void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED, LDISC_CLK)))
- return(0);
-#ifdef DEBUG
- if(debug) { printf("arc: unit %d using open().\n", unit); }
-#endif
- fd = open(device, OPEN_FLAGS);
- if(fd < 0) {
-#ifdef DEBUG
- if(debug) { printf("arc: failed [open()] to open %s.\n", device); }
-#endif
- return(0);
+ snprintf(device, sizeof(device), DEVICE, unit);
+ temp_fd = refclock_open(device, SPEED, LDISC_CLK);
+ if (temp_fd <= 0)
+ return 0;
+ DPRINTF(1, ("arc: unit %d using tty_open().\n", unit));
+ fd = tty_open(device, OPEN_FLAGS, 0777);
+ if (fd < 0) {
+ msyslog(LOG_ERR, "MSF_ARCRON(%d): failed second open(%s, 0777): %m.\n",
+ unit, device);
+ close(temp_fd);
+ return 0;
}
+ close(temp_fd);
+ temp_fd = -1;
+#ifndef SYS_WINNT
fcntl(fd, F_SETFL, 0); /* clear the descriptor flags */
-#ifdef DEBUG
- if(debug)
- { printf("arc: opened RS232 port with file descriptor %d.\n", fd); }
#endif
+ DPRINTF(1, ("arc: opened RS232 port with file descriptor %d.\n", fd));
#ifdef HAVE_TERMIOS
- tcgetattr(fd, &arg);
+ if (tcgetattr(fd, &arg) < 0) {
+ msyslog(LOG_ERR, "MSF_ARCRON(%d): tcgetattr(%s): %m.\n",
+ unit, device);
+ close(fd);
+ return 0;
+ }
arg.c_iflag = IGNBRK | ISTRIP;
arg.c_oflag = 0;
@@ -677,28 +678,36 @@ arc_start(
arg.c_cc[VMIN] = 1;
arg.c_cc[VTIME] = 0;
- tcsetattr(fd, TCSANOW, &arg);
+ if (tcsetattr(fd, TCSANOW, &arg) < 0) {
+ msyslog(LOG_ERR, "MSF_ARCRON(%d): tcsetattr(%s): %m.\n",
+ unit, device);
+ close(fd);
+ return 0;
+ }
#else
- msyslog(LOG_ERR, "ARCRON: termios not supported in this driver");
+ msyslog(LOG_ERR, "ARCRON: termios required by this driver");
(void)close(fd);
return 0;
#endif
- up = (struct arcunit *) emalloc(sizeof(struct arcunit));
- if(!up) { (void) close(fd); return(0); }
/* Set structure to all zeros... */
- memset((char *)up, 0, sizeof(struct arcunit));
+ up = emalloc_zero(sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = arc_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
- if(!io_addclock(&pp->io)) { (void) close(fd); free(up); return(0); }
- pp->unitptr = (caddr_t)up;
+ if (!io_addclock(&pp->io)) {
+ close(fd);
+ pp->io.fd = -1;
+ free(up);
+ return(0);
+ }
+ pp->unitptr = up;
/*
* Initialize miscellaneous variables
@@ -769,9 +778,11 @@ arc_shutdown(
peer->action = dummy_event_handler;
pp = peer->procptr;
- up = (struct arcunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ up = pp->unitptr;
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
/*
@@ -812,9 +823,9 @@ send_slow(
if(spaceleft < sl) { /* Should not normally happen... */
#ifdef DEBUG
msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)",
- sl, spaceleft);
+ sl, spaceleft);
#endif
- return(0); /* FAILED! */
+ return(0); /* FAILED! */
}
/* Copy in the command to be sent. */
@@ -846,10 +857,10 @@ get1(char *p, int *val)
(((q) < MIN_CLOCK_QUALITY_OK) ? "TOO POOR, will not use clock" : \
"OK, will use clock"))
- /*
+/*
* arc_receive - receive data from the serial interface
*/
- static void
+static void
arc_receive(
struct recvbuf *rbufp
)
@@ -869,7 +880,7 @@ arc_receive(
*/
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
- up = (struct arcunit *)pp->unitptr;
+ up = pp->unitptr;
/*
@@ -1005,7 +1016,7 @@ arc_receive(
/* Just in case we still have lots of rubbish in the buffer... */
/* ...and to avoid the same timestamp being reused by mistake, */
/* eg on receipt of the \r coming in on its own after the */
- /* timecode. */
+ /* timecode. */
if(pp->lencode >= LENARC) {
#ifdef DEBUG
if(debug && (rbufp->recv_buffer[0] != '\r'))
@@ -1083,9 +1094,9 @@ arc_receive(
}
#endif
msyslog(LOG_NOTICE,
- "ARCRON: sync finished, signal quality %d: %s",
- up->quality,
- quality_action(up->quality));
+ "ARCRON: sync finished, signal quality %d: %s",
+ up->quality,
+ quality_action(up->quality));
up->resyncing = 0; /* Resync is over. */
quality_average = 0;
quality_sum = 0;
@@ -1210,7 +1221,7 @@ arc_receive(
if(pp->year >= YEAR_PIVOT+2000-2 ) { /* Y2KFixes */
/*This should get attention B^> */
msyslog(LOG_NOTICE,
- "ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!");
+ "ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!");
}
#ifdef DEBUG
if(debug) {
@@ -1271,50 +1282,52 @@ arc_receive(
if(peer->MODE > 0) {
if(pp->sloppyclockflag & CLK_FLAG1) {
struct tm local;
- struct tm *gmtp;
- time_t unixtime;
+ struct tm *gmtp;
+ time_t unixtime;
- /*
- * Convert to GMT for sites that distribute localtime.
+ /*
+ * Convert to GMT for sites that distribute localtime.
* This means we have to do Y2K conversion on the
* 2-digit year; otherwise, we get the time wrong.
- */
-
+ */
+
+ memset(&local, 0, sizeof(local));
+
local.tm_year = pp->year-1900;
- local.tm_mon = month-1;
- local.tm_mday = pp->day;
- local.tm_hour = pp->hour;
- local.tm_min = pp->minute;
- local.tm_sec = pp->second;
- switch (peer->MODE) {
+ local.tm_mon = month-1;
+ local.tm_mday = pp->day;
+ local.tm_hour = pp->hour;
+ local.tm_min = pp->minute;
+ local.tm_sec = pp->second;
+ switch (peer->MODE) {
case 1:
local.tm_isdst = (flags & 2);
break;
case 2:
- local.tm_isdst = (flags & 2);
+ local.tm_isdst = (flags & 2);
break;
case 3:
switch (flags & 3) {
case 0: /* It is unclear exactly when the
- Arcron changes from DST->ST and
+ Arcron changes from DST->ST and
ST->DST. Testing has shown this
to be irregular. For the time
being, let the OS decide. */
- local.tm_isdst = 0;
+ local.tm_isdst = 0;
#ifdef DEBUG
if (debug)
printf ("arc: DST = 00 (0)\n");
#endif
break;
case 1: /* dst->st time */
- local.tm_isdst = -1;
+ local.tm_isdst = -1;
#ifdef DEBUG
if (debug)
printf ("arc: DST = 01 (1)\n");
#endif
break;
case 2: /* st->dst time */
- local.tm_isdst = -1;
+ local.tm_isdst = -1;
#ifdef DEBUG
if (debug)
printf ("arc: DST = 10 (2)\n");
@@ -1331,26 +1344,26 @@ arc_receive(
break;
default:
msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d",
- peer->MODE);
+ peer->MODE);
return;
break;
}
- unixtime = mktime (&local);
- if ((gmtp = gmtime (&unixtime)) == NULL)
- {
+ unixtime = mktime (&local);
+ if ((gmtp = gmtime (&unixtime)) == NULL)
+ {
pp->lencode = 0;
- refclock_report (peer, CEVNT_FAULT);
- return;
- }
+ refclock_report (peer, CEVNT_FAULT);
+ return;
+ }
pp->year = gmtp->tm_year+1900;
- month = gmtp->tm_mon+1;
- pp->day = ymd2yd(pp->year,month,gmtp->tm_mday);
- /* pp->day = gmtp->tm_yday; */
- pp->hour = gmtp->tm_hour;
- pp->minute = gmtp->tm_min;
- pp->second = gmtp->tm_sec;
+ month = gmtp->tm_mon+1;
+ pp->day = ymd2yd(pp->year,month,gmtp->tm_mday);
+ /* pp->day = gmtp->tm_yday; */
+ pp->hour = gmtp->tm_hour;
+ pp->minute = gmtp->tm_min;
+ pp->second = gmtp->tm_sec;
#ifdef DEBUG
- if (debug)
+ if (debug)
{
printf ("arc: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
pp->year,month,gmtp->tm_mday,pp->hour,pp->minute,
@@ -1359,10 +1372,10 @@ arc_receive(
#endif
} else
{
- /*
- * For more rational sites distributing UTC
- */
- pp->day = ymd2yd(pp->year,month,pp->day);
+ /*
+ * For more rational sites distributing UTC
+ */
+ pp->day = ymd2yd(pp->year,month,pp->day);
}
}
@@ -1391,10 +1404,10 @@ arc_receive(
if(up->saved_flags != pp->sloppyclockflag) {
#ifdef DEBUG
msyslog(LOG_NOTICE, "ARCRON: flags enabled: %s%s%s%s",
- ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
- ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
- ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."),
- ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
+ ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
+ ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
+ ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."),
+ ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
/* Note effects of flags changing... */
if(debug) {
printf("arc: PRECISION = %d.\n", peer->precision);
@@ -1436,7 +1449,7 @@ arc_receive(
/* request_time() sends a time request to the clock with given peer. */
/* This automatically reports a fault if necessary. */
/* No data should be sent after this until arc_poll() returns. */
-static void request_time P((int, struct peer *));
+static void request_time (int, struct peer *);
static void
request_time(
int unit,
@@ -1444,7 +1457,7 @@ request_time(
)
{
struct refclockproc *pp = peer->procptr;
- register struct arcunit *up = (struct arcunit *)pp->unitptr;
+ register struct arcunit *up = pp->unitptr;
#ifdef DEBUG
if(debug) { printf("arc: unit %d: requesting time.\n", unit); }
#endif
@@ -1475,7 +1488,7 @@ arc_poll(
int resync_needed; /* Should we start a resync? */
pp = peer->procptr;
- up = (struct arcunit *)pp->unitptr;
+ up = pp->unitptr;
#if 0
pp->lencode = 0;
memset(pp->a_lastcode, 0, sizeof(pp->a_lastcode));
diff --git a/ntpd/refclock_as2201.c b/ntpd/refclock_as2201.c
index f04d417bea83..163c2afee1a2 100644
--- a/ntpd/refclock_as2201.c
+++ b/ntpd/refclock_as2201.c
@@ -129,10 +129,10 @@ static char stat_command[][30] = {
/*
* Function prototypes
*/
-static int as2201_start P((int, struct peer *));
-static void as2201_shutdown P((int, struct peer *));
-static void as2201_receive P((struct recvbuf *));
-static void as2201_poll P((int, struct peer *));
+static int as2201_start (int, struct peer *);
+static void as2201_shutdown (int, struct peer *);
+static void as2201_receive (struct recvbuf *);
+static void as2201_poll (int, struct peer *);
/*
* Transfer vector
@@ -165,26 +165,23 @@ as2201_start(
/*
* Open serial port. Use CLK line discipline, if available.
*/
- (void)sprintf(gpsdev, DEVICE, unit);
+ snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_CLK)))
return (0);
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct as2201unit *)
- emalloc(sizeof(struct as2201unit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct as2201unit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = as2201_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -217,8 +214,10 @@ as2201_shutdown(
pp = peer->procptr;
up = (struct as2201unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
diff --git a/ntpd/refclock_atom.c b/ntpd/refclock_atom.c
index 2e469ecd4054..d8a9d3e27add 100644
--- a/ntpd/refclock_atom.c
+++ b/ntpd/refclock_atom.c
@@ -14,21 +14,23 @@
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
-#if defined(REFCLOCK) && defined(CLOCK_ATOM)
-
-#ifdef HAVE_PPSAPI
-# include "ppsapi_timepps.h"
-#endif /* HAVE_PPSAPI */
+/*
+ * This driver requires the PPSAPI interface (RFC 2783)
+ */
+#if defined(REFCLOCK) && defined(CLOCK_ATOM) && defined(HAVE_PPSAPI)
+#include "ppsapi_timepps.h"
+#include "refclock_atom.h"
/*
* This driver furnishes an interface for pulse-per-second (PPS) signals
* produced by a cesium clock, timing receiver or related equipment. It
- * can be used to remove accumulated jitter and retime a secondary
- * server when synchronized to a primary server over a congested, wide-
- * area network and before redistributing the time to local clients.
+ * can be used to remove accumulated jitter over a congested link and
+ * retime a server before redistributing the time to clients. It can
+ *also be used as a holdover should all other synchronization sources
+ * beconme unreachable.
*
* 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
+ * within +-0.4 s by another means, such as a radio clock or NTP
* itself. There are two ways to connect the PPS signal, normally at TTL
* levels, to the computer. One is to shift to EIA levels and connect to
* pin 8 (DCD) of a serial port. This requires a level converter and
@@ -36,27 +38,13 @@
* to connect the PPS signal directly to pin 10 (ACK) of a PC paralell
* port. These methods are architecture dependent.
*
- * Both methods require a modified device driver and kernel interface
- * compatible with the Pulse-per-Second API for Unix-like Operating
+ * This driver requires 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
+ * available for FreeBSD, Linux, SunOS, Solaris and Tru64. However, at
+ * present only the Tru64 implementation provides the full generality of
* the API with multiple PPS drivers and multiple handles per driver. If
* the PPSAPI is normally implemented in the /usr/include/sys/timepps.h
* header file and kernel support specific to each operating system.
- * However, this driver can operate without this interface if means are
- * proviced to call the pps_sample() routine from another driver. Please
- * note; if the PPSAPI interface is present, it must be used.
- *
- * In many configurations a single port is used for the radio timecode
- * and PPS signal. In order to provide for this configuration and others
- * involving dedicated multiple serial/parallel ports, the driver first
- * attempts to open the device /dev/pps%d, where %d is the unit number.
- * If this fails, the driver attempts to open the device specified by
- * the pps configuration command. If a port is to be shared, the pps
- * command must be placed before the radio device(s) and the radio
- * device(s) must be placed before the PPS driver(s) in the
- * configuration file.
*
* This driver normally uses the PLL/FLL clock discipline implemented in
* the ntpd code. Ordinarily, this is the most accurate means, as the
@@ -65,80 +53,62 @@
* to hundreds of PPM), it's better to used the kernel support, if
* available.
*
+ * This deriver is subject to the mitigation rules described in the
+ * "mitigation rulse and the prefer peer" page. However, there is an
+ * important difference. If this driver becomes the PPS driver according
+ * to these rules, it is acrive only if (a) a prefer peer other than
+ * this driver is among the survivors or (b) there are no survivors and
+ * the minsane option of the tos command is zero. This is intended to
+ * support space missions where updates from other spacecraft are
+ * infrequent, but a reliable PPS signal, such as from an Ultra Stable
+ * Oscillator (USO) is available.
+ *
* Fudge Factors
*
- * If flag2 is dim (default), the on-time epoch is the assert edge of
- * the PPS signal; if lit, the on-time epoch is the clear edge. If flag2
- * is lit, the assert edge is used; if flag3 is dim (default), the
- * kernel PPS support is disabled; if lit it is enabled. The time1
- * parameter can be used to compensate for miscellaneous device driver
- * and OS delays.
+ * The PPS timestamp is captured on the rising (assert) edge if flag2 is
+ * dim (default) and on the falling (clear) edge if lit. If flag3 is dim
+ * (default), the kernel PPS support is disabled; if lit it is enabled.
+ * If flag4 is lit, each timesampt is copied to the clockstats file for
+ * later analysis. This can be useful when constructing Allan deviation
+ * plots. The time1 parameter can be used to compensate for
+ * miscellaneous device driver and OS delays.
*/
/*
* Interface definitions
*/
-#ifdef HAVE_PPSAPI
#define DEVICE "/dev/pps%d" /* device name and unit */
-#endif /* HAVE_PPSAPI */
-
#define PRECISION (-20) /* precision assumed (about 1 us) */
#define REFID "PPS\0" /* reference ID */
#define DESCRIPTION "PPS Clock Discipline" /* WRU */
-#define NANOSECOND 1000000000 /* one second (ns) */
-#define RANGEGATE 500000 /* range gate (ns) */
-static struct peer *pps_peer; /* atom driver for PPS sources */
-
-#ifdef HAVE_PPSAPI
/*
* PPS unit control structure
*/
struct ppsunit {
- struct timespec ts; /* last timestamp */
- int fddev; /* pps device descriptor */
- pps_params_t pps_params; /* pps parameters */
- pps_info_t pps_info; /* last pps data */
- pps_handle_t handle; /* pps handlebars */
+ struct refclock_atom atom; /* atom structure pointer */
+ int fddev; /* file descriptor */
};
-#endif /* HAVE_PPSAPI */
/*
* Function prototypes
*/
-static int atom_start P((int, struct peer *));
-static void atom_poll P((int, struct peer *));
-static void atom_shutdown P((int, struct peer *));
-#ifdef HAVE_PPSAPI
-static void atom_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
-static void atom_timer P((int, struct peer *));
-static int atom_ppsapi P((struct peer *, int));
-#endif /* HAVE_PPSAPI */
+static int atom_start (int, struct peer *);
+static void atom_shutdown (int, struct peer *);
+static void atom_poll (int, struct peer *);
+static void atom_timer (int, struct peer *);
/*
* Transfer vector
*/
-#ifdef HAVE_PPSAPI
struct refclock refclock_atom = {
atom_start, /* start up driver */
atom_shutdown, /* shut down driver */
atom_poll, /* transmit poll message */
- atom_control, /* fudge control */
+ noentry, /* control (not used) */
noentry, /* initialize driver (not used) */
noentry, /* buginfo (not used) */
atom_timer, /* called once per second */
};
-#else /* HAVE_PPSAPI */
-struct refclock refclock_atom = {
- atom_start, /* start up driver */
- atom_shutdown, /* shut down driver */
- atom_poll, /* transmit poll message */
- noentry, /* fudge control (not used) */
- noentry, /* initialize driver (not used) */
- noentry, /* buginfo (not used) */
- NOFLAGS /* not used */
-};
-#endif /* HAVE_PPPSAPI */
/*
@@ -151,22 +121,17 @@ atom_start(
)
{
struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- register struct ppsunit *up;
+ struct ppsunit *up;
char device[80];
- int mode;
-#endif /* HAVE_PPSAPI */
/*
* Allocate and initialize unit structure
*/
- pps_peer = peer;
pp = peer->procptr;
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
pp->stratum = STRATUM_UNSPEC;
memcpy((char *)&pp->refid, REFID, 4);
-#ifdef HAVE_PPSAPI
up = emalloc(sizeof(struct ppsunit));
memset(up, 0, sizeof(struct ppsunit));
pp->unitptr = (caddr_t)up;
@@ -175,35 +140,18 @@ atom_start(
* Open PPS device. This can be any serial or parallel port and
* not necessarily the port used for the associated radio.
*/
- sprintf(device, DEVICE, unit);
- up->fddev = open(device, O_RDWR, 0777);
+ snprintf(device, sizeof(device), DEVICE, unit);
+ up->fddev = tty_open(device, O_RDWR, 0777);
if (up->fddev <= 0) {
msyslog(LOG_ERR,
- "refclock_atom: %s: %m", device);
- return (0);
- }
-
- /*
- * Light off the PPSAPI interface.
- */
- if (time_pps_create(up->fddev, &up->handle) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_create failed: %m");
+ "refclock_atom: %s: %m", device);
return (0);
}
/*
- * If the mode is nonzero, use that for the time_pps_setparams()
- * mode; otherwise, PPS_CAPTUREASSERT. Enable kernel PPS if
- * flag3 is lit.
+ * Light up the PPSAPI interface.
*/
- mode = peer->ttl;
- if (mode == 0)
- mode = PPS_CAPTUREASSERT;
- return (atom_ppsapi(peer, mode));
-#else /* HAVE_PPSAPI */
- return (1);
-#endif /* HAVE_PPSAPI */
+ return (refclock_ppsapi(up->fddev, &up->atom));
}
@@ -217,249 +165,44 @@ atom_shutdown(
)
{
struct refclockproc *pp;
- register struct ppsunit *up;
+ struct ppsunit *up;
pp = peer->procptr;
up = (struct ppsunit *)pp->unitptr;
-#ifdef HAVE_PPSAPI
if (up->fddev > 0)
close(up->fddev);
- if (up->handle != 0)
- time_pps_destroy(up->handle);
-#endif /* HAVE_PPSAPI */
- if (pps_peer == peer)
- pps_peer = NULL;
free(up);
}
-
-#ifdef HAVE_PPSAPI
-/*
- * atom_control - fudge control
- */
-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;
- int mode;
-
- pp = peer->procptr;
- if (peer->ttl != 0) /* all legal modes must be nonzero */
- return;
-
- if (pp->sloppyclockflag & CLK_FLAG2)
- mode = PPS_CAPTURECLEAR;
- else
- mode = PPS_CAPTUREASSERT;
- atom_ppsapi(peer, mode);
-}
-
-
-/*
- * Initialize PPSAPI
- */
-int
-atom_ppsapi(
- struct peer *peer, /* peer structure pointer */
- int mode /* mode */
- )
-{
- struct refclockproc *pp;
- register struct ppsunit *up;
- int capability;
-
- pp = peer->procptr;
- up = (struct ppsunit *)pp->unitptr;
- if (up->handle == 0)
- return (0);
-
- if (time_pps_getcap(up->handle, &capability) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_getcap failed: %m");
- return (0);
- }
- memset(&up->pps_params, 0, sizeof(pps_params_t));
- up->pps_params.api_version = PPS_API_VERS_1;
- up->pps_params.mode = mode | PPS_TSFMT_TSPEC;
- if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_setparams failed: %m");
- return (0);
- }
- if (pp->sloppyclockflag & CLK_FLAG3) {
- if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
- up->pps_params.mode & ~PPS_TSFMT_TSPEC,
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_kcbind failed: %m");
- return (0);
- }
- pps_enable = 1;
- }
-#if DEBUG
- if (debug) {
- time_pps_getparams(up->handle, &up->pps_params);
- printf(
- "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x\n",
- up->fddev, capability, up->pps_params.api_version,
- up->pps_params.mode);
- }
-#endif
- return (1);
-}
-
-
/*
* atom_timer - called once per second
- *
- * This routine is called once per second when the PPSAPI interface is
- * present. It snatches the PPS timestamp from the kernel and saves the
- * sign-extended fraction in a circular buffer for processing at the
- * next poll event.
*/
-static void
+void
atom_timer(
- int unit, /* unit number (not used) */
+ int unit, /* unit pointer (not used) */
struct peer *peer /* peer structure pointer */
)
{
- register struct ppsunit *up;
+ struct ppsunit *up;
struct refclockproc *pp;
- pps_info_t pps_info;
- struct timespec timeout, ts;
- long sec, nsec;
- double dtemp;
- char tbuf[80]; /* monitor buffer */
+ char tbuf[80];
- /*
- * Convert the timespec nanoseconds field to signed double and
- * save in the median filter. for billboards. No harm is done if
- * previous data are overwritten. If the discipline comes bum or
- * the data grow stale, just forget it. A range gate rejects new
- * samples if less than a jiggle time from the next second.
- */
pp = peer->procptr;
up = (struct ppsunit *)pp->unitptr;
- if (up->handle == 0)
+ if (refclock_pps(peer, &up->atom, pp->sloppyclockflag) <= 0)
return;
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
- if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
- &timeout) < 0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- if (up->pps_params.mode & PPS_CAPTUREASSERT) {
- ts = up->pps_info.assert_timestamp;
- } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
- ts = up->pps_info.clear_timestamp;
- } else {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
+ peer->flags |= FLAG_PPS;
/*
- * There can be zero, one or two PPS seconds between polls. If
- * zero, either the poll clock is slightly faster than the PPS
- * clock or the PPS clock has died. If the PPS clock advanced
- * once between polls, we make sure the fraction time difference
- * since the last sample is within the range gate of 5 ms (500
- * PPM). If the PPS clock advanced twice since the last poll,
- * the poll bracketed more than one second and the first second
- * was lost to a slip. Since the interval since the last sample
- * found is now two seconds, just widen the range gate. If the
- * PPS clock advanced three or more times, either the signal has
- * failed for a number of seconds or we have runts, in which
- * case just ignore them.
- *
* If flag4 is lit, record each second offset to clockstats.
* That's so we can make awesome Allan deviation plots.
*/
- sec = ts.tv_sec - up->ts.tv_sec;
- nsec = ts.tv_nsec - up->ts.tv_nsec;
- up->ts = ts;
- if (nsec < 0) {
- sec --;
- nsec += NANOSECOND;
- } else if (nsec >= NANOSECOND) {
- sec++;
- nsec -= NANOSECOND;
- }
- if (sec * NANOSECOND + nsec > NANOSECOND + RANGEGATE)
- return;
-
- else if (sec * NANOSECOND + nsec < NANOSECOND - RANGEGATE)
- return;
-
- pp->lastrec.l_ui = ts.tv_sec + JAN_1970;
- dtemp = ts.tv_nsec * FRAC / 1e9;
- if (dtemp >= FRAC)
- 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);
- if (pp->sloppyclockflag & CLK_FLAG4){
- sprintf(tbuf, "%.9f", dtemp);
+ if (pp->sloppyclockflag & CLK_FLAG4) {
+ snprintf(tbuf, sizeof(tbuf), "%.9f",
+ pp->filter[pp->coderecv]);
record_clock_stats(&peer->srcadr, tbuf);
}
-#ifdef DEBUG
- if (debug > 1)
- printf("atom_timer: %lu %f %f\n", current_time,
- dtemp, pp->fudgetime1);
-#endif
- return;
-}
-#endif /* HAVE_PPSAPI */
-
-
-/*
- * pps_sample - receive PPS data from some other clock driver
- *
- * This routine is called once per second when the external clock driver
- * processes PPS information. It processes the PPS timestamp and saves
- * the sign-extended fraction in a circular buffer for processing at the
- * next poll event. This works only for a single PPS device.
- *
- * The routine should be used by another configured driver ONLY when
- * this driver is configured as well and the PPSAPI is NOT in use.
- */
-int
-pps_sample(
- l_fp *offset /* PPS offset */
- )
-{
- register struct peer *peer;
- struct refclockproc *pp;
- l_fp lftmp;
- double doffset;
-
- peer = pps_peer;
- if (peer == NULL)
- return (1);
-
- pp = peer->procptr;
-
- /*
- * Convert the timeval to l_fp and save for billboards. Sign-
- * extend the fraction and stash in the buffer. No harm is done
- * if previous data are overwritten. If the discipline comes bum
- * or the data grow stale, just forget it.
- */
- pp->lastrec = *offset;
- L_CLR(&lftmp);
- L_ADDF(&lftmp, pp->lastrec.l_f);
- LFPTOD(&lftmp, doffset);
- SAMPLE(-doffset + pp->fudgetime1);
- return (0);
}
@@ -473,45 +216,24 @@ atom_poll(
)
{
struct refclockproc *pp;
- pp = peer->procptr;
- pp->polls++;
/*
- * Valid time is returned only if the prefer peer has survived
- * the intersection algorithm and within 0.4 s of local time
- * and not too long ago. This ensures the PPS time is within
- * 0.5 s of the local time and the seconds numbering is
- * unambiguous. Note that the leap bits, stratum and refid are
- * set from the prefer peer, unless overriden by a fudge
- * command.
+ * Don't wiggle the clock until some other driver has numbered
+ * the seconds.
*/
- if (pp->codeproc == pp->coderecv) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
-
- } else if (sys_prefer == NULL) {
- pp->codeproc = pp->coderecv;
+ if (sys_leap == LEAP_NOTINSYNC)
return;
- } else if (fabs(sys_prefer->offset) >= 0.4) {
- pp->codeproc = pp->coderecv;
+ pp = peer->procptr;
+ pp->polls++;
+ if (pp->codeproc == pp->coderecv) {
+ peer->flags &= ~FLAG_PPS;
+ refclock_report(peer, CEVNT_TIMEOUT);
return;
}
- pp->leap = sys_prefer->leap;
- if (pp->stratum >= STRATUM_UNSPEC)
- peer->stratum = sys_prefer->stratum;
- else
- peer->stratum = pp->stratum;
pp->lastref = pp->lastrec;
refclock_receive(peer);
}
#else
int refclock_atom_bs;
-int
-pps_sample(
- l_fp *offset /* PPS offset */
- )
-{
- return (1);
-}
#endif /* REFCLOCK */
diff --git a/ntpd/refclock_bancomm.c b/ntpd/refclock_bancomm.c
index 9fc8c82c4aff..3bb0ffea430a 100644
--- a/ntpd/refclock_bancomm.c
+++ b/ntpd/refclock_bancomm.c
@@ -20,26 +20,29 @@
* vme_control() and vme_buginfo() have been deleted because
* they are no longer being used.
*
- * The time on the bc635 TFP must be set to GMT due to the
- * fact that NTP makes use of GMT for all its calculations.
- *
- * Installation of the Datum/Bancomm driver creates the
- * device file /dev/btfp0
- *
* 04/28/2005 Rob Neal
* Modified to add support for Symmetricom bc637PCI-U Time &
* Frequency Processor.
+ * 2/21/2007 Ali Ghorashi
+ * Modified to add support for Symmetricom bc637PCI-U Time &
+ * Frequency Processor on Solaris.
+ * Tested on Solaris 10 with a bc635 card.
+ *
* Card bus type (VME/VXI or PCI) and environment are specified via the
* "mode" keyword on the server command in ntp.conf.
- * server 127.127.16.u prefer mode m (...)
- * Modes currently supported are
+ * server 127.127.16.u prefer mode M
+ * where u is the id (usually 0) of the entry in /dev (/dev/stfp0)
+ *
+ * and M is one of the following modes:
* 1 : FreeBSD PCI 635/637.
* 2 : Linux or Windows PCI 635/637.
+ * 3 : Solaris PCI 635/637
* not specified, or other number:
* : Assumed to be VME/VXI legacy Bancomm card on Solaris.
* Linux and Windows platforms require Symmetricoms' proprietary driver
- * for the TFP card.
- * Tested on FreeBSD 5.3 with a 637 card.
+ * for the TFP card.
+ * Solaris requires Symmetricom's driver and its header file (freely distributed) to
+ * be installed and running.
*/
#ifdef HAVE_CONFIG_H
@@ -58,7 +61,6 @@
#include <syslog.h>
#include <ctype.h>
-/* STUFF BY RES */
struct btfp_time /* Structure for reading 5 time words */
/* in one ioctl(2) operation. */
{
@@ -85,9 +87,37 @@ struct btfp_time /* Structure for reading 5 time words */
#define READTIME _IOR('u', 5, struct btfp_time )
#endif
-#define VMEFD "/dev/btfp0"
+/* Solaris specific section */
+struct stfp_tm {
+ int32_t tm_sec;
+ int32_t tm_min;
+ int32_t tm_hour;
+ int32_t tm_mday;
+ int32_t tm_mon;
+ int32_t tm_year;
+ int32_t tm_wday;
+ int32_t tm_yday;
+ int32_t tm_isdst;
+};
+
+struct stfp_time {
+ struct stfp_tm tm;
+ int32_t usec; /* usec 0 - 999999 */
+ int32_t hnsec; /* hnsec 0 - 9 (hundreds of nsecs) */
+ int32_t status;
+};
+
+#define SELTIMEFORMAT 2
+# define TIME_DECIMAL 0
+# define TIME_BINARY 1
-struct vmedate { /* structure returned by get_vmetime.c */
+#if defined(__sun__)
+#undef READTIME
+#define READTIME 9
+#endif /** __sun___ **/
+/* end solaris specific section */
+
+struct vmedate { /* structure returned by get_vmetime.c */
unsigned short year;
unsigned short day;
unsigned short hr;
@@ -97,7 +127,6 @@ struct vmedate { /* structure returned by get_vmetime.c */
unsigned short status;
};
-/* END OF STUFF FROM RES */
typedef void *SYMMT_PCI_HANDLE;
/*
@@ -139,7 +168,11 @@ static void vme_shutdown (int, struct peer *);
static void vme_receive (struct recvbuf *);
static void vme_poll (int unit, struct peer *);
struct vmedate *get_datumtime(struct vmedate *);
-void tvme_fill(struct vmedate *, uint32_t btm[2]);
+void tvme_fill(struct vmedate *, uint32_t btm[2]);
+void stfp_time2tvme(struct vmedate *time_vme, struct stfp_time *stfp);
+inline const char *DEVICE_NAME(int n);
+
+
/*
* Define the bc*() functions as weak so we can compile/link without them.
* Only clients with the card will have the proprietary vendor device driver
@@ -167,6 +200,15 @@ int regvalue;
int tfp_type; /* mode selector, indicate platform and driver interface */
SYMMT_PCI_HANDLE stfp_handle;
+/**
+ * this macro returns the device name based on
+ * the platform we are running on and the device number
+ */
+#if defined(__sun__)
+inline const char *DEVICE_NAME(int n) {static char s[20]={0}; snprintf(s,19,"/dev/stfp%d",n);return s;}
+#else
+inline const char* DEVICE_NAME(int n) {static char s[20]={0}; snprintf(s,19,"/dev/btfp%d",n);return s;}
+#endif /**__sun__**/
/*
* vme_start - open the VME device and initialize data for processing
@@ -185,6 +227,7 @@ vme_start(
tfp_type = (int)(peer->ttl);
switch (tfp_type) {
case 1:
+ case 3:
break;
case 2:
stfp_handle = bcStartPci(); /* init the card in lin/win */
@@ -197,9 +240,9 @@ vme_start(
*/
#ifdef DEBUG
- printf("Opening DATUM VME DEVICE \n");
+ printf("Opening DATUM DEVICE %s\n",DEVICE_NAME(peer->refclkunit));
#endif
- if ( (fd_vme = open(VMEFD, O_RDWR)) < 0) {
+ if ( (fd_vme = open(DEVICE_NAME(peer->refclkunit), O_RDWR)) < 0) {
msyslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev);
return (0);
}
@@ -207,6 +250,7 @@ vme_start(
switch (tfp_type) {
case 1: break;
case 2: break;
+ case 3:break;
default:
/* Release capture lockout in case it was set before. */
if( ioctl( fd_vme, RUNLOCK, &dummy ) )
@@ -268,8 +312,10 @@ vme_shutdown(
vme = (struct vmeunit *)pp->unitptr;
io_closeclock(&pp->io);
pp->unitptr = NULL;
- free(vme);
- if (tfp_type == 2) bcStopPci(stfp_handle);
+ if (NULL != vme)
+ free(vme);
+ if (tfp_type == 2)
+ bcStopPci(stfp_handle);
}
@@ -324,14 +370,15 @@ vme_poll(
tadr = gmtime(&tloc);
tptr->year = (unsigned short)(tadr->tm_year + 1900);
- sprintf(pp->a_lastcode,
- "%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d",
- tptr->day,
- tptr->hr,
- tptr->mn,
- tptr->sec,
- tptr->frac,
- tptr->status);
+ snprintf(pp->a_lastcode,
+ sizeof(pp->a_lastcode),
+ "%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d",
+ tptr->day,
+ tptr->hr,
+ tptr->mn,
+ tptr->sec,
+ tptr->frac,
+ tptr->status);
pp->lencode = (u_short) strlen(pp->a_lastcode);
@@ -376,10 +423,10 @@ get_datumtime(struct vmedate *time_vme)
struct btfp_time vts;
uint32_t btm[2];
uint8_t dmy;
+ struct stfp_time stfpm;
- if ( time_vme == (struct vmedate *)NULL) {
- time_vme = (struct vmedate *)malloc(sizeof(struct vmedate ));
- }
+ if (time_vme == NULL)
+ time_vme = emalloc(sizeof(*time_vme));
switch (tfp_type) {
case 1: /* BSD, PCI, 2 32bit time words */
@@ -397,41 +444,65 @@ get_datumtime(struct vmedate *time_vme)
}
tvme_fill(time_vme, btm);
break;
+
+ case 3: /** solaris **/
+ memset(&stfpm,0,sizeof(stfpm));
+
+ /* we need the time in decimal format */
+ /* Here we rudely assume that we are the only user of the driver.
+ * Other programs will have to set their own time format before reading
+ * the time.
+ */
+ if(ioctl (fd_vme, SELTIMEFORMAT, TIME_DECIMAL)){
+ msyslog(LOG_ERR, "Could not set time format\n");
+ return (NULL);
+ }
+ /* read the time */
+ if (ioctl(fd_vme, READTIME, &stfpm)) {
+ msyslog(LOG_ERR, "ioctl error: %m");
+ return(NULL);
+ }
+ stfp_time2tvme(time_vme, &stfpm);
+ break;
default: /* legacy bancomm card */
if (ioctl(fd_vme, READTIME, &vts)) {
- msyslog(LOG_ERR, "get_datumtime error: %m");
+ msyslog(LOG_ERR,
+ "get_datumtime error: %m");
return(NULL);
}
/* Get day */
- sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
- ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
+ snprintf(cbuf, sizeof(cbuf), "%3.3x",
+ ((vts.btfp_time[ 0 ] & 0x000f) << 8) +
+ ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
time_vme->day = (unsigned short)atoi(cbuf);
/* Get hour */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
-
+ snprintf(cbuf, sizeof(cbuf), "%2.2x",
+ vts.btfp_time[ 1 ] & 0x00ff);
time_vme->hr = (unsigned short)atoi(cbuf);
/* Get minutes */
- sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
+ snprintf(cbuf, sizeof(cbuf), "%2.2x",
+ (vts.btfp_time[ 2 ] & 0xff00) >> 8);
time_vme->mn = (unsigned short)atoi(cbuf);
/* Get seconds */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
+ snprintf(cbuf, sizeof(cbuf), "%2.2x",
+ vts.btfp_time[ 2 ] & 0x00ff);
time_vme->sec = (unsigned short)atoi(cbuf);
/* Get microseconds. Yes, we ignore the 0.1 microsecond digit so
we can use the TVTOTSF function later on...*/
- sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ],
- vts.btfp_time[ 4 ]>>8);
-
+ snprintf(cbuf, sizeof(cbuf), "%4.4x%2.2x",
+ vts.btfp_time[ 3 ],
+ vts.btfp_time[ 4 ] >> 8);
time_vme->frac = (u_long) atoi(cbuf);
/* Get status bit */
- time_vme->status = (vts.btfp_time[0] & 0x0010) >>4;
+ time_vme->status = (vts.btfp_time[0] & 0x0010) >> 4;
break;
}
@@ -462,6 +533,21 @@ tvme_fill(struct vmedate *time_vme, uint32_t btm[2])
return;
}
+
+/* Assign values to time_vme struct. Mostly for readability */
+void
+stfp_time2tvme(struct vmedate *time_vme, struct stfp_time *stfp)
+{
+
+ time_vme->day = stfp->tm.tm_yday+1;
+ time_vme->hr = stfp->tm.tm_hour;
+ time_vme->mn = stfp->tm.tm_min;
+ time_vme->sec = stfp->tm.tm_sec;
+ time_vme->frac = stfp->usec*1000;
+ time_vme->frac += stfp->hnsec * 100;
+ time_vme->status = stfp->status;
+ return;
+}
#else
int refclock_bancomm_bs;
#endif /* REFCLOCK */
diff --git a/ntpd/refclock_chronolog.c b/ntpd/refclock_chronolog.c
index a1d131ec0304..ba4f60b4ed62 100644
--- a/ntpd/refclock_chronolog.c
+++ b/ntpd/refclock_chronolog.c
@@ -67,10 +67,10 @@ struct chronolog_unit {
/*
* Function prototypes
*/
-static int chronolog_start P((int, struct peer *));
-static void chronolog_shutdown P((int, struct peer *));
-static void chronolog_receive P((struct recvbuf *));
-static void chronolog_poll P((int, struct peer *));
+static int chronolog_start (int, struct peer *);
+static void chronolog_shutdown (int, struct peer *);
+static void chronolog_receive (struct recvbuf *);
+static void chronolog_poll (int, struct peer *);
/*
* Transfer vector
@@ -104,7 +104,7 @@ chronolog_start(
* Open serial port. Don't bother with CLK line discipline, since
* it's not available.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
#ifdef DEBUG
if (debug)
printf ("starting Chronolog with device %s\n",device);
@@ -115,12 +115,8 @@ chronolog_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct chronolog_unit *)
- emalloc(sizeof(struct chronolog_unit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct chronolog_unit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = chronolog_receive;
@@ -128,8 +124,10 @@ chronolog_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
+ pp->unitptr = NULL;
return (0);
}
@@ -157,8 +155,10 @@ chronolog_shutdown(
pp = peer->procptr;
up = (struct chronolog_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -240,6 +240,8 @@ chronolog_receive(
* otherwise, we get the time wrong.
*/
+ memset(&local, 0, sizeof(local));
+
local.tm_year = up->year;
local.tm_mon = up->month-1;
local.tm_mday = up->day;
diff --git a/ntpd/refclock_chu.c b/ntpd/refclock_chu.c
index 843e9aaa4079..ca14dc600fb4 100644
--- a/ntpd/refclock_chu.c
+++ b/ntpd/refclock_chu.c
@@ -26,47 +26,47 @@
#ifdef ICOM
#include "icom.h"
#endif /* ICOM */
-
/*
* Audio CHU demodulator/decoder
*
* This driver synchronizes the computer time using data encoded in
* radio transmissions from Canadian time/frequency station CHU in
* Ottawa, Ontario. Transmissions are made continuously on 3330 kHz,
- * 7335 kHz and 14670 kHz in upper sideband, compatible AM mode. An
+ * 7850 kHz and 14670 kHz in upper sideband, compatible AM mode. An
* ordinary shortwave receiver can be tuned manually to one of these
* frequencies or, in the case of ICOM receivers, the receiver can be
- * tuned automatically using this program as propagation conditions
- * change throughout the day and night.
+ * tuned automatically as propagation conditions change throughout the
+ * day and season.
*
- * The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a suported workstation hardware and
- * operating system. These include Solaris, SunOS, FreeBSD, NetBSD and
- * Linux. In this implementation, only one audio driver and codec can be
- * supported on a single machine.
+ * The driver requires an audio codec or sound card with sampling rate 8
+ * kHz and mu-law companding. This is the same standard as used by the
+ * telephone industry and is supported by most hardware and operating
+ * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
+ * implementation, only one audio driver and codec can be supported on a
+ * single machine.
*
* The driver can be compiled to use a Bell 103 compatible modem or
* modem chip to receive the radio signal and demodulate the data.
* Alternatively, the driver can be compiled to use the audio codec of
- * the Sun workstation or another with compatible audio drivers. In the
+ * the workstation or another with compatible audio drivers. In the
* latter case, the driver implements the modem using DSP routines, so
* the radio can be connected directly to either the microphone on line
* input port. In either case, the driver decodes the data using a
- * maximum likelihood technique which exploits the considerable degree
+ * maximum-likelihood technique which exploits the considerable degree
* of redundancy available to maximize accuracy and minimize errors.
*
* The CHU time broadcast includes an audio signal compatible with the
- * Bell 103 modem standard (mark = 2225 Hz, space = 2025 Hz). It consist
- * of nine, ten-character bursts transmitted at 300 bps and beginning
- * each second from second 31 to second 39 of the minute. Each character
- * consists of eight data bits plus one start bit and two stop bits to
- * encode two hex digits. The burst data consist of five characters (ten
- * hex digits) followed by a repeat of these characters. In format A,
- * the characters are repeated in the same polarity; in format B, the
- * characters are repeated in the opposite polarity.
+ * Bell 103 modem standard (mark = 2225 Hz, space = 2025 Hz). The signal
+ * consists of nine, ten-character bursts transmitted at 300 bps between
+ * seconds 31 and 39 of each minute. Each character consists of eight
+ * data bits plus one start bit and two stop bits to encode two hex
+ * digits. The burst data consist of five characters (ten hex digits)
+ * followed by a repeat of these characters. In format A, the characters
+ * are repeated in the same polarity; in format B, the characters are
+ * repeated in the opposite polarity.
*
* Format A bursts are sent at seconds 32 through 39 of the minute in
- * hex digits
+ * hex digits (nibble swapped)
*
* 6dddhhmmss6dddhhmmss
*
@@ -96,10 +96,10 @@
* By design, the last stop bit of the last character in the burst
* coincides with 0.5 second. Since characters have 11 bits and are
* transmitted at 300 bps, the last stop bit of the first character
- * coincides with 0.5 - 10 * 11/300 = 0.133 second. Depending on the
- * UART, character interrupts can vary somewhere between the beginning
- * of bit 9 and end of bit 11. These eccentricities can be corrected
- * along with the radio propagation delay using fudge time 1.
+ * coincides with 0.5 - 9 * 11/300 = 0.170 second. Depending on the
+ * UART, character interrupts can vary somewhere between the end of bit
+ * 9 and end of bit 11. These eccentricities can be corrected along with
+ * the radio propagation delay using fudge time 1.
*
* Debugging aids
*
@@ -107,11 +107,15 @@
* data helpful in diagnosing problems with the radio signal and serial
* connections. With debugging enabled (-d on the ntpd command line),
* the driver produces one line for each burst in two formats
- * corresponding to format A and B. Following is format A:
+ * corresponding to format A and B.Each line begins with the format code
+ * chuA or chuB followed by the status code and signal level (0-9999).
+ * The remainder of the line is as follows.
+ *
+ * Following is format A:
*
* n b f s m code
*
- * where n is the number of characters in the burst (0-11), b the burst
+ * where n is the number of characters in the burst (0-10), b the burst
* distance (0-40), f the field alignment (-1, 0, 1), s the
* synchronization distance (0-16), m the burst number (2-9) and code
* the burst characters as received. Note that the hex digits in each
@@ -119,43 +123,50 @@
*
* 10 38 0 16 9 06851292930685129293
*
- * is interpreted as containing 11 characters with burst distance 38,
+ * is interpreted as containing 10 characters with burst distance 38,
* field alignment 0, synchronization distance 16 and burst number 9.
* The nibble-swapped timecode shows day 58, hour 21, minute 29 and
* second 39.
*
- * When the audio driver is compiled, format A is preceded by
- * the current gain (0-255) and relative signal level (0-9999). The
- * receiver folume control should be set so that the gain is somewhere
- * near the middle of the range 0-255, which results in a signal level
- * near 1000.
- *
* Following is format B:
*
* n b s code
*
- * where n is the number of characters in the burst (0-11), b the burst
+ * where n is the number of characters in the burst (0-10), b the burst
* distance (0-40), s the synchronization distance (0-40) and code the
* burst characters as received. Note that the hex digits in each
* character are reversed and the last ten digits inverted, so the burst
*
- * 11 40 1091891300ef6e76ecff
+ * 10 40 1091891300ef6e76ec
*
- * is interpreted as containing 11 characters with burst distance 40.
+ * is interpreted as containing 10 characters with burst distance 40.
* The nibble-swapped timecode shows DUT1 +0.1 second, year 1998 and TAI
* - UTC 31 seconds.
*
+ * Each line is preceeded by the code chuA or chuB, as appropriate. If
+ * the audio driver is compiled, the current gain (0-255) and relative
+ * signal level (0-9999) follow the code. The receiver volume control
+ * should be set so that the gain is somewhere near the middle of the
+ * range 0-255, which results in a signal level near 1000.
+ *
* In addition to the above, the reference timecode is updated and
* written to the clockstats file and debug score after the last burst
* received in the minute. The format is
*
- * qq yyyy ddd hh:mm:ss nn dd tt
+ * sq yyyy ddd hh:mm:ss l s dd t agc ident m b
*
- * where qq are the error flags, as described below, yyyy is the year,
- * ddd the day, hh:mm:ss the time of day, nn the number of format A
- * bursts received during the previous minute, dd the decoding distance
- * and tt the number of timestamps. The error flags are cleared after
- * every update.
+ * s '?' before first synchronized and ' ' after that
+ * q status code (see below)
+ * yyyy year
+ * ddd day of year
+ * hh:mm:ss time of day
+ * l leap second indicator (space, L or D)
+ * dst Canadian daylight code (opaque)
+ * t number of minutes since last synchronized
+ * agc audio gain (0 - 255)
+ * ident identifier (CHU0 3330 kHz, CHU1 7850 kHz, CHU2 14670 kHz)
+ * m signal metric (0 - 100)
+ * b number of timecodes for the previous minute (0 - 59)
*
* Fudge factors
*
@@ -184,6 +195,11 @@
* 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.
+ *
+ * Alarm codes
+ *
+ * CEVNT_BADTIME invalid date or time
+ * CEVNT_PROP propagation failure - no stations heard
*/
/*
* Interface definitions
@@ -194,8 +210,8 @@
#define DEVICE "/dev/chu%d" /* device name and unit */
#define SPEED232 B300 /* UART speed (300 baud) */
#ifdef ICOM
-#define TUNE .001 /* offset for narrow filter (kHz) */
-#define DWELL 5 /* minutes in a probe cycle */
+#define TUNE .001 /* offset for narrow filter (MHz) */
+#define DWELL 5 /* minutes in a dwell */
#define NCHAN 3 /* number of channels */
#define ISTAGE 3 /* number of integrator stages */
#endif /* ICOM */
@@ -210,6 +226,7 @@
#define SIZE 256 /* decompanding table size */
#define MAXAMP 6000. /* maximum signal level */
#define MAXCLP 100 /* max clips above reference per s */
+#define SPAN 800. /* min envelope span */
#define LIMIT 1000. /* soft limiter threshold */
#define AGAIN 6. /* baseband gain */
#define LAG 10 /* discriminator lag */
@@ -224,23 +241,28 @@
* Decoder definitions
*/
#define CHAR (11. / 300.) /* character time (s) */
-#define FUDGE .185 /* offset to first stop bit (s) */
#define BURST 11 /* max characters per burst */
#define MINCHAR 9 /* min characters per burst */
#define MINDIST 28 /* min burst distance (of 40) */
-#define MINBURST 4 /* min bursts in minute */
#define MINSYNC 8 /* min sync distance (of 16) */
#define MINSTAMP 20 /* min timestamps (of 60) */
-#define METRIC 50. /* min channel metric */
-#define PANIC 1440 /* panic timeout (m) */
-#define HOLD 30 /* reach hold (m) */
+#define MINMETRIC 50 /* min channel metric (of 160) */
/*
- * Hex extension codes (>= 16)
+ * The on-time synchronization point for the driver is the last stop bit
+ * of the first character 170 ms. The modem delay is 0.8 ms, while the
+ * receiver delay is approxmately 4.7 ms at 2125 Hz. The fudge value 1.3
+ * ms due to the codec and other causes was determined by calibrating to
+ * a PPS signal from a GPS receiver. The additional propagation delay
+ * specific to each receiver location can be programmed in the fudge
+ * time1.
+ *
+ * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
+ * generally within 0.5 ms short term with 0.3 ms jitter. The long-term
+ * offsets vary up to 0.3 ms due to ionospheric layer height variations.
+ * The processor load due to the driver is 0.4 percent.
*/
-#define HEX_MISS 16 /* miss _ */
-#define HEX_SOFT 17 /* soft error * */
-#define HEX_HARD 18 /* hard error = */
+#define PDELAY ((170 + .8 + 4.7 + 1.3) / 1000) /* system delay (s) */
/*
* Status bits (status)
@@ -256,6 +278,7 @@
#define AVALID 0x0100 /* valid A frame */
#define BVALID 0x0200 /* valid B frame */
#define INSYNC 0x0400 /* clock synchronized */
+#define METRIC 0x0800 /* one or more stations heard */
/*
* Alarm status bits (alarm)
@@ -273,12 +296,13 @@
#ifdef HAVE_AUDIO
/*
- * Maximum likelihood UART structure. There are eight of these
+ * Maximum-likelihood UART structure. There are eight of these
* corresponding to the number of phases.
*/
struct surv {
- double shift[12]; /* mark register */
- double es_max, es_min; /* max/min envelope signals */
+ l_fp cstamp; /* last bit timestamp */
+ double shift[12]; /* sample shift register */
+ double span; /* shift register envelope span */
double dist; /* sample distance */
int uart; /* decoded character */
};
@@ -301,19 +325,19 @@ struct xmtr {
* CHU unit control structure
*/
struct chuunit {
- u_char decode[20][16]; /* maximum likelihood decoding matrix */
+ u_char decode[20][16]; /* maximum-likelihood decoding matrix */
l_fp cstamp[BURST]; /* character timestamps */
l_fp tstamp[MAXSTAGE]; /* timestamp samples */
l_fp timestamp; /* current buffer timestamp */
l_fp laststamp; /* last buffer timestamp */
l_fp charstamp; /* character time as a l_fp */
+ int second; /* counts the seconds of the minute */
int errflg; /* error flags */
int status; /* status bits */
char ident[5]; /* station ID and channel */
#ifdef ICOM
int fd_icom; /* ICOM file descriptor */
- int chan; /* data channel */
- int achan; /* active channel */
+ int chan; /* radio channel */
int dwell; /* dwell cycle */
struct xmtr xmtr[NCHAN]; /* station metric */
#endif /* ICOM */
@@ -328,6 +352,8 @@ struct chuunit {
int burdist; /* burst distance */
int syndist; /* sync distance */
int burstcnt; /* format A bursts this minute */
+ double maxsignal; /* signal level (modem only) */
+ int gain; /* codec gain (modem only) */
/*
* Format particulars
@@ -344,7 +370,6 @@ struct chuunit {
int fd_audio; /* audio port file descriptor */
double comp[SIZE]; /* decompanding table */
int port; /* codec port */
- int gain; /* codec gain */
int mongain; /* codec monitor gain */
int clipcnt; /* sample clip count */
int seccnt; /* second interval counter */
@@ -357,15 +382,15 @@ struct chuunit {
double disc[LAG]; /* discriminator shift register */
double lpf[27]; /* FIR lowpass filter */
double monitor; /* audio monitor */
- double maxsignal; /* signal level */
int discptr; /* discriminator pointer */
/*
- * Maximum likelihood UART variables
+ * Maximum-likelihood UART variables
*/
double baud; /* baud interval */
struct surv surv[8]; /* UART survivor structures */
int decptr; /* decode pointer */
+ int decpha; /* decode phase */
int dbrk; /* holdoff counter */
#endif /* HAVE_AUDIO */
};
@@ -373,31 +398,32 @@ struct chuunit {
/*
* Function prototypes
*/
-static int chu_start P((int, struct peer *));
-static void chu_shutdown P((int, struct peer *));
-static void chu_receive P((struct recvbuf *));
-static void chu_poll P((int, struct peer *));
+static int chu_start (int, struct peer *);
+static void chu_shutdown (int, struct peer *);
+static void chu_receive (struct recvbuf *);
+static void chu_second (int, struct peer *);
+static void chu_poll (int, struct peer *);
/*
* More function prototypes
*/
-static void chu_decode P((struct peer *, int));
-static void chu_burst P((struct peer *));
-static void chu_clear P((struct peer *));
-static void chu_a P((struct peer *, int));
-static void chu_b P((struct peer *, int));
-static int chu_dist P((int, int));
-static double chu_major P((struct peer *));
+static void chu_decode (struct peer *, int, l_fp);
+static void chu_burst (struct peer *);
+static void chu_clear (struct peer *);
+static void chu_a (struct peer *, int);
+static void chu_b (struct peer *, int);
+static int chu_dist (int, int);
+static double chu_major (struct peer *);
#ifdef HAVE_AUDIO
-static void chu_uart P((struct surv *, double));
-static void chu_rf P((struct peer *, double));
-static void chu_gain P((struct peer *));
-static void chu_audio_receive P((struct recvbuf *rbufp));
+static void chu_uart (struct surv *, double);
+static void chu_rf (struct peer *, double);
+static void chu_gain (struct peer *);
+static void chu_audio_receive (struct recvbuf *rbufp);
#endif /* HAVE_AUDIO */
#ifdef ICOM
-static int chu_newchan P((struct peer *, double));
+static int chu_newchan (struct peer *, double);
#endif /* ICOM */
-static void chu_serial_receive P((struct recvbuf *rbufp));
+static void chu_serial_receive (struct recvbuf *rbufp);
/*
* Global variables
@@ -410,7 +436,7 @@ static char hexchar[] = "0123456789abcdef_*=";
* transmits on USB with carrier so we can use AM and the narrow SSB
* filter.
*/
-static double qsy[NCHAN] = {3.330, 7.335, 14.670}; /* freq (MHz) */
+static double qsy[NCHAN] = {3.330, 7.850, 14.670}; /* freq (MHz) */
#endif /* ICOM */
/*
@@ -423,7 +449,7 @@ struct refclock refclock_chu = {
noentry, /* not used (old chu_control) */
noentry, /* initialize driver (not used) */
noentry, /* not used (old chu_buginfo) */
- NOFLAGS /* not used */
+ chu_second /* housekeeping timer */
};
@@ -449,7 +475,7 @@ chu_start(
double step; /* codec adjustment */
/*
- * Open audio device.
+ * Open audio device. Don't complain if not there.
*/
fd_audio = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
#ifdef DEBUG
@@ -458,12 +484,12 @@ chu_start(
#endif
/*
- * Open serial port in raw mode.
+ * If audio is unavailable, Open serial port in raw mode.
*/
if (fd_audio > 0) {
fd = fd_audio;
} else {
- sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
fd = refclock_open(device, SPEED232, LDISC_RAW);
}
#else /* HAVE_AUDIO */
@@ -471,7 +497,7 @@ chu_start(
/*
* Open serial port in raw mode.
*/
- sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
fd = refclock_open(device, SPEED232, LDISC_RAW);
#endif /* HAVE_AUDIO */
if (fd <= 0)
@@ -480,12 +506,8 @@ chu_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct chuunit *)
- emalloc(sizeof(struct chuunit)))) {
- close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct chuunit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = chu_receive;
@@ -494,7 +516,9 @@ chu_start(
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
close(fd);
+ pp->io.fd = -1;
free(up);
+ pp->unitptr = NULL;
return (0);
}
@@ -504,7 +528,7 @@ chu_start(
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
strcpy(up->ident, "CHU");
- memcpy(&peer->refid, up->ident, 4);
+ memcpy(&pp->refid, up->ident, 4);
DTOLFP(CHAR, &up->charstamp);
#ifdef HAVE_AUDIO
@@ -543,16 +567,11 @@ chu_start(
}
if (up->fd_icom > 0) {
if (chu_newchan(peer, 0) != 0) {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: radio not found");
- up->errflg = CEVNT_FAULT;
+ msyslog(LOG_NOTICE, "icom: radio not found");
close(up->fd_icom);
up->fd_icom = 0;
} else {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: autotune enabled");
+ msyslog(LOG_NOTICE, "icom: autotune enabled");
}
}
#endif /* ICOM */
@@ -674,7 +693,6 @@ chu_audio_receive(
*/
up->seccnt = (up->seccnt + 1) % SECOND;
if (up->seccnt == 0) {
- pp->second = (pp->second + 1) % 60;
chu_gain(peer);
}
}
@@ -698,7 +716,7 @@ chu_audio_receive(
*
* This routine implements a 300-baud Bell 103 modem with mark 2225 Hz
* and space 2025 Hz. It uses a bandpass filter followed by a soft
- * limiter, FM discriminator and lowpass filter. A maximum likelihood
+ * limiter, FM discriminator and lowpass filter. A maximum-likelihood
* decoder samples the baseband signal at eight times the baud rate and
* detects the start bit of each character.
*
@@ -723,7 +741,6 @@ chu_rf(
double limit; /* limiter signal */
double disc; /* discriminator signal */
double lpf; /* lowpass signal */
- double span; /* UART signal span */
double dist; /* UART signal distance */
int i, j;
@@ -732,7 +749,8 @@ chu_rf(
/*
* Bandpass filter. 4th-order elliptic, 500-Hz bandpass centered
- * at 2125 Hz. Passband ripple 0.3 dB, stopband ripple 50 dB.
+ * at 2125 Hz. Passband ripple 0.3 dB, stopband ripple 50 dB,
+ * phase delay 0.24 ms.
*/
signal = (up->bpf[8] = up->bpf[7]) * 5.844676e-01;
signal += (up->bpf[7] = up->bpf[6]) * 4.884860e-01;
@@ -778,7 +796,7 @@ chu_rf(
disc = -SQRT(-disc);
/*
- * Lowpass filter. Raised cosine, Ts = 1 / 300, beta = 0.1.
+ * Lowpass filter. Raised cosine FIR, Ts = 1 / 300, beta = 0.1.
*/
lpf = (up->lpf[26] = up->lpf[25]) * 2.538771e-02;
lpf += (up->lpf[25] = up->lpf[24]) * 1.084671e-01;
@@ -809,44 +827,68 @@ chu_rf(
lpf += up->lpf[0] = disc * 2.538771e-02;
/*
- * Maximum likelihood decoder. The UART updates each of the
+ * Maximum-likelihood decoder. The UART updates each of the
* eight survivors and determines the span, slice level and
* tentative decoded character. Valid 11-bit characters are
- * framed so that bit 1 and bit 11 (stop bits) are mark and bit
- * 2 (start bit) is space. When a valid character is found, the
+ * framed so that bit 10 and bit 11 (stop bits) are mark and bit
+ * 1 (start bit) is space. When a valid character is found, the
* survivor with maximum distance determines the final decoded
* character.
*/
up->baud += 1. / SECOND;
if (up->baud > 1. / (BAUD * 8.)) {
up->baud -= 1. / (BAUD * 8.);
+ up->decptr = (up->decptr + 1) % 8;
sp = &up->surv[up->decptr];
- span = sp->es_max - sp->es_min;
- up->maxsignal += (span - up->maxsignal) / 80.;
+ sp->cstamp = up->timestamp;
+ chu_uart(sp, -lpf * AGAIN);
if (up->dbrk > 0) {
up->dbrk--;
- } else if ((sp->uart & 0x403) == 0x401 && span > 1000.)
- {
- dist = 0;
- j = 0;
- for (i = 0; i < 8; i++) {
- if (up->surv[i].dist > dist) {
- dist = up->surv[i].dist;
- j = i;
- }
+ if (up->dbrk > 0)
+ return;
+
+ up->decpha = up->decptr;
+ }
+ if (up->decptr != up->decpha)
+ return;
+
+ dist = 0;
+ j = -1;
+ for (i = 0; i < 8; i++) {
+
+ /*
+ * The timestamp is taken at the last bit, so
+ * for correct decoding we reqire sufficient
+ * span and correct start bit and two stop bits.
+ */
+ if ((up->surv[i].uart & 0x601) != 0x600 ||
+ up->surv[i].span < SPAN)
+ continue;
+
+ if (up->surv[i].dist > dist) {
+ dist = up->surv[i].dist;
+ j = i;
}
- chu_decode(peer, (up->surv[j].uart >> 2) &
- 0xff);
- up->dbrk = 80;
}
- up->decptr = (up->decptr + 1) % 8;
- chu_uart(sp, -lpf * AGAIN);
+ if (j < 0)
+ return;
+
+ /*
+ * Process the character, then blank the decoder until
+ * the end of the next character.This sets the decoding
+ * phase of the entire burst from the phase of the first
+ * character.
+ */
+ up->maxsignal = up->surv[j].span;
+ chu_decode(peer, (up->surv[j].uart >> 1) & 0xff,
+ up->surv[j].cstamp);
+ up->dbrk = 88;
}
}
/*
- * chu_uart - maximum likelihood UART
+ * chu_uart - maximum-likelihood UART
*
* This routine updates a shift register holding the last 11 envelope
* samples. It then computes the slice level and span over these samples
@@ -882,12 +924,15 @@ chu_uart(
}
/*
- * Determine the slice level midway beteen the maximum and
- * minimum and the span as the maximum less the minimum. Compute
- * the distance on the assumption the first and last bits must
- * be mark, the second space and the rest either mark or space.
+ * Determine the span as the maximum less the minimum and the
+ * slice level as the minimum plus a fraction of the span. Note
+ * the slight bias toward mark to correct for the modem tendency
+ * to make more mark than space errors. Compute the distance on
+ * the assumption the last two bits must be mark, the first
+ * space and the rest either mark or space.
*/
- slice = (es_max + es_min) / 2.;
+ sp->span = es_max - es_min;
+ slice = es_min + .45 * sp->span;
dist = 0;
sp->uart = 0;
for (i = 1; i < 12; i++) {
@@ -895,9 +940,9 @@ chu_uart(
dtemp = sp->shift[i];
if (dtemp > slice)
sp->uart |= 0x1;
- if (i == 1 || i == 11) {
+ if (i == 1 || i == 2) {
dist += dtemp - es_min;
- } else if (i == 10) {
+ } else if (i == 11) {
dist += es_max - dtemp;
} else {
if (dtemp > slice)
@@ -906,9 +951,7 @@ chu_uart(
dist += es_max - dtemp;
}
}
- sp->es_max = es_max;
- sp->es_min = es_min;
- sp->dist = dist / (11 * (es_max - es_min));
+ sp->dist = dist / (11 * sp->span);
}
#endif /* HAVE_AUDIO */
@@ -931,12 +974,8 @@ chu_serial_receive(
pp = peer->procptr;
up = (struct chuunit *)pp->unitptr;
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- up->timestamp = rbufp->recv_time;
dpt = (u_char *)&rbufp->recv_space;
- chu_decode(peer, *dpt);
+ chu_decode(peer, *dpt, rbufp->recv_time);
}
@@ -946,7 +985,8 @@ chu_serial_receive(
static void
chu_decode(
struct peer *peer, /* peer structure pointer */
- int hexhex /* data character */
+ int hexhex, /* data character */
+ l_fp cstamp /* data character timestamp */
)
{
struct refclockproc *pp;
@@ -979,11 +1019,11 @@ chu_decode(
/*
* Append the character to the current burst and append the
- * timestamp to the timestamp list.
+ * character timestamp to the timestamp list.
*/
if (up->ndx < BURST) {
up->cbuf[up->ndx] = hexhex & 0xff;
- up->cstamp[up->ndx] = up->timestamp;
+ up->cstamp[up->ndx] = cstamp;
up->ndx++;
}
@@ -1061,7 +1101,9 @@ chu_b(
u_char code[11]; /* decoded timecode */
char tbuf[80]; /* trace buffer */
- l_fp offset; /* timestamp offset */
+ char * p;
+ size_t chars;
+ size_t cb;
int i;
pp = peer->procptr;
@@ -1069,15 +1111,25 @@ chu_b(
/*
* In a format B burst, a character is considered valid only if
- * the first occurrence matches the last occurrence. The burst
- * is considered valid only if all characters are valid; that
- * is, only if the distance is 40. Note that once a valid frame
- * has been found errors are ignored.
+ * the first occurence matches the last occurence. The burst is
+ * considered valid only if all characters are valid; that is,
+ * only if the distance is 40. Note that once a valid frame has
+ * been found errors are ignored.
*/
- sprintf(tbuf, "chuB %04x %2d %2d ", up->status, nchar,
- -up->burdist);
- for (i = 0; i < nchar; i++)
- sprintf(&tbuf[strlen(tbuf)], "%02x", up->cbuf[i]);
+ snprintf(tbuf, sizeof(tbuf), "chuB %04x %4.0f %2d %2d ",
+ up->status, up->maxsignal, nchar, -up->burdist);
+ cb = sizeof(tbuf);
+ p = tbuf;
+ for (i = 0; i < nchar; i++) {
+ chars = strlen(p);
+ if (cb < chars + 1) {
+ msyslog(LOG_ERR, "chu_b() fatal out buffer");
+ exit(1);
+ }
+ cb -= chars;
+ p += chars;
+ snprintf(p, cb, "%02x", up->cbuf[i]);
+ }
if (pp->sloppyclockflag & CLK_FLAG4)
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
@@ -1088,11 +1140,10 @@ chu_b(
up->status |= BFRAME;
return;
}
- up->status |= BVALID;
/*
- * Convert the burst data to internal format. If this succeeds,
- * save the timestamps for later.
+ * Convert the burst data to internal format. Don't bother with
+ * the timestamps.
*/
for (i = 0; i < 5; i++) {
code[2 * i] = hexchar[up->cbuf[i] & 0xf];
@@ -1104,17 +1155,9 @@ chu_b(
up->status |= BFORMAT;
return;
}
+ up->status |= BVALID;
if (up->leap & 0x8)
up->dut = -up->dut;
- offset.l_ui = 31;
- offset.l_f = 0;
- for (i = 0; i < nchar && i < 10; i++) {
- up->tstamp[up->ntstamp] = up->cstamp[i];
- L_SUB(&up->tstamp[up->ntstamp], &offset);
- L_ADD(&offset, &up->charstamp);
- if (up->ntstamp < MAXSTAGE - 1)
- up->ntstamp++;
- }
}
@@ -1131,6 +1174,9 @@ chu_a(
struct chuunit *up;
char tbuf[80]; /* trace buffer */
+ char * p;
+ size_t chars;
+ size_t cb;
l_fp offset; /* timestamp offset */
int val; /* distance */
int temp;
@@ -1143,7 +1189,7 @@ chu_a(
* Determine correct burst phase. There are three cases
* corresponding to in-phase, one character early or one
* character late. These cases are distinguished by the position
- * of the framing digits x6 at positions 0 and 5 and x3 at
+ * of the framing digits 0x6 at positions 0 and 5 and 0x3 at
* positions 4 and 9. The correct phase is when the distance
* relative to the framing digits is maximum. The burst is valid
* only if the maximum distance is at least MINSYNC.
@@ -1164,27 +1210,31 @@ chu_a(
k = i;
}
}
+
+ /*
+ * Extract the second number; it must be in the range 2 through
+ * 9 and the two repititions must be the same.
+ */
temp = (up->cbuf[k + 4] >> 4) & 0xf;
- if (temp > 9 || k + 9 >= nchar || temp != ((up->cbuf[k + 9] >>
- 4) & 0xf))
+ if (temp < 2 || temp > 9 || k + 9 >= nchar || temp !=
+ ((up->cbuf[k + 9] >> 4) & 0xf))
temp = 0;
-#ifdef HAVE_AUDIO
- if (up->fd_audio)
- sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ",
- up->status, up->maxsignal, nchar, up->burdist, k,
- up->syndist, temp);
- else
- sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ",
- up->status, nchar, up->burdist, k, up->syndist,
- temp);
-
-#else
- sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ", up->status,
- nchar, up->burdist, k, up->syndist, temp);
-#endif /* HAVE_AUDIO */
- for (i = 0; i < nchar; i++)
- sprintf(&tbuf[strlen(tbuf)], "%02x",
- up->cbuf[i]);
+ snprintf(tbuf, sizeof(tbuf),
+ "chuA %04x %4.0f %2d %2d %2d %2d %1d ", up->status,
+ up->maxsignal, nchar, up->burdist, k, up->syndist,
+ temp);
+ cb = sizeof(tbuf);
+ p = tbuf;
+ for (i = 0; i < nchar; i++) {
+ chars = strlen(p);
+ if (cb < chars + 1) {
+ msyslog(LOG_ERR, "chu_a() fatal out buffer");
+ exit(1);
+ }
+ cb -= chars;
+ p += chars;
+ snprintf(p, cb, "%02x", up->cbuf[i]);
+ }
if (pp->sloppyclockflag & CLK_FLAG4)
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
@@ -1203,8 +1253,11 @@ chu_a(
* processing. In addition, the seconds decode is advanced from
* the previous burst to the current one.
*/
- if (temp != 0) {
- pp->second = 30 + temp;
+ if (temp == 0) {
+ up->status |= AFORMAT;
+ } else {
+ up->status |= AVALID;
+ up->second = pp->second = 30 + temp;
offset.l_ui = 30 + temp;
offset.l_f = 0;
i = 0;
@@ -1216,7 +1269,7 @@ chu_a(
up->tstamp[up->ntstamp] = up->cstamp[i];
L_SUB(&up->tstamp[up->ntstamp], &offset);
L_ADD(&offset, &up->charstamp);
- if (up->ntstamp < MAXSTAGE - 1)
+ if (up->ntstamp < MAXSTAGE - 1)
up->ntstamp++;
}
while (temp > up->prevsec) {
@@ -1229,6 +1282,10 @@ chu_a(
up->prevsec++;
}
}
+
+ /*
+ * Stash the data in the decoding matrix.
+ */
i = -(2 * k);
for (j = 0; j < nchar; j++) {
if (i < 0 || i > 18) {
@@ -1240,7 +1297,6 @@ chu_a(
up->decode[i][(up->cbuf[j] >> 4) & 0xf]++;
i++;
}
- up->status |= AVALID;
up->burstcnt++;
}
@@ -1255,6 +1311,22 @@ chu_poll(
)
{
struct refclockproc *pp;
+
+ pp = peer->procptr;
+ pp->polls++;
+}
+
+
+/*
+ * chu_second - process minute data
+ */
+static void
+chu_second(
+ int unit,
+ struct peer *peer /* peer structure pointer */
+ )
+{
+ struct refclockproc *pp;
struct chuunit *up;
l_fp offset;
char synchar, qual, leapchar;
@@ -1263,40 +1335,24 @@ chu_poll(
pp = peer->procptr;
up = (struct chuunit *)pp->unitptr;
- if (pp->coderecv == pp->codeproc)
- up->errflg = CEVNT_TIMEOUT;
- else
- pp->polls++;
/*
- * If once in sync and the radio has not been heard for awhile
- * (30 m), it is no longer reachable. If not heard in a long
- * while (one day), turn out the lights and start from scratch.
+ * This routine is called once per minute to process the
+ * accumulated burst data. We do a bit of fancy footwork so that
+ * this doesn't run while burst data are being accumulated.
*/
- minset = ((current_time - peer->update) + 30) / 60;
- if (up->status & INSYNC) {
- if (minset > PANIC)
- up->status = 0;
- else if (minset <= HOLD)
- peer->reach |= 1;
- }
+ up->second = (up->second + 1) % 60;
+ if (up->second != 0)
+ return;
/*
* Process the last burst, if still in the burst buffer.
- * Don't mess with anything if nothing has been heard. If the
- * minute contains a valid A frame and valid B frame, assume
- * synchronized; however, believe the time only if within metric
- * threshold. Note the quality indicator is only for
- * diagnostics; the data are used only if in sync and above
- * metric threshold.
+ * If the minute contains a valid B frame with sufficient A
+ * frame metric, it is considered valid. However, the timecode
+ * is sent to clockstats even if invalid.
*/
chu_burst(peer);
- if (up->burstcnt == 0) {
-#ifdef ICOM
- chu_newchan(peer, 0);
-#endif /* ICOM */
- return;
- }
+ minset = ((current_time - peer->update) + 30) / 60;
dtemp = chu_major(peer);
qual = 0;
if (up->status & (BFRAME | AFRAME))
@@ -1307,7 +1363,7 @@ chu_poll(
qual |= DECERR;
if (up->status & STAMP)
qual |= TSPERR;
- if (up->status & AVALID && up->status & BVALID)
+ if (up->status & BVALID && dtemp >= MINMETRIC)
up->status |= INSYNC;
synchar = leapchar = ' ';
if (!(up->status & INSYNC)) {
@@ -1322,35 +1378,20 @@ chu_poll(
} else {
pp->leap = LEAP_NOWARNING;
}
-#ifdef HAVE_AUDIO
- if (up->fd_audio)
- sprintf(pp->a_lastcode,
- "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %d %s %.0f %d",
- synchar, qual, pp->year, pp->day, pp->hour,
- pp->minute, pp->second, leapchar, up->dst, up->dut,
- minset, up->gain, up->ident, dtemp, up->ntstamp);
- else
- sprintf(pp->a_lastcode,
- "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %s %.0f %d",
- synchar, qual, pp->year, pp->day, pp->hour,
- pp->minute, pp->second, leapchar, up->dst, up->dut,
- minset, up->ident, dtemp, up->ntstamp);
-#else
- sprintf(pp->a_lastcode,
- "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %s %.0f %d",
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
+ "%c%1X %04d %03d %02d:%02d:%02d %c%x %+d %d %d %s %.0f %d",
synchar, qual, pp->year, pp->day, pp->hour, pp->minute,
- pp->second, leapchar, up->dst, up->dut, minset, up->ident,
- dtemp, up->ntstamp);
-#endif /* HAVE_AUDIO */
+ pp->second, leapchar, up->dst, up->dut, minset, up->gain,
+ up->ident, dtemp, up->ntstamp);
pp->lencode = strlen(pp->a_lastcode);
/*
* If in sync and the signal metric is above threshold, the
* timecode is ipso fatso valid and can be selected to
- * discipline the clock. Be sure not to leave stray timestamps
- * around if signals are too weak or the clock time is invalid.
+ * discipline the clock.
*/
- if (up->status & INSYNC && dtemp > METRIC) {
+ if (up->status & INSYNC && !(up->status & (DECODE | STAMP)) &&
+ dtemp > MINMETRIC) {
if (!clocktime(pp->day, pp->hour, pp->minute, 0, GMT,
up->tstamp[0].l_ui, &pp->yearstart, &offset.l_ui)) {
up->errflg = CEVNT_BADTIME;
@@ -1358,15 +1399,14 @@ chu_poll(
offset.l_uf = 0;
for (i = 0; i < up->ntstamp; i++)
refclock_process_offset(pp, offset,
- up->tstamp[i], FUDGE +
+ up->tstamp[i], PDELAY +
pp->fudgetime1);
pp->lastref = up->timestamp;
refclock_receive(peer);
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- } else if (pp->sloppyclockflag & CLK_FLAG4) {
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
}
+ if (dtemp > 0)
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
#ifdef DEBUG
if (debug)
printf("chu: timecode %d %s\n", pp->lencode,
@@ -1394,8 +1434,8 @@ chu_major(
struct chuunit *up;
u_char code[11]; /* decoded timecode */
- int mindist; /* minimum distance */
- int val1, val2; /* maximum distance */
+ int metric; /* distance metric */
+ int val1; /* maximum distance */
int synchar; /* stray cat */
int temp;
int i, j, k;
@@ -1406,54 +1446,32 @@ chu_major(
/*
* Majority decoder. Each burst encodes two replications at each
* digit position in the timecode. Each row of the decoding
- * matrix encodes the number of occurrences of each digit found
+ * matrix encodes the number of occurences of each digit found
* at the corresponding position. The maximum over all
* occurrences at each position is the distance for this
- * position and the corresponding digit is the maximum
- * likelihood candidate. If the distance is zero, assume a miss
- * '_'; if the distance is not more than half the total number
- * of occurrences, assume a soft error '*'; if two different
- * digits with the same distance are found, assume a hard error
- * '='. These will later cause a format error when the timecode
- * is interpreted. The decoding distance is defined as the
- * minimum distance over the first nine digits. The tenth digit
- * varies over the seconds, so we don't count it.
+ * position and the corresponding digit is the maximum-
+ * likelihood candidate. If the distance is not more than half
+ * the total number of occurences, a majority has not been found
+ * and the data are discarded. The decoding distance is defined
+ * as the sum of the distances over the first nine digits. The
+ * tenth digit varies over the seconds, so we don't count it.
*/
- mindist = 16;
+ metric = 0;
for (i = 0; i < 9; i++) {
- val1 = val2 = 0;
+ val1 = 0;
k = 0;
for (j = 0; j < 16; j++) {
temp = up->decode[i][j] + up->decode[i + 10][j];
if (temp > val1) {
- val2 = val1;
val1 = temp;
k = j;
}
}
- if (val1 == 0)
- code[i] = HEX_MISS;
- else if (val1 == val2)
- code[i] = HEX_HARD;
- else if (val1 <= up->burstcnt)
- code[i] = HEX_SOFT;
- else
- code[i] = k;
- if (val1 < mindist)
- mindist = val1;
- code[i] = hexchar[code[i]];
+ if (val1 <= up->burstcnt)
+ up->status |= DECODE;
+ metric += val1;
+ code[i] = hexchar[k];
}
- code[i] = 0;
-
- /*
- * A valid timecode requires a minimum distance at least half
- * the total number of occurrences. A valid timecode also
- * requires at least 20 valid timestamps.
- */
- if (up->burstcnt < MINBURST || mindist < up->burstcnt)
- up->status |= DECODE;
- if (up->ntstamp < MINSTAMP)
- up->status |= STAMP;
/*
* Compute the timecode timestamp from the days, hours and
@@ -1463,15 +1481,11 @@ chu_major(
* for the years and does not use the years of the timecode.
*/
if (sscanf((char *)code, "%1x%3d%2d%2d", &synchar, &pp->day,
- &pp->hour, &pp->minute) != 4) {
- up->status |= AFORMAT;
- return (0);
- }
- if (up->status & (DECODE | STAMP)) {
- up->errflg = CEVNT_BADREPLY;
- return (0);
- }
- return (mindist * 100. / (2. * up->burstcnt));
+ &pp->hour, &pp->minute) != 4)
+ up->status |= DECODE;
+ if (up->ntstamp < MINSTAMP)
+ up->status |= STAMP;
+ return (metric);
}
@@ -1495,7 +1509,7 @@ chu_clear(
*/
up->ndx = up->prevsec = 0;
up->burstcnt = up->ntstamp = 0;
- up->status &= INSYNC;
+ up->status &= INSYNC | METRIC;
for (i = 0; i < 20; i++) {
for (j = 0; j < 16; j++)
up->decode[i][j] = 0;
@@ -1516,99 +1530,77 @@ chu_newchan(
struct chuunit *up;
struct refclockproc *pp;
struct xmtr *sp;
- char tbuf[80]; /* trace buffer */
int rval;
double metric;
- int i, j;
+ int i;
pp = peer->procptr;
up = (struct chuunit *)pp->unitptr;
/*
* The radio can be tuned to three channels: 0 (3330 kHz), 1
- * (7335 kHz) and 2 (14670 kHz). There are five one-minute
+ * (7850 kHz) and 2 (14670 kHz). There are five one-minute
* dwells in each cycle. During the first dwell the radio is
- * tuned to one of three probe channels; during the remaining
- * four dwells the radio is tuned to the data channel. The probe
- * channel is selects as the least recently used. At the end of
- * each dwell the channel metrics are measured and the highest
- * one is selected as the data channel.
+ * tuned to one of the three channels to measure the channel
+ * metric. The channel is selected as the one least recently
+ * measured. During the remaining four dwells the radio is tuned
+ * to the channel with the highest channel metric.
*/
if (up->fd_icom <= 0)
return (0);
- sp = &up->xmtr[up->achan];
+ /*
+ * Update the current channel metric and age of all channels.
+ * Scan all channels for the highest metric.
+ */
+ sp = &up->xmtr[up->chan];
sp->metric -= sp->integ[sp->iptr];
sp->integ[sp->iptr] = met;
sp->metric += sp->integ[sp->iptr];
+ sp->probe = 0;
sp->iptr = (sp->iptr + 1) % ISTAGE;
metric = 0;
- j = 0;
for (i = 0; i < NCHAN; i++) {
up->xmtr[i].probe++;
- if (i == up->achan)
- up->xmtr[i].probe = 0;
- if (up->xmtr[i].metric < metric)
- continue;
- metric = up->xmtr[i].metric;
- j = i;
- }
- if (j != up->chan && metric > 0) {
- up->chan = j;
- sprintf(tbuf, "chu: QSY to %.3f MHz metric %.0f",
- qsy[up->chan], metric);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
+ if (up->xmtr[i].metric > metric) {
+ up->status |= METRIC;
+ metric = up->xmtr[i].metric;
+ up->chan = i;
+ }
}
/*
- * Start the next dwell. We speed up the initial sync a little.
- * If not in sync and no bursts were heard the previous dwell,
- * restart the probe.
+ * Start the next dwell. If the first dwell or no stations have
+ * been heard, continue round-robin scan.
*/
- rval = 0;
- if (up->burstcnt == 0 && !(up->status & INSYNC))
- up->dwell = 0;
-#ifdef DEBUG
- if (debug)
- printf(
- "chu: at %ld dwell %d achan %d metric %.0f chan %d\n",
- current_time, up->dwell, up->achan, sp->metric,
- up->chan);
-#endif
- if (up->dwell == 0) {
+ up->dwell = (up->dwell + 1) % DWELL;
+ if (up->dwell == 0 || metric == 0) {
rval = 0;
for (i = 0; i < NCHAN; i++) {
- if (up->xmtr[i].probe < rval)
- continue;
- rval = up->xmtr[i].probe;
- up->achan = i;
- }
- rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
- qsy[up->achan] + TUNE);
-#ifdef DEBUG
- if (debug)
- printf("chu: at %ld probe channel %d\n",
- current_time, up->achan);
-#endif
- } else {
- if (up->achan != up->chan) {
- rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
- qsy[up->chan] + TUNE);
- up->achan = up->chan;
+ if (up->xmtr[i].probe > rval) {
+ rval = up->xmtr[i].probe;
+ up->chan = i;
+ }
}
}
- sprintf(up->ident, "CHU%d", up->achan);
- memcpy(&peer->refid, up->ident, 4);
- up->dwell = (up->dwell + 1) % DWELL;
+
+ /* Retune the radio at each dwell in case somebody nudges the
+ * tuning knob.
+ */
+ rval = icom_freq(up->fd_icom, peer->ttl & 0x7f, qsy[up->chan] +
+ TUNE);
+ snprintf(up->ident, sizeof(up->ident), "CHU%d", up->chan);
+ memcpy(&pp->refid, up->ident, 4);
+ memcpy(&peer->refid, up->ident, 4);
+ if (metric == 0 && up->status & METRIC) {
+ up->status &= ~METRIC;
+ refclock_report(peer, CEVNT_PROP);
+ }
return (rval);
}
#endif /* ICOM */
+
/*
* chu_dist - determine the distance of two octet arguments
*/
@@ -1645,11 +1637,12 @@ chu_dist(
/*
* chu_gain - adjust codec gain
*
- * This routine is called once each second. If the signal envelope
- * amplitude is too low, the codec gain is bumped up by four units; if
- * too high, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
+ * This routine is called at the end of each second. During the second
+ * the number of signal clips above the MAXAMP threshold (6000). If
+ * there are no clips, the gain is bumped up; if there are more than
+ * MAXCLP clips (100), it is bumped down. The decoder is relatively
+ * insensitive to amplitude, so this crudity works just peachy. The
+ * routine also jiggles the input port and selectively mutes the
*/
static void
chu_gain(
diff --git a/ntpd/refclock_conf.c b/ntpd/refclock_conf.c
index dc29d1e798fe..845e913f77c0 100644
--- a/ntpd/refclock_conf.c
+++ b/ntpd/refclock_conf.c
@@ -138,7 +138,7 @@ extern struct refclock refclock_nmea;
#define refclock_nmea refclock_none
#endif
-#ifdef CLOCK_ATOM
+#if defined (CLOCK_ATOM) && defined(HAVE_PPSAPI)
extern struct refclock refclock_atom;
#else
#define refclock_atom refclock_none
@@ -168,8 +168,8 @@ extern struct refclock refclock_shm;
#define refclock_shm refclock_none
#endif
-#ifdef CLOCK_PALISADE
-extern struct refclock refclock_palisade;
+#ifdef CLOCK_PALISADE
+extern struct refclock refclock_palisade;
#else
#define refclock_palisade refclock_none
#endif
@@ -264,7 +264,7 @@ extern struct refclock refclock_neoclock4x;
*
* Types are defined in ntp.h. The index must match this.
*/
-struct refclock *refclock_conf[] = {
+struct refclock * const refclock_conf[] = {
&refclock_none, /* 0 REFCLK_NONE */
&refclock_local, /* 1 REFCLK_LOCAL */
&refclock_none, /* 2 deprecated: REFCLK_GPS_TRAK */
diff --git a/ntpd/refclock_datum.c b/ntpd/refclock_datum.c
index b26fe73cfc9e..247d7da4acf5 100644
--- a/ntpd/refclock_datum.c
+++ b/ntpd/refclock_datum.c
@@ -173,13 +173,13 @@ static struct datum_pts_unit
** Callback function prototypes that ntpd needs to know about.
*/
-static int datum_pts_start P((int, struct peer *));
-static void datum_pts_shutdown P((int, struct peer *));
-static void datum_pts_poll P((int, struct peer *));
-static void datum_pts_control P((int, struct refclockstat *,
- struct refclockstat *, struct peer *));
-static void datum_pts_init P((void));
-static void datum_pts_buginfo P((int, struct refclockbug *, struct peer *));
+static int datum_pts_start (int, struct peer *);
+static void datum_pts_shutdown (int, struct peer *);
+static void datum_pts_poll (int, struct peer *);
+static void datum_pts_control (int, struct refclockstat *,
+ struct refclockstat *, struct peer *);
+static void datum_pts_init (void);
+static void datum_pts_buginfo (int, struct refclockbug *, struct peer *);
/*
** This is the call back function structure that ntpd actually uses for
@@ -219,7 +219,7 @@ struct refclock refclock_datum = {
** the adjtime() call.
*/
-static void datum_pts_receive P((struct recvbuf *));
+static void datum_pts_receive (struct recvbuf *);
/*......................................................................*/
/* datum_pts_start - start up the datum PTS. This means open the */
@@ -259,13 +259,13 @@ datum_pts_start(
*/
temp_datum_pts_unit = (struct datum_pts_unit **)
- malloc((nunits+1)*sizeof(struct datum_pts_unit *));
+ emalloc((nunits+1)*sizeof(struct datum_pts_unit *));
if (nunits > 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
nunits*sizeof(struct datum_pts_unit *));
free(datum_pts_unit);
datum_pts_unit = temp_datum_pts_unit;
datum_pts_unit[nunits] = (struct datum_pts_unit *)
- malloc(sizeof(struct datum_pts_unit));
+ emalloc(sizeof(struct datum_pts_unit));
datum_pts = datum_pts_unit[nunits];
datum_pts->unit = unit; /* set my unit id */
@@ -292,6 +292,8 @@ datum_pts_start(
#ifdef HAVE_TERMIOS
+ memset(&arg, 0, sizeof(arg));
+
arg.c_iflag = IGNBRK;
arg.c_oflag = 0;
arg.c_cflag = B9600 | CS8 | CREAD | PARENB | CLOCAL;
@@ -395,7 +397,7 @@ datum_pts_shutdown(
if (nunits > 1) {
temp_datum_pts_unit = (struct datum_pts_unit **)
- malloc((nunits-1)*sizeof(struct datum_pts_unit *));
+ emalloc((nunits-1)*sizeof(struct datum_pts_unit *));
if (i!= 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
i*sizeof(struct datum_pts_unit *));
diff --git a/ntpd/refclock_dumbclock.c b/ntpd/refclock_dumbclock.c
index 10ff2cfe893b..f300ac9bc5a1 100644
--- a/ntpd/refclock_dumbclock.c
+++ b/ntpd/refclock_dumbclock.c
@@ -35,7 +35,7 @@ extern int async_write(int, const void *, unsigned int);
*
* Input format:
*
- * hh:mm:ss <cr>
+ * hh:mm:ss <cr>
*
* hh:mm:ss -- what you'd expect, with a 24 hour clock. (Heck, that's the only
* way it could get stupider.) We take time on the <cr>.
@@ -64,21 +64,21 @@ extern int async_write(int, const void *, unsigned int);
* Dumb clock control structure
*/
struct dumbclock_unit {
- u_char tcswitch; /* timecode switch */
- l_fp laststamp; /* last receive timestamp */
- u_char lasthour; /* last hour (for monitor) */
- u_char linect; /* count ignored lines (for monitor */
- struct tm ymd; /* struct tm for y/m/d only */
+ u_char tcswitch; /* timecode switch */
+ l_fp laststamp; /* last receive timestamp */
+ u_char lasthour; /* last hour (for monitor) */
+ u_char linect; /* count ignored lines (for monitor */
+ struct tm ymd; /* struct tm for y/m/d only */
};
/*
* Function prototypes
*/
-static int dumbclock_start P((int, struct peer *));
-static void dumbclock_shutdown P((int, struct peer *));
-static void dumbclock_receive P((struct recvbuf *));
+static int dumbclock_start (int, struct peer *);
+static void dumbclock_shutdown (int, struct peer *);
+static void dumbclock_receive (struct recvbuf *);
#if 0
-static void dumbclock_poll P((int, struct peer *));
+static void dumbclock_poll (int, struct peer *);
#endif
/*
@@ -115,24 +115,20 @@ dumbclock_start(
* Open serial port. Don't bother with CLK line discipline, since
* it's not available.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
#ifdef DEBUG
if (debug)
printf ("starting Dumbclock with device %s\n",device);
#endif
fd = refclock_open(device, SPEED232, 0);
- if (fd < 0)
+ if (!fd)
return (0);
/*
* Allocate and initialize unit structure
*/
- up = (struct dumbclock_unit *)emalloc(sizeof(struct dumbclock_unit));
- if (up == NULL) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct dumbclock_unit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = dumbclock_receive;
@@ -140,8 +136,10 @@ dumbclock_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
+ pp->unitptr = NULL;
return (0);
}
@@ -153,14 +151,10 @@ dumbclock_start(
tm_time_p = gmtime(&now);
#endif
if (tm_time_p)
- {
- up->ymd = *tm_time_p;
- }
+ up->ymd = *tm_time_p;
else
- {
- return 0;
- }
-
+ return 0;
+
/*
* Initialize miscellaneous variables
*/
@@ -185,8 +179,10 @@ dumbclock_shutdown(
pp = peer->procptr;
up = (struct dumbclock_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -202,12 +198,12 @@ dumbclock_receive(
struct refclockproc *pp;
struct peer *peer;
- l_fp trtmp; /* arrival timestamp */
- int hours; /* hour-of-day */
- int minutes; /* minutes-past-the-hour */
- int seconds; /* seconds */
- int temp; /* int temp */
- int got_good; /* got a good time flag */
+ l_fp trtmp; /* arrival timestamp */
+ int hours; /* hour-of-day */
+ int minutes; /* minutes-past-the-hour */
+ int seconds; /* seconds */
+ int temp; /* int temp */
+ int got_good; /* got a good time flag */
/*
* Initialize pointers and read the timecode and timestamp
@@ -222,7 +218,7 @@ dumbclock_receive(
up->tcswitch = 1;
up->laststamp = trtmp;
} else
- up->tcswitch = 0;
+ up->tcswitch = 0;
return;
}
pp->lencode = (u_short)temp;
@@ -249,16 +245,18 @@ dumbclock_receive(
struct tm asserted_tm; /* the struct tm of the same */
int adjyear;
int adjmon;
- int reality_delta;
+ time_t reality_delta;
time_t now;
/*
* Convert to GMT for sites that distribute localtime. This
- * means we have to figure out what day it is. Easier said
+ * means we have to figure out what day it is. Easier said
* than done...
*/
+ memset(&asserted_tm, 0, sizeof(asserted_tm));
+
asserted_tm.tm_year = up->ymd.tm_year;
asserted_tm.tm_mon = up->ymd.tm_mon;
asserted_tm.tm_mday = up->ymd.tm_mday;
@@ -383,4 +381,4 @@ dumbclock_poll(
#else
int refclock_dumbclock_bs;
-#endif /* REFCLOCK */
+#endif /* defined(REFCLOCK) && defined(CLOCK_DUMBCLOCK) */
diff --git a/ntpd/refclock_fg.c b/ntpd/refclock_fg.c
index ce5085a757c6..5f2ca4b66617 100644
--- a/ntpd/refclock_fg.c
+++ b/ntpd/refclock_fg.c
@@ -33,11 +33,11 @@
/*
* Function prototypes
*/
-static int fg_init P((int));
-static int fg_start P((int, struct peer *));
-static void fg_shutdown P((int, struct peer *));
-static void fg_poll P((int, struct peer *));
-static void fg_receive P((struct recvbuf *));
+static int fg_init (int);
+static int fg_start (int, struct peer *);
+static void fg_shutdown (int, struct peer *);
+static void fg_poll (int, struct peer *);
+static void fg_receive (struct recvbuf *);
/*
* Forum Graphic unit control structure
diff --git a/ntpd/refclock_gpsvme.c b/ntpd/refclock_gpsvme.c
index 9f9e85c9fa8d..c3322fdebf2d 100644
--- a/ntpd/refclock_gpsvme.c
+++ b/ntpd/refclock_gpsvme.c
@@ -104,13 +104,9 @@ psc_start(
return 0;
}
- if (!up) {
- msyslog(LOG_ERR, "psc_start: unit: %d, emalloc: %m", unit);
- return 0;
- }
memset(up, '\0', sizeof *up);
- sprintf(buf, DEVICE, unit); /* dev file name */
+ snprintf(buf, sizeof(buf), DEVICE, unit); /* dev file name */
fd[unit] = open(buf, O_RDONLY); /* open device file */
if (fd[unit] < 0) {
msyslog(LOG_ERR, "psc_start: unit: %d, open failed. %m", unit);
@@ -131,7 +127,7 @@ psc_start(
pp->io.fd = -1;
pp->unitptr = (caddr_t) up;
get_systime(&pp->lastrec);
- memcpy((char *)&pp->refid, REFID, 4);
+ memcpy(&pp->refid, REFID, 4);
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
up->unit = unit;
@@ -149,8 +145,10 @@ psc_shutdown(
struct peer *peer
)
{
- free(peer->procptr->unitptr);
- close(fd[unit]);
+ if (NULL != peer->procptr->unitptr)
+ free(peer->procptr->unitptr);
+ if (fd[unit] > 0)
+ close(fd[unit]);
}
/* psc_poll: read, decode, and record device time */
@@ -196,9 +194,10 @@ psc_poll(
pp->nsec = 1000000*BCD2INT3((tlo & 0x00FFF000) >> 12) +
BCD2INT3(tlo & 0x00000FFF);
- sprintf(pp->a_lastcode, "%3.3d %2.2d:%2.2d:%2.2d.%09ld %02x %08x %08x",
- pp->day, pp->hour, pp->minute, pp->second, pp->nsec, status, thi,
- tlo);
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
+ "%3.3d %2.2d:%2.2d:%2.2d.%09ld %02x %08x %08x", pp->day,
+ pp->hour, pp->minute, pp->second, pp->nsec, status, thi,
+ tlo);
pp->lencode = strlen(pp->a_lastcode);
/* compute the timecode timestamp */
diff --git a/ntpd/refclock_heath.c b/ntpd/refclock_heath.c
index a56b491b416a..cd74eca3173d 100644
--- a/ntpd/refclock_heath.c
+++ b/ntpd/refclock_heath.c
@@ -186,10 +186,10 @@ static int speed[] = {B1200, B2400, B4800, B9600};
/*
* Function prototypes
*/
-static int heath_start P((int, struct peer *));
-static void heath_shutdown P((int, struct peer *));
-static void heath_receive P((struct recvbuf *));
-static void heath_poll P((int, struct peer *));
+static int heath_start (int, struct peer *);
+static void heath_shutdown (int, struct peer *);
+static void heath_receive (struct recvbuf *);
+static void heath_poll (int, struct peer *);
/*
* Transfer vector
@@ -221,7 +221,7 @@ heath_start(
/*
* Open serial port
*/
- sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
if (!(fd = refclock_open(device, speed[peer->ttl & 0x3],
LDISC_REMOTE)))
return (0);
@@ -231,7 +231,8 @@ heath_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
return (0);
}
@@ -241,7 +242,7 @@ heath_start(
peer->precision = PRECISION;
peer->burst = NSTAGE;
pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
+ memcpy(&pp->refid, REFID, 4);
return (1);
}
@@ -258,7 +259,8 @@ heath_shutdown(
struct refclockproc *pp;
pp = peer->procptr;
- io_closeclock(&pp->io);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
}
diff --git a/ntpd/refclock_hopfpci.c b/ntpd/refclock_hopfpci.c
index 81c186d168bd..284e3011c909 100644
--- a/ntpd/refclock_hopfpci.c
+++ b/ntpd/refclock_hopfpci.c
@@ -124,24 +124,17 @@ hopfpci_start(
/*
* 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));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
#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);
+ if (!OpenHopfDevice()) {
+ msyslog(LOG_ERR, "Start: %s unit: %d failed!", DEVICE, unit);
+ free(up);
return (0);
}
#endif
@@ -158,17 +151,12 @@ hopfpci_start(
/*
* 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;
- }
+ memcpy((char *)&pp->refid, REFID, 4);
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ up->leap_status = 0;
+ up->unit = (short) unit;
+ return (1);
}
@@ -187,6 +175,8 @@ hopfpci_shutdown(
#else
CloseHopfDevice();
#endif
+ if (NULL != peer->procptr->unitptr)
+ free(peer->procptr->unitptr);
}
@@ -221,9 +211,11 @@ hopfpci_poll(
else
pp->leap = LEAP_NOWARNING;
- sprintf(pp->a_lastcode,"ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d",
- m_time.wStatus, pp->hour, pp->minute, pp->second,
- pp->nsec / 1000000, m_time.wDay, m_time.wMonth, m_time.wYear);
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
+ "ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d",
+ m_time.wStatus, pp->hour, pp->minute, pp->second,
+ pp->nsec / 1000000, m_time.wDay, m_time.wMonth,
+ m_time.wYear);
pp->lencode = (u_short)strlen(pp->a_lastcode);
get_systime(&pp->lastrec);
diff --git a/ntpd/refclock_hopfser.c b/ntpd/refclock_hopfser.c
index 9037d4a9222a..48eea0022bb7 100644
--- a/ntpd/refclock_hopfser.c
+++ b/ntpd/refclock_hopfser.c
@@ -95,11 +95,11 @@ struct hopfclock_unit {
* 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 *)); */
+static int hopfserial_start (int, struct peer *);
+static void hopfserial_shutdown (int, struct peer *);
+static void hopfserial_receive (struct recvbuf *);
+static void hopfserial_poll (int, struct peer *);
+/* static void hopfserial_io (struct recvbuf *); */
/*
* Transfer vector
*/
@@ -127,11 +127,8 @@ hopfserial_start (
int fd;
char gpsdev[20];
-#ifdef SYS_WINNT
- (void) sprintf(gpsdev, "COM%d:", unit);
-#else
- (void) sprintf(gpsdev, DEVICE, unit);
-#endif
+ snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
+
/* LDISC_STD, LDISC_RAW
* Open serial port. Use CLK line discipline, if available.
*/
@@ -149,18 +146,8 @@ hopfserial_start (
/*
* 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));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = hopfserial_receive;
@@ -169,10 +156,12 @@ hopfserial_start (
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
#ifdef DEBUG
- printf("hopfSerialClock(%d) io_addclock\n",unit);
+ printf("hopfSerialClock(%d) io_addclock\n", unit);
#endif
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
+ pp->unitptr = NULL;
return (0);
}
@@ -205,8 +194,11 @@ hopfserial_shutdown (
pp = peer->procptr;
up = (struct hopfclock_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -292,7 +284,7 @@ hopfserial_receive (
/* preparation for timecode ntpq rl command ! */
#if 0
- wsprintf(pp->a_lastcode,
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
"STATUS: %1X%1X, DATE: %02d.%02d.%04d TIME: %02d:%02d:%02d",
synch,
DoW,
diff --git a/ntpd/refclock_hpgps.c b/ntpd/refclock_hpgps.c
index 5efd19eaa274..5867a1d7b278 100644
--- a/ntpd/refclock_hpgps.c
+++ b/ntpd/refclock_hpgps.c
@@ -125,10 +125,10 @@ struct hpgpsunit {
/*
* Function prototypes
*/
-static int hpgps_start P((int, struct peer *));
-static void hpgps_shutdown P((int, struct peer *));
-static void hpgps_receive P((struct recvbuf *));
-static void hpgps_poll P((int, struct peer *));
+static int hpgps_start (int, struct peer *);
+static void hpgps_shutdown (int, struct peer *);
+static void hpgps_receive (struct recvbuf *);
+static void hpgps_poll (int, struct peer *);
/*
* Transfer vector
@@ -162,7 +162,7 @@ hpgps_start(
* Open serial port. Use CLK line discipline, if available.
* Default is HP 58503A, mode arg selects HP Z3801A
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
/* mode parameter to server config line shares ttl slot */
if ((peer->ttl == 1)) {
if (!(fd = refclock_open(device, SPEED232Z,
@@ -175,19 +175,16 @@ hpgps_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct hpgpsunit *)
- emalloc(sizeof(struct hpgpsunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct hpgpsunit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = hpgps_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -232,8 +229,10 @@ hpgps_shutdown(
pp = peer->procptr;
up = (struct hpgpsunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -532,18 +531,25 @@ hpgps_receive(
pp->leap = LEAP_NOTINSYNC;
}
else {
+ pp->leap = LEAP_NOWARNING;
switch (leapchar) {
- case '+':
- pp->leap = LEAP_ADDSECOND;
+ case '0':
break;
- case '0':
- pp->leap = LEAP_NOWARNING;
+ /* See http://bugs.ntp.org/1090
+ * Ignore leap announcements unless June or December.
+ * Better would be to use :GPSTime? to find the month,
+ * but that seems too likely to introduce other bugs.
+ */
+ case '+':
+ if ((month==6) || (month==12))
+ pp->leap = LEAP_ADDSECOND;
break;
case '-':
- pp->leap = LEAP_DELSECOND;
+ if ((month==6) || (month==12))
+ pp->leap = LEAP_DELSECOND;
break;
default:
diff --git a/ntpd/refclock_irig.c b/ntpd/refclock_irig.c
index 6be09d9bacf8..0a4747319c4b 100644
--- a/ntpd/refclock_irig.c
+++ b/ntpd/refclock_irig.c
@@ -25,27 +25,36 @@
/*
* Audio IRIG-B/E demodulator/decoder
*
- * This driver receives, demodulates and decodes IRIG-B/E signals when
- * connected to the audio codec /dev/audio. The IRIG signal format is an
- * amplitude-modulated carrier with pulse-width modulated data bits. For
- * IRIG-B, the carrier frequency is 1000 Hz and bit rate 100 b/s; for
- * IRIG-E, the carrier frequenchy is 100 Hz and bit rate 10 b/s. The
- * driver automatically recognizes which format is in use.
+ * This driver synchronizes the computer time using data encoded in
+ * IRIG-B/E signals commonly produced by GPS receivers and other timing
+ * devices. The IRIG signal is an amplitude-modulated carrier with
+ * pulse-width modulated data bits. For IRIG-B, the carrier frequency is
+ * 1000 Hz and bit rate 100 b/s; for IRIG-E, the carrier frequenchy is
+ * 100 Hz and bit rate 10 b/s. The driver automatically recognizes which
+ & format is in use.
+ *
+ * The driver requires an audio codec or sound card with sampling rate 8
+ * kHz and mu-law companding. This is the same standard as used by the
+ * telephone industry and is supported by most hardware and operating
+ * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
+ * implementation, only one audio driver and codec can be supported on a
+ * single machine.
*
* The program processes 8000-Hz mu-law companded samples using separate
* signal filters for IRIG-B and IRIG-E, a comb filter, envelope
* detector and automatic threshold corrector. Cycle crossings relative
* to the corrected slice level determine the width of each pulse and
- * its value - zero, one or position identifier. The data encode 20 BCD
- * digits which determine the second, minute, hour and day of the year
- * and sometimes the year and synchronization condition. The comb filter
- * exponentially averages the corresponding samples of successive baud
- * intervals in order to reliably identify the reference carrier cycle.
- * A type-II phase-lock loop (PLL) performs additional integration and
- * interpolation to accurately determine the zero crossing of that
- * cycle, which determines the reference timestamp. A pulse-width
- * discriminator demodulates the data pulses, which are then encoded as
- * the BCD digits of the timecode.
+ * its value - zero, one or position identifier.
+ *
+ * The data encode 20 BCD digits which determine the second, minute,
+ * hour and day of the year and sometimes the year and synchronization
+ * condition. The comb filter exponentially averages the corresponding
+ * samples of successive baud intervals in order to reliably identify
+ * the reference carrier cycle. A type-II phase-lock loop (PLL) performs
+ * additional integration and interpolation to accurately determine the
+ * zero crossing of that cycle, which determines the reference
+ * timestamp. A pulse-width discriminator demodulates the data pulses,
+ * which are then encoded as the BCD digits of the timecode.
*
* The timecode and reference timestamp are updated once each second
* with IRIG-B (ten seconds with IRIG-E) and local clock offset samples
@@ -60,70 +69,60 @@
* decompanded input signal amplitude must be greater than 100 units and
* the codec sample frequency error less than 250 PPM (.025 percent).
*
- * The program performs a number of error checks to protect against
- * overdriven or underdriven input signal levels, incorrect signal
- * format or improper hardware configuration. Specifically, if any of
- * the following errors occur for a time measurement, the data are
- * rejected.
- *
- * o The peak carrier amplitude is less than DRPOUT (100). This usually
- * means dead IRIG signal source, broken cable or wrong input port.
- *
- * o The frequency error is greater than MAXFREQ +-250 PPM (.025%). This
- * usually means broken codec hardware or wrong codec configuration.
- *
- * o The modulation index is less than MODMIN (0.5). This usually means
- * overdriven IRIG signal or wrong IRIG format.
- *
- * o A frame synchronization error has occurred. This usually means
- * wrong IRIG signal format or the IRIG signal source has lost
- * synchronization (signature control).
- *
- * o A data decoding error has occurred. This usually means wrong IRIG
- * signal format.
- *
- * o The current second of the day is not exactly one greater than the
- * previous one. This usually means a very noisy IRIG signal or
- * insufficient CPU resources.
+ * Monitor Data
*
- * o An audio codec error (overrun) occurred. This usually means
- * insufficient CPU resources, as sometimes happens with Sun SPARC
- * IPCs when doing something useful.
+ * The timecode format used for debugging and data recording includes
+ * data helpful in diagnosing problems with the IRIG signal and codec
+ * connections. The driver produces one line for each timecode in the
+ * following format:
*
- * Note that additional checks are done elsewhere in the reference clock
- * interface routines.
+ * 00 00 98 23 19:26:52 2782 143 0.694 10 0.3 66.5 3094572411.00027
*
- * Debugging aids
+ * If clockstats is enabled, the most recent line is written to the
+ * clockstats file every 64 s. If verbose recording is enabled (fudge
+ * flag 4) each line is written as generated.
*
- * The timecode format used for debugging and data recording includes
- * data helpful in diagnosing problems with the IRIG signal and codec
- * connections. With debugging enabled (-d on the ntpd command line),
- * the driver produces one line for each timecode in the following
- * format:
+ * The first field containes the error flags in hex, where the hex bits
+ * are interpreted as below. This is followed by the year of century,
+ * day of year and time of day. Note that the time of day is for the
+ * previous minute, not the current time. The status indicator and year
+ * are not produced by some IRIG devices and appear as zeros. Following
+ * these fields are the carrier amplitude (0-3000), codec gain (0-255),
+ * modulation index (0-1), time constant (4-10), carrier phase error
+ * +-.5) and carrier frequency error (PPM). The last field is the on-
+ * time timestamp in NTP format.
*
- * 00 1 98 23 19:26:52 721 143 0.694 20 0.1 66.5 3094572411.00027
+ * The error flags are defined as follows in hex:
*
- * The most recent line is also written to the clockstats file at 64-s
- * intervals.
+ * x01 Low signal. The carrier amplitude is less than 100 units. This
+ * is usually the result of no signal or wrong input port.
+ * x02 Frequency error. The codec frequency error is greater than 250
+ * PPM. This may be due to wrong signal format or (rarely)
+ * defective codec.
+ * x04 Modulation error. The IRIG modulation index is less than 0.5.
+ * This is usually the result of an overdriven codec, wrong signal
+ * format or wrong input port.
+ * x08 Frame synch error. The decoder frame does not match the IRIG
+ * frame. This is usually the result of an overdriven codec, wrong
+ * signal format or noisy IRIG signal. It may also be the result of
+ * an IRIG signature check which indicates a failure of the IRIG
+ * signal synchronization source.
+ * x10 Data bit error. The data bit length is out of tolerance. This is
+ * usually the result of an overdriven codec, wrong signal format
+ * or noisy IRIG signal.
+ * x20 Seconds numbering discrepancy. The decoder second does not match
+ * the IRIG second. This is usually the result of an overdriven
+ * codec, wrong signal format or noisy IRIG signal.
+ * x40 Codec error (overrun). The machine is not fast enough to keep up
+ * with the codec.
+ * x80 Device status error (Spectracom).
*
- * The first field contains the error flags in hex, where the hex bits
- * are interpreted as below. This is followed by the IRIG status
- * indicator, year of century, day of year and time of day. The status
- * indicator and year are not produced by some IRIG devices. Following
- * these fields are the signal amplitude (0-8100), codec gain (0-255),
- * modulation index (0-1), time constant (2-20), carrier phase error
- * (us) and carrier frequency error (PPM). The last field is the on-time
- * timestamp in NTP format.
*
- * The fraction part of the on-time timestamp is a good indicator of how
- * well the driver is doing. Once upon a time, an UltrSPARC 30 and
- * Solaris 2.7 kept the clock within a few tens of microseconds relative
- * to the IRIG-B signal. Accuracy with IRIG-E was about ten times worse.
- * Unfortunately, Sun broke the 2.7 audio driver in 2.8, which has a 10-
- * ms sawtooth modulation. The driver attempts to remove the modulation
- * by some clever estimation techniques which mostly work. With the
- * "mixerctl -o" command before starting the daemon, the jitter is down
- * to about 100 microseconds. Your experience may vary.
+ * Once upon a time, an UltrSPARC 30 and Solaris 2.7 kept the clock
+ * within a few tens of microseconds relative to the IRIG-B signal.
+ * Accuracy with IRIG-E was about ten times worse. Unfortunately, Sun
+ * broke the 2.7 audio driver in 2.8, which has a 10-ms sawtooth
+ * modulation.
*
* Unlike other drivers, which can have multiple instantiations, this
* one supports only one. It does not seem likely that more than one
@@ -137,8 +136,13 @@
* port, where 0 is the mike port (default) and 1 is the line-in port.
* It does not seem useful to select the compact disc player port. Fudge
* flag3 enables audio monitoring of the input signal. For this purpose,
- * the monitor gain is set to a default value. Fudgetime2 is used as a
+ * the monitor gain is set t a default value. Fudgetime2 is used as a
* frequency vernier for broken codec sample frequency.
+ *
+ * Alarm codes
+ *
+ * CEVNT_BADTIME invalid date or time
+ * CEVNT_TIMEOUT no IRIG data since last poll
*/
/*
* Interface definitions
@@ -152,26 +156,30 @@
#define BAUD 80 /* samples per baud interval */
#define OFFSET 128 /* companded sample offset */
#define SIZE 256 /* decompanding table size */
-#define CYCLE 8 /* samples per carrier cycle */
-#define SUBFLD 10 /* bits per subfield */
-#define FIELD 10 /* subfields per field */
+#define CYCLE 8 /* samples per bit */
+#define SUBFLD 10 /* bits per frame */
+#define FIELD 100 /* bits per second */
#define MINTC 2 /* min PLL time constant */
-#define MAXTC 20 /* max PLL time constant max */
-#define MAXAMP 6000. /* maximum signal level */
-#define MAXCLP 100 /* max clips above reference per s */
-#define DRPOUT 100. /* dropout signal level */
+#define MAXTC 10 /* max PLL time constant max */
+#define MAXAMP 3000. /* maximum signal amplitude */
+#define MINAMP 2000. /* minimum signal amplitude */
+#define DRPOUT 100. /* dropout signal amplitude */
#define MODMIN 0.5 /* minimum modulation index */
#define MAXFREQ (250e-6 * SECOND) /* freq tolerance (.025%) */
-#define PI 3.1415926535 /* the real thing */
-#ifdef IRIG_SUCKS
-#define WIGGLE 11 /* wiggle filter length */
-#endif /* IRIG_SUCKS */
/*
- * Experimentally determined filter delays
+ * The on-time synchronization point is the positive-going zero crossing
+ * of the first cycle of the second. The IIR baseband filter phase delay
+ * is 1.03 ms for IRIG-B and 3.47 ms for IRIG-E. The fudge value 2.68 ms
+ * due to the codec and other causes was determined by calibrating to a
+ * PPS signal from a GPS receiver.
+ *
+ * The results with a 2.4-GHz P4 running FreeBSD 6.1 are generally
+ * within .02 ms short-term with .02 ms jitter. The processor load due
+ * to the driver is 0.51 percent.
*/
-#define IRIG_B .0019 /* IRIG-B filter delay */
-#define IRIG_E .0019 /* IRIG-E filter delay */
+#define IRIG_B ((1.03 + 2.68) / 1000) /* IRIG-B system delay (s) */
+#define IRIG_E ((3.47 + 2.68) / 1000) /* IRIG-E system delay (s) */
/*
* Data bit definitions
@@ -181,7 +189,7 @@
#define BITP 2 /* position identifier */
/*
- * Error flags (up->errflg)
+ * Error flags
*/
#define IRIG_ERR_AMP 0x01 /* low carrier amplitude */
#define IRIG_ERR_FREQ 0x02 /* frequency tolerance exceeded */
@@ -192,13 +200,18 @@
#define IRIG_ERR_ERROR 0x40 /* codec error (overrun) */
#define IRIG_ERR_SIGERR 0x80 /* IRIG status error (Spectracom) */
+static char hexchar[] = "0123456789abcdef";
+
/*
* IRIG unit control structure
*/
struct irigunit {
- u_char timecode[21]; /* timecode string */
+ u_char timecode[2 * SUBFLD + 1]; /* timecode string */
l_fp timestamp; /* audio sample timestamp */
l_fp tick; /* audio sample increment */
+ l_fp refstamp; /* reference timestamp */
+ l_fp chrstamp; /* baud timestamp */
+ l_fp prvstamp; /* previous baud timestamp */
double integ[BAUD]; /* baud integrator */
double phase, freq; /* logical clock phase and frequency */
double zxing; /* phase detector integrator */
@@ -212,20 +225,20 @@ struct irigunit {
* Audio codec variables
*/
double comp[SIZE]; /* decompanding table */
+ double signal; /* peak signal for AGC */
int port; /* codec port */
int gain; /* codec gain */
int mongain; /* codec monitor gain */
- int clipcnt; /* sample clipped count */
int seccnt; /* second interval counter */
/*
* RF variables
*/
- double hpf[5]; /* IRIG-B filter shift register */
+ double bpf[9]; /* IRIG-B filter shift register */
double lpf[5]; /* IRIG-E filter shift register */
+ double envmin, envmax; /* envelope min and max */
+ double slice; /* envelope slice level */
double intmin, intmax; /* integrated envelope min and max */
- double envmax; /* peak amplitude */
- double envmin; /* noise amplitude */
double maxsignal; /* integrated peak amplitude */
double noise; /* integrated noise amplitude */
double lastenv[CYCLE]; /* last cycle amplitudes */
@@ -235,7 +248,6 @@ struct irigunit {
int decim; /* sample decimation factor */
int envphase; /* envelope phase */
int envptr; /* envelope phase pointer */
- int carphase; /* carrier phase */
int envsw; /* envelope state */
int envxing; /* envelope slice crossing */
int tc; /* time constant */
@@ -248,36 +260,30 @@ struct irigunit {
int pulse; /* cycle counter */
int cycles; /* carrier cycles */
int dcycles; /* data cycles */
- int xptr; /* translate table pointer */
- int lastbit; /* last code element length */
+ int lastbit; /* last code element */
int second; /* previous second */
- int fieldcnt; /* subfield count in field */
+ int bitcnt; /* bit count in frame */
+ int frmcnt; /* bit count in second */
+ int xptr; /* timecode pointer */
int bits; /* demodulated bits */
- int bitcnt; /* bit count in subfield */
-#ifdef IRIG_SUCKS
- l_fp wigwag; /* wiggle accumulator */
- int wp; /* wiggle filter pointer */
- l_fp wiggle[WIGGLE]; /* wiggle filter */
- l_fp wigbot[WIGGLE]; /* wiggle bottom fisher*/
-#endif /* IRIG_SUCKS */
- l_fp wuggle;
};
/*
* Function prototypes
*/
-static int irig_start P((int, struct peer *));
-static void irig_shutdown P((int, struct peer *));
-static void irig_receive P((struct recvbuf *));
-static void irig_poll P((int, struct peer *));
+static int irig_start (int, struct peer *);
+static void irig_shutdown (int, struct peer *);
+static void irig_receive (struct recvbuf *);
+static void irig_poll (int, struct peer *);
/*
* More function prototypes
*/
-static void irig_base P((struct peer *, double));
-static void irig_rf P((struct peer *, double));
-static void irig_decode P((struct peer *, int));
-static void irig_gain P((struct peer *));
+static void irig_base (struct peer *, double);
+static void irig_rf (struct peer *, double);
+static void irig_baud (struct peer *, int);
+static void irig_decode (struct peer *, int);
+static void irig_gain (struct peer *);
/*
* Transfer vector
@@ -292,16 +298,6 @@ struct refclock refclock_irig = {
NOFLAGS /* not used */
};
-/*
- * Global variables
- */
-static char hexchar[] = { /* really quick decoding table */
- '0', '8', '4', 'c', /* 0000 0001 0010 0011 */
- '2', 'a', '6', 'e', /* 0100 0101 0110 0111 */
- '1', '9', '5', 'd', /* 1000 1001 1010 1011 */
- '3', 'b', '7', 'f' /* 1100 1101 1110 1111 */
-};
-
/*
* irig_start - open the devices and initialize data for processing
@@ -336,12 +332,8 @@ irig_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct irigunit *)
- emalloc(sizeof(struct irigunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct irigunit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = irig_receive;
@@ -349,8 +341,10 @@ irig_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void)close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
+ pp->unitptr = NULL;
return (0);
}
@@ -362,7 +356,6 @@ irig_start(
memcpy((char *)&pp->refid, REFID, 4);
up->tc = MINTC;
up->decim = 1;
- up->fdelay = IRIG_B;
up->gain = 127;
/*
@@ -376,7 +369,7 @@ irig_start(
for (i = 3; i < OFFSET; i++) {
up->comp[i] = up->comp[i - 1] + step;
up->comp[OFFSET + i] = -up->comp[i];
- if (i % 16 == 0)
+ if (i % 16 == 0)
step *= 2.;
}
DTOLFP(1. / SECOND, &up->tick);
@@ -398,8 +391,10 @@ irig_shutdown(
pp = peer->procptr;
up = (struct irigunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -442,19 +437,6 @@ irig_receive(
sample = up->comp[~*dpt++ & 0xff];
/*
- * Clip noise spikes greater than MAXAMP. If no clips,
- * increase the gain a tad; if the clips are too high,
- * decrease a tad.
- */
- if (sample > MAXAMP) {
- sample = MAXAMP;
- up->clipcnt++;
- } else if (sample < -MAXAMP) {
- sample = -MAXAMP;
- up->clipcnt++;
- }
-
- /*
* Variable frequency oscillator. The codec oscillator
* runs at the nominal rate of 8000 samples per second,
* or 125 us per sample. A frequency change of one unit
@@ -462,7 +444,7 @@ irig_receive(
* per second, which results in a frequency change of
* 125 PPM.
*/
- up->phase += up->freq / SECOND;
+ up->phase += (up->freq + clock_codec) / SECOND;
up->phase += pp->fudgetime2 / 1e6;
if (up->phase >= .5) {
up->phase -= 1.;
@@ -474,6 +456,11 @@ irig_receive(
irig_rf(peer, sample);
}
L_ADD(&up->timestamp, &up->tick);
+ sample = fabs(sample);
+ if (sample > up->signal)
+ up->signal = sample;
+ up->signal += (sample - up->signal) /
+ 1000;
/*
* Once each second, determine the IRIG format and gain.
@@ -487,8 +474,9 @@ irig_receive(
up->decim = 10;
up->fdelay = IRIG_E;
}
- irig_gain(peer);
up->irig_b = up->irig_e = 0;
+ irig_gain(peer);
+
}
}
@@ -505,14 +493,14 @@ irig_receive(
up->mongain = 0;
}
+
/*
* irig_rf - RF processing
*
- * This routine filters the RF signal using a highpass filter for IRIG-B
+ * This routine filters the RF signal using a bandass filter for IRIG-B
* and a lowpass filter for IRIG-E. In case of IRIG-E, the samples are
- * decimated by a factor of ten. The lowpass filter functions also as a
- * decimation filter in this case. Note that the codec filters function
- * as roofing filters to attenuate both the high and low ends of the
+ * decimated by a factor of ten. Note that the codec filters function as
+ * roofing filters to attenuate both the high and low ends of the
* passband. IIR filter coefficients were determined using Matlab Signal
* Processing Toolkit.
*/
@@ -534,36 +522,45 @@ irig_rf(
up = (struct irigunit *)pp->unitptr;
/*
- * IRIG-B filter. 4th-order elliptic, 800-Hz highpass, 0.3 dB
- * passband ripple, -50 dB stopband ripple, phase delay .0022
- * s)
+ * IRIG-B filter. Matlab 4th-order IIR elliptic, 800-1200 Hz
+ * bandpass, 0.3 dB passband ripple, -50 dB stopband ripple,
+ * phase delay 1.03 ms.
*/
- irig_b = (up->hpf[4] = up->hpf[3]) * 2.322484e-01;
- irig_b += (up->hpf[3] = up->hpf[2]) * -1.103929e+00;
- irig_b += (up->hpf[2] = up->hpf[1]) * 2.351081e+00;
- irig_b += (up->hpf[1] = up->hpf[0]) * -2.335036e+00;
- up->hpf[0] = sample - irig_b;
- irig_b = up->hpf[0] * 4.335855e-01
- + up->hpf[1] * -1.695859e+00
- + up->hpf[2] * 2.525004e+00
- + up->hpf[3] * -1.695859e+00
- + up->hpf[4] * 4.335855e-01;
+ irig_b = (up->bpf[8] = up->bpf[7]) * 6.505491e-001;
+ irig_b += (up->bpf[7] = up->bpf[6]) * -3.875180e+000;
+ irig_b += (up->bpf[6] = up->bpf[5]) * 1.151180e+001;
+ irig_b += (up->bpf[5] = up->bpf[4]) * -2.141264e+001;
+ irig_b += (up->bpf[4] = up->bpf[3]) * 2.712837e+001;
+ irig_b += (up->bpf[3] = up->bpf[2]) * -2.384486e+001;
+ irig_b += (up->bpf[2] = up->bpf[1]) * 1.427663e+001;
+ irig_b += (up->bpf[1] = up->bpf[0]) * -5.352734e+000;
+ up->bpf[0] = sample - irig_b;
+ irig_b = up->bpf[0] * 4.952157e-003
+ + up->bpf[1] * -2.055878e-002
+ + up->bpf[2] * 4.401413e-002
+ + up->bpf[3] * -6.558851e-002
+ + up->bpf[4] * 7.462108e-002
+ + up->bpf[5] * -6.558851e-002
+ + up->bpf[6] * 4.401413e-002
+ + up->bpf[7] * -2.055878e-002
+ + up->bpf[8] * 4.952157e-003;
up->irig_b += irig_b * irig_b;
/*
- * IRIG-E filter. 4th-order elliptic, 130-Hz lowpass, 0.3 dB
- * passband ripple, -50 dB stopband ripple, phase delay .0219 s.
+ * IRIG-E filter. Matlab 4th-order IIR elliptic, 130-Hz lowpass,
+ * 0.3 dB passband ripple, -50 dB stopband ripple, phase delay
+ * 3.47 ms.
*/
- irig_e = (up->lpf[4] = up->lpf[3]) * 8.694604e-01;
- irig_e += (up->lpf[3] = up->lpf[2]) * -3.589893e+00;
- irig_e += (up->lpf[2] = up->lpf[1]) * 5.570154e+00;
- irig_e += (up->lpf[1] = up->lpf[0]) * -3.849667e+00;
+ irig_e = (up->lpf[4] = up->lpf[3]) * 8.694604e-001;
+ irig_e += (up->lpf[3] = up->lpf[2]) * -3.589893e+000;
+ irig_e += (up->lpf[2] = up->lpf[1]) * 5.570154e+000;
+ irig_e += (up->lpf[1] = up->lpf[0]) * -3.849667e+000;
up->lpf[0] = sample - irig_e;
- irig_e = up->lpf[0] * 3.215696e-03
- + up->lpf[1] * -1.174951e-02
- + up->lpf[2] * 1.712074e-02
- + up->lpf[3] * -1.174951e-02
- + up->lpf[4] * 3.215696e-03;
+ irig_e = up->lpf[0] * 3.215696e-003
+ + up->lpf[1] * -1.174951e-002
+ + up->lpf[2] * 1.712074e-002
+ + up->lpf[3] * -1.174951e-002
+ + up->lpf[4] * 3.215696e-003;
up->irig_e += irig_e * irig_e;
/*
@@ -583,7 +580,8 @@ irig_rf(
*
* This routine processes the baseband signal and demodulates the AM
* carrier using a synchronous detector. It then synchronizes to the
- * data frame at the baud rate and decodes the data pulses.
+ * data frame at the baud rate and decodes the width-modulated data
+ * pulses.
*/
static void
irig_base(
@@ -597,10 +595,10 @@ irig_base(
/*
* Local variables
*/
- double xxing; /* phase detector interpolated output */
double lope; /* integrator output */
double env; /* envelope detector output */
- double dtemp; /* double temp */
+ double dtemp;
+ int carphase; /* carrier phase */
pp = peer->procptr;
up = (struct irigunit *)pp->unitptr;
@@ -608,50 +606,42 @@ irig_base(
/*
* Synchronous baud integrator. Corresponding samples of current
* and past baud intervals are integrated to refine the envelope
- * amplitude and phase estimate. We keep one cycle of both the
- * raw and integrated data for later use.
+ * amplitude and phase estimate. We keep one cycle (1 ms) of the
+ * raw data and one baud (10 ms) of the integrated data.
*/
up->envphase = (up->envphase + 1) % BAUD;
- up->carphase = (up->carphase + 1) % CYCLE;
up->integ[up->envphase] += (sample - up->integ[up->envphase]) /
(5 * up->tc);
lope = up->integ[up->envphase];
- up->lastenv[up->carphase] = sample;
- up->lastint[up->carphase] = lope;
+ carphase = up->envphase % CYCLE;
+ up->lastenv[carphase] = sample;
+ up->lastint[carphase] = lope;
/*
- * Phase detector. Sample amplitudes are integrated over the
- * baud interval. Cycle phase is determined from these
- * amplitudes using an eight-sample cyclic buffer. A phase
- * change of 360 degrees produces an output change of one unit.
+ * Phase detector. Find the negative-going zero crossing
+ * relative to sample 4 in the 8-sample sycle. A phase change of
+ * 360 degrees produces an output change of one unit.
*/
- if (up->lastsig > 0 && lope <= 0) {
- xxing = lope / (up->lastsig - lope);
- up->zxing += (up->carphase - 4 + xxing) / CYCLE;
- }
+ if (up->lastsig > 0 && lope <= 0)
+ up->zxing += (double)(carphase - 4) / CYCLE;
up->lastsig = lope;
/*
- * Update signal/noise estimates and PLL phase/frequency.
+ * End of the baud. Update signal/noise estimates and PLL
+ * phase, frequency and time constant.
*/
if (up->envphase == 0) {
-
- /*
- * Update envelope signal and noise estimates and mess
- * with error bits.
- */
- up->maxsignal = up->intmax;
- up->noise = up->intmin;
+ up->maxsignal = up->intmax; up->noise = up->intmin;
+ up->intmin = 1e6; up->intmax = -1e6;
if (up->maxsignal < DRPOUT)
up->errflg |= IRIG_ERR_AMP;
if (up->maxsignal > 0)
- up->modndx = (up->intmax - up->intmin) /
- up->intmax;
+ up->modndx = (up->maxsignal - up->noise) /
+ up->maxsignal;
else
up->modndx = 0;
if (up->modndx < MODMIN)
up->errflg |= IRIG_ERR_MOD;
- up->intmin = 1e6; up->intmax = 0;
if (up->errflg & (IRIG_ERR_AMP | IRIG_ERR_FREQ |
IRIG_ERR_MOD | IRIG_ERR_SYNCH)) {
up->tc = MINTC;
@@ -681,17 +671,17 @@ irig_base(
/*
* Synchronous demodulator. There are eight samples in the cycle
- * and ten cycles in the baud interval. The amplitude of each
- * cycle is determined at the last sample in the cycle. The
+ * and ten cycles in the baud. Since the PLL has aligned the
+ * negative-going zero crossing at sample 4, the maximum
+ * amplitude is at sample 2 and minimum at sample 6. The
* beginning of the data pulse is determined from the integrated
* samples, while the end of the pulse is determined from the
* raw samples. The raw data bits are demodulated relative to
* the slice level and left-shifted in the decoding register.
*/
- if (up->carphase != 7)
+ if (carphase != 7)
return;
- env = (up->lastenv[2] - up->lastenv[6]) / 2.;
lope = (up->lastint[2] - up->lastint[6]) / 2.;
if (lope > up->intmax)
up->intmax = lope;
@@ -705,91 +695,130 @@ irig_base(
* when three correct frames have been found.
*/
up->pulse = (up->pulse + 1) % 10;
- if (up->pulse == 1)
- up->envmax = env;
- else if (up->pulse == 9)
- up->envmin = env;
- up->dcycles <<= 1;
- if (env >= (up->envmax + up->envmin) / 2.)
- up->dcycles |= 1;
up->cycles <<= 1;
if (lope >= (up->maxsignal + up->noise) / 2.)
up->cycles |= 1;
if ((up->cycles & 0x303c0f03) == 0x300c0300) {
- l_fp ltemp;
- int bitz;
-
- /*
- * The PLL time constant starts out small, in order to
- * sustain a frequency tolerance of 250 PPM. It
- * gradually increases as the loop settles down. Note
- * that small wiggles are not believed, unless they
- * persist for lots of samples.
- */
- if (up->pulse != 9)
+ if (up->pulse != 0)
up->errflg |= IRIG_ERR_SYNCH;
- up->pulse = 9;
- up->exing = -up->yxing;
- if (fabs(up->envxing - up->envphase) <= 1) {
- up->tcount++;
- if (up->tcount > 50 * up->tc) {
- up->tc++;
- if (up->tc > MAXTC)
- up->tc = MAXTC;
- up->tcount = 0;
- up->envxing = up->envphase;
- } else {
- up->exing -= up->envxing - up->envphase;
- }
- } else {
+ up->pulse = 0;
+ }
+
+ /*
+ * Assemble the baud and max/min to get the slice level for the
+ * next baud. The slice level is based on the maximum over the
+ * first two bits and the minimum over the last two bits, with
+ * the slice level halfway between the maximum and minimum.
+ */
+ env = (up->lastenv[2] - up->lastenv[6]) / 2.;
+ up->dcycles <<= 1;
+ if (env >= up->slice)
+ up->dcycles |= 1;
+ switch(up->pulse) {
+
+ case 0:
+ irig_baud(peer, up->dcycles);
+ if (env < up->envmin)
+ up->envmin = env;
+ up->slice = (up->envmax + up->envmin) / 2;
+ up->envmin = 1e6; up->envmax = -1e6;
+ break;
+
+ case 1:
+ up->envmax = env;
+ break;
+
+ case 2:
+ if (env > up->envmax)
+ up->envmax = env;
+ break;
+
+ case 9:
+ up->envmin = env;
+ break;
+ }
+}
+
+/*
+ * irig_baud - update the PLL and decode the pulse-width signal
+ */
+static void
+irig_baud(
+ struct peer *peer, /* peer structure pointer */
+ int bits /* decoded bits */
+ )
+{
+ struct refclockproc *pp;
+ struct irigunit *up;
+ double dtemp;
+ l_fp ltemp;
+
+ pp = peer->procptr;
+ up = (struct irigunit *)pp->unitptr;
+
+ /*
+ * The PLL time constant starts out small, in order to
+ * sustain a frequency tolerance of 250 PPM. It
+ * gradually increases as the loop settles down. Note
+ * that small wiggles are not believed, unless they
+ * persist for lots of samples.
+ */
+ up->exing = -up->yxing;
+ if (fabs(up->envxing - up->envphase) <= 1) {
+ up->tcount++;
+ if (up->tcount > 20 * up->tc) {
+ up->tc++;
+ if (up->tc > MAXTC)
+ up->tc = MAXTC;
up->tcount = 0;
up->envxing = up->envphase;
+ } else {
+ up->exing -= up->envxing - up->envphase;
}
+ } else {
+ up->tcount = 0;
+ up->envxing = up->envphase;
+ }
- /*
- * Determine a reference timestamp, accounting for the
- * codec delay and filter delay. Note the timestamp is
- * for the previous frame, so we have to backtrack for
- * this plus the delay since the last carrier positive
- * zero crossing.
- */
- dtemp = up->decim * ((up->exing + BAUD) / SECOND + 1.) +
- up->fdelay;
- DTOLFP(dtemp, &ltemp);
- pp->lastrec = up->timestamp;
- L_SUB(&pp->lastrec, &ltemp);
+ /*
+ * Strike the baud timestamp as the positive zero crossing of
+ * the first bit, accounting for the codec delay and filter
+ * delay.
+ */
+ up->prvstamp = up->chrstamp;
+ dtemp = up->decim * (up->exing / SECOND) + up->fdelay;
+ DTOLFP(dtemp, &ltemp);
+ up->chrstamp = up->timestamp;
+ L_SUB(&up->chrstamp, &ltemp);
- /*
- * The data bits are collected in ten-bit frames. The
- * first two and last two bits are determined by frame
- * sync and ignored here; the resulting patterns
- * represent zero (0-1 bits), one (2-4 bits) and
- * position identifier (5-6 bits). The remaining
- * patterns represent errors and are treated as zeros.
- */
- bitz = up->dcycles & 0xfc;
- switch(bitz) {
-
- case 0x00:
- case 0x80:
- irig_decode(peer, BIT0);
- break;
-
- case 0xc0:
- case 0xe0:
- case 0xf0:
- irig_decode(peer, BIT1);
- break;
-
- case 0xf8:
- case 0xfc:
- irig_decode(peer, BITP);
- break;
-
- default:
- irig_decode(peer, 0);
- up->errflg |= IRIG_ERR_DECODE;
- }
+ /*
+ * The data bits are collected in ten-bit bauds. The first two
+ * bits are not used. The resulting patterns represent runs of
+ * 0-1 bits (0), 2-4 bits (1) and 5-7 bits (PI). The remaining
+ * 8-bit run represents a soft error and is treated as 0.
+ */
+ switch (up->dcycles & 0xff) {
+
+ case 0x00: /* 0-1 bits (0) */
+ case 0x80:
+ irig_decode(peer, BIT0);
+ break;
+
+ case 0xc0: /* 2-4 bits (1) */
+ case 0xe0:
+ case 0xf0:
+ irig_decode(peer, BIT1);
+ break;
+
+ case 0xf8: /* (5-7 bits (PI) */
+ case 0xfc:
+ case 0xfe:
+ irig_decode(peer, BITP);
+ break;
+
+ default: /* 8 bits (error) */
+ irig_decode(peer, BIT0);
+ up->errflg |= IRIG_ERR_DECODE;
}
}
@@ -797,11 +826,10 @@ irig_base(
/*
* irig_decode - decode the data
*
- * This routine assembles bits into digits, digits into subfields and
- * subfields into the timecode field. Bits can have values of zero, one
- * or position identifier. There are four bits per digit, two digits per
- * subfield and ten subfields per field. The last bit in every subfield
- * and the first bit in the first subfield are position identifiers.
+ * This routine assembles bauds into digits, digits into frames and
+ * frames into the timecode fields. Bits can have values of zero, one
+ * or position identifier. There are four bits per digit, ten digits per
+ * frame and ten frames per second.
*/
static void
irig_decode(
@@ -811,115 +839,58 @@ irig_decode(
{
struct refclockproc *pp;
struct irigunit *up;
-#ifdef IRIG_SUCKS
- int i;
-#endif /* IRIG_SUCKS */
/*
* Local variables
*/
- char syncchar; /* sync character (Spectracom) */
- char sbs[6]; /* binary seconds since 0h */
- char spare[2]; /* mulligan digits */
+ int syncdig; /* sync digit (Spectracom) */
+ char sbs[6 + 1]; /* binary seconds since 0h */
+ char spare[2 + 1]; /* mulligan digits */
+ int temp;
- pp = peer->procptr;
+ pp = peer->procptr;
up = (struct irigunit *)pp->unitptr;
/*
- * Assemble subfield bits.
+ * Assemble frame bits.
*/
- up->bits <<= 1;
+ up->bits >>= 1;
if (bit == BIT1) {
- up->bits |= 1;
+ up->bits |= 0x200;
} else if (bit == BITP && up->lastbit == BITP) {
/*
- * Frame sync - two adjacent position identifiers.
- * Monitor the reference timestamp and wiggle the
- * clock, but only if no errors have occurred.
+ * Frame sync - two adjacent position identifiers, which
+ * mark the beginning of the second. The reference time
+ * is the beginning of the second position identifier,
+ * so copy the character timestamp to the reference
+ * timestamp.
*/
- up->bitcnt = 1;
- up->fieldcnt = 0;
- up->lastbit = 0;
- if (up->errflg == 0) {
-#ifdef IRIG_SUCKS
- l_fp ltemp;
-
- /*
- * You really don't wanna know what comes down
- * here. Leave it to say Solaris 2.8 broke the
- * nice clean audio stream, apparently affected
- * by a 5-ms sawtooth jitter. Sundown on
- * Solaris. This leaves a little twilight.
- *
- * The scheme involves differentiation, forward
- * learning and integration. The sawtooth has a
- * period of 11 seconds. The timestamp
- * differences are integrated and subtracted
- * from the signal.
- */
- ltemp = pp->lastrec;
- L_SUB(&ltemp, &pp->lastref);
- if (ltemp.l_f < 0)
- ltemp.l_i = -1;
- else
- ltemp.l_i = 0;
- pp->lastref = pp->lastrec;
- if (!L_ISNEG(&ltemp))
- L_CLR(&up->wigwag);
- else
- L_ADD(&up->wigwag, &ltemp);
- L_SUB(&pp->lastrec, &up->wigwag);
- up->wiggle[up->wp] = ltemp;
-
- /*
- * Bottom fisher. To understand this, you have
- * to know about velocity microphones and AM
- * transmitters. No further explanation is
- * offered, as this is truly a black art.
- */
- up->wigbot[up->wp] = pp->lastrec;
- for (i = 0; i < WIGGLE; i++) {
- if (i != up->wp)
- up->wigbot[i].l_ui++;
- L_SUB(&pp->lastrec, &up->wigbot[i]);
- if (L_ISNEG(&pp->lastrec))
- L_ADD(&pp->lastrec,
- &up->wigbot[i]);
- else
- pp->lastrec = up->wigbot[i];
- }
- up->wp++;
- up->wp %= WIGGLE;
- up->wuggle = pp->lastrec;
- refclock_process(pp);
-#else /* IRIG_SUCKS */
- pp->lastref = pp->lastrec;
- up->wuggle = pp->lastrec;
- refclock_process(pp);
-#endif /* IRIG_SUCKS */
- }
- up->errflg = 0;
+ if (up->frmcnt != 1)
+ up->errflg |= IRIG_ERR_SYNCH;
+ up->frmcnt = 1;
+ up->refstamp = up->prvstamp;
}
- up->bitcnt = (up->bitcnt + 1) % SUBFLD;
- if (up->bitcnt == 0) {
+ up->lastbit = bit;
+ if (up->frmcnt % SUBFLD == 0) {
/*
- * End of subfield. Encode two hexadecimal digits in
- * little-endian timecode field.
+ * End of frame. Encode two hexadecimal digits in
+ * little-endian timecode field. Note frame 1 is shifted
+ * right one bit to account for the marker PI.
*/
- if (up->fieldcnt == 0)
- up->bits <<= 1;
- if (up->xptr < 2)
- up->xptr = 2 * FIELD;
- up->timecode[--up->xptr] = hexchar[(up->bits >> 5) &
- 0xf];
- up->timecode[--up->xptr] = hexchar[up->bits & 0xf];
- up->fieldcnt = (up->fieldcnt + 1) % FIELD;
- if (up->fieldcnt == 0) {
+ temp = up->bits;
+ if (up->frmcnt == 10)
+ temp >>= 1;
+ if (up->xptr >= 2) {
+ up->timecode[--up->xptr] = hexchar[temp & 0xf];
+ up->timecode[--up->xptr] = hexchar[(temp >> 5) &
+ 0xf];
+ }
+ if (up->frmcnt == 0) {
/*
- * End of field. Decode the timecode and wind
+ * End of second. Decode the timecode and wind
* the clock. Not all IRIG generators have the
* year; if so, it is nonzero after year 2000.
* Not all have the hardware status bit; if so,
@@ -931,40 +902,68 @@ irig_decode(
* refclock_process() will reject the timecode
* as invalid.
*/
- up->xptr = 2 * FIELD;
+ up->xptr = 2 * SUBFLD;
if (sscanf((char *)up->timecode,
- "%6s%2d%c%2s%3d%2d%2d%2d", sbs, &pp->year,
- &syncchar, spare, &pp->day, &pp->hour,
+ "%6s%2d%1d%2s%3d%2d%2d%2d", sbs, &pp->year,
+ &syncdig, spare, &pp->day, &pp->hour,
&pp->minute, &pp->second) != 8)
pp->leap = LEAP_NOTINSYNC;
else
pp->leap = LEAP_NOWARNING;
up->second = (up->second + up->decim) % 60;
- if (pp->year > 0)
- pp->year += 2000;
+
+ /*
+ * Raise an alarm if the day field is zero,
+ * which happens when signature control is
+ * enabled and the device has lost
+ * synchronization. Raise an alarm if the year
+ * field is nonzero and the sync indicator is
+ * zero, which happens when a Spectracom radio
+ * has lost synchronization. Raise an alarm if
+ * the expected second does not agree with the
+ * decoded second, which happens with a garbled
+ * IRIG signal. We are very particular.
+ */
+ if (pp->day == 0 || (pp->year != 0 && syncdig ==
+ 0))
+ up->errflg |= IRIG_ERR_SIGERR;
if (pp->second != up->second)
up->errflg |= IRIG_ERR_CHECK;
up->second = pp->second;
- sprintf(pp->a_lastcode,
- "%02x %c %2d %3d %02d:%02d:%02d %4.0f %3d %6.3f %2d %6.1f %6.1f %s",
- up->errflg, syncchar, pp->year, pp->day,
+
+ /*
+ * Wind the clock only if there are no errors
+ * and the time constant has reached the
+ * maximum.
+ */
+ if (up->errflg == 0 && up->tc == MAXTC) {
+ pp->lastref = pp->lastrec;
+ pp->lastrec = up->refstamp;
+ if (!refclock_process(pp))
+ refclock_report(peer,
+ CEVNT_BADTIME);
+ }
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
+ "%02x %02d %03d %02d:%02d:%02d %4.0f %3d %6.3f %2d %6.2f %6.1f %s",
+ up->errflg, pp->year, pp->day,
pp->hour, pp->minute, pp->second,
up->maxsignal, up->gain, up->modndx,
up->tc, up->exing * 1e6 / SECOND, up->freq *
- 1e6 / SECOND, ulfptoa(&up->wuggle, 6));
+ 1e6 / SECOND, ulfptoa(&pp->lastrec, 6));
pp->lencode = strlen(pp->a_lastcode);
+ up->errflg = 0;
if (pp->sloppyclockflag & CLK_FLAG4) {
record_clock_stats(&peer->srcadr,
pp->a_lastcode);
#ifdef DEBUG
if (debug)
- printf("irig: %s\n",
+ printf("irig %s\n",
pp->a_lastcode);
#endif /* DEBUG */
}
}
}
- up->lastbit = bit;
+ up->frmcnt = (up->frmcnt + 1) % FIELD;
}
@@ -973,8 +972,7 @@ irig_decode(
*
* This routine sweeps up the timecode updates since the last poll. For
* IRIG-B there should be at least 60 updates; for IRIG-E there should
- * be at least 6. If nothing is heard, a timeout event is declared and
- * any orphaned timecode updates are sent to foster care.
+ * be at least 6. If nothing is heard, a timeout event is declared.
*/
static void
irig_poll(
@@ -992,12 +990,13 @@ irig_poll(
refclock_report(peer, CEVNT_TIMEOUT);
return;
- } else {
- refclock_receive(peer);
+ }
+ refclock_receive(peer);
+ if (!(pp->sloppyclockflag & CLK_FLAG4)) {
record_clock_stats(&peer->srcadr, pp->a_lastcode);
#ifdef DEBUG
if (debug)
- printf("irig: %s\n", pp->a_lastcode);
+ printf("irig %s\n", pp->a_lastcode);
#endif /* DEBUG */
}
pp->polls++;
@@ -1008,11 +1007,10 @@ irig_poll(
/*
* irig_gain - adjust codec gain
*
- * This routine is called once each second. If the signal envelope
- * amplitude is too low, the codec gain is bumped up by four units; if
- * too high, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
+ * This routine is called at the end of each second. It uses the AGC to
+ * bradket the maximum signal level between MINAMP and MAXAMP to avoid
+ * hunting. The routine also jiggles the input port and selectively
+ * mutes the monitor.
*/
static void
irig_gain(
@@ -1030,19 +1028,19 @@ irig_gain(
* gain control field. Thus, it may take awhile for changes to
* wiggle the hardware bits.
*/
- if (up->clipcnt == 0) {
+ if (up->maxsignal < MINAMP) {
up->gain += 4;
if (up->gain > MAXGAIN)
up->gain = MAXGAIN;
- } else if (up->clipcnt > MAXCLP) {
+ } else if (up->maxsignal > MAXAMP) {
up->gain -= 4;
if (up->gain < 0)
up->gain = 0;
}
audio_gain(up->gain, up->mongain, up->port);
- up->clipcnt = 0;
}
+
#else
int refclock_irig_bs;
#endif /* REFCLOCK */
diff --git a/ntpd/refclock_jjy.c b/ntpd/refclock_jjy.c
index d1707ced0f21..df7869dc987b 100644
--- a/ntpd/refclock_jjy.c
+++ b/ntpd/refclock_jjy.c
@@ -3,80 +3,95 @@
*/
/**********************************************************************/
-/* */
-/* Copyright (C) 2001-2004, Takao Abe. All rights reserved. */
-/* */
+/* */
+/* Copyright (C) 2001-2004, Takao Abe. All rights reserved. */
+/* */
/* Permission to use, copy, modify, and distribute this software */
-/* and its documentation for any purpose is hereby granted */
+/* and its documentation for any purpose is hereby granted */
/* without fee, provided that the following conditions are met: */
-/* */
+/* */
/* One retains the entire copyright notice properly, and both the */
/* copyright notice and this license. in the documentation and/or */
-/* other materials provided with the distribution. */
-/* */
+/* other materials provided with the distribution. */
+/* */
/* This software and the name of the author must not be used to */
/* endorse or promote products derived from this software without */
-/* prior written permission. */
-/* */
+/* prior written permission. */
+/* */
/* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED */
-/* WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE */
-/* IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A */
-/* PARTICULAR PURPOSE. */
+/* WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE */
+/* IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A */
+/* PARTICULAR PURPOSE. */
/* IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT, */
/* INDIRECT, GENERAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
-/* ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
+/* ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
/* GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS */
/* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
-/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING */
+/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING */
/* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF */
/* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-/* */
+/* */
/* This driver is developed in my private time, and is opened as */
-/* voluntary contributions for the NTP. */
+/* voluntary contributions for the NTP. */
/* The manufacturer of the JJY receiver has not participated in */
-/* a development of this driver. */
+/* a development of this driver. */
/* The manufacturer does not warrant anything about this driver, */
-/* and is not liable for anything about this driver. */
-/* */
+/* and is not liable for anything about this driver. */
+/* */
/**********************************************************************/
-/* */
-/* Author Takao Abe */
-/* Email abetakao@bea.hi-ho.ne.jp */
-/* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */
-/* */
+/* */
+/* Author Takao Abe */
+/* Email takao_abe@xurb.jp */
+/* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */
+/* */
+/* The email address abetakao@bea.hi-ho.ne.jp is never read */
+/* from 2010, because a few filtering rule are provided by the */
+/* "hi-ho.ne.jp", and lots of spam mail are reached. */
+/* New email address for supporting the refclock_jjy is */
+/* takao_abe@xurb.jp */
+/* */
/**********************************************************************/
-/* */
-/* History */
-/* */
-/* 2001/07/15 */
-/* [New] Support the Tristate Ltd. JJY receiver */
-/* */
-/* 2001/08/04 */
-/* [Change] Log to clockstats even if bad reply */
-/* [Fix] PRECISION = (-3) (about 100 ms) */
-/* [Add] Support the C-DEX Co.Ltd. JJY receiver */
-/* */
-/* 2001/12/04 */
+/* */
+/* History */
+/* */
+/* 2001/07/15 */
+/* [New] Support the Tristate Ltd. JJY receiver */
+/* */
+/* 2001/08/04 */
+/* [Change] Log to clockstats even if bad reply */
+/* [Fix] PRECISION = (-3) (about 100 ms) */
+/* [Add] Support the C-DEX Co.Ltd. JJY receiver */
+/* */
+/* 2001/12/04 */
/* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */
-/* */
-/* 2002/07/12 */
-/* [Fix] Portability for FreeBSD ( patched by the user ) */
-/* */
-/* 2004/10/31 */
+/* */
+/* 2002/07/12 */
+/* [Fix] Portability for FreeBSD ( patched by the user ) */
+/* */
+/* 2004/10/31 */
/* [Change] Command send timing for the Tristate Ltd. JJY receiver */
-/* JJY-01 ( Firmware version 2.01 ) */
-/* Thanks to Andy Taki for testing under FreeBSD */
-/* */
-/* 2004/11/28 */
-/* [Add] Support the Echo Keisokuki LT-2000 receiver */
-/* */
-/* 2006/11/04 */
-/* [Fix] C-DEX JST2000 */
-/* Thanks to Hideo Kuramatsu for the patch */
-/* */
-/* 2009/04/05 */
-/* [Add] Support the CITIZEN T.I.C JJY-200 receiver */
-/* */
+/* JJY-01 ( Firmware version 2.01 ) */
+/* Thanks to Andy Taki for testing under FreeBSD */
+/* */
+/* 2004/11/28 */
+/* [Add] Support the Echo Keisokuki LT-2000 receiver */
+/* */
+/* 2006/11/04 */
+/* [Fix] C-DEX JST2000 */
+/* Thanks to Hideo Kuramatsu for the patch */
+/* */
+/* 2009/04/05 */
+/* [Add] Support the CITIZEN T.I.C JJY-200 receiver */
+/* */
+/* 2010/11/20 */
+/* [Change] Bug 1618 ( Harmless ) */
+/* Code clean up ( Remove unreachable codes ) in */
+/* jjy_start() */
+/* [Change] Change clockstats format of the Tristate JJY01/02 */
+/* Issues more command to get the status of the receiver */
+/* when "fudge 127.127.40.X flag1 1" is specified */
+/* ( DATE,STIM -> DCST,STUS,DATE,STIM ) */
+/* */
/**********************************************************************/
#ifdef HAVE_CONFIG_H
@@ -99,74 +114,76 @@
#include "ntp_stdlib.h"
/**********************************************************************/
-/* */
-/* The Tristate Ltd. JJY receiver JJY01 */
-/* */
-/* Command Response Remarks */
+/* */
+/* The Tristate Ltd. JJY receiver JJY01 */
+/* */
+/* Command Response Remarks */
/* ------------ ---------------------- --------------------- */
-/* date<CR><LF> YYYY/MM/DD XXX<CR><LF> */
-/* time<CR><LF> HH:MM:SS<CR><LF> */
-/* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */
-/* */
-/* During synchronization after a receiver is turned on, */
-/* It replies the past time from 2000/01/01 00:00:00. */
-/* The function "refclock_process" checks the time and tells */
-/* as an insanity time. */
-/* */
+/* dcst<CR><LF> VALID|INVALID<CR><LF> */
+/* stus<CR><LF> ADJUSTED|UNADJUSTED<CR><LF> */
+/* date<CR><LF> YYYY/MM/DD XXX<CR><LF> */
+/* time<CR><LF> HH:MM:SS<CR><LF> */
+/* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */
+/* */
+/* During synchronization after a receiver is turned on, */
+/* It replies the past time from 2000/01/01 00:00:00. */
+/* The function "refclock_process" checks the time and tells */
+/* as an insanity time. */
+/* */
/**********************************************************************/
-/* */
-/* The C-DEX Co. Ltd. JJY receiver JST2000 */
-/* */
-/* Command Response Remarks */
+/* */
+/* The C-DEX Co. Ltd. JJY receiver JST2000 */
+/* */
+/* Command Response Remarks */
/* ------------ ---------------------- --------------------- */
-/* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
-/* */
+/* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
+/* */
/**********************************************************************/
-/* */
-/* The Echo Keisokuki Co. Ltd. JJY receiver LT2000 */
-/* */
-/* Command Response Remarks */
+/* */
+/* The Echo Keisokuki Co. Ltd. JJY receiver LT2000 */
+/* */
+/* Command Response Remarks */
/* ------------ ---------------------- --------------------- */
-/* # Mode 1 (Request&Send) */
-/* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */
-/* C Mode 2 (Continuous) */
-/* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
-/* <SUB> Second signal */
-/* */
+/* # Mode 1 (Request&Send) */
+/* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */
+/* C Mode 2 (Continuous) */
+/* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
+/* <SUB> Second signal */
+/* */
/**********************************************************************/
-/* */
-/* The CITIZEN T.I.C CO., LTD. JJY receiver JJY200 */
-/* */
-/* Command Response Remarks */
+/* */
+/* The CITIZEN T.I.C CO., LTD. JJY receiver JJY200 */
+/* */
+/* Command Response Remarks */
/* ------------ ---------------------- --------------------- */
-/* 'XX YY/MM/DD W HH:MM:SS<CR> */
-/* XX: OK|NG|ER */
-/* W: 0(Monday)-6(Sunday) */
-/* */
+/* 'XX YY/MM/DD W HH:MM:SS<CR> */
+/* XX: OK|NG|ER */
+/* W: 0(Monday)-6(Sunday) */
+/* */
/**********************************************************************/
/*
* Interface definitions
*/
-#define DEVICE "/dev/jjy%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define SPEED232_TRISTATE_JJY01 B9600 /* UART speed (9600 baud) */
-#define SPEED232_CDEX_JST2000 B9600 /* UART speed (9600 baud) */
-#define SPEED232_ECHOKEISOKUKI_LT2000 B9600 /* UART speed (9600 baud) */
-#define SPEED232_CITIZENTIC_JJY200 B4800 /* UART speed (4800 baud) */
-#define REFID "JJY" /* reference ID */
+#define DEVICE "/dev/jjy%d" /* device name and unit */
+#define SPEED232 B9600 /* uart speed (9600 baud) */
+#define SPEED232_TRISTATE_JJY01 B9600 /* UART speed (9600 baud) */
+#define SPEED232_CDEX_JST2000 B9600 /* UART speed (9600 baud) */
+#define SPEED232_ECHOKEISOKUKI_LT2000 B9600 /* UART speed (9600 baud) */
+#define SPEED232_CITIZENTIC_JJY200 B4800 /* UART speed (4800 baud) */
+#define REFID "JJY" /* reference ID */
#define DESCRIPTION "JJY Receiver"
-#define PRECISION (-3) /* precision assumed (about 100 ms) */
+#define PRECISION (-3) /* precision assumed (about 100 ms) */
/*
* JJY unit control structure
*/
struct jjyunit {
- char unittype ; /* UNITTYPE_XXXXXXXXXX */
- short operationmode ; /* Echo Keisokuki LT-2000 : 1 or 2 */
+ char unittype ; /* UNITTYPE_XXXXXXXXXX */
+ short operationmode ; /* Echo Keisokuki LT-2000 : 1 or 2 */
short version ;
- short linediscipline ; /* LDISC_CLK or LDISC_RAW */
- char bPollFlag ; /* Set by jjy_pool and Reset by jjy_receive */
+ short linediscipline ; /* LDISC_CLK or LDISC_RAW */
+ char bPollFlag ; /* Set by jjy_pool and Reset by jjy_receive */
int linecount ;
int lineerror ;
int year, month, day, hour, minute, second, msecond ;
@@ -187,37 +204,39 @@ struct jjyunit {
/*
* Function prototypes
*/
-static int jjy_start P((int, struct peer *));
-static void jjy_shutdown P((int, struct peer *));
-static void jjy_poll P((int, struct peer *));
-static void jjy_poll_tristate_jjy01 P((int, struct peer *));
-static void jjy_poll_cdex_jst2000 P((int, struct peer *));
-static void jjy_poll_echokeisokuki_lt2000 P((int, struct peer *));
-static void jjy_poll_citizentic_jjy200 P((int, struct peer *));
-static void jjy_receive P((struct recvbuf *));
-static int jjy_receive_tristate_jjy01 P((struct recvbuf *));
-static int jjy_receive_cdex_jst2000 P((struct recvbuf *));
-static int jjy_receive_echokeisokuki_lt2000 P((struct recvbuf *));
-static int jjy_receive_citizentic_jjy200 P((struct recvbuf *));
+static int jjy_start (int, struct peer *);
+static void jjy_shutdown (int, struct peer *);
+static void jjy_poll (int, struct peer *);
+static void jjy_poll_tristate_jjy01 (int, struct peer *);
+static void jjy_poll_cdex_jst2000 (int, struct peer *);
+static void jjy_poll_echokeisokuki_lt2000(int, struct peer *);
+static void jjy_poll_citizentic_jjy200 (int, struct peer *);
+static void jjy_receive (struct recvbuf *);
+static int jjy_receive_tristate_jjy01 (struct recvbuf *);
+static int jjy_receive_cdex_jst2000 (struct recvbuf *);
+static int jjy_receive_echokeisokuki_lt2000 (struct recvbuf *);
+static int jjy_receive_citizentic_jjy200 (struct recvbuf *);
+
+static void printableString ( char*, int, char*, int ) ;
/*
* Transfer vector
*/
struct refclock refclock_jjy = {
- jjy_start, /* start up driver */
- jjy_shutdown, /* shutdown driver */
- jjy_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* not used */
- noentry, /* not used */
- NOFLAGS /* not used */
+ jjy_start, /* start up driver */
+ jjy_shutdown, /* shutdown driver */
+ jjy_poll, /* transmit poll message */
+ noentry, /* not used */
+ noentry, /* not used */
+ noentry, /* not used */
+ NOFLAGS /* not used */
};
/*
* Start up driver return code
*/
#define RC_START_SUCCESS 1
-#define RC_START_ERROR 0
+#define RC_START_ERROR 0
/*
* Local constants definition
@@ -225,6 +244,49 @@ struct refclock refclock_jjy = {
#define MAX_LOGTEXT 64
+/*
+ * Tristate JJY01/JJY02 constants definition
+ */
+
+#define TS_JJY01_COMMAND_NUMBER_DATE 1
+#define TS_JJY01_COMMAND_NUMBER_TIME 2
+#define TS_JJY01_COMMAND_NUMBER_STIM 3
+#define TS_JJY01_COMMAND_NUMBER_STUS 4
+#define TS_JJY01_COMMAND_NUMBER_DCST 5
+
+#define TS_JJY01_REPLY_DATE "yyyy/mm/dd www\r\n"
+#define TS_JJY01_REPLY_STIM "hh:mm:ss\r\n"
+#define TS_JJY01_REPLY_STUS_YES "adjusted\r\n"
+#define TS_JJY01_REPLY_STUS_NO "unadjusted\r\n"
+#define TS_JJY01_REPLY_DCST_VALID "valid\r\n"
+#define TS_JJY01_REPLY_DCST_INVALID "invalid\r\n"
+
+#define TS_JJY01_REPLY_LENGTH_DATE 14 /* Length without <CR><LF> */
+#define TS_JJY01_REPLY_LENGTH_STIM 8 /* Length without <CR><LF> */
+#define TS_JJY01_REPLY_LENGTH_STUS_YES 8 /* Length without <CR><LF> */
+#define TS_JJY01_REPLY_LENGTH_STUS_NO 10 /* Length without <CR><LF> */
+#define TS_JJY01_REPLY_LENGTH_DCST_VALID 5 /* Length without <CR><LF> */
+#define TS_JJY01_REPLY_LENGTH_DCST_INVALID 7 /* Length without <CR><LF> */
+
+static struct
+{
+ char commandNumber ;
+ char *commandLog ;
+ char *command ;
+ int commandLength ;
+} tristate_jjy01_command_sequence[] =
+{
+ /* dcst<CR><LF> -> VALID<CR><LF> or INVALID<CR><LF> */
+ { TS_JJY01_COMMAND_NUMBER_DCST, "dcst", "dcst\r\n", 6 },
+ /* stus<CR><LF> -> ADJUSTED<CR><LF> or UNADJUSTED<CR><LF> */
+ { TS_JJY01_COMMAND_NUMBER_STUS, "stus", "stus\r\n", 6 },
+ /* date<CR><LF> -> YYYY/MM/DD WWW<CR><LF> */
+ { TS_JJY01_COMMAND_NUMBER_DATE, "date", "date\r\n", 6 },
+ /* stim<CR><LF> -> HH:MM:SS<CR><LF> */
+ { TS_JJY01_COMMAND_NUMBER_STIM, "stim", "stim\r\n", 6 },
+ { 0 , NULL , NULL , 0 }
+} ;
+
/**************************************************************************************************/
/* jjy_start - open the devices and initialize data for processing */
@@ -233,7 +295,7 @@ static int
jjy_start ( int unit, struct peer *peer )
{
- struct jjyunit *up ;
+ struct jjyunit *up ;
struct refclockproc *pp ;
int fd ;
char *pDeviceName ;
@@ -250,35 +312,33 @@ jjy_start ( int unit, struct peer *peer )
/*
* Open serial port
*/
- if ( ! ( pDeviceName = (char*) emalloc ( strlen(DEVICE) + 10 ) ) ) {
- return RC_START_ERROR ;
- }
- sprintf ( pDeviceName, DEVICE, unit ) ;
+ pDeviceName = emalloc ( strlen(DEVICE) + 10 );
+ snprintf ( pDeviceName, strlen(DEVICE) + 10, DEVICE, unit ) ;
/*
* peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
*/
switch ( peer->ttl ) {
case 0 :
- case 1 :
- iDiscipline = LDISC_CLK ;
- iSpeed232 = SPEED232_TRISTATE_JJY01 ;
- break ;
- case 2 :
- iDiscipline = LDISC_RAW ;
- iSpeed232 = SPEED232_CDEX_JST2000 ;
- break ;
- case 3 :
- iDiscipline = LDISC_CLK ;
- iSpeed232 = SPEED232_ECHOKEISOKUKI_LT2000 ;
- break ;
- case 4 :
- iDiscipline = LDISC_CLK ;
- iSpeed232 = SPEED232_CITIZENTIC_JJY200 ;
- break ;
+ case 1 :
+ iDiscipline = LDISC_CLK ;
+ iSpeed232 = SPEED232_TRISTATE_JJY01 ;
+ break ;
+ case 2 :
+ iDiscipline = LDISC_RAW ;
+ iSpeed232 = SPEED232_CDEX_JST2000 ;
+ break ;
+ case 3 :
+ iDiscipline = LDISC_CLK ;
+ iSpeed232 = SPEED232_ECHOKEISOKUKI_LT2000 ;
+ break ;
+ case 4 :
+ iDiscipline = LDISC_CLK ;
+ iSpeed232 = SPEED232_CITIZENTIC_JJY200 ;
+ break ;
default :
msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
- ntoa(&peer->srcadr), peer->ttl ) ;
+ ntoa(&peer->srcadr), peer->ttl ) ;
free ( (void*) pDeviceName ) ;
return RC_START_ERROR ;
}
@@ -292,12 +352,8 @@ jjy_start ( int unit, struct peer *peer )
/*
* Allocate and initialize unit structure
*/
- if ( ! ( up = (struct jjyunit *) emalloc (sizeof(struct jjyunit)) ) ) {
- close ( fd ) ;
- return RC_START_ERROR ;
- }
-
- memset ( (char*)up, 0, sizeof(struct jjyunit) ) ;
+ up = emalloc (sizeof(*up));
+ memset ( up, 0, sizeof(*up) ) ;
up->linediscipline = iDiscipline ;
/*
@@ -312,9 +368,12 @@ jjy_start ( int unit, struct peer *peer )
case 1 :
up->unittype = UNITTYPE_TRISTATE_JJY01 ;
up->version = 100 ;
- up->lineexpect = 2 ;
- up->charexpect[0] = 14 ; /* YYYY/MM/DD WWW<CR><LF> */
- up->charexpect[1] = 8 ; /* HH:MM:SS<CR><LF> */
+ /* 2010/11/20 */
+ /* Command sequence is defined by the struct tristate_jjy01_command_sequence, */
+ /* and the following 3 lines are not used in the mode LDISC_CLK. */
+ /* up->lineexpect = 2 ; */
+ /* up->charexpect[0] = 14 ; */ /* YYYY/MM/DD WWW<CR><LF> */
+ /* up->charexpect[1] = 8 ; */ /* HH:MM:SS<CR><LF> */
break ;
case 2 :
up->unittype = UNITTYPE_CDEX_JST2000 ;
@@ -325,8 +384,8 @@ jjy_start ( int unit, struct peer *peer )
up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
up->operationmode = 2 ; /* Mode 2 : Continuous mode */
up->lineexpect = 1 ;
- switch ( up->operationmode ) {
- case 1 :
+ switch ( up->operationmode ) {
+ case 1 :
up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
break ;
case 2 :
@@ -334,28 +393,31 @@ jjy_start ( int unit, struct peer *peer )
break ;
}
break ;
- case 4 :
- up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
- up->lineexpect = 1 ;
- up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
- break ;
- default :
- msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
- ntoa(&peer->srcadr), peer->ttl ) ;
- close ( fd ) ;
- free ( (void*) up ) ;
- return RC_START_ERROR ;
+ case 4 :
+ up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
+ up->lineexpect = 1 ;
+ up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
+ break ;
+
+ /* 2010/11/20 */
+ /* The "default:" section of this switch block is never executed, */
+ /* because the former switch block traps the same "default:" case. */
+ /* This "default:" section codes are removed to avoid spending time */
+ /* in the future looking, though the codes are functionally harmless. */
+
}
pp = peer->procptr ;
pp->unitptr = (caddr_t) up ;
pp->io.clock_recv = jjy_receive ;
pp->io.srcclock = (caddr_t) peer ;
- pp->io.datalen = 0 ;
- pp->io.fd = fd ;
+ pp->io.datalen = 0 ;
+ pp->io.fd = fd ;
if ( ! io_addclock(&pp->io) ) {
close ( fd ) ;
- free ( (void*) up ) ;
+ pp->io.fd = -1 ;
+ free ( up ) ;
+ pp->unitptr = NULL ;
return RC_START_ERROR ;
}
@@ -363,8 +425,8 @@ jjy_start ( int unit, struct peer *peer )
* Initialize miscellaneous variables
*/
peer->precision = PRECISION ;
- peer->burst = 1 ;
- pp->clockdesc = DESCRIPTION ;
+ peer->burst = 1 ;
+ pp->clockdesc = DESCRIPTION ;
memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
return RC_START_SUCCESS ;
@@ -379,13 +441,15 @@ static void
jjy_shutdown ( int unit, struct peer *peer )
{
- struct jjyunit *up;
+ struct jjyunit *up;
struct refclockproc *pp;
pp = peer->procptr ;
up = (struct jjyunit *) pp->unitptr ;
- io_closeclock ( &pp->io ) ;
- free ( (void*) up ) ;
+ if ( -1 != pp->io.fd )
+ io_closeclock ( &pp->io ) ;
+ if ( NULL != up )
+ free ( up ) ;
}
@@ -397,9 +461,9 @@ static void
jjy_receive ( struct recvbuf *rbufp )
{
- struct jjyunit *up ;
+ struct jjyunit *up ;
struct refclockproc *pp ;
- struct peer *peer;
+ struct peer *peer;
l_fp tRecvTimestamp; /* arrival timestamp */
int rc ;
@@ -426,11 +490,14 @@ jjy_receive ( struct recvbuf *rbufp )
/*
* Copy received charaters to temporary buffer
*/
- for ( i = 0 ; i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ; i ++ , up->charcount ++ ) {
+ for ( i = 0 ;
+ i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ;
+ i ++ , up->charcount ++ ) {
up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
}
while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
- for ( i = 0 ; i < up->charcount - 1 ; i ++ ) up->rawbuf[i] = up->rawbuf[i+1] ;
+ for ( i = 0 ; i < up->charcount - 1 ; i ++ )
+ up->rawbuf[i] = up->rawbuf[i+1] ;
up->charcount -- ;
}
bCntrlChar = 0 ;
@@ -441,7 +508,9 @@ jjy_receive ( struct recvbuf *rbufp )
}
}
if ( pp->lencode > 0 && up->linecount < up->lineexpect ) {
- if ( bCntrlChar == 0 && up->charcount < up->charexpect[up->linecount] ) return ;
+ if ( bCntrlChar == 0 &&
+ up->charcount < up->charexpect[up->linecount] )
+ return ;
}
up->rawbuf[up->charcount] = 0 ;
} else {
@@ -474,9 +543,9 @@ jjy_receive ( struct recvbuf *rbufp )
rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
break ;
- case UNITTYPE_CITIZENTIC_JJY200 :
- rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
- break ;
+ case UNITTYPE_CITIZENTIC_JJY200 :
+ rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
+ break ;
default :
rc = 0 ;
@@ -485,8 +554,11 @@ jjy_receive ( struct recvbuf *rbufp )
}
if ( up->linediscipline == LDISC_RAW ) {
- if ( up->linecount <= up->lineexpect && up->charcount > up->charexpect[up->linecount-1] ) {
- for ( i = 0 ; i < up->charcount - up->charexpect[up->linecount-1] ; i ++ ) {
+ if ( up->linecount <= up->lineexpect &&
+ up->charcount > up->charexpect[up->linecount-1] ) {
+ for ( i = 0 ;
+ i < up->charcount - up->charexpect[up->linecount-1] ;
+ i ++ ) {
up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
}
up->charcount -= up->charexpect[up->linecount-1] ;
@@ -495,20 +567,29 @@ jjy_receive ( struct recvbuf *rbufp )
}
}
- if ( rc == 0 ) return ;
+ if ( rc == 0 )
+ return ;
- up->bPollFlag = 0 ;
+ up->bPollFlag = 0 ;
if ( up->lineerror != 0 ) {
refclock_report ( peer, CEVNT_BADREPLY ) ;
- strcpy ( sLogText, "BAD REPLY [" ) ;
+ strncpy ( sLogText, "BAD REPLY [",
+ sizeof( sLogText ) ) ;
if ( up->linediscipline == LDISC_RAW ) {
- strncat ( sLogText, up->rawbuf, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
+ strncat ( sLogText, up->rawbuf,
+ sizeof( sLogText ) -
+ strlen ( sLogText ) - 1 ) ;
} else {
- strncat ( sLogText, pp->a_lastcode, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
+ strncat ( sLogText, pp->a_lastcode,
+ sizeof( sLogText ) -
+ strlen ( sLogText ) - 1 ) ;
}
sLogText[MAX_LOGTEXT-1] = 0 ;
- if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 ) strcat ( sLogText, "]" ) ;
+ if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 )
+ strncat ( sLogText, "]",
+ sizeof( sLogText ) -
+ strlen ( sLogText ) - 1 ) ;
record_clock_stats ( &peer->srcadr, sLogText ) ;
return ;
}
@@ -535,9 +616,11 @@ jjy_receive ( struct recvbuf *rbufp )
#ifdef DEBUG
if ( debug ) {
printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST ",
- up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
+ up->year, up->month, up->day, up->hour,
+ up->minute, up->second, up->msecond/100 ) ;
printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
- pp->year, pp->day, pp->hour, pp->minute, pp->second, (int)(pp->nsec/100000000) ) ;
+ pp->year, pp->day, pp->hour, pp->minute,
+ pp->second, (int)(pp->nsec/100000000) ) ;
}
#endif
@@ -546,8 +629,10 @@ jjy_receive ( struct recvbuf *rbufp )
* timecode timestamp.
*/
- sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
- up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
+ snprintf ( sLogText, sizeof(sLogText),
+ "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
+ up->year, up->month, up->day,
+ up->hour, up->minute, up->second, up->msecond/100 ) ;
record_clock_stats ( &peer->srcadr, sLogText ) ;
if ( ! refclock_process ( pp ) ) {
@@ -568,14 +653,21 @@ jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
static char *sFunctionName = "jjy_receive_tristate_jjy01" ;
- struct jjyunit *up ;
+ struct jjyunit *up ;
struct refclockproc *pp ;
- struct peer *peer;
+ struct peer *peer;
char *pBuf ;
int iLen ;
int rc ;
+ int bOverMidnight = 0 ;
+
+ char sLogText [ MAX_LOGTEXT ], sReplyText [ MAX_LOGTEXT ] ;
+
+ char *pCmd ;
+ int iCmdLen ;
+
/*
* Initialize pointers and read the timecode and timestamp
*/
@@ -587,35 +679,28 @@ jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
pBuf = up->rawbuf ;
iLen = up->charcount ;
} else {
- pBuf = pp->a_lastcode ;
- iLen = pp->lencode ;
+ pBuf = pp->a_lastcode ;
+ iLen = pp->lencode ;
}
- switch ( up->linecount ) {
+ switch ( tristate_jjy01_command_sequence[up->linecount-1].commandNumber ) {
- case 1 : /* YYYY/MM/DD WWW */
+ case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */
- if ( iLen != 14 ) {
-#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
- }
-#endif
+ if ( iLen != TS_JJY01_REPLY_LENGTH_DATE ) {
up->lineerror = 1 ;
break ;
}
- rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
- if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
-#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Date error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
- }
-#endif
+
+ rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year,
+ &up->month, &up->day ) ;
+ if ( rc != 3 || up->year < 2000 || up->month < 1 ||
+ up->month > 12 || up->day < 1 || up->day > 31 ) {
up->lineerror = 1 ;
break ;
}
- /*** Start of modification on 2004/10/31 */
+ /*** Start of modification on 2004/10/31 ***/
/*
* Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
* The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
@@ -623,66 +708,75 @@ jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
* so this driver issues the second command "stim" after the reply of the first command "date".
*/
+ /*** 2010/11/20 ***/
/*
- * Send "stim<CR><LF>" or "time<CR><LF>" command
+ * Codes of a next command issue are moved to the end of this function.
*/
-
- if ( up->version >= 100 ) {
-#ifdef DEBUG
- if ( debug ) {
- printf ( "%s (refclock_jjy.c) : send 'stim<CR><LF>'\n", sFunctionName ) ;
- }
-#endif
- if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
- } else {
-#ifdef DEBUG
- if ( debug ) {
- printf ( "%s (refclock_jjy.c) : send 'time<CR><LF>'\n", sFunctionName ) ;
- }
-#endif
- if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
- }
/*** End of modification ***/
- return 0 ;
+ break ;
- case 2 : /* HH:MM:SS */
+ case TS_JJY01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
+ case TS_JJY01_COMMAND_NUMBER_STIM : /* HH:MM:SS */
- if ( iLen != 8 ) {
-#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
- }
-#endif
+ if ( iLen != TS_JJY01_REPLY_LENGTH_STIM ) {
up->lineerror = 1 ;
break ;
}
- rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
- if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
-#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Time error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
- }
-#endif
+
+ rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour,
+ &up->minute, &up->second ) ;
+ if ( rc != 3 || up->hour > 23 || up->minute > 59 ||
+ up->second > 60 ) {
up->lineerror = 1 ;
break ;
}
+
up->msecond = 0 ;
- if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
+ if ( up->hour == 0 && up->minute == 0 &&
+ up->second <= 2 ) {
/*
- * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
- * But the JJY receiver replies a date and time separately.
+ * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver separately,
+ * and the JJY receiver replies a date and time separately.
* Just after midnight transitions, we ignore this time.
*/
- return 0 ;
+ bOverMidnight = 1 ;
}
break ;
+ case TS_JJY01_COMMAND_NUMBER_STUS :
+
+ if ( ( iLen == TS_JJY01_REPLY_LENGTH_STUS_YES
+ && strncmp( pBuf, TS_JJY01_REPLY_STUS_YES,
+ TS_JJY01_REPLY_LENGTH_STUS_YES ) == 0 )
+ || ( iLen == TS_JJY01_REPLY_LENGTH_STUS_NO
+ && strncmp( pBuf, TS_JJY01_REPLY_STUS_NO,
+ TS_JJY01_REPLY_LENGTH_STUS_NO ) == 0 ) ) {
+ /* Good */
+ } else {
+ up->lineerror = 1 ;
+ break ;
+ }
+
+ break ;
+
+ case TS_JJY01_COMMAND_NUMBER_DCST :
+
+ if ( ( iLen == TS_JJY01_REPLY_LENGTH_DCST_VALID
+ && strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID,
+ TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0 )
+ || ( iLen == TS_JJY01_REPLY_LENGTH_DCST_INVALID
+ && strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID,
+ TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) ) {
+ /* Good */
+ } else {
+ up->lineerror = 1 ;
+ break ;
+ }
+
+ break ;
+
default : /* Unexpected reply */
up->lineerror = 1 ;
@@ -690,7 +784,53 @@ jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
}
- return 1 ;
+ /* Clockstats Log */
+
+ printableString( sReplyText, sizeof(sReplyText), pBuf, iLen ) ;
+ snprintf ( sLogText, sizeof(sLogText), "%d: %s -> %c: %s",
+ up->linecount,
+ tristate_jjy01_command_sequence[up->linecount-1].commandLog,
+ ( up->lineerror == 0 )
+ ? ( ( bOverMidnight == 0 )
+ ? 'O'
+ : 'S' )
+ : 'X',
+ sReplyText ) ;
+ record_clock_stats ( &peer->srcadr, sLogText ) ;
+
+ /* Check before issue next command */
+
+ if ( up->lineerror != 0 ) {
+ /* Do not issue next command */
+ return 0 ;
+ }
+
+ if ( bOverMidnight != 0 ) {
+ /* Do not issue next command */
+ return 0 ;
+ }
+
+ if ( tristate_jjy01_command_sequence[up->linecount].command == NULL ) {
+ /* Command sequence completed */
+ return 1 ;
+ }
+
+ /* Issue next command */
+
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : send '%s'\n",
+ sFunctionName, tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
+ }
+#endif
+
+ pCmd = tristate_jjy01_command_sequence[up->linecount].command ;
+ iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
+ if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
+ }
+
+ return 0 ;
}
@@ -721,8 +861,8 @@ jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
pBuf = up->rawbuf ;
iLen = up->charcount ;
} else {
- pBuf = pp->a_lastcode ;
- iLen = pp->lencode ;
+ pBuf = pp->a_lastcode ;
+ iLen = pp->lencode ;
}
switch ( up->linecount ) {
@@ -731,22 +871,29 @@ jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
if ( iLen != 15 ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
+ sFunctionName, iLen ) ;
+ }
#endif
up->lineerror = 1 ;
break ;
}
rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
- &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
- if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
- || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+ &up->year, &up->month, &up->day,
+ &up->hour, &up->minute, &up->second,
+ &up->msecond ) ;
+ if ( rc != 7 || up->month < 1 || up->month > 12 ||
+ up->day < 1 || up->day > 31 || up->hour > 23 ||
+ up->minute > 59 || up->second > 60 ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n", sFunctionName,
- rc, up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n",
+ sFunctionName, rc, up->year,
+ up->month, up->day, up->hour,
+ up->minute, up->second,
+ up->msecond ) ;
+ }
#endif
up->lineerror = 1 ;
break ;
@@ -776,12 +923,12 @@ jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
struct jjyunit *up ;
struct refclockproc *pp ;
- struct peer *peer;
+ struct peer *peer;
char *pBuf ;
int iLen ;
int rc ;
- int i, ibcc, ibcc1, ibcc2 ;
+ int i, ibcc, ibcc1, ibcc2 ;
/*
* Initialize pointers and read the timecode and timestamp
@@ -794,19 +941,21 @@ jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
pBuf = up->rawbuf ;
iLen = up->charcount ;
} else {
- pBuf = pp->a_lastcode ;
- iLen = pp->lencode ;
+ pBuf = pp->a_lastcode ;
+ iLen = pp->lencode ;
}
switch ( up->linecount ) {
case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
- if ( ( up->operationmode == 1 && iLen != 15 ) || ( up->operationmode == 2 && iLen != 17 ) ) {
+ if ( ( up->operationmode == 1 && iLen != 15 ) ||
+ ( up->operationmode == 2 && iLen != 17 ) ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
+ sFunctionName, iLen ) ;
+ }
#endif
if ( up->operationmode == 1 ) {
#ifdef DEBUG
@@ -824,30 +973,39 @@ jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
if ( up->operationmode == 1 ) {
- for ( i = ibcc = 0 ; i < 13 ; i ++ ) ibcc ^= pBuf[i] ;
- ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
- ibcc2 = 0x30 | ( ( ibcc ) & 0xF ) ;
- if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
+ for ( i = ibcc = 0 ; i < 13 ; i ++ )
+ ibcc ^= pBuf[i] ;
+ ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
+ ibcc2 = 0x30 | ( ( ibcc ) & 0xF ) ;
+ if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n", sFunctionName, pBuf[13]&0xFF, pBuf[14]&0xFF, ibcc1, ibcc2 ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n",
+ sFunctionName,
+ pBuf[13] & 0xFF,
+ pBuf[14] & 0xFF,
+ ibcc1, ibcc2 ) ;
+ }
#endif
up->lineerror = 1 ;
break ;
}
- }
+ }
rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
- &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second ) ;
- if ( rc != 6 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
- || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+ &up->year, &up->month, &up->day,
+ &up->hour, &up->minute, &up->second ) ;
+ if ( rc != 6 || up->month < 1 || up->month > 12 ||
+ up->day < 1 || up->day > 31 || up->hour > 23 ||
+ up->minute > 59 || up->second > 60 ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n", sFunctionName,
- rc, up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n",
+ sFunctionName, rc, up->year,
+ up->month, up->day, up->hour,
+ up->minute, up->second ) ;
+ }
#endif
up->lineerror = 1 ;
break ;
@@ -880,7 +1038,8 @@ jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
/* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
#ifdef DEBUG
if ( debug ) {
- printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
+ printf ( "%s (refclock_jjy.c) : send '#'\n",
+ sFunctionName ) ;
}
#endif
if ( write ( pp->io.fd, "#",1 ) != 1 ) {
@@ -895,7 +1054,8 @@ jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
#ifdef DEBUG
if ( debug ) {
- printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
+ printf ( "%s (refclock_jjy.c) : send '#'\n",
+ sFunctionName ) ;
}
#endif
if ( write ( pp->io.fd, "#",1 ) != 1 ) {
@@ -917,84 +1077,91 @@ static int
jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
{
- static char *sFunctionName = "jjy_receive_citizentic_jjy200" ;
+ static char *sFunctionName = "jjy_receive_citizentic_jjy200" ;
- struct jjyunit *up ;
- struct refclockproc *pp ;
- struct peer *peer;
+ struct jjyunit *up ;
+ struct refclockproc *pp ;
+ struct peer *peer;
- char *pBuf ;
- int iLen ;
- int rc ;
- char cApostrophe, sStatus[3] ;
- int iWeekday ;
+ char *pBuf ;
+ int iLen ;
+ int rc ;
+ char cApostrophe, sStatus[3] ;
+ int iWeekday ;
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *) rbufp->recv_srcclock ;
- pp = peer->procptr ;
- up = (struct jjyunit *) pp->unitptr ;
+ /*
+ * Initialize pointers and read the timecode and timestamp
+ */
+ peer = (struct peer *) rbufp->recv_srcclock ;
+ pp = peer->procptr ;
+ up = (struct jjyunit *) pp->unitptr ;
- if ( up->linediscipline == LDISC_RAW ) {
- pBuf = up->rawbuf ;
- iLen = up->charcount ;
- } else {
- pBuf = pp->a_lastcode ;
- iLen = pp->lencode ;
- }
+ if ( up->linediscipline == LDISC_RAW ) {
+ pBuf = up->rawbuf ;
+ iLen = up->charcount ;
+ } else {
+ pBuf = pp->a_lastcode ;
+ iLen = pp->lencode ;
+ }
- /*
- * JJY-200 sends a timestamp every second.
- * So, a timestamp is ignored unless it is right after polled.
- */
- if ( ! up->bPollFlag ) return 0 ;
+ /*
+ * JJY-200 sends a timestamp every second.
+ * So, a timestamp is ignored unless it is right after polled.
+ */
+ if ( ! up->bPollFlag )
+ return 0 ;
- switch ( up->linecount ) {
+ switch ( up->linecount ) {
- case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
+ case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
- if ( iLen != 23 ) {
+ if ( iLen != 23 ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
+ sFunctionName, iLen ) ;
+ }
#endif
- up->lineerror = 1 ;
- break ;
- }
-
- rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
- &cApostrophe, sStatus,
- &up->year, &up->month, &up->day, &iWeekday, &up->hour, &up->minute, &up->second ) ;
- sStatus[2] = 0 ;
- if ( rc != 9 || cApostrophe != '\'' || strcmp( sStatus, "OK" ) != 0
- || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
- || iWeekday > 6
- || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+ up->lineerror = 1 ;
+ break ;
+ }
+
+ rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
+ &cApostrophe, sStatus, &up->year,
+ &up->month, &up->day, &iWeekday,
+ &up->hour, &up->minute, &up->second ) ;
+ sStatus[2] = 0 ;
+ if ( rc != 9 || cApostrophe != '\'' ||
+ strcmp( sStatus, "OK" ) != 0 || up->month < 1 ||
+ up->month > 12 || up->day < 1 || up->day > 31 ||
+ iWeekday > 6 || up->hour > 23 || up->minute > 59 ||
+ up->second > 60 ) {
#ifdef DEBUG
- if ( debug >= 2 ) {
- printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n", sFunctionName,
- rc, cApostrophe, sStatus, up->year, up->month, up->day, iWeekday, up->hour, up->minute, up->second ) ;
- }
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n",
+ sFunctionName, rc, cApostrophe,
+ sStatus, up->year, up->month,
+ up->day, iWeekday, up->hour,
+ up->minute, up->second ) ;
+ }
#endif
- up->lineerror = 1 ;
- break ;
- }
+ up->lineerror = 1 ;
+ break ;
+ }
- up->year += 2000 ;
- up->msecond = 0 ;
+ up->year += 2000 ;
+ up->msecond = 0 ;
- break ;
+ break ;
- default : /* Unexpected reply */
+ default : /* Unexpected reply */
- up->lineerror = 1 ;
- break ;
+ up->lineerror = 1 ;
+ break ;
- }
+ }
- return 1 ;
+ return 1 ;
}
@@ -1026,7 +1193,7 @@ jjy_poll ( int unit, struct peer *peer )
pp->polls ++ ;
- up->bPollFlag = 1 ;
+ up->bPollFlag = 1 ;
up->linecount = 0 ;
up->lineerror = 0 ;
up->charcount = 0 ;
@@ -1045,9 +1212,9 @@ jjy_poll ( int unit, struct peer *peer )
jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
break ;
- case UNITTYPE_CITIZENTIC_JJY200 :
- jjy_poll_citizentic_jjy200 ( unit, peer ) ;
- break ;
+ case UNITTYPE_CITIZENTIC_JJY200 :
+ jjy_poll_citizentic_jjy200 ( unit, peer ) ;
+ break ;
default :
break ;
@@ -1062,21 +1229,44 @@ static void
jjy_poll_tristate_jjy01 ( int unit, struct peer *peer )
{
+ static char *sFunctionName = "jjy_poll_tristate_jjy01" ;
+
+ struct jjyunit *up;
struct refclockproc *pp;
+ char *pCmd ;
+ int iCmdLen ;
+
pp = peer->procptr;
+ up = (struct jjyunit *) pp->unitptr ;
+
+ if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
+ up->linecount = 2 ;
+ }
+
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->linecount=%d\n",
+ sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
+ up->linecount ) ;
+ }
+#endif
/*
- * Send "date<CR><LF>" command
+ * Send a first command
*/
#ifdef DEBUG
if ( debug ) {
- printf ( "jjy_poll_tristate_jjy01 (refclock_jjy.c) : send 'date<CR><LF>'\n" ) ;
+ printf ( "%s (refclock_jjy.c) : send '%s'\n",
+ sFunctionName,
+ tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
}
#endif
- if ( write ( pp->io.fd, "date\r\n",6 ) != 6 ) {
+ pCmd = tristate_jjy01_command_sequence[up->linecount].command ;
+ iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
+ if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
refclock_report ( peer, CEVNT_FAULT ) ;
}
@@ -1150,10 +1340,58 @@ static void
jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
{
- /* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
+ /* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
+
+}
+
+/**************************************************************************************************/
+
+static void
+printableString ( char *sOutput, int iOutputLen, char *sInput, int iInputLen )
+{
+
+ char *printableControlChar[] = {
+ "<NUL>", "<SOH>", "<STX>", "<ETX>",
+ "<EOT>", "<ENQ>", "<ACK>", "<BEL>",
+ "<BS>" , "<HT>" , "<LF>" , "<VT>" ,
+ "<FF>" , "<CR>" , "<SO>" , "<SI>" ,
+ "<DLE>", "<DC1>", "<DC2>", "<DC3>",
+ "<DC4>", "<NAK>", "<SYN>", "<ETB>",
+ "<CAN>", "<EM>" , "<SUB>", "<ESC>",
+ "<FS>" , "<GS>" , "<RS>" , "<US>" ,
+ " " } ;
+
+ int i, j, n ;
+
+ for ( i = j = 0 ; i < iInputLen && j < iOutputLen ; i ++ ) {
+ if ( isprint( sInput[i] ) ) {
+ n = 1 ;
+ if ( j + 1 >= iOutputLen )
+ break ;
+ sOutput[j] = sInput[i] ;
+ } else if ( ( sInput[i] & 0xFF ) <
+ COUNTOF(printableControlChar) ) {
+ n = strlen( printableControlChar[sInput[i] & 0xFF] ) ;
+ if ( j + n + 1 >= iOutputLen )
+ break ;
+ strncpy( sOutput + j,
+ printableControlChar[sInput[i] & 0xFF],
+ (size_t)iOutputLen - j ) ;
+ } else {
+ n = 5 ;
+ if ( j + n + 1 >= iOutputLen ) break ;
+ snprintf( sOutput + j, (size_t)iOutputLen - j,
+ "<x%X>", sInput[i] & 0xFF ) ;
+ }
+ j += n ;
+ }
+
+ sOutput[min(j, iOutputLen - 1)] = '\0' ;
}
+/**************************************************************************************************/
+
#else
int refclock_jjy_bs ;
#endif /* REFCLOCK */
diff --git a/ntpd/refclock_jupiter.c b/ntpd/refclock_jupiter.c
index c10d9fa0df1d..844d24f59daa 100644
--- a/ntpd/refclock_jupiter.c
+++ b/ntpd/refclock_jupiter.c
@@ -135,28 +135,28 @@ struct instance {
/*
* Function prototypes
*/
-static void jupiter_canmsg P((struct instance *, u_int));
-static u_short jupiter_cksum P((u_short *, u_int));
-static int jupiter_config P((struct instance *));
-static void jupiter_debug P((struct peer *, char *, char *, ...))
+static void jupiter_canmsg (struct instance *, u_int);
+static u_short jupiter_cksum (u_short *, u_int);
+static int jupiter_config (struct instance *);
+static void jupiter_debug (struct peer *, char *, char *, ...)
__attribute__ ((format (printf, 3, 4)));
-static char * jupiter_parse_t P((struct instance *, u_short *));
-static char * jupiter_parse_gpos P((struct instance *, u_short *));
-static void jupiter_platform P((struct instance *, u_int));
-static void jupiter_poll P((int, struct peer *));
-static void jupiter_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
+static char * jupiter_parse_t (struct instance *, u_short *);
+static char * jupiter_parse_gpos (struct instance *, u_short *);
+static void jupiter_platform (struct instance *, u_int);
+static void jupiter_poll (int, struct peer *);
+static void jupiter_control (int, struct refclockstat *, struct
+ refclockstat *, struct peer *);
#ifdef HAVE_PPSAPI
-static int jupiter_ppsapi P((struct instance *));
-static int jupiter_pps P((struct instance *));
+static int jupiter_ppsapi (struct instance *);
+static int jupiter_pps (struct instance *);
#endif /* HAVE_PPSAPI */
-static int jupiter_recv P((struct instance *));
-static void jupiter_receive P((struct recvbuf *rbufp));
-static void jupiter_reqmsg P((struct instance *, u_int, u_int));
-static void jupiter_reqonemsg P((struct instance *, u_int));
-static char * jupiter_send P((struct instance *, struct jheader *));
-static void jupiter_shutdown P((int, struct peer *));
-static int jupiter_start P((int, struct peer *));
+static int jupiter_recv (struct instance *);
+static void jupiter_receive (struct recvbuf *rbufp);
+static void jupiter_reqmsg (struct instance *, u_int, u_int);
+static void jupiter_reqonemsg (struct instance *, u_int);
+static char * jupiter_send (struct instance *, struct jheader *);
+static void jupiter_shutdown (int, struct peer *);
+static int jupiter_start (int, struct peer *);
/*
* Transfer vector
@@ -188,7 +188,7 @@ jupiter_start(
/*
* Open serial port
*/
- (void)sprintf(gpsdev, DEVICE, unit);
+ snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
if (fd == 0) {
jupiter_debug(peer, "jupiter_start", "open %s: %s",
@@ -197,12 +197,8 @@ jupiter_start(
}
/* Allocate unit structure */
- if ((instance = (struct instance *)
- emalloc(sizeof(struct instance))) == NULL) {
- (void) close(fd);
- return (0);
- }
- memset((char *)instance, 0, sizeof(struct instance));
+ instance = emalloc(sizeof(*instance));
+ memset(instance, 0, sizeof(*instance));
instance->peer = peer;
pp = peer->procptr;
pp->io.clock_recv = jupiter_receive;
@@ -210,7 +206,7 @@ jupiter_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
free(instance);
return (0);
}
@@ -934,10 +930,10 @@ jupiter_send(struct instance *instance, struct jheader *hp)
}
if ((cc = write(instance->peer->procptr->io.fd, (char *)hp, size)) < 0) {
- (void)sprintf(errstr, "write: %s", strerror(errno));
+ snprintf(errstr, sizeof(errstr), "write: %s", strerror(errno));
return (errstr);
} else if (cc != size) {
- (void)sprintf(errstr, "short write (%d != %d)", cc, size);
+ snprintf(errstr, sizeof(errstr), "short write (%d != %d)", cc, size);
return (errstr);
}
return (NULL);
diff --git a/ntpd/refclock_leitch.c b/ntpd/refclock_leitch.c
index e1ba0c409582..52b65085c8f0 100644
--- a/ntpd/refclock_leitch.c
+++ b/ntpd/refclock_leitch.c
@@ -43,6 +43,7 @@
* STATUS: G (good), D (diag fail), T (time not provided) or
* P (last phone update failed)
*/
+#define PRECISION (-20) /* 1x10-8 */
#define MAXUNITS 1 /* max number of LEITCH units */
#define LEITCHREFID "ATOM" /* reference id */
#define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
@@ -96,20 +97,20 @@ struct leitchunit {
/*
* Function prototypes
*/
-static void leitch_init P((void));
-static int leitch_start P((int, struct peer *));
-static void leitch_shutdown P((int, struct peer *));
-static void leitch_poll P((int, struct peer *));
-static void leitch_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
+static void leitch_init (void);
+static int leitch_start (int, struct peer *);
+static void leitch_shutdown (int, struct peer *);
+static void leitch_poll (int, struct peer *);
+static void leitch_control (int, struct refclockstat *, struct refclockstat *, struct peer *);
#define leitch_buginfo noentry
-static void leitch_receive P((struct recvbuf *));
-static void leitch_process P((struct leitchunit *));
+static void leitch_receive (struct recvbuf *);
+static void leitch_process (struct leitchunit *);
#if 0
-static void leitch_timeout P((struct peer *));
+static void leitch_timeout (struct peer *);
#endif
-static int leitch_get_date P((struct recvbuf *, struct leitchunit *));
-static int leitch_get_time P((struct recvbuf *, struct leitchunit *, int));
-static int days_per_year P((int));
+static int leitch_get_date (struct recvbuf *, struct leitchunit *);
+static int leitch_get_time (struct recvbuf *, struct leitchunit *, int);
+static int days_per_year (int);
static struct leitchunit leitchunits[MAXUNITS];
static u_char unitinuse[MAXUNITS];
@@ -149,9 +150,17 @@ leitch_shutdown(
struct peer *peer
)
{
+ struct leitchunit *leitch;
+
+ if (unit >= MAXUNITS) {
+ return;
+ }
+ leitch = &leitchunits[unit];
+ if (-1 != leitch->leitchio.fd)
+ io_closeclock(&leitch->leitchio);
#ifdef DEBUG
if (debug)
- fprintf(stderr, "leitch_shutdown()\n");
+ fprintf(stderr, "leitch_shutdown()\n");
#endif
}
@@ -257,7 +266,7 @@ leitch_start(
/*
* Open serial port.
*/
- (void) sprintf(leitchdev, LEITCH232, unit);
+ snprintf(leitchdev, sizeof(leitchdev), LEITCH232, unit);
fd232 = open(leitchdev, O_RDWR, 0777);
if (fd232 == -1) {
msyslog(LOG_ERR,
@@ -266,7 +275,7 @@ leitch_start(
}
leitch = &leitchunits[unit];
- memset((char*)leitch, 0, sizeof(*leitch));
+ memset(leitch, 0, sizeof(*leitch));
#if defined(HAVE_SYSV_TTYS)
/*
@@ -386,6 +395,7 @@ leitch_start(
leitch->leitchio.datalen = 0;
leitch->leitchio.fd = fd232;
if (!io_addclock(&leitch->leitchio)) {
+ leitch->leitchio.fd = -1;
goto screwed;
}
@@ -393,7 +403,7 @@ leitch_start(
* All done. Initialize a few random peer variables, then
* return success.
*/
- peer->precision = 0;
+ peer->precision = PRECISION;
peer->stratum = stratumtouse[unit];
peer->refid = refid[unit];
unitinuse[unit] = 1;
diff --git a/ntpd/refclock_local.c b/ntpd/refclock_local.c
index dc6f1aefda67..d1b28718e993 100644
--- a/ntpd/refclock_local.c
+++ b/ntpd/refclock_local.c
@@ -24,19 +24,20 @@
/*
* This is a hack to allow a machine to use its own system clock as a
* reference clock, i.e., to free-run using no outside clock discipline
- * source. This is useful if you want to use NTP in an isolated
- * environment with no radio clock or NIST modem available. Pick a
- * machine that you figure has a good clock oscillator and configure it
- * with this driver. Set the clock using the best means available, like
+ * source. Note that the clock selection algorithm will not select this
+ * driver unless all other sources of synchronization have been lost.
+ * This is useful if you want to use NTP in an isolated environment
+ * with no radio clock or NIST modem available. Pick a machine that you
+ * figure has a good clock oscillator and configure it with this
+ * driver. Set the clock using the best means available, like
* eyeball-and-wristwatch. Then, point all the other machines at this
* one or use broadcast (not multicast) mode to distribute time.
*
* Another application for this driver is if you want to use a
* particular server's clock as the clock of last resort when all other
* normal synchronization sources have gone away. This is especially
- * useful if that server has an ovenized oscillator. For this you would
- * configure this driver at a higher stratum (say 5) to prevent the
- * server's stratum from falling below that.
+ * useful if that server has an ovenized oscillator. However, the
+ * preferred was to do this is using orphan mode. See the documentation.
*
* A third application for this driver is when an external discipline
* source is available, such as the NIST "lockclock" program, which
@@ -52,42 +53,17 @@
* oscillator. In extreme cases, this can cause clients to exceed the
* 128-ms slew window and drop off the NTP subnet.
*
- * THis driver includes provisions to telegraph synchronization state
- * and related variables by means of kernel variables with specially
- * modified kernels. This is done using the ntp_adjtime() syscall.
- * In the cases where another protocol or device synchronizes the local
- * host, the data given to the kernel can be slurped up by this driver
- * and distributed to clients by ordinary NTP messaging.
- *
- * In the default mode the behavior of the clock selection algorithm is
- * modified when this driver is in use. The algorithm is designed so
- * that this driver will never be selected unless no other discipline
- * source is available. This can be overriden with the prefer keyword of
- * the server configuration command, in which case only this driver will
- * be selected for synchronization and all other discipline sources will
- * be ignored. This behavior is intended for use when an external
- * discipline source controls the system clock.
- *
* Fudge Factors
*
- * The stratum for this driver set at 5 by default, but it can be
- * changed by the fudge command and/or the ntpdc utility. The reference
- * ID is 127.0.0.1 by default, but can be changed using the same mechanism.
- * *NEVER* configure this driver to operate at a stratum which might
- * possibly disrupt a client with access to a bona fide primary server,
- * unless the local clock oscillator is reliably disciplined by another
- * source. *NEVER NEVER* configure a server which might devolve to an
- * undisciplined local clock to use multicast mode. Always remember that
- * an improperly configured local clock driver let loose in the Internet
- * can cause very serious disruption. This is why most of us who care
- * about good time use cryptographic authentication.
+ * If fudge flag1 is lit, the leap second bit is set in the peer
+ * status word. It should be set early in the day of a leap second
+ * event and set dark on the day after the event.
*
- * This driver provides a mechanism to trim the local clock in both time
- * and frequency, as well as a way to manipulate the leap bits. The
- * fudge time1 parameter adjusts the time, in seconds, and the fudge
- * time2 parameter adjusts the frequency, in ppm. The fudge time1
- * parameter is additive; that is, it adds an increment to the current
- * time. The fudge time2 parameter directly sets the frequency.
+ * Note the fudge time1 and time2 have been deprecated. The fudge time1
+ * was intended to apply a bias offset. This can be done using the Unix
+ * date command. The fudge time2 was intended to apply a bias frequency.
+ * This can be done using the frequency file and/or the freq
+ * configuration command.
*/
/*
* Local interface definitions
@@ -107,20 +83,11 @@ extern u_long current_time;
*/
extern s_char sys_precision;
-#ifdef KERNEL_PLL
-/*
- * Imported from ntp_loopfilter
- */
-extern int pll_control; /* kernel pll control */
-extern int kern_enable; /* kernel pll enabled */
-extern int ext_enable; /* external clock enable */
-#endif /* KERNEL_PLL */
-
/*
* Function prototypes
*/
-static int local_start P((int, struct peer *));
-static void local_poll P((int, struct peer *));
+static int local_start (int, struct peer *);
+static void local_poll (int, struct peer *);
/*
* Local variables
@@ -191,6 +158,12 @@ local_poll(
#endif /* KERNEL_PLL LOCKCLOCK */
struct refclockproc *pp;
+ /*
+ * Do no evil unless the house is dark or lit with our own lamp.
+ */
+ if (!(sys_peer == NULL || sys_peer == peer))
+ return;
+
#if defined(VMS) && defined(VMS_LOCALUNIT)
if (unit == VMS_LOCALUNIT) {
extern void vms_local_poll(struct peer *);
@@ -199,6 +172,7 @@ local_poll(
return;
}
#endif /* VMS && VMS_LOCALUNIT */
+
pp = peer->procptr;
pp->polls++;
@@ -209,12 +183,8 @@ local_poll(
* time1 (s) and a continuous frequency adjustment using fudge
* time 2 (ppm).
*/
- get_systime(&pp->lastrec);
- pp->fudgetime1 += pp->fudgetime2 * 1e-6 * (current_time -
- poll_time);
poll_time = current_time;
- refclock_process_offset(pp, pp->lastrec, pp->lastrec,
- pp->fudgetime1);
+ refclock_process_offset(pp, pp->lastrec, pp->lastrec, 0);
/*
* If another process is disciplining the system clock, we set
@@ -245,13 +215,15 @@ local_poll(
pp->disp = 0;
pp->jitter = 0;
#else /* KERNEL_PLL LOCKCLOCK */
- pp->leap = LEAP_NOWARNING;
+ if (pp->sloppyclockflag & CLK_FLAG1)
+ pp->leap = LEAP_ADDSECOND;
+ else
+ pp->leap = LEAP_NOWARNING;
pp->disp = DISPERSION;
pp->jitter = 0;
#endif /* KERNEL_PLL LOCKCLOCK */
pp->lastref = pp->lastrec;
refclock_receive(peer);
- pp->fudgetime1 = 0;
}
#else
int refclock_local_bs;
diff --git a/ntpd/refclock_msfees.c b/ntpd/refclock_msfees.c
index 98034b587098..1b25c1c38c4e 100644
--- a/ntpd/refclock_msfees.c
+++ b/ntpd/refclock_msfees.c
@@ -382,11 +382,15 @@ dump_buf(
int i;
register char *ptr = buff;
- sprintf(ptr, text);
- for (i=from; i<to; i++)
- { while (*ptr) ptr++;
- if ((ptr-buff) > DUMP_BUF_SIZE) msyslog(LOG_DEBUG, "D: %s", ptr=buff);
- sprintf(ptr, " %06d", ((int)coffs[i].l_f) / 4295);
+ snprintf(buff, sizeof(buff), text);
+ for (i = from; i < to; i++) {
+ ptr += strlen(ptr);
+ if ((ptr - buff) > DUMP_BUF_SIZE) {
+ msyslog(LOG_DEBUG, "D: %s", buff);
+ ptr = buff;
+ }
+ snprintf(ptr, sizeof(buff) - (ptr - buff),
+ " %06d", ((int)coffs[i].l_f) / 4295);
}
msyslog(LOG_DEBUG, "D: %s", buff);
}
@@ -450,7 +454,7 @@ msfees_start(
/* Unit okay, attempt to open the devices. We do them both at
* once to make sure we can */
- (void) sprintf(eesdev, EES232, unit);
+ snprintf(eesdev, sizeof(eesdev), EES232, unit);
fd232 = open(eesdev, O_RDWR, 0777);
if (fd232 == -1) {
@@ -987,17 +991,20 @@ ees_receive(
/* Dump the deltas each minute */
if (dbg & DB_DUMP_DELTAS)
- { if (/*0 <= ees->second && */
- ees->second < ((sizeof deltas) / (sizeof deltas[0]))) deltas[ees->second] = delta_sfsec;
+ {
+ if (/*0 <= ees->second && */
+ ees->second < COUNTOF(deltas))
+ deltas[ees->second] = delta_sfsec;
/* Dump on second 1, as second 0 sometimes missed */
if (ees->second == 1) {
- char text[16 * ((sizeof deltas) / (sizeof deltas[0]))];
+ char text[16 * COUNTOF(deltas)];
char *cptr=text;
int i;
- for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) {
- sprintf(cptr, " %d.%04d",
- msec(deltas[i]), subms(deltas[i]));
- while (*cptr) cptr++;
+ for (i = 0; i < COUNTOF(deltas); i++) {
+ snprintf(cptr, sizeof(text) / COUNTOF(deltas),
+ " %d.%04d", msec(deltas[i]),
+ subms(deltas[i]));
+ cptr += strlen(cptr);
}
msyslog(LOG_ERR, "Deltas: %d.%04d<->%d.%04d: %s",
msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE),
diff --git a/ntpd/refclock_mx4200.c b/ntpd/refclock_mx4200.c
index 68150b7c4240..f863dca08d98 100644
--- a/ntpd/refclock_mx4200.c
+++ b/ntpd/refclock_mx4200.c
@@ -167,28 +167,28 @@ static char pmvxg[] = "PMVXG";
/*
* Function prototypes
*/
-static int mx4200_start P((int, struct peer *));
-static void mx4200_shutdown P((int, struct peer *));
-static void mx4200_receive P((struct recvbuf *));
-static void mx4200_poll P((int, struct peer *));
-
-static char * mx4200_parse_t P((struct peer *));
-static char * mx4200_parse_p P((struct peer *));
-static char * mx4200_parse_s P((struct peer *));
+static int mx4200_start (int, struct peer *);
+static void mx4200_shutdown (int, struct peer *);
+static void mx4200_receive (struct recvbuf *);
+static void mx4200_poll (int, struct peer *);
+
+static char * mx4200_parse_t (struct peer *);
+static char * mx4200_parse_p (struct peer *);
+static char * mx4200_parse_s (struct peer *);
#ifdef QSORT_USES_VOID_P
-int mx4200_cmpl_fp P((const void *, const void *));
+int mx4200_cmpl_fp (const void *, const void *);
#else
-int mx4200_cmpl_fp P((const l_fp *, const l_fp *));
+int mx4200_cmpl_fp (const l_fp *, const l_fp *);
#endif /* not QSORT_USES_VOID_P */
-static int mx4200_config P((struct peer *));
-static void mx4200_ref P((struct peer *));
-static void mx4200_send P((struct peer *, char *, ...))
+static int mx4200_config (struct peer *);
+static void mx4200_ref (struct peer *);
+static void mx4200_send (struct peer *, char *, ...)
__attribute__ ((format (printf, 2, 3)));
-static u_char mx4200_cksum P((char *, int));
-static int mx4200_jday P((int, int, int));
-static void mx4200_debug P((struct peer *, char *, ...))
+static u_char mx4200_cksum (char *, int);
+static int mx4200_jday (int, int, int);
+static void mx4200_debug (struct peer *, char *, ...)
__attribute__ ((format (printf, 2, 3)));
-static int mx4200_pps P((struct peer *));
+static int mx4200_pps (struct peer *);
/*
* Transfer vector
@@ -222,7 +222,7 @@ mx4200_start(
/*
* Open serial port
*/
- (void)sprintf(gpsdev, DEVICE, unit);
+ snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_PPS))) {
return (0);
}
@@ -230,19 +230,16 @@ mx4200_start(
/*
* Allocate unit structure
*/
- if (!(up = (struct mx4200unit *) emalloc(sizeof(struct mx4200unit)))) {
- perror("emalloc");
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct mx4200unit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = mx4200_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -274,8 +271,10 @@ mx4200_shutdown(
pp = peer->procptr;
up = (struct mx4200unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -576,9 +575,9 @@ mx4200_ref(
}
alt = up->avg_alt;
minute = (lat - (double)(int)lat) * 60.0;
- sprintf(lats,"%02d%02.4f", (int)lat, minute);
+ snprintf(lats, sizeof(lats), "%02d%02.4f", (int)lat, minute);
minute = (lon - (double)(int)lon) * 60.0;
- sprintf(lons,"%03d%02.4f", (int)lon, minute);
+ snprintf(lons, sizeof(lons), "%03d%02.4f", (int)lon, minute);
mx4200_send(peer, "%s,%03d,,,,,%s,%c,%s,%c,%.2f,%d", pmvxg,
PMVXG_S_INITMODEA,
@@ -961,18 +960,18 @@ mx4200_parse_t(
char time_mark_valid, time_sync, op_mode;
int sentence_type, valid;
int year, day_of_year, month, day_of_month;
- int hour, minute, second, leapsec;
+ int hour, minute, second, leapsec_warn;
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 (!) */
+ leapsec_warn = 0; /* Not all receivers output leap second warnings (!) */
sscanf(pp->a_lastcode,
"$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",
&sentence_type, &time_mark_valid, &year, &month, &day_of_month,
&hour, &minute, &second, &time_sync, &op_mode,
- &oscillator_offset, &time_mark_error, &time_bias, &leapsec);
+ &oscillator_offset, &time_mark_error, &time_bias, &leapsec_warn);
if (sentence_type != PMVXG_D_TRECOVOUT)
return ("wrong rec-type");
@@ -1005,8 +1004,8 @@ mx4200_parse_t(
mx4200_debug(peer,
"mx4200_parse_t: bad time %02d:%02d:%02d",
hour, minute, second);
- if (leapsec != 0)
- mx4200_debug(peer, " (leap %+d\n)", leapsec);
+ if (leapsec_warn != 0)
+ mx4200_debug(peer, " (leap %+d\n)", leapsec_warn);
mx4200_debug(peer, "\n");
refclock_report(peer, CEVNT_BADTIME);
return ("bad time");
@@ -1068,7 +1067,7 @@ mx4200_parse_t(
/*
* Setup leap second indicator
*/
- switch (leapsec) {
+ switch (leapsec_warn) {
case 0:
pp->leap = LEAP_NOWARNING;
break;
@@ -1085,12 +1084,12 @@ mx4200_parse_t(
/*
* Any change to the leap second warning status?
*/
- if (leapsec != up->last_leap ) {
+ if (leapsec_warn != up->last_leap ) {
msyslog(LOG_DEBUG,
"mx4200: leap second warning: %d to %d (%d)",
- up->last_leap, leapsec, pp->leap);
+ up->last_leap, leapsec_warn, pp->leap);
}
- up->last_leap = leapsec;
+ up->last_leap = leapsec_warn;
/*
* Copy time data for billboard monitoring.
@@ -1520,14 +1519,14 @@ mx4200_pps(
if (time_pps_fetch(up->pps_h, PPS_TSFMT_TSPEC, &(up->pps_i),
&timeout) < 0) {
mx4200_debug(peer,
- "mx4200_pps: time_pps_fetch: serial=%ul, %s\n",
+ "mx4200_pps: time_pps_fetch: serial=%lu, %s\n",
(unsigned long)up->pps_i.assert_sequence, strerror(errno));
refclock_report(peer, CEVNT_FAULT);
return(1);
}
if (temp_serial == up->pps_i.assert_sequence) {
mx4200_debug(peer,
- "mx4200_pps: assert_sequence serial not incrementing: %ul\n",
+ "mx4200_pps: assert_sequence serial not incrementing: %lu\n",
(unsigned long)up->pps_i.assert_sequence);
refclock_report(peer, CEVNT_FAULT);
return(1);
@@ -1540,7 +1539,7 @@ mx4200_pps(
if (up->pps_i.assert_sequence == up->lastserial) {
mx4200_debug(peer, "mx4200_pps: no new pps event\n");
} else {
- mx4200_debug(peer, "mx4200_pps: missed %ul pps events\n",
+ mx4200_debug(peer, "mx4200_pps: missed %lu pps events\n",
up->pps_i.assert_sequence - up->lastserial - 1UL);
}
refclock_report(peer, CEVNT_FAULT);
diff --git a/ntpd/refclock_neoclock4x.c b/ntpd/refclock_neoclock4x.c
index 374c81aeac74..c3d6033be28f 100644
--- a/ntpd/refclock_neoclock4x.c
+++ b/ntpd/refclock_neoclock4x.c
@@ -3,18 +3,11 @@
* Refclock_neoclock4x.c
* - NeoClock4X driver for DCF77 or FIA Timecode
*
- * Date: 2006-01-11 v1.15
+ * Date: 2009-12-04 v1.16
*
* see http://www.linum.com/redir/jump/id=neoclock4x&action=redir
* for details about the NeoClock4X device
*
- * Copyright (C) 2002-2004 by Linum Software GmbH <neoclock4x@linum.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
*/
#ifdef HAVE_CONFIG_H
@@ -109,7 +102,7 @@
#define NEOCLOCK4X_OFFSET_ANTENNA2 33
#define NEOCLOCK4X_OFFSET_CRC 35
-#define NEOCLOCK4X_DRIVER_VERSION "1.15 (2006-01-11)"
+#define NEOCLOCK4X_DRIVER_VERSION "1.16 (2009-12-04)"
#define NSEC_TO_MILLI 1000000
@@ -138,20 +131,20 @@ struct neoclock4x_unit {
int utc_msec;
};
-static int neoclock4x_start P((int, struct peer *));
-static void neoclock4x_shutdown P((int, struct peer *));
-static void neoclock4x_receive P((struct recvbuf *));
-static void neoclock4x_poll P((int, struct peer *));
-static void neoclock4x_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
-
-static int neol_atoi_len P((const char str[], int *, int));
-static int neol_hexatoi_len P((const char str[], int *, int));
-static void neol_jdn_to_ymd P((unsigned long, int *, int *, int *));
-static void neol_localtime P((unsigned long, int* , int*, int*, int*, int*, int*));
-static unsigned long neol_mktime P((int, int, int, int, int, int));
+static int neoclock4x_start (int, struct peer *);
+static void neoclock4x_shutdown (int, struct peer *);
+static void neoclock4x_receive (struct recvbuf *);
+static void neoclock4x_poll (int, struct peer *);
+static void neoclock4x_control (int, struct refclockstat *, struct refclockstat *, struct peer *);
+
+static int neol_atoi_len (const char str[], int *, int);
+static int neol_hexatoi_len (const char str[], int *, int);
+static void neol_jdn_to_ymd (unsigned long, int *, int *, int *);
+static void neol_localtime (unsigned long, int* , int*, int*, int*, int*, int*);
+static unsigned long neol_mktime (int, int, int, int, int, int);
#if !defined(NEOCLOCK4X_FIRMWARE)
-static int neol_query_firmware P((int, int, char *, int));
-static int neol_check_firmware P((int, const char*, char *));
+static int neol_query_firmware (int, int, char *, int);
+static int neol_check_firmware (int, const char*, char *);
#endif
struct refclock refclock_neoclock4x = {
@@ -1024,6 +1017,12 @@ neol_query_firmware(int fd,
{
NLOG(NLOG_CLOCKINFO)
msyslog(LOG_INFO, "NeoClock4X(%d): firmware version: %s", unit, firmware);
+
+ if(strstr(firmware, "/R2"))
+ {
+ msyslog(LOG_INFO, "NeoClock4X(%d): Your NeoClock4X uses the new R2 firmware release. Please note the changed LED behaviour.", unit);
+ }
+
}
return (flag);
@@ -1110,4 +1109,16 @@ int refclock_neoclock4x_bs;
* - remove some unsued #ifdefs
* - fix nsec calculation, closes #499
*
+ * 2009/12/04 cjh
+ * Revision 1.16
+ * - change license to ntp COPYRIGHT notice. This should allow Debian
+ * to add this refclock driver in further releases.
+ * - detect R2 hardware
+ *
*/
+
+
+
+
+
+
diff --git a/ntpd/refclock_nmea.c b/ntpd/refclock_nmea.c
index a176ee86c139..22ec19d9015f 100644
--- a/ntpd/refclock_nmea.c
+++ b/ntpd/refclock_nmea.c
@@ -2,13 +2,27 @@
* refclock_nmea.c - clock driver for an NMEA GPS CLOCK
* Michael Petry Jun 20, 1994
* based on refclock_heathn.c
+ *
+ * Updated to add support for Accord GPS Clock
+ * Venu Gopal Dec 05, 2007
+ * neo.venu@gmail.com, venugopal_d@pgad.gov.in
+ *
+ * Updated to process 'time1' fudge factor
+ * Venu Gopal May 05, 2008
+ *
+ * Converted to common PPSAPI code, separate PPS fudge time1
+ * from serial timecode fudge time2.
+ * Dave Hart July 1, 2009
+ * hart@ntp.org, davehart@davehart.com
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_NMEA)
+#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
@@ -17,24 +31,35 @@
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include "ntp_calendar.h"
#ifdef HAVE_PPSAPI
# include "ppsapi_timepps.h"
+# include "refclock_atom.h"
#endif /* HAVE_PPSAPI */
#ifdef SYS_WINNT
+#undef write /* ports/winnt/include/config.h: #define write _write */
extern int async_write(int, const void *, unsigned int);
-#undef write
#define write(fd, data, octets) async_write(fd, data, octets)
#endif
+#ifndef TIMESPECTOTS
+#define TIMESPECTOTS(ptspec, pts) \
+ do { \
+ DTOLFP((ptspec)->tv_nsec * 1.0e-9, pts); \
+ (pts)->l_ui += (u_int32)((ptspec)->tv_sec) + JAN_1970; \
+ } while (0)
+#endif
+
+
/*
- * This driver supports the NMEA GPS Receiver with
+ * This driver supports NMEA-compatible GPS receivers
*
- * Protype was refclock_trak.c, Thanks a lot.
+ * Prototype was refclock_trak.c, Thanks a lot.
*
* The receiver used spits out the NMEA sentences for boat navigation.
- * And you thought it was an information superhighway. Try a raging river
+ * 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.
@@ -52,80 +77,139 @@ extern int async_write(int, const void *, unsigned int);
* bit 0 - enables RMC (1)
* bit 1 - enables GGA (2)
* bit 2 - enables GLL (4)
- * multiple sentences may be selected
+ * bit 3 - enables ZDA (8) - Standard Time & Date
+ * bit 3 - enables ZDG (8) - Accord GPS Clock's custom sentence with GPS time
+ * very close to standard ZDA
+ *
+ * Multiple sentences may be selected except when ZDG/ZDA is selected.
+ *
+ * bit 4/5/6 - selects the baudrate for serial port :
+ * 0 for 4800 (default)
+ * 1 for 9600
+ * 2 for 19200
+ * 3 for 38400
+ * 4 for 57600
+ * 5 for 115200
*/
+#define NMEA_MESSAGE_MASK_OLD 0x07
+#define NMEA_MESSAGE_MASK_SINGLE 0x08
+#define NMEA_MESSAGE_MASK (NMEA_MESSAGE_MASK_OLD | NMEA_MESSAGE_MASK_SINGLE)
+
+#define NMEA_BAUDRATE_MASK 0x70
+#define NMEA_BAUDRATE_SHIFT 4
/*
* Definitions
*/
-#ifdef SYS_WINNT
-# define DEVICE "COM%d:" /* COM 1 - 3 supported */
-#else
-# define DEVICE "/dev/gps%d" /* name of radio device */
-#endif
+#define DEVICE "/dev/gps%d" /* GPS serial device */
+#define PPSDEV "/dev/gpspps%d" /* PPSAPI device override */
#define SPEED232 B4800 /* uart speed (4800 bps) */
#define PRECISION (-9) /* precision assumed (about 2 ms) */
#define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
#define REFID "GPS\0" /* reference id */
#define DESCRIPTION "NMEA GPS Clock" /* who we are */
-#define NANOSECOND 1000000000 /* one second (ns) */
-#define RANGEGATE 500000 /* range gate (ns) */
+#ifndef O_NOCTTY
+#define M_NOCTTY 0
+#else
+#define M_NOCTTY O_NOCTTY
+#endif
+#ifndef O_NONBLOCK
+#define M_NONBLOCK 0
+#else
+#define M_NONBLOCK O_NONBLOCK
+#endif
+#define PPSOPENMODE (O_RDWR | M_NOCTTY | M_NONBLOCK)
-#define LENNMEA 75 /* min timecode length */
+/* NMEA sentence array indexes for those we use */
+#define NMEA_GPRMC 0 /* recommended min. nav. */
+#define NMEA_GPGGA 1 /* fix and quality */
+#define NMEA_GPGLL 2 /* geo. lat/long */
+#define NMEA_GPZDA 3 /* date/time */
+/*
+ * $GPZDG is a proprietary sentence that violates the spec, by not
+ * using $P and an assigned company identifier to prefix the sentence
+ * identifier. When used with this driver, the system needs to be
+ * isolated from other NTP networks, as it operates in GPS time, not
+ * UTC as is much more common. GPS time is >15 seconds different from
+ * UTC due to not respecting leap seconds since 1970 or so. Other
+ * than the different timebase, $GPZDG is similar to $GPZDA.
+ */
+#define NMEA_GPZDG 4
+#define NMEA_ARRAY_SIZE (NMEA_GPZDG + 1)
/*
- * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
- * leap.
+ * Sentence selection mode bits
*/
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+#define USE_ALL 0 /* any/all */
+#define USE_GPRMC 1
+#define USE_GPGGA 2
+#define USE_GPGLL 4
+#define USE_GPZDA_ZDG 8 /* affects both */
+
+/* mapping from sentence index to controlling mode bit */
+u_char sentence_mode[NMEA_ARRAY_SIZE] =
+{
+ USE_GPRMC,
+ USE_GPGGA,
+ USE_GPGLL,
+ USE_GPZDA_ZDG,
+ USE_GPZDA_ZDG
+};
/*
* Unit control structure
*/
struct nmeaunit {
- int pollcnt; /* poll message counter */
- int polled; /* Hand in a sample? */
- l_fp tstamp; /* timestamp of last poll */
#ifdef HAVE_PPSAPI
- struct timespec ts; /* last timestamp */
- pps_params_t pps_params; /* pps parameters */
- pps_info_t pps_info; /* last pps data */
- pps_handle_t handle; /* pps handlebars */
+ struct refclock_atom atom; /* PPSAPI structure */
+ int ppsapi_tried; /* attempt PPSAPI once */
+ int ppsapi_lit; /* time_pps_create() worked */
+ int ppsapi_fd; /* fd used with PPSAPI */
+ int ppsapi_gate; /* allow edge detection processing */
+ int tcount; /* timecode sample counter */
+ int pcount; /* PPS sample counter */
#endif /* HAVE_PPSAPI */
+ l_fp tstamp; /* timestamp of last poll */
+ int gps_time; /* 0 UTC, 1 GPS time */
+ /* per sentence checksum seen flag */
+ struct calendar used; /* hh:mm:ss of used sentence */
+ u_char cksum_seen[NMEA_ARRAY_SIZE];
};
/*
* Function prototypes
*/
-static int nmea_start P((int, struct peer *));
-static void nmea_shutdown P((int, struct peer *));
+static int nmea_start (int, struct peer *);
+static void nmea_shutdown (int, struct peer *);
+static void nmea_receive (struct recvbuf *);
+static void nmea_poll (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 *));
+static void nmea_control (int, struct refclockstat *,
+ struct refclockstat *, struct peer *);
+static void nmea_timer (int, struct peer *);
+#define NMEA_CONTROL nmea_control
+#define NMEA_TIMER nmea_timer
+#else
+#define NMEA_CONTROL noentry
+#define NMEA_TIMER noentry
#endif /* HAVE_PPSAPI */
-static void nmea_receive P((struct recvbuf *));
-static void nmea_poll P((int, struct peer *));
-static void gps_send P((int, const char *, struct peer *));
-static char *field_parse P((char *, int));
+static void gps_send (int, const char *, struct peer *);
+static char * field_parse (char *, int);
+static int nmea_checksum_ok(const char *);
+static void nmea_day_unfold(struct calendar*);
+static void nmea_century_unfold(struct calendar*);
/*
* Transfer vector
*/
struct refclock refclock_nmea = {
nmea_start, /* start up driver */
- nmea_shutdown, /* shut down driver */
+ nmea_shutdown, /* shut down driver */
nmea_poll, /* transmit poll message */
-#ifdef HAVE_PPSAPI
- nmea_control, /* fudge control */
-#else
- noentry, /* fudge control */
-#endif /* HAVE_PPSAPI */
+ NMEA_CONTROL, /* fudge control */
noentry, /* initialize driver */
noentry, /* buginfo */
- NOFLAGS /* not used */
+ NMEA_TIMER /* called once per second */
};
/*
@@ -141,77 +225,124 @@ nmea_start(
struct refclockproc *pp;
int fd;
char device[20];
+ int baudrate;
+ char *baudtext;
+
+ pp = peer->procptr;
/*
* Open serial port. Use CLK line discipline, if available.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
+
+ /*
+ * Opening the serial port with appropriate baudrate
+ * based on the value of bit 4/5/6
+ */
+ switch ((peer->ttl & NMEA_BAUDRATE_MASK) >> NMEA_BAUDRATE_SHIFT) {
+ case 0:
+ case 6:
+ case 7:
+ default:
+ baudrate = SPEED232;
+ baudtext = "4800";
+ break;
+ case 1:
+ baudrate = B9600;
+ baudtext = "9600";
+ break;
+ case 2:
+ baudrate = B19200;
+ baudtext = "19200";
+ break;
+ case 3:
+ baudrate = B38400;
+ baudtext = "38400";
+ break;
+#ifdef B57600
+ case 4:
+ baudrate = B57600;
+ baudtext = "57600";
+ break;
+#endif
+#ifdef B115200
+ case 5:
+ baudrate = B115200;
+ baudtext = "115200";
+ break;
+#endif
+ }
- fd = refclock_open(device, SPEED232, LDISC_CLK);
+ fd = refclock_open(device, baudrate, LDISC_CLK);
+
if (fd <= 0) {
#ifdef HAVE_READLINK
- /* nmead support added by Jon Miner (cp_n18@yahoo.com)
- *
- * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
- * for information about nmead
- *
- * To use this, you need to create a link from /dev/gpsX to
- * the server:port where nmead is running. Something like this:
- *
- * ln -s server:port /dev/gps1
- */
- char buffer[80];
- char *nmea_host;
- int nmea_port;
- int len;
- struct hostent *he;
- struct protoent *p;
- struct sockaddr_in so_addr;
-
- if ((len = readlink(device,buffer,sizeof(buffer))) == -1)
- return(0);
- buffer[len] = 0;
-
- if ((nmea_host = strtok(buffer,":")) == NULL)
- return(0);
-
- nmea_port = atoi(strtok(NULL,":"));
-
- if ((he = gethostbyname(nmea_host)) == NULL)
- return(0);
- if ((p = getprotobyname("ip")) == NULL)
- return(0);
- so_addr.sin_family = AF_INET;
- so_addr.sin_port = htons(nmea_port);
- so_addr.sin_addr = *((struct in_addr *) he->h_addr);
-
- if ((fd = socket(PF_INET,SOCK_STREAM,p->p_proto)) == -1)
- return(0);
- if (connect(fd,(struct sockaddr *)&so_addr,SOCKLEN(&so_addr)) == -1) {
- close(fd);
- return (0);
- }
+ /* nmead support added by Jon Miner (cp_n18@yahoo.com)
+ *
+ * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
+ * for information about nmead
+ *
+ * To use this, you need to create a link from /dev/gpsX
+ * to the server:port where nmead is running. Something
+ * like this:
+ *
+ * ln -s server:port /dev/gps1
+ */
+ char buffer[80];
+ char *nmea_host, *nmea_tail;
+ int nmea_port;
+ int len;
+ struct hostent *he;
+ struct protoent *p;
+ struct sockaddr_in so_addr;
+
+ if ((len = readlink(device,buffer,sizeof(buffer))) == -1)
+ return(0);
+ buffer[len] = 0;
+
+ if ((nmea_host = strtok(buffer,":")) == NULL)
+ return(0);
+ if ((nmea_tail = strtok(NULL,":")) == NULL)
+ return(0);
+
+ nmea_port = atoi(nmea_tail);
+
+ if ((he = gethostbyname(nmea_host)) == NULL)
+ return(0);
+ if ((p = getprotobyname("tcp")) == NULL)
+ return(0);
+ memset(&so_addr, 0, sizeof(so_addr));
+ so_addr.sin_family = AF_INET;
+ so_addr.sin_port = htons(nmea_port);
+ so_addr.sin_addr = *((struct in_addr *) he->h_addr);
+
+ if ((fd = socket(PF_INET,SOCK_STREAM,p->p_proto)) == -1)
+ return(0);
+ if (connect(fd,(struct sockaddr *)&so_addr, sizeof(so_addr)) == -1) {
+ close(fd);
+ return (0);
+ }
#else
- return (0);
+ pp->io.fd = -1;
+ return (0);
#endif
- }
+ }
+
+ msyslog(LOG_NOTICE, "%s serial %s open at %s bps",
+ refnumtoa(&peer->srcadr), device, baudtext);
/*
* Allocate and initialize unit structure
*/
- up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));
- if (up == NULL) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct nmeaunit));
- pp = peer->procptr;
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp->io.clock_recv = nmea_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ pp->io.fd = -1;
+ close(fd);
free(up);
return (0);
}
@@ -222,29 +353,19 @@ nmea_start(
*/
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);
+ memcpy(&pp->refid, REFID, 4);
+
+ gps_send(fd,"$PMOTG,RMC,0000*1D\r\n", peer);
-#ifdef HAVE_PPSAPI
- /*
- * Start the PPSAPI interface if it is there. Default to use
- * the assert edge and do not enable the kernel hardpps.
- */
- if (time_pps_create(fd, &up->handle) < 0) {
- up->handle = 0;
- msyslog(LOG_ERR,
- "refclock_nmea: time_pps_create failed: %m");
- return (1);
- }
- return(nmea_ppsapi(peer, 0, 0));
-#else
return (1);
-#endif /* HAVE_PPSAPI */
}
+
/*
* nmea_shutdown - shut down a GPS clock
+ *
+ * NOTE this routine is called after nmea_start() returns failure,
+ * as well as during a normal shutdown due to ntpq :config unpeer.
*/
static void
nmea_shutdown(
@@ -255,150 +376,234 @@ nmea_shutdown(
register struct nmeaunit *up;
struct refclockproc *pp;
+ UNUSED_ARG(unit);
+
pp = peer->procptr;
up = (struct nmeaunit *)pp->unitptr;
+ if (up != NULL) {
#ifdef HAVE_PPSAPI
- if (up->handle != 0)
- time_pps_destroy(up->handle);
-#endif /* HAVE_PPSAPI */
- io_closeclock(&pp->io);
- free(up);
+ if (up->ppsapi_lit) {
+ time_pps_destroy(up->atom.handle);
+ if (up->ppsapi_fd != pp->io.fd)
+ close(up->ppsapi_fd);
+ }
+#endif
+ free(up);
+ }
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
}
-#ifdef HAVE_PPSAPI
/*
- * nmea_control - fudge control
+ * nmea_control - configure fudge params
*/
+#ifdef HAVE_PPSAPI
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 */
+ int unit,
+ struct refclockstat *in_st,
+ struct refclockstat *out_st,
+ struct peer *peer
)
{
+ char device[32];
+ register struct nmeaunit *up;
struct refclockproc *pp;
+ int pps_fd;
+
+ UNUSED_ARG(in_st);
+ UNUSED_ARG(out_st);
pp = peer->procptr;
- nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
- pp->sloppyclockflag & CLK_FLAG3);
+ up = (struct nmeaunit *)pp->unitptr;
+
+ if (!(CLK_FLAG1 & pp->sloppyclockflag)) {
+ if (!up->ppsapi_tried)
+ return;
+ up->ppsapi_tried = 0;
+ if (!up->ppsapi_lit)
+ return;
+ peer->flags &= ~FLAG_PPS;
+ peer->precision = PRECISION;
+ time_pps_destroy(up->atom.handle);
+ if (up->ppsapi_fd != pp->io.fd)
+ close(up->ppsapi_fd);
+ up->atom.handle = 0;
+ up->ppsapi_lit = 0;
+ up->ppsapi_fd = -1;
+ return;
+ }
+
+ if (up->ppsapi_tried)
+ return;
+ /*
+ * Light up the PPSAPI interface.
+ */
+ up->ppsapi_tried = 1;
+
+ /*
+ * if /dev/gpspps$UNIT can be opened that will be used for
+ * PPSAPI. Otherwise, the GPS serial device /dev/gps$UNIT
+ * already opened is used for PPSAPI as well.
+ */
+ snprintf(device, sizeof(device), PPSDEV, unit);
+
+ pps_fd = open(device, PPSOPENMODE, S_IRUSR | S_IWUSR);
+
+ if (-1 == pps_fd)
+ pps_fd = pp->io.fd;
+
+ if (refclock_ppsapi(pps_fd, &up->atom)) {
+ up->ppsapi_lit = 1;
+ up->ppsapi_fd = pps_fd;
+ /* prepare to use the PPS API for our own purposes now. */
+ refclock_params(pp->sloppyclockflag, &up->atom);
+ return;
+ }
+
+ NLOG(NLOG_CLOCKINFO)
+ msyslog(LOG_WARNING, "%s flag1 1 but PPSAPI fails",
+ refnumtoa(&peer->srcadr));
}
+#endif /* HAVE_PPSAPI */
/*
- * Initialize PPSAPI
+ * nmea_timer - called once per second, fetches PPS
+ * timestamp and stuffs in median filter.
*/
-int
-nmea_ppsapi(
- struct peer *peer, /* peer structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
+#ifdef HAVE_PPSAPI
+static void
+nmea_timer(
+ int unit,
+ struct peer * peer
)
{
- struct refclockproc *pp;
struct nmeaunit *up;
- int capability;
+ struct refclockproc *pp;
+
+ UNUSED_ARG(unit);
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);
+ if (up->ppsapi_lit && up->ppsapi_gate &&
+ refclock_pps(peer, &up->atom, pp->sloppyclockflag) > 0) {
+ up->pcount++,
+ peer->flags |= FLAG_PPS;
+ peer->precision = PPS_PRECISION;
+ }
}
+#endif /* HAVE_PPSAPI */
+#ifdef HAVE_PPSAPI
/*
- * Get PPSAPI timestamps.
+ * This function is used to correlate a receive time stamp and a
+ * reference time with a PPS edge time stamp. It applies the necessary
+ * fudges (fudge1 for PPS, fudge2 for receive time) and then tries to
+ * move the receive time stamp to the corresponding edge. This can
+ * warp into future, if a transmission delay of more than 500ms is not
+ * compensated with a corresponding fudge time2 value, because then
+ * the next PPS edge is nearer than the last. (Similiar to what the
+ * PPS ATOM driver does, but we deal with full time stamps here, not
+ * just phase shift information.) Likewise, a negative fudge time2
+ * value must be used if the reference time stamp correlates with the
+ * *following* PPS pulse.
*
- * Return 0 on failure and 1 on success.
+ * Note that the receive time fudge value only needs to move the receive
+ * stamp near a PPS edge but that close proximity is not required;
+ * +/-100ms precision should be enough. But since the fudge value will
+ * probably also be used to compensate the transmission delay when no PPS
+ * edge can be related to the time stamp, it's best to get it as close
+ * as possible.
+ *
+ * It should also be noted that the typical use case is matching to
+ * the preceeding edge, as most units relate their sentences to the
+ * current second.
+ *
+ * The function returns PPS_RELATE_NONE (0) if no PPS edge correlation
+ * can be fixed; PPS_RELATE_EDGE (1) when a PPS edge could be fixed, but
+ * the distance to the reference time stamp is too big (exceeds +/-400ms)
+ * and the ATOM driver PLL cannot be used to fix the phase; and
+ * PPS_RELATE_PHASE (2) when the ATOM driver PLL code can be used.
+ *
+ * On output, the receive time stamp is replaced with the
+ * corresponding PPS edge time if a fix could be made; the PPS fudge
+ * is updated to reflect the proper fudge time to apply. (This implies
+ * that 'refclock_process_f()' must be used!)
*/
+#define PPS_RELATE_NONE 0 /* no pps correlation possible */
+#define PPS_RELATE_EDGE 1 /* recv time fixed, no phase lock */
+#define PPS_RELATE_PHASE 2 /* recv time fixed, phase lock ok */
+
static int
-nmea_pps(
- struct nmeaunit *up,
- l_fp *tsptr
- )
+refclock_ppsrelate(
+ const struct refclockproc *pp , /* for sanity */
+ const struct refclock_atom *ap , /* for PPS io */
+ const l_fp *reftime ,
+ l_fp *rd_stamp, /* i/o read stamp */
+ double pp_fudge, /* pps fudge */
+ double *rd_fudge) /* i/o read fudge */
{
- 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);
+ pps_info_t pps_info;
+ struct timespec timeout;
+ l_fp pp_stamp, pp_delta;
+ double delta, idelta;
+
+ if (pp->leap == LEAP_NOTINSYNC)
+ return PPS_RELATE_NONE; /* clock is insane, no chance */
+
+ memset(&timeout, 0, sizeof(timeout));
+ memset(&pps_info, 0, sizeof(pps_info_t));
+
+ if (time_pps_fetch(ap->handle, PPS_TSFMT_TSPEC,
+ &pps_info, &timeout) < 0)
+ return PPS_RELATE_NONE;
+
+ /* get last active PPS edge before receive */
+ if (ap->pps_params.mode & PPS_CAPTUREASSERT)
+ timeout = pps_info.assert_timestamp;
+ else if (ap->pps_params.mode & PPS_CAPTURECLEAR)
+ timeout = pps_info.clear_timestamp;
+ else
+ return PPS_RELATE_NONE;
+
+ /* get delta between receive time and PPS time */
+ TIMESPECTOTS(&timeout, &pp_stamp);
+ pp_delta = *rd_stamp;
+ L_SUB(&pp_delta, &pp_stamp);
+ LFPTOD(&pp_delta, delta);
+ delta += pp_fudge - *rd_fudge;
+ if (fabs(delta) > 1.5)
+ return PPS_RELATE_NONE; /* PPS timeout control */
+
+ /* eventually warp edges, check phase */
+ idelta = floor(delta + 0.5);
+ pp_fudge -= idelta;
+ delta -= idelta;
+ if (fabs(delta) > 0.45)
+ return PPS_RELATE_NONE; /* dead band control */
+
+ /* we actually have a PPS edge to relate with! */
+ *rd_stamp = pp_stamp;
+ *rd_fudge = pp_fudge;
+
+ /* if whole system out-of-sync, do not try to PLL */
+ if (sys_leap == LEAP_NOTINSYNC)
+ return PPS_RELATE_EDGE; /* cannot PLL with atom code */
+
+ /* check against reftime if ATOM PLL can be used */
+ pp_delta = *reftime;
+ L_SUB(&pp_delta, &pp_stamp);
+ LFPTOD(&pp_delta, delta);
+ delta += pp_fudge;
+ if (fabs(delta) > 0.45)
+ return PPS_RELATE_EDGE; /* cannot PLL with atom code */
+
+ /* all checks passed, gets an AAA rating here! */
+ return PPS_RELATE_PHASE; /* can PLL with atom code */
}
-#endif /* HAVE_PPSAPI */
+#endif /* HAVE_PPSAPI */
/*
* nmea_receive - receive data from the serial interface
@@ -411,171 +616,223 @@ nmea_receive(
register struct nmeaunit *up;
struct refclockproc *pp;
struct peer *peer;
- int month, day;
- int i;
- char *cp, *dp;
- int cmdtype;
- /* Use these variables to hold data until we decide its worth keeping */
+ char *cp, *dp, *msg;
+ u_char sentence;
+ /* Use these variables to hold data until we decide its worth
+ * keeping */
char rd_lastcode[BMAX];
- l_fp rd_tmp;
- u_short rd_lencode;
+ l_fp rd_timestamp, reftime;
+ int rd_lencode;
+ double rd_fudge;
+ struct calendar date;
/*
* Initialize pointers and read the timecode and timestamp
*/
- peer = (struct peer *)rbufp->recv_srcclock;
+ peer = rbufp->recv_peer;
pp = peer->procptr;
up = (struct nmeaunit *)pp->unitptr;
- rd_lencode = (u_short)refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
+
+ rd_lencode = refclock_gtlin(
+ rbufp,
+ rd_lastcode,
+ sizeof(rd_lastcode),
+ &rd_timestamp);
/*
- * There is a case that a <CR><LF> gives back a "blank" line
+ * There is a case that a <CR><LF> gives back a "blank" line.
+ * We can't have a well-formed sentence with less than 8 chars.
*/
- if (rd_lencode == 0)
- return;
+ if (0 == rd_lencode)
+ return;
-#ifdef DEBUG
- if (debug)
- printf("nmea: gpsread %d %s\n", rd_lencode,
- rd_lastcode);
-#endif
+ if (rd_lencode < 8) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ DPRINTF(1, ("nmea: gpsread %d %s\n", rd_lencode, rd_lastcode));
/*
* We check the timecode format and decode its contents. The
* we only care about a few of them. The most important being
* the $GPRMC format
* $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
- * For Magellan (ColorTrak) GLL probably datum (order of sentences)
- * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL
+ * mode (0,1,2,3) selects sentence ANY/ALL, RMC, GGA, GLL, ZDA
* $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,...
+ * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
* $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
- * $GPAPB,...
- * $GPGSA,...
- * $GPGSV,...
- * $GPGSV,...
+ *
+ * Defining GPZDA to support Standard Time & Date
+ * sentence. The sentence has the following format
+ *
+ * $--ZDA,HHMMSS.SS,DD,MM,YYYY,TH,TM,*CS<CR><LF>
+ *
+ * Apart from the familiar fields,
+ * 'TH' Time zone Hours
+ * 'TM' Time zone Minutes
+ *
+ * Defining GPZDG to support Accord GPS Clock's custom NMEA
+ * sentence. The sentence has the following format
+ *
+ * $GPZDG,HHMMSS.S,DD,MM,YYYY,AA.BB,V*CS<CR><LF>
+ *
+ * It contains the GPS timestamp valid for next PPS pulse.
+ * Apart from the familiar fields,
+ * 'AA.BB' denotes the signal strength( should be < 05.00 )
+ * 'V' denotes the GPS sync status :
+ * '0' indicates INVALID time,
+ * '1' indicates accuracy of +/-20 ms
+ * '2' indicates accuracy of +/-100 ns
*/
-#define GPXXX 0
-#define GPRMC 1
-#define GPGGA 2
-#define GPGLL 4
- cp = rd_lastcode;
- cmdtype=0;
- if(strncmp(cp,"$GPRMC",6)==0) {
- cmdtype=GPRMC;
- }
- else if(strncmp(cp,"$GPGGA",6)==0) {
- cmdtype=GPGGA;
- }
- else if(strncmp(cp,"$GPGLL",6)==0) {
- cmdtype=GPGLL;
- }
- else if(strncmp(cp,"$GPXXX",6)==0) {
- cmdtype=GPXXX;
- }
- else
- return;
+ cp = rd_lastcode;
+ if (cp[0] == '$') {
+ /* Allow for GLGGA and GPGGA etc. */
+ msg = cp + 3;
+
+ if (strncmp(msg, "RMC", 3) == 0)
+ sentence = NMEA_GPRMC;
+ else if (strncmp(msg, "GGA", 3) == 0)
+ sentence = NMEA_GPGGA;
+ else if (strncmp(msg, "GLL", 3) == 0)
+ sentence = NMEA_GPGLL;
+ else if (strncmp(msg, "ZDG", 3) == 0)
+ sentence = NMEA_GPZDG;
+ else if (strncmp(msg, "ZDA", 3) == 0)
+ sentence = NMEA_GPZDA;
+ else
+ return;
+ } else
+ return;
/* See if I want to process this message type */
- if ( ((peer->ttl == 0) && (cmdtype != GPRMC))
- || ((peer->ttl != 0) && !(cmdtype & peer->ttl)) )
+ if ((peer->ttl & NMEA_MESSAGE_MASK) &&
+ !(peer->ttl & sentence_mode[sentence]))
return;
- pp->lencode = rd_lencode;
- strcpy(pp->a_lastcode,rd_lastcode);
- cp = pp->a_lastcode;
-
- pp->lastrec = up->tstamp = rd_tmp;
- up->pollcnt = 2;
+ /*
+ * $GPZDG provides GPS time not UTC, and the two mix poorly.
+ * Once have processed a $GPZDG, do not process any further
+ * UTC sentences (all but $GPZDG currently).
+ */
+ if (up->gps_time && NMEA_GPZDG != sentence)
+ return;
-#ifdef DEBUG
- if (debug)
- printf("nmea: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
+ /*
+ * Apparently, older NMEA specifications (which are expensive)
+ * did not require the checksum for all sentences. $GPMRC is
+ * the only one so far identified which has always been required
+ * to include a checksum.
+ *
+ * Today, most NMEA GPS receivers checksum every sentence. To
+ * preserve its error-detection capabilities with modern GPSes
+ * while allowing operation without checksums on all but $GPMRC,
+ * we keep track of whether we've ever seen a checksum on a
+ * given sentence, and if so, reject future checksum failures.
+ */
+ if (nmea_checksum_ok(rd_lastcode)) {
+ up->cksum_seen[sentence] = TRUE;
+ } else if (NMEA_GPRMC == sentence || up->cksum_seen[sentence]) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+ cp = rd_lastcode;
/* Grab field depending on clock string type */
- switch( cmdtype ) {
- case GPRMC:
+ memset(&date, 0, sizeof(date));
+ switch (sentence) {
+
+ case NMEA_GPRMC:
/*
* Test for synchronization. Check for quality byte.
*/
- dp = field_parse(cp,2);
- if( dp[0] != 'A')
+ 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);
+ dp = field_parse(cp, 1);
break;
-
- case GPGGA:
+ case NMEA_GPGGA:
/*
* Test for synchronization. Check for quality byte.
*/
- dp = field_parse(cp,6);
- if( dp[0] == '0')
+ 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);
+ dp = field_parse(cp, 1);
break;
-
- case GPGLL:
+ case NMEA_GPGLL:
/*
* Test for synchronization. Check for quality byte.
*/
- dp = field_parse(cp,6);
- if( dp[0] != 'A')
+ 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);
+ dp = field_parse(cp, 5);
break;
+
+ case NMEA_GPZDG:
+ /* For $GPZDG check for validity of GPS time. */
+ dp = field_parse(cp, 6);
+ if (dp[0] == '0')
+ pp->leap = LEAP_NOTINSYNC;
+ else
+ pp->leap = LEAP_NOWARNING;
+ /* fall through to NMEA_GPZDA */
+ case NMEA_GPZDA:
+ if (NMEA_GPZDA == sentence)
+ pp->leap = LEAP_NOWARNING;
- case GPXXX:
- return;
- default:
- return;
+ /* Now point at the time field */
+ dp = field_parse(cp, 1);
+ break;
+ default:
+ return;
}
- /*
- * Check time code format of NMEA
- */
-
- if( !isdigit((int)dp[0]) ||
- !isdigit((int)dp[1]) ||
- !isdigit((int)dp[2]) ||
- !isdigit((int)dp[3]) ||
- !isdigit((int)dp[4]) ||
- !isdigit((int)dp[5])
- ) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
+ /*
+ * Check time code format of NMEA
+ */
+ if (!isdigit((int)dp[0]) ||
+ !isdigit((int)dp[1]) ||
+ !isdigit((int)dp[2]) ||
+ !isdigit((int)dp[3]) ||
+ !isdigit((int)dp[4]) ||
+ !isdigit((int)dp[5])) {
+
+ DPRINTF(1, ("NMEA time code %c%c%c%c%c%c non-numeric",
+ dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]));
+ refclock_report(peer, CEVNT_BADTIME);
+ 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
- */
+ date.hour = ((dp[0] - '0') * 10) + dp[1] - '0';
+ date.minute = ((dp[2] - '0') * 10) + dp[3] - '0';
+ date.second = ((dp[4] - '0') * 10) + dp[5] - '0';
+ /*
+ * Default to 0 milliseconds, if decimal convert milliseconds in
+ * one, two or three digits
+ */
pp->nsec = 0;
if (dp[6] == '.') {
if (isdigit((int)dp[7])) {
@@ -589,103 +846,190 @@ nmea_receive(
}
}
- if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
- || pp->nsec > 1000000000) {
+ if (date.hour > 23 || date.minute > 59 ||
+ date.second > 59 || pp->nsec > 1000000000) {
+
+ DPRINTF(1, ("NMEA hour/min/sec/nsec range %02d:%02d:%02d.%09ld\n",
+ pp->hour, pp->minute, pp->second, pp->nsec));
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ /*
+ * Used only the first recognized sentence each second.
+ */
+ if (date.hour == up->used.hour &&
+ date.minute == up->used.minute &&
+ date.second == up->used.second)
+ return;
+
+ pp->lencode = (u_short)rd_lencode;
+ memcpy(pp->a_lastcode, rd_lastcode, pp->lencode + 1);
+ up->tstamp = rd_timestamp;
+ pp->lastrec = up->tstamp;
+ DPRINTF(1, ("nmea: timecode %d %s\n", pp->lencode, pp->a_lastcode));
/*
* Convert date and check values.
*/
- if (cmdtype==GPRMC) {
- dp = field_parse(cp,9);
- day = dp[0] - '0';
- day = (day * 10) + dp[1] - '0';
- month = dp[2] - '0';
- month = (month * 10) + dp[3] - '0';
- pp->year = dp[4] - '0';
- pp->year = (pp->year * 10) + dp[5] - '0';
- }
- else {
- /* only time */
- time_t tt = time(NULL);
- struct tm * t = gmtime(&tt);
- day = t->tm_mday;
- month = t->tm_mon + 1;
- pp->year= t->tm_year;
- }
-
- if (month < 1 || month > 12 || day < 1) {
- refclock_report(peer, CEVNT_BADTIME);
+ if (NMEA_GPRMC == sentence) {
+
+ dp = field_parse(cp,9);
+ date.monthday = 10 * (dp[0] - '0') + (dp[1] - '0');
+ date.month = 10 * (dp[2] - '0') + (dp[3] - '0');
+ date.year = 10 * (dp[4] - '0') + (dp[5] - '0');
+ nmea_century_unfold(&date);
+
+ } else if (NMEA_GPZDA == sentence || NMEA_GPZDG == sentence) {
+
+ dp = field_parse(cp, 2);
+ date.monthday = 10 * (dp[0] - '0') + (dp[1] - '0');
+ dp = field_parse(cp, 3);
+ date.month = 10 * (dp[0] - '0') + (dp[1] - '0');
+ dp = field_parse(cp, 4);
+ date.year = 1000 * (dp[0] - '0') + 100 * (dp[1] - '0')
+ + 10 * (dp[2] - '0') + (dp[3] - '0');
+
+ } else
+ nmea_day_unfold(&date);
+
+ if (date.month < 1 || date.month > 12 ||
+ date.monthday < 1 || date.monthday > 31) {
+ refclock_report(peer, CEVNT_BADDATE);
return;
}
- /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
- /* good thing that 2000 is a leap year */
- /* pp->year will be 00-99 if read from GPS, 00-> (years since 1900) from tm_year */
- if (pp->year % 4) {
- if (day > day1tab[month - 1]) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
+ up->used.hour = date.hour;
+ up->used.minute = date.minute;
+ up->used.second = date.second;
+
+ /*
+ * If "fudge 127.127.20.__ flag4 1" is configured in ntp.conf,
+ * remove the location and checksum from the NMEA sentence
+ * recorded as the last timecode and visible to remote users
+ * with:
+ *
+ * ntpq -c clockvar <server>
+ *
+ * Note that this also removes the location from the clockstats
+ * log (if it is enabled). Some NTP operators monitor their
+ * NMEA GPS using the change in location in clockstats over
+ * time as as a proxy for the quality of GPS reception and
+ * thereby time reported.
+ */
+ if (CLK_FLAG4 & pp->sloppyclockflag) {
+ /*
+ * Start by pointing cp and dp at the fields with
+ * longitude and latitude in the last timecode.
+ */
+ switch (sentence) {
+
+ case NMEA_GPGLL:
+ cp = field_parse(pp->a_lastcode, 1);
+ dp = field_parse(cp, 2);
+ break;
+
+ case NMEA_GPGGA:
+ cp = field_parse(pp->a_lastcode, 2);
+ dp = field_parse(cp, 2);
+ break;
+
+ case NMEA_GPRMC:
+ cp = field_parse(pp->a_lastcode, 3);
+ dp = field_parse(cp, 2);
+ break;
+
+ case NMEA_GPZDA:
+ case NMEA_GPZDG:
+ default:
+ cp = dp = NULL;
}
- for (i = 0; i < month - 1; i++)
- day += day1tab[i];
- } else {
- if (day > day2tab[month - 1]) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
+
+ /* Blank the entire latitude & longitude. */
+ while (cp) {
+ while (',' != *cp) {
+ if ('.' != *cp)
+ *cp = '_';
+ cp++;
+ }
+
+ /* Longitude at cp then latitude at dp */
+ if (cp < dp)
+ cp = dp;
+ else
+ cp = NULL;
}
- for (i = 0; i < month - 1; i++)
- day += day2tab[i];
- }
- pp->day = day;
+ /* Blank the checksum, the last two characters */
+ if (dp) {
+ cp = pp->a_lastcode + pp->lencode - 2;
+ if (0 == cp[2])
+ cp[0] = cp[1] = '_';
+ }
-#ifdef HAVE_PPSAPI
- /*
- * If the PPSAPI is working, rather use its timestamps.
- * assume that the PPS occurs on the second so blow any msec
- */
- if (nmea_pps(up, &rd_tmp) == 1) {
- pp->lastrec = up->tstamp = rd_tmp;
- pp->nsec = 0;
}
-#endif /* HAVE_PPSAPI */
/*
- * Process the new sample in the median filter and determine the
- * reference clock offset and dispersion. We use lastrec as both
- * the reference time and receive time, in order to avoid being
- * cute, like setting the reference time later than the receive
- * time, which may cause a paranoid protocol module to chuck out
- * the data.
+ * Get the reference time stamp from the calendar buffer.
+ * Process the new sample in the median filter and determine
+ * the timecode timestamp, but only if the PPS is not in
+ * control.
*/
+ rd_fudge = pp->fudgetime2;
+ date.yearday = 0; /* make sure it's not used */
+ DTOLFP(pp->nsec * 1.0e-9, &reftime);
+ reftime.l_ui += caltontp(&date);
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
+ /* $GPZDG postprocessing first... */
+ if (NMEA_GPZDG == sentence) {
+ /*
+ * Note if we're only using GPS timescale from now on.
+ */
+ if (!up->gps_time) {
+ up->gps_time = 1;
+ NLOG(NLOG_CLOCKINFO)
+ msyslog(LOG_INFO, "%s using only $GPZDG",
+ refnumtoa(&peer->srcadr));
+ }
+ /*
+ * $GPZDG indicates the second after the *next* PPS
+ * pulse. So we remove 1 second from the reference
+ * time now.
+ */
+ reftime.l_ui--;
}
-
-
+#ifdef HAVE_PPSAPI
+ up->tcount++;
/*
- * Only go on if we had been polled.
+ * If we have PPS running, we try to associate the sentence with
+ * the last active edge of the PPS signal.
*/
- if (!up->polled)
- return;
- up->polled = 0;
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-
- /* If we get here - what we got from the clock is OK, so say so */
- refclock_report(peer, CEVNT_NOMINAL);
+ if (up->ppsapi_lit)
+ switch (refclock_ppsrelate(pp, &up->atom, &reftime,
+ &rd_timestamp, pp->fudgetime1,
+ &rd_fudge))
+ {
+ case PPS_RELATE_EDGE:
+ up->ppsapi_gate = 0;
+ break;
+ case PPS_RELATE_PHASE:
+ up->ppsapi_gate = 1;
+ break;
+ default:
+ break;
+ }
+ else
+ up->ppsapi_gate = 0;
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ if (up->ppsapi_gate && (peer->flags & FLAG_PPS))
+ return;
+#endif /* HAVE_PPSAPI */
+ refclock_process_offset(pp, reftime, rd_timestamp, rd_fudge);
}
+
/*
* nmea_poll - called by the transmit procedure
*
@@ -703,23 +1047,47 @@ nmea_poll(
pp = peer->procptr;
up = (struct nmeaunit *)pp->unitptr;
- if (up->pollcnt == 0)
- refclock_report(peer, CEVNT_TIMEOUT);
- else
- up->pollcnt--;
+
+ /*
+ * Process median filter samples. If none received, declare a
+ * timeout and keep going.
+ */
+#ifdef HAVE_PPSAPI
+ if (up->pcount == 0) {
+ peer->flags &= ~FLAG_PPS;
+ peer->precision = PRECISION;
+ }
+ if (up->tcount == 0) {
+ pp->coderecv = pp->codeproc;
+ refclock_report(peer, CEVNT_TIMEOUT);
+ return;
+ }
+ up->pcount = up->tcount = 0;
+#else /* HAVE_PPSAPI */
+ if (pp->coderecv == pp->codeproc) {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ return;
+ }
+#endif /* HAVE_PPSAPI */
+
pp->polls++;
- up->polled = 1;
+ pp->lastref = pp->lastrec;
+ refclock_receive(peer);
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
/*
- * usually nmea_receive can get a timestamp every second
+ * usually nmea_receive can get a timestamp every second,
+ * but at least one Motorola unit needs prompting each
+ * time.
*/
gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
}
+
/*
*
- * gps_send(fd,cmd, peer) Sends a command to the GPS receiver.
+ * gps_send(fd,cmd, peer) Sends a command to the GPS receiver.
* as gps_send(fd,"rqts,u\r", peer);
*
* We don't currently send any data, but would like to send
@@ -735,12 +1103,12 @@ gps_send(
struct peer *peer
)
{
-
if (write(fd, cmd, strlen(cmd)) == -1) {
refclock_report(peer, CEVNT_FAULT);
}
}
+
static char *
field_parse(
char *cp,
@@ -750,14 +1118,159 @@ field_parse(
char *tp;
int i = fn;
- for (tp = cp; *tp != '\0'; tp++) {
+ for (tp = cp; i && *tp; tp++)
if (*tp == ',')
- i--;
- if (i == 0)
- break;
+ i--;
+
+ return tp;
+}
+
+
+/*
+ * nmea_checksum_ok verifies 8-bit XOR checksum is correct then returns 1
+ *
+ * format is $XXXXX,1,2,3,4*ML
+ *
+ * 8-bit XOR of characters between $ and * noninclusive is transmitted
+ * in last two chars M and L holding most and least significant nibbles
+ * in hex representation such as:
+ *
+ * $GPGLL,5057.970,N,00146.110,E,142451,A*27
+ * $GPVTG,089.0,T,,,15.2,N,,*7F
+ */
+int
+nmea_checksum_ok(
+ const char *sentence
+ )
+{
+ u_char my_cs;
+ u_long input_cs;
+ const char *p;
+
+ my_cs = 0;
+ p = sentence;
+
+ if ('$' != *p++)
+ return 0;
+
+ for ( ; *p && '*' != *p; p++) {
+
+ my_cs ^= *p;
}
- return (++tp);
+
+ if ('*' != *p++)
+ return 0;
+
+ if (0 == p[0] || 0 == p[1] || 0 != p[2])
+ return 0;
+
+ if (0 == hextoint(p, &input_cs))
+ return 0;
+
+ if (my_cs != input_cs)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * -------------------------------------------------------------------
+ * funny calendar-oriented stuff -- a bit hard to grok.
+ * -------------------------------------------------------------------
+ */
+/*
+ * Do a periodic unfolding of a truncated value around a given pivot
+ * value.
+ * The result r will hold to pivot <= r < pivot+period (period>0) or
+ * pivot+period < r <= pivot (period < 0) and value % period == r % period,
+ * using floor division convention.
+ */
+static time_t
+nmea_periodic_unfold(
+ time_t pivot,
+ time_t value,
+ time_t period)
+{
+ /*
+ * This will only work as long as 'value - pivot%period' does
+ * not create a signed overflow condition.
+ */
+ value = (value - (pivot % period)) % period;
+ if (value && (value ^ period) < 0)
+ value += period;
+ return pivot + value;
}
+
+/*
+ * Unfold a time-of-day (seconds since midnight) around the current
+ * system time in a manner that guarantees an absolute difference of
+ * less than 12hrs.
+ *
+ * This function is used for NMEA sentences that contain no date
+ * information. This requires the system clock to be in +/-12hrs
+ * around the true time, or the clock will synchronize the system 1day
+ * off if not augmented with a time sources that also provide the
+ * necessary date information.
+ *
+ * The function updates the refclockproc structure is also uses as
+ * input to fetch the time from.
+ */
+static void
+nmea_day_unfold(
+ struct calendar *jd)
+{
+ time_t value, pivot;
+ struct tm *tdate;
+
+ value = ((time_t)jd->hour * MINSPERHR
+ + (time_t)jd->minute) * SECSPERMIN
+ + (time_t)jd->second;
+ pivot = time(NULL) - SECSPERDAY/2;
+
+ value = nmea_periodic_unfold(pivot, value, SECSPERDAY);
+ tdate = gmtime(&value);
+ if (tdate) {
+ jd->year = tdate->tm_year + 1900;
+ jd->yearday = tdate->tm_yday + 1;
+ jd->month = tdate->tm_mon + 1;
+ jd->monthday = tdate->tm_mday;
+ jd->hour = tdate->tm_hour;
+ jd->minute = tdate->tm_min;
+ jd->second = tdate->tm_sec;
+ } else {
+ jd->year = 0;
+ jd->yearday = 0;
+ jd->month = 0;
+ jd->monthday = 0;
+ }
+}
+
+/*
+ * Unfold a 2-digit year into full year spec around the current year
+ * of the system time. This requires the system clock to be in -79/+19
+ * years around the true time, or the result will be off by
+ * 100years. The assymetric behaviour was chosen to enable inital sync
+ * for systems that do not have a battery-backup-clock and start with
+ * a date that is typically years in the past.
+ *
+ * The function updates the calendar structure that is also used as
+ * input to fetch the year from.
+ */
+static void
+nmea_century_unfold(
+ struct calendar *jd)
+{
+ time_t pivot_time;
+ struct tm *pivot_date;
+ time_t pivot_year;
+
+ /* get warp limit and century start of pivot from system time */
+ pivot_time = time(NULL);
+ pivot_date = gmtime(&pivot_time);
+ pivot_year = pivot_date->tm_year + 1900 - 20;
+ jd->year = nmea_periodic_unfold(pivot_year, jd->year, 100);
+}
+
#else
int refclock_nmea_bs;
-#endif /* REFCLOCK */
+#endif /* REFCLOCK && CLOCK_NMEA */
diff --git a/ntpd/refclock_oncore.c b/ntpd/refclock_oncore.c
index e1d23a991845..bce8db882bdc 100644
--- a/ntpd/refclock_oncore.c
+++ b/ntpd/refclock_oncore.c
@@ -52,6 +52,48 @@
* MANUFACTUR DATE 2J17 MANUFACTUR DATE 3G15
*
* --------------------------------------------------------------------------
+ * Reg Clemens (June 2009)
+ * BUG[1220] OK, big patch, but mostly done mechanically. Change direct calls to write
+ * to clockstats to a call to oncore_log, which now calls the old routine plus msyslog.
+ * Have to set the LOG_LEVELS of the calls for msyslog, and this was done by hand. New
+ * routine oncore_log.
+ * --------------------------------------------------------------------------
+ * Reg Clemens (June 2009)
+ * BUG[1218] The comment on where the oncore driver gets its input file does not
+ * agree with the code. Change the comment.
+ * --------------------------------------------------------------------------
+ * Reg Clemens (June 2009)
+ * change exit statements to return(0) in main program. I had assumed that if the
+ * PPS driver did not start for some reason, we shuould stop NTPD itelf. Others
+ * disagree. We now give an ERR log message and stop this driver.
+ * --------------------------------------------------------------------------
+ * Reg Clemens (June 2009)
+ * A bytes available message for the input subsystem (Debug message).
+ * --------------------------------------------------------------------------
+ * Reg Clemens (Nov 2008)
+ * This code adds a message for TRAIM messages. Users often worry about the
+ * driver not starting up, and it is often because of signal strength being low.
+ * Low signal strength will give TRAIM messages.
+ * --------------------------------------------------------------------------
+ * Reg Clemens (Nov 2008)
+ * Add waiting on Almanac Message.
+ * --------------------------------------------------------------------------
+ * Reg Clemens (Nov 2008)
+ * Add back in @@Bl code to do the @@Bj/@@Gj that is in later ONCOREs
+ * LEAP SECONDS: All of the ONCORE receivers, VP -> M12T have the @@Bj command
+ * that says 'Leap Pending'. As documented it only becomes true in the month
+ * before the leap second is to be applied, but in practice at least some of
+ * the receivers turn this indicator on as soon as the message is posted, which
+ * can be 6months early. As such, we use the Bj command to turn on the
+ * instance->pp->leap indicator but only run this test in December and June for
+ * updates on 1Jan and 1July.
+ *
+ * The @@Gj command exists in later ONCOREs, and it gives the exact date
+ * and size of the Leap Update. It can be emulated in the VP using the @@Bl
+ * command which reads the raw Satellite Broadcast Messages.
+ * We use these two commands to print informative messages in the clockstats
+ * file once per day as soon as the message appears on the satellites.
+ * --------------------------------------------------------------------------
* Reg Clemens (Feb 2006)
* Fix some gcc4 compiler complaints
* Fix possible segfault in oncore_init_shmem
@@ -141,6 +183,18 @@
# include <sys/sio.h>
#endif
+struct Bl {
+ int dt_ls;
+ int dt_lsf;
+ int WN;
+ int DN;
+ int WN_lsf;
+ int DN_lsf;
+ int wn_flg;
+ int lsf_flg;
+ int Bl_day;
+} Bl;
+
enum receive_state {
ONCORE_NO_IDEA,
ONCORE_CHECK_ID,
@@ -265,10 +319,14 @@ struct instance {
u_char count4; /* cycles thru leap after Gj to issue Bj */
u_char count5; /* cycles thru get_timestamp waiting for valid UTC correction */
u_char count5_set; /* only set count5 once */
+ u_char counta; /* count for waiting on almanac message */
u_char pollcnt;
u_char timeout; /* count to retry Cj after Fa self-test */
+ u_char max_len; /* max length message seen by oncore_log, for debugging */
+ u_char max_count; /* count for message statistics */
struct RSM rsm; /* bits extracted from Receiver Status Msg in @@Ea */
+ struct Bl Bl; /* Satellite Broadcast Data Message */
u_char printed;
u_char polled;
u_long ev_serial;
@@ -281,6 +339,7 @@ struct instance {
u_char saw_At;
u_char saw_Ay;
u_char saw_Az;
+ s_char saw_Bj;
s_char saw_Gj;
u_char have_dH;
u_char init_type;
@@ -299,55 +358,57 @@ struct instance {
#define rcvbuf instance->Rcvbuf
#define rcvptr instance->Rcvptr
-static int oncore_start P((int, struct peer *));
-static void oncore_poll P((int, struct peer *));
-static void oncore_shutdown P((int, struct peer *));
-static void oncore_consume P((struct instance *));
-static void oncore_read_config P((struct instance *));
-static void oncore_receive P((struct recvbuf *));
-static int oncore_ppsapi P((struct instance *));
-static void oncore_get_timestamp P((struct instance *, long, long));
-static void oncore_init_shmem P((struct instance *));
-
-static void oncore_antenna_report P((struct instance *, enum antenna_state));
-static void oncore_chan_test P((struct instance *));
-static void oncore_check_almanac P((struct instance *));
-static void oncore_check_antenna P((struct instance *));
-static void oncore_check_leap_sec P((struct instance *));
-static int oncore_checksum_ok P((u_char *, int));
-static void oncore_compute_dH P((struct instance *));
-static void oncore_load_almanac P((struct instance *));
-static void oncore_print_Cb P((struct instance *, u_char *));
-/* static void oncore_print_array P((u_char *, int)); */
-static void oncore_print_posn P((struct instance *));
-static void oncore_sendmsg P((int, u_char *, size_t));
-static void oncore_set_posn P((struct instance *));
-static void oncore_set_traim P((struct instance *));
-static void oncore_shmem_get_3D P((struct instance *));
-static void oncore_ss P((struct instance *));
-static int oncore_wait_almanac P((struct instance *));
-
-static void oncore_msg_any P((struct instance *, u_char *, size_t, int));
-static void oncore_msg_Adef P((struct instance *, u_char *, size_t));
-static void oncore_msg_Ag P((struct instance *, u_char *, size_t));
-static void oncore_msg_As P((struct instance *, u_char *, size_t));
-static void oncore_msg_At P((struct instance *, u_char *, size_t));
-static void oncore_msg_Ay P((struct instance *, u_char *, size_t));
-static void oncore_msg_Az P((struct instance *, u_char *, size_t));
-static void oncore_msg_BaEaHa P((struct instance *, u_char *, size_t));
-static void oncore_msg_Bd P((struct instance *, u_char *, size_t));
-static void oncore_msg_Bj P((struct instance *, u_char *, size_t));
-static void oncore_msg_BnEnHn P((struct instance *, u_char *, size_t));
-static void oncore_msg_CaFaIa P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cb P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cf P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cj P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cj_id P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cj_init P((struct instance *, u_char *, size_t));
-static void oncore_msg_Ga P((struct instance *, u_char *, size_t));
-static void oncore_msg_Gb P((struct instance *, u_char *, size_t));
-static void oncore_msg_Gj P((struct instance *, u_char *, size_t));
-static void oncore_msg_Sz P((struct instance *, u_char *, size_t));
+static int oncore_start (int, struct peer *);
+static void oncore_poll (int, struct peer *);
+static void oncore_shutdown (int, struct peer *);
+static void oncore_consume (struct instance *);
+static void oncore_read_config (struct instance *);
+static void oncore_receive (struct recvbuf *);
+static int oncore_ppsapi (struct instance *);
+static void oncore_get_timestamp (struct instance *, long, long);
+static void oncore_init_shmem (struct instance *);
+
+static void oncore_antenna_report (struct instance *, enum antenna_state);
+static void oncore_chan_test (struct instance *);
+static void oncore_check_almanac (struct instance *);
+static void oncore_check_antenna (struct instance *);
+static void oncore_check_leap_sec (struct instance *);
+static int oncore_checksum_ok (u_char *, int);
+static void oncore_compute_dH (struct instance *);
+static void oncore_load_almanac (struct instance *);
+static void oncore_log (struct instance *, int, const char *);
+static void oncore_print_Cb (struct instance *, u_char *);
+/* static void oncore_print_array (u_char *, int); */
+static void oncore_print_posn (struct instance *);
+static void oncore_sendmsg (struct instance *, u_char *, size_t);
+static void oncore_set_posn (struct instance *);
+static void oncore_set_traim (struct instance *);
+static void oncore_shmem_get_3D (struct instance *);
+static void oncore_ss (struct instance *);
+static int oncore_wait_almanac (struct instance *);
+
+static void oncore_msg_any (struct instance *, u_char *, size_t, int);
+static void oncore_msg_Adef (struct instance *, u_char *, size_t);
+static void oncore_msg_Ag (struct instance *, u_char *, size_t);
+static void oncore_msg_As (struct instance *, u_char *, size_t);
+static void oncore_msg_At (struct instance *, u_char *, size_t);
+static void oncore_msg_Ay (struct instance *, u_char *, size_t);
+static void oncore_msg_Az (struct instance *, u_char *, size_t);
+static void oncore_msg_BaEaHa (struct instance *, u_char *, size_t);
+static void oncore_msg_Bd (struct instance *, u_char *, size_t);
+static void oncore_msg_Bj (struct instance *, u_char *, size_t);
+static void oncore_msg_Bl (struct instance *, u_char *, size_t);
+static void oncore_msg_BnEnHn (struct instance *, u_char *, size_t);
+static void oncore_msg_CaFaIa (struct instance *, u_char *, size_t);
+static void oncore_msg_Cb (struct instance *, u_char *, size_t);
+static void oncore_msg_Cf (struct instance *, u_char *, size_t);
+static void oncore_msg_Cj (struct instance *, u_char *, size_t);
+static void oncore_msg_Cj_id (struct instance *, u_char *, size_t);
+static void oncore_msg_Cj_init (struct instance *, u_char *, size_t);
+static void oncore_msg_Ga (struct instance *, u_char *, size_t);
+static void oncore_msg_Gb (struct instance *, u_char *, size_t);
+static void oncore_msg_Gj (struct instance *, u_char *, size_t);
+static void oncore_msg_Sz (struct instance *, u_char *, size_t);
struct refclock refclock_oncore = {
oncore_start, /* start up driver */
@@ -367,7 +428,7 @@ struct refclock refclock_oncore = {
static struct msg_desc {
const char flag[3];
const int len;
- void (*handler) P((struct instance *, u_char *, size_t));
+ void (*handler) (struct instance *, u_char *, size_t);
const char *fmt;
int shmem;
} oncore_messages[] = {
@@ -395,6 +456,7 @@ static struct msg_desc {
{ "Bb", 92, 0, "" },
{ "Bd", 23, oncore_msg_Bd, "" },
{ "Bj", 8, oncore_msg_Bj, "" },
+ { "Bl", 41, oncore_msg_Bl, "" },
{ "Ca", 9, oncore_msg_CaFaIa, "" },
{ "Cb", 33, oncore_msg_Cb, "" },
{ "Cf", 7, oncore_msg_Cf, "" },
@@ -446,6 +508,7 @@ static u_char oncore_cmd_Bb[] = { 'B', 'b', 1 }; /* 6/8/12 Visible Satel
static u_char oncore_cmd_Bd[] = { 'B', 'd', 1 }; /* 6/8/12? Almanac Status Msg. */
static u_char oncore_cmd_Be[] = { 'B', 'e', 1 }; /* 6/8/12 Request Almanac Data */
static u_char oncore_cmd_Bj[] = { 'B', 'j', 0 }; /* 6/8 Leap Second Pending */
+static u_char oncore_cmd_Bl[] = { 'B', 'l', 1 }; /* VP Satellite Broadcast Data Msg */
static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg off, traim on */
static u_char oncore_cmd_Bn[] = { 'B', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg on, traim on */
static u_char oncore_cmd_Bnx[] = { 'B', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg off, traim off */
@@ -531,18 +594,14 @@ oncore_start(
#define STRING_LEN 32
register struct instance *instance;
struct refclockproc *pp;
- int fd1, fd2, num;
+ int fd1, fd2;
char device1[STRING_LEN], device2[STRING_LEN], Msg[160];
- const char *cp;
struct stat stat1, stat2;
/* create instance structure for this unit */
- if (!(instance = (struct instance *) malloc(sizeof *instance))) {
- perror("malloc");
- return (0);
- }
- memset((char *) instance, 0, sizeof *instance);
+ instance = emalloc(sizeof(*instance));
+ memset(instance, 0, sizeof(*instance));
/* initialize miscellaneous variables */
@@ -570,20 +629,17 @@ oncore_start(
pp->clockdesc = "Motorola Oncore GPS Receiver";
memcpy((char *)&pp->refid, "GPS\0", (size_t) 4);
- cp = "ONCORE DRIVER -- CONFIGURING";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
+ oncore_log(instance, LOG_NOTICE, "ONCORE DRIVER -- CONFIGURING");
instance->o_state = ONCORE_NO_IDEA;
- cp = "state = ONCORE_NO_IDEA";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_NO_IDEA");
/* Now open files.
* This is a bit complicated, a we dont want to open the same file twice
* (its a problem on some OS), and device2 may not exist for the new PPS
*/
- (void)sprintf(device1, DEVICE1, unit);
- (void)sprintf(device2, DEVICE2, unit);
+ (void)snprintf(device1, sizeof(device1), DEVICE1, unit);
+ (void)snprintf(device2, sizeof(device2), DEVICE2, unit);
/* OPEN DEVICES */
/* opening different devices for fd1 and fd2 presents no problems */
@@ -594,42 +650,68 @@ oncore_start(
Since things ALWAYS work if we only open the device once, we check
to see if the two devices are in fact the same, then proceed to
do one open or two.
- */
+ For use with linuxPPS we assume that the N_TTY file has been opened
+ and that the line discipline has been changed to N_PPS by another
+ program (say ppsldisc) so that the two files expected by the oncore
+ driver can be opened.
+
+ Note that the linuxPPS N_PPS file is just like a N_TTY, so we can do
+ the stat below without error even though the file has already had its
+ line discipline changed by another process.
+
+ The Windows port of ntpd arranges to return duplicate handles for
+ multiple opens of the same serial device, and doesn't have inodes
+ for serial handles, so we just open both on Windows.
+ */
+#ifndef SYS_WINNT
if (stat(device1, &stat1)) {
- sprintf(Msg, "Can't stat fd1 (%s)\n", device1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- exit(1);
+ snprintf(Msg, sizeof(Msg), "Can't stat fd1 (%s)",
+ device1);
+ oncore_log(instance, LOG_ERR, Msg);
+ return(0); /* exit, no file, can't start driver */
}
if (stat(device2, &stat2)) {
- sprintf(Msg, "Can't stat fd2 (%s)\n", device2);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- exit(1);
+ stat2.st_dev = stat2.st_ino = -2;
+ snprintf(Msg, sizeof(Msg),
+ "Can't stat fd2 (%s) errno = %d",
+ device2, errno);
+ oncore_log(instance, LOG_ERR, Msg);
}
+#endif /* !SYS_WINNT */
if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW))) {
- sprintf(Msg, "Can't open fd1 (%s)\n", device1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- exit(1);
+ snprintf(Msg, sizeof(Msg), "Can't open fd1 (%s)",
+ device1);
+ oncore_log(instance, LOG_ERR, Msg);
+ return(0); /* exit, can't open file, can't start driver */
}
+ /* for LINUX the PPS device is the result of a line discipline.
+ It seems simplest to let an external program create the appropriate
+ /dev/pps<n> file, and only check (carefully) for its existance here
+ */
+
+#ifndef SYS_WINNT
if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) /* same device here */
fd2 = fd1;
- else { /* different devices here */
- if ((fd2=open(device2, O_RDWR)) < 0) {
- sprintf(Msg, "Can't open fd2 (%s)\n", device2);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- exit(1);
+ else
+#endif /* !SYS_WINNT */
+ { /* different devices here */
+ if ((fd2=tty_open(device2, O_RDWR, 0777)) < 0) {
+ snprintf(Msg, sizeof(Msg),
+ "Can't open fd2 (%s)", device2);
+ oncore_log(instance, LOG_ERR, Msg);
+ return(0); /* exit, can't open PPS file, can't start driver */
}
}
- num = fd2;
- /* open ppsapi soure */
+ /* open ppsapi source */
- if (time_pps_create(num, &instance->pps_h) < 0) {
- record_clock_stats(&(instance->peer->srcadr), "PPSAPI not found in kernel");
- return(0);
+ if (time_pps_create(fd2, &instance->pps_h) < 0) {
+ oncore_log(instance, LOG_ERR, "exit, PPSAPI not found in kernel");
+ return(0); /* exit, don't find PPSAPI in kernel */
}
/* continue initialization */
@@ -649,7 +731,7 @@ oncore_start(
pp->io.datalen = 0;
pp->io.fd = fd1;
if (!io_addclock(&pp->io)) {
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: io_addclock");
+ oncore_log(instance, LOG_ERR, "can't do io_addclock");
(void) close(fd1);
free(instance);
return (0);
@@ -671,12 +753,11 @@ oncore_start(
*/
instance->o_state = ONCORE_CHECK_ID;
- cp = "state = ONCORE_CHECK_ID";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_CHECK_ID");
instance->timeout = 4;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */
+ oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
instance->pollcnt = 2;
return (1);
@@ -730,17 +811,14 @@ oncore_poll(
instance = (struct instance *) peer->procptr->unitptr;
if (instance->timeout) {
- char *cp;
-
instance->timeout--;
if (instance->timeout == 0) {
- cp = "Oncore: No response from @@Cj, shutting down driver";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_ERR,
+ "Oncore: No response from @@Cj, shutting down driver");
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);
+ oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ oncore_log(instance, LOG_WARNING, "Oncore: Resend @@Cj");
}
return;
}
@@ -768,12 +846,14 @@ oncore_ppsapi(
char *cp, Msg[160];
if (time_pps_getcap(instance->pps_h, &cap) < 0) {
- msyslog(LOG_ERR, "time_pps_getcap failed: %m");
+ msnprintf(Msg, sizeof(Msg), "time_pps_getcap failed: %m");
+ oncore_log(instance, LOG_ERR, Msg);
return (0);
}
if (time_pps_getparams(instance->pps_h, &instance->pps_p) < 0) {
- msyslog(LOG_ERR, "time_pps_getparams failed: %m");
+ msnprintf(Msg, sizeof(Msg), "time_pps_getparams failed: %m");
+ oncore_log(instance, LOG_ERR, Msg);
return (0);
}
@@ -782,26 +862,28 @@ oncore_ppsapi(
*/
if (instance->assert) {
- cp = "Assert.";
+ cp = "Assert";
mode = PPS_CAPTUREASSERT;
mode1 = PPS_OFFSETASSERT;
} else {
- cp = "Clear.";
+ cp = "Clear";
mode = PPS_CAPTURECLEAR;
mode1 = PPS_OFFSETCLEAR;
}
- sprintf(Msg, "Initializing timeing to %s.", cp);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Initializing timing to %s.", cp);
+ oncore_log(instance, LOG_INFO, Msg);
if (!(mode & cap)) {
- sprintf(Msg, "Can't set timeing to %s, exiting...", cp);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Can't set timing to %s, exiting...", cp);
+ oncore_log(instance, LOG_ERR, Msg);
return(0);
}
if (!(mode1 & cap)) {
- sprintf(Msg, "Can't set PPS_%sCLEAR, this will increase jitter.", cp);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Can't set %s, this will increase jitter.", cp);
+ oncore_log(instance, LOG_NOTICE, Msg);
mode1 = 0;
}
@@ -810,8 +892,8 @@ oncore_ppsapi(
instance->pps_p.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: time_pps_setparams fails");
- exit(1);
+ oncore_log(instance, LOG_ERR, "ONCORE: time_pps_setparams fails");
+ return(0); /* exit, can't do time_pps_setparans on PPS file */
}
/* If HARDPPS is on, we tell kernel */
@@ -819,7 +901,7 @@ oncore_ppsapi(
if (instance->hardpps) {
int i;
- record_clock_stats(&(instance->peer->srcadr), "HARDPPS Set.");
+ oncore_log(instance, LOG_INFO, "HARDPPS Set.");
if (instance->assert)
i = PPS_CAPTUREASSERT;
@@ -830,10 +912,12 @@ oncore_ppsapi(
if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i,
PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR, "time_pps_kcbind failed: %m");
- record_clock_stats(&(instance->peer->srcadr), "HARDPPS failed, abort...");
+ msnprintf(Msg, sizeof(Msg), "time_pps_kcbind failed: %m");
+ oncore_log(instance, LOG_ERR, Msg);
+ oncore_log(instance, LOG_ERR, "HARDPPS failed, abort...");
return (0);
}
+
pps_enable = 1;
}
return(1);
@@ -854,7 +938,7 @@ oncore_init_shmem(
struct stat sbuf;
size_t shmem_length;
- /*
+ /*
* The first thing we do is see if there is an instance->shmem_fname file (still)
* out there from a previous run. If so, we copy it in and use it to initialize
* shmem (so we won't lose our almanac if we need it).
@@ -863,16 +947,13 @@ oncore_init_shmem(
shmem_old = 0;
shmem_old_size = 0;
if ((fd = open(instance->shmem_fname, O_RDONLY)) < 0)
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't open SHMEM file");
+ oncore_log(instance, LOG_WARNING, "ONCORE: Can't open SHMEM file");
else {
fstat(fd, &sbuf);
shmem_old_size = sbuf.st_size;
if (shmem_old_size != 0) {
- shmem_old = (u_char *) malloc((unsigned) sbuf.st_size);
- if (shmem_old == NULL)
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't malloc buffer for shmem_old");
- else
- read(fd, shmem_old, shmem_old_size);
+ shmem_old = emalloc((unsigned) sbuf.st_size);
+ read(fd, shmem_old, shmem_old_size);
}
close(fd);
}
@@ -880,7 +961,7 @@ oncore_init_shmem(
/* OK, we now create the NEW SHMEM. */
if ((instance->shmemfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't open shmem");
+ oncore_log(instance, LOG_WARNING, "ONCORE: Can't open shmem");
if (shmem_old)
free(shmem_old);
@@ -913,16 +994,7 @@ oncore_init_shmem(
}
shmem_length = n + 2;
- buf = malloc(shmem_length);
- if (buf == NULL) {
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't malloc buffer for shmem");
- close(instance->shmemfd);
- if (shmem_old)
- free(shmem_old);
-
- return;
- }
-
+ buf = emalloc(shmem_length);
memset(buf, 0, shmem_length);
/* next build the new SHMEM buffer in memory */
@@ -977,7 +1049,7 @@ oncore_init_shmem(
free(buf);
if (i != shmem_length) {
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: error writing shmem");
+ oncore_log(instance, LOG_ERR, "ONCORE: error writing shmem");
close(instance->shmemfd);
return;
}
@@ -995,9 +1067,10 @@ oncore_init_shmem(
return;
}
- sprintf(Msg, "SHMEM (size = %ld) is CONFIGURED and available as %s",
- (u_long) shmem_length, instance->shmem_fname);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "SHMEM (size = %ld) is CONFIGURED and available as %s",
+ (u_long) shmem_length, instance->shmem_fname);
+ oncore_log(instance, LOG_NOTICE, Msg);
}
#endif /* ONCORE_SHMEM_STATUS */
@@ -1014,10 +1087,10 @@ oncore_read_config(
{
/*
* First we try to open the configuration file
- * /etc/oncoreN
+ * /etc/ntp.oncore.N
* where N is the unit number viz 127.127.30.N.
* If we don't find it we try
- * /etc/ntp.oncore.N
+ * /etc/ntp.oncoreN
* and then
* /etc/ntp.oncore
*
@@ -1127,7 +1200,7 @@ oncore_read_config(
*/
FILE *fd;
- char *cp, *cc, *ca, line[100], units[2], device[20], Msg[160], **cpp;
+ char *cp, *cc, *ca, line[100], units[2], device[64], Msg[160], **cpp;
char *dirs[] = { "/etc/ntp", "/etc", 0 };
int i, sign, lat_flg, long_flg, ht_flg, mode, mask;
double f1, f2, f3;
@@ -1135,14 +1208,16 @@ oncore_read_config(
fd = NULL; /* just to shutup gcc complaint */
for (cpp=dirs; *cpp; cpp++) {
cp = *cpp;
- sprintf(device, "%s/ntp.oncore.%d", cp, instance->unit); /* try "ntp.oncore.0 */
+ snprintf(device, sizeof(device), "%s/ntp.oncore.%d",
+ cp, instance->unit); /* try "ntp.oncore.0 */
if ((fd=fopen(device, "r")))
break;
- sprintf(device, "%s/ntp.oncore%d", cp, instance->unit); /* try "ntp.oncore0" */
+ snprintf(device, sizeof(device), "%s/ntp.oncore%d",
+ cp, instance->unit); /* try "ntp.oncore0" */
if ((fd=fopen(device, "r")))
break;
- sprintf(device, "%s/ntp.oncore", cp); /* and finally "ntp.oncore" */
- if ((fd=fopen(device, "r")))
+ snprintf(device, sizeof(device), "%s/ntp.oncore", cp);
+ if ((fd=fopen(device, "r"))) /* last try "ntp.oncore" */
break;
}
@@ -1188,9 +1263,7 @@ oncore_read_config(
continue;
if (!strncmp(cc, "STATUS", (size_t) 6) || !strncmp(cc, "SHMEM", (size_t) 5)) {
- i = strlen(ca);
- instance->shmem_fname = (char *) malloc((unsigned) (i+1));
- strcpy(instance->shmem_fname, ca);
+ instance->shmem_fname = estrdup(ca);
continue;
}
@@ -1242,8 +1315,10 @@ oncore_read_config(
if (f1 < 0 || f1 > 1.e9)
f1 = 0;
if (f1 < 0 || f1 > 999999) {
- sprintf(Msg, "PPS Cable delay of %fns out of Range, ignored", f1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "PPS Cable delay of %fns out of Range, ignored",
+ f1);
+ oncore_log(instance, LOG_WARNING, Msg);
} else
instance->delay = f1; /* delay in ns */
} else if (!strncmp(cc, "OFFSET", (size_t) 6)) {
@@ -1261,8 +1336,10 @@ oncore_read_config(
if (f1 < 0 || f1 > 1.e9)
f1 = 0;
if (f1 < 0 || f1 > 999999999.) {
- sprintf(Msg, "PPS Offset of %fns out of Range, ignored", f1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "PPS Offset of %fns out of Range, ignored",
+ f1);
+ oncore_log(instance, LOG_WARNING, Msg);
} else
instance->offset = f1; /* offset in ns */
} else if (!strncmp(cc, "MODE", (size_t) 4)) {
@@ -1302,18 +1379,22 @@ oncore_read_config(
instance->posn_set = 1;
if (!( lat_flg && long_flg && ht_flg )) {
- printf("ONCORE: incomplete data on %s\n", device);
+ snprintf(Msg, sizeof(Msg),
+ "ONCORE: incomplete data on %s", device);
+ oncore_log (instance, LOG_WARNING, Msg);
instance->posn_set = 0;
if (mode == 1 || mode == 3) {
- sprintf(Msg, "Input Mode = %d, but no/incomplete position, mode set to %d", mode, mode+1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Input Mode = %d, but no/incomplete position, mode set to %d",
+ mode, mode+1);
+ oncore_log(instance, LOG_WARNING, Msg);
mode++;
}
}
instance->init_type = mode;
- sprintf(Msg, "Input mode = %d", mode);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Input mode = %d", mode);
+ oncore_log(instance, LOG_INFO, Msg);
}
@@ -1336,17 +1417,27 @@ oncore_receive(
instance = (struct instance *) peer->procptr->unitptr;
p = (u_char *) &rbufp->recv_space;
-#if 0
+#ifdef ONCORE_VERBOSE_RECEIVE
if (debug > 4) {
int i;
- printf("ONCORE: >>>");
- for(i=0; i<rbufp->recv_length; i++)
- printf("%02x ", p[i]);
- printf("\n");
- printf("ONCORE: >>>");
- for(i=0; i<rbufp->recv_length; i++)
- printf("%03o ", p[i]);
- printf("\n");
+ char Msg[120], Msg2[10];
+
+ snprintf(Msg, sizeof(Msg), ">>> %d bytes available",
+ rbufp->recv_length);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ strncpy(Msg, ">>>", sizeof(Msg));
+ for (i = 0; i < rbufp->recv_length; i++) {
+ snprintf(Msg2, sizeof(Msg2), "%02x ", p[i]);
+ strncat(Msg, Msg2, sizeof(Msg));
+ }
+ oncore_log(instance, LOG_DEBUG, Msg);
+
+ strncpy(Msg, ">>>", sizeof(Msg));
+ for (i = 0; i < rbufp->recv_length; i++) {
+ snprintf(Msg2, sizeof(Msg2), "%03o ", p[i]);
+ strncat(Msg, Msg2, sizeof(Msg));
+ }
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
@@ -1378,9 +1469,14 @@ oncore_consume(
for (i=1; i < rcvptr-1; i++)
if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
break;
-#ifdef DEBUG
- if (debug > 4)
- printf("ONCORE[%d]: >>> skipping %d chars\n", instance->unit, i);
+#ifdef ONCORE_VERBOSE_CONSUME
+ if (debug > 4) {
+ char Msg[120];
+
+ snprintf(Msg, sizeof(Msg),
+ ">>> skipping %d chars", i);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ }
#endif
if (i != rcvptr)
memcpy(rcvbuf, rcvbuf+i, (size_t)(rcvptr-i));
@@ -1394,9 +1490,15 @@ oncore_consume(
if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
break;
if (m == l) {
-#ifdef DEBUG
- if (debug > 4)
- printf("ONCORE[%d]: >>> Unknown MSG, skipping 4 (%c%c)\n", instance->unit, rcvbuf[2], rcvbuf[3]);
+#ifdef ONCORE_VERBOSE_CONSUME
+ if (debug > 4) {
+ char Msg[120];
+
+ snprintf(Msg, sizeof(Msg),
+ ">>> Unknown MSG, skipping 4 (%c%c)",
+ rcvbuf[2], rcvbuf[3]);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ }
#endif
memcpy(rcvbuf, rcvbuf+4, (size_t) 4);
rcvptr -= 4;
@@ -1404,9 +1506,16 @@ oncore_consume(
}
l = oncore_messages[m].len;
-#if 0
- if (debug > 3)
- printf("ONCORE[%d]: GOT: %c%c %d of %d entry %d\n", instance->unit, rcvbuf[2], rcvbuf[3], rcvptr, l, m);
+#ifdef ONCORE_VERBOSE_CONSUME
+ if (debug > 3) {
+ char Msg[120];
+
+ snprintf(Msg, sizeof(Msg),
+ "GOT: %c%c %d of %d entry %d",
+ instance->unit, rcvbuf[2], rcvbuf[3],
+ rcvptr, l, m);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ }
#endif
/* Got the entire message ? */
@@ -1416,9 +1525,9 @@ oncore_consume(
/* are we at the end of message? should be <Cksum><CR><LF> */
if (rcvbuf[l-2] != '\r' || rcvbuf[l-1] != '\n') {
-#ifdef DEBUG
+#ifdef ONCORE_VERBOSE_CONSUME
if (debug)
- printf("ONCORE[%d]: NO <CR><LF> at end of message\n", instance->unit);
+ oncore_log(instance, LOG_DEBUG, "NO <CR><LF> at end of message");
#endif
} else { /* check the CheckSum */
if (oncore_checksum_ok(rcvbuf, l)) {
@@ -1431,13 +1540,18 @@ oncore_consume(
if (oncore_messages[m].handler)
oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
}
-#ifdef DEBUG
+#ifdef ONCORE_VERBOSE_CONSUME
else if (debug) {
- printf("ONCORE[%d]: Checksum mismatch!\n", instance->unit);
- printf("ONCORE[%d]: @@%c%c ", instance->unit, rcvbuf[2], rcvbuf[3]);
- for (i=4; i<l; i++)
- printf("%03o ", rcvbuf[i]);
- printf("\n");
+ char Msg[120], Msg2[10];
+
+ oncore_log(instance, LOG_ERR, "Checksum mismatch!");
+ snprintf(Msg, sizeof(Msg), "@@%c%c ", rcvbuf[2], rcvbuf[3]);
+ for (i = 4; i < l; i++) {
+ snprintf(Msg2, sizeof(Msg2),
+ "%03o ", rcvbuf[i]);
+ strncat(Msg, Msg2, sizeof(Msg));
+ }
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
}
@@ -1467,10 +1581,13 @@ oncore_get_timestamp(
struct timeval *tsp = 0;
#endif
int current_mode;
- u_long i;
pps_params_t current_params;
struct timespec timeout;
+ struct peer *peer;
pps_info_t pps_i;
+ char Msg[140];
+
+ peer = instance->peer;
#if 1
/* If we are in SiteSurvey mode, then we are in 3D mode, and we fall thru.
@@ -1479,18 +1596,22 @@ oncore_get_timestamp(
* This gives good time, which gets better when the SS is done.
*/
- if ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D))
+ if ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D)) {
#else
/* old check, only fall thru for SS_DONE and 0D mode, 2h45m wait for ticks */
- if ((instance->site_survey != ONCORE_SS_DONE) || (instance->mode != MODE_0D))
+ if ((instance->site_survey != ONCORE_SS_DONE) || (instance->mode != MODE_0D)) {
#endif
+ peer->flags &= ~FLAG_PPS;
return;
+ }
/* Don't do anything without an almanac to define the GPS->UTC delta */
- if (instance->rsm.bad_almanac)
+ if (instance->rsm.bad_almanac) {
+ peer->flags &= ~FLAG_PPS;
return;
+ }
/* Once the Almanac is valid, the M12+T does not produce valid UTC
* immediately.
@@ -1500,6 +1621,7 @@ oncore_get_timestamp(
if (instance->count5) {
instance->count5--;
+ peer->flags &= ~FLAG_PPS;
return;
}
@@ -1508,51 +1630,63 @@ oncore_get_timestamp(
timeout.tv_nsec = 0;
if (time_pps_fetch(instance->pps_h, PPS_TSFMT_TSPEC, &pps_i,
&timeout) < 0) {
- printf("ONCORE: time_pps_fetch failed\n");
+ oncore_log(instance, LOG_ERR, "time_pps_fetch failed");
+ peer->flags &= ~FLAG_PPS;
return;
}
if (instance->assert) {
tsp = &pps_i.assert_timestamp;
-#ifdef DEBUG
+#ifdef ONCORE_VERBOSE_GET_TIMESTAMP
if (debug > 2) {
+ u_long i;
+
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);
+ snprintf(Msg, sizeof(Msg),
+ "serial/j (%lu, %lu) %ld.%09ld", 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);
+ snprintf(Msg, sizeof(Msg),
+ "serial/j (%lu, %lu) %ld.%06ld", i, j,
+ (long)tsp->tv_sec, (long)tsp->tv_usec);
# endif
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (pps_i.assert_sequence == j) {
- printf("ONCORE: oncore_get_timestamp, error serial pps\n");
+ oncore_log(instance, LOG_NOTICE, "ONCORE: oncore_get_timestamp, error serial pps");
+ peer->flags &= ~FLAG_PPS;
return;
}
+
instance->ev_serial = pps_i.assert_sequence;
} else {
tsp = &pps_i.clear_timestamp;
-#ifdef DEBUG
+#if 0
if (debug > 2) {
+ u_long i;
+
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);
+ snprintf(Msg, sizeof(Msg),
+ "serial/j (%lu, %lu) %ld.%09ld", 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);
+ snprintf(Msg. sizeof(Msg),
+ "serial/j (%lu, %lu) %ld.%06ld", i, j,
+ (long)tsp->tv_sec, (long)tsp->tv_usec);
# endif
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (pps_i.clear_sequence == j) {
- printf("ONCORE: oncore_get_timestamp, error serial pps\n");
+ oncore_log(instance, LOG_ERR, "oncore_get_timestamp, error serial pps");
+ peer->flags &= ~FLAG_PPS;
return;
}
instance->ev_serial = pps_i.clear_sequence;
@@ -1611,12 +1745,16 @@ oncore_get_timestamp(
*/
if (time_pps_getcap(instance->pps_h, &current_mode) < 0) {
- msyslog(LOG_ERR, "time_pps_getcap failed: %m");
+ msnprintf(Msg, sizeof(Msg), "time_pps_getcap failed: %m");
+ oncore_log(instance, LOG_ERR, Msg);
+ peer->flags &= ~FLAG_PPS;
return;
}
if (time_pps_getparams(instance->pps_h, &current_params) < 0) {
- msyslog(LOG_ERR, "time_pps_getparams failed: %m");
+ msnprintf(Msg, sizeof(Msg), "time_pps_getparams failed: %m");
+ oncore_log(instance, LOG_ERR, Msg);
+ peer->flags &= ~FLAG_PPS;
return;
}
@@ -1631,7 +1769,7 @@ oncore_get_timestamp(
current_params.clear_offset.tv_nsec = -dt2;
if (time_pps_setparams(instance->pps_h, &current_params))
- record_clock_stats(&(instance->peer->srcadr), "ONCORE: Error doing time_pps_setparams");
+ oncore_log(instance, LOG_ERR, "ONCORE: Error doing time_pps_setparams");
/* have time from UNIX origin, convert to NTP origin. */
@@ -1656,17 +1794,22 @@ oncore_get_timestamp(
if (instance->chan == 6 || instance->chan == 8) {
char f1[5], f2[5], f3[5], f4[5];
if (instance->traim) {
- sprintf(f1, "%d", instance->BEHn[21]);
- sprintf(f2, "%d", instance->BEHn[22]);
- sprintf(f3, "%2d", instance->BEHn[23]*256+instance->BEHn[24]);
- sprintf(f4, "%3d", (s_char) instance->BEHn[25]);
+ snprintf(f1, sizeof(f1), "%d",
+ instance->BEHn[21]);
+ snprintf(f2, sizeof(f2), "%d",
+ instance->BEHn[22]);
+ snprintf(f3, sizeof(f3), "%2d",
+ instance->BEHn[23] * 256 +
+ instance->BEHn[24]);
+ snprintf(f4, sizeof(f4), "%3d",
+ (s_char)instance->BEHn[25]);
} else {
- strcpy(f1, "x");
- strcpy(f2, "x");
- strcpy(f3, "xx");
- strcpy(f4, "xxx");
+ strncpy(f1, "x", sizeof(f1));
+ strncpy(f2, "x", sizeof(f2));
+ strncpy(f3, "xx", sizeof(f3));
+ strncpy(f4, "xxx", sizeof(f4));
}
- sprintf(instance->pp->a_lastcode, /* MAX length 128, currently at 121 */
+ snprintf(Msg, sizeof(Msg), /* MAX length 128, currently at 127 */
"%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s sat %d%d%d%d%d%d%d%d",
ts.l_ui, j,
instance->pp->year, instance->pp->day,
@@ -1684,17 +1827,22 @@ oncore_get_timestamp(
} else if (instance->chan == 12) {
char f1[5], f2[5], f3[5], f4[5];
if (instance->traim) {
- sprintf(f1, "%d", instance->BEHn[6]);
- sprintf(f2, "%d", instance->BEHn[7]);
- sprintf(f3, "%d", instance->BEHn[12]*256+instance->BEHn[13]);
- sprintf(f4, "%3d", (s_char) instance->BEHn[14]);
+ snprintf(f1, sizeof(f1), "%d",
+ instance->BEHn[6]);
+ snprintf(f2, sizeof(f2), "%d",
+ instance->BEHn[7]);
+ snprintf(f3, sizeof(f3), "%d",
+ instance->BEHn[12] * 256 +
+ instance->BEHn[13]);
+ snprintf(f4, sizeof(f4), "%3d",
+ (s_char)instance->BEHn[14]);
} else {
- strcpy(f1, "x");
- strcpy(f2, "x");
- strcpy(f3, "x");
- strcpy(f4, "xxx");
+ strncpy(f1, "x", sizeof(f1));
+ strncpy(f2, "x", sizeof(f2));
+ strncpy(f3, "xx", sizeof(f3));
+ strncpy(f4, "xxx", sizeof(f4));
}
- sprintf(instance->pp->a_lastcode,
+ snprintf(Msg, sizeof(Msg),
"%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s sat %d%d%d%d%d%d%d%d%d%d%d%d",
ts.l_ui, j,
instance->pp->year, instance->pp->day,
@@ -1712,23 +1860,15 @@ oncore_get_timestamp(
);
}
-#ifdef DEBUG
- if (debug > 2) {
- int n;
-
- n = strlen(instance->pp->a_lastcode);
- printf("ONCORE[%d]: len = %d %s\n", instance->unit, n, instance->pp->a_lastcode);
- }
-#endif
-
/* and some things I dont understand (magic ntp things) */
if (!refclock_process(instance->pp)) {
refclock_report(instance->peer, CEVNT_BADTIME);
+ peer->flags &= ~FLAG_PPS;
return;
}
- record_clock_stats(&(instance->peer->srcadr), instance->pp->a_lastcode);
+ oncore_log(instance, LOG_INFO, Msg); /* this is long message above */
instance->pollcnt = 2;
if (instance->polled) {
@@ -1737,6 +1877,7 @@ oncore_get_timestamp(
instance->pp->lastref = instance->pp->lastrec;
refclock_receive(instance->peer);
}
+ peer->flags |= FLAG_PPS;
}
@@ -1755,15 +1896,18 @@ oncore_msg_any(
int idx
)
{
+#ifdef ONCORE_VERBOSE_MSG_ANY
int i;
const char *fmt = oncore_messages[idx].fmt;
const char *p;
+ char *q;
+ char *qlim;
#ifdef HAVE_GETCLOCK
struct timespec ts;
#endif
struct timeval tv;
+ char Msg[120], Msg2[10];
-#ifdef DEBUG
if (debug > 3) {
# ifdef HAVE_GETCLOCK
(void) getclock(TIMEOFDAY, &ts);
@@ -1772,26 +1916,38 @@ oncore_msg_any(
# else
GETTIMEOFDAY(&tv, 0);
# endif
- printf("ONCORE[%d]: %ld.%06ld\n", instance->unit, (long) tv.tv_sec, (long) tv.tv_usec);
+ snprintf(Msg, sizeof(Msg), "%ld.%06ld",
+ (long)tv.tv_sec, (long)tv.tv_usec);
+ oncore_log(instance, LOG_DEBUG, Msg);
if (!*fmt) {
- printf(">>@@%c%c ", buf[2], buf[3]);
- for(i=2; i < len && i < 2400 ; i++)
- printf("%02x", buf[i]);
- printf("\n");
+ snprintf(Msg, sizeof(Msg), ">>@@%c%c ", buf[2],
+ buf[3]);
+ for(i = 2; i < len && i < 2400 ; i++) {
+ snprintf(Msg2, sizeof(Msg2), "%02x",
+ buf[i]);
+ strncpy(Msg, Msg2, sizeof(Msg));
+
+ }
+ oncore_log(instance, LOG_DEBUG, Msg);
return;
} else {
- printf("##");
- for (p = fmt; *p; p++) {
- putchar(*p);
- putchar('_');
+ strncat(Msg, "##", sizeof(Msg));
+ qlim = Msg + sizeof(Msg) - 3;
+ for (p = fmt, q = Msg + 2; q < qlim && *p; ) {
+ *q++ = *p++;
+ *q++ = '_';
}
- printf("\n%c%c", buf[2], buf[3]);
+ *q = '\0';
+ oncore_log(instance, LOG_DEBUG, Msg);
+ snprintf(Msg, sizeof(Msg), "%c%c", buf[2],
+ buf[3]);
i = 4;
for (p = fmt; *p; p++) {
- printf("%02x", buf[i++]);
+ snprintf(Msg2, "%02x", buf[i++]);
+ strncat(Msg, Msg2, sizeof(Msg));
}
- printf("\n");
+ oncore_log(instance, LOG_DEBUG, Msg);
}
}
#endif
@@ -1827,8 +1983,10 @@ oncore_msg_Ag(
cp = "is";
instance->Ag = buf[4];
- sprintf(Msg, "Satellite mask angle %s %d degrees", cp, (int) instance->Ag);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Satellite mask angle %s %d degrees", cp,
+ (int)instance->Ag);
+ oncore_log(instance, LOG_INFO, Msg);
}
@@ -1866,16 +2024,13 @@ oncore_msg_At(
size_t len
)
{
- char *cp;
-
instance->saw_At = 1;
if (instance->site_survey == ONCORE_SS_TESTING) {
if (buf[4] == 2) {
- record_clock_stats(&(instance->peer->srcadr),
+ oncore_log(instance, LOG_NOTICE,
"Initiating hardware 3D site survey");
- cp = "SSstate = ONCORE_SS_HW";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_HW");
instance->site_survey = ONCORE_SS_HW;
}
}
@@ -1904,8 +2059,9 @@ oncore_msg_Ay(
instance->offset = buf_w32(&buf[4]);
- sprintf(Msg, "PPS Offset is set to %ld ns", instance->offset);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "PPS Offset is set to %ld ns",
+ instance->offset);
+ oncore_log(instance, LOG_INFO, Msg);
}
@@ -1930,8 +2086,9 @@ oncore_msg_Az(
instance->delay = buf_w32(&buf[4]);
- sprintf(Msg, "Cable delay is set to %ld ns", instance->delay);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Cable delay is set to %ld ns",
+ instance->delay);
+ oncore_log(instance, LOG_INFO, Msg);
}
@@ -1977,21 +2134,24 @@ oncore_msg_BaEaHa(
else /* set from test */
instance->chan = instance->chan_ck;
- sprintf(Msg, "Input says chan = %d", instance->chan_in);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Model # says chan = %d", instance->chan_id);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Testing says chan = %d", instance->chan_ck);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Using chan = %d", instance->chan);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Input says chan = %d",
+ instance->chan_in);
+ oncore_log(instance, LOG_INFO, Msg);
+ snprintf(Msg, sizeof(Msg), "Model # says chan = %d",
+ instance->chan_id);
+ oncore_log(instance, LOG_INFO, Msg);
+ snprintf(Msg, sizeof(Msg), "Testing says chan = %d",
+ instance->chan_ck);
+ oncore_log(instance, LOG_INFO, Msg);
+ snprintf(Msg, sizeof(Msg), "Using chan = %d",
+ instance->chan);
+ oncore_log(instance, LOG_INFO, Msg);
instance->o_state = ONCORE_HAVE_CHAN;
- cp = "state = ONCORE_HAVE_CHAN";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_HAVE_CHAN");
instance->timeout = 4;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
return;
}
@@ -2030,9 +2190,9 @@ oncore_msg_BaEaHa(
/* if not, message out */
if (instance->chan != 12 && !instance->saw_At) {
- cp = "Not Good, no @@At command (no Position Hold), must be a GT/GT+";
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ oncore_log(instance, LOG_NOTICE,
+ "Not Good, no @@At command (no Position Hold), must be a GT/GT+");
+ oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
}
/* have an Almanac, can start the SiteSurvey
@@ -2046,35 +2206,33 @@ oncore_msg_BaEaHa(
case 1: /* Use given Position */
case 3:
instance->site_survey = ONCORE_SS_DONE;
- cp = "SSstate = ONCORE_SS_DONE";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
break;
case 2:
case 4: /* Site Survey */
- cp = "SSstate = ONCORE_SS_TESTING";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_TESTING");
instance->site_survey = ONCORE_SS_TESTING;
instance->count1 = 1;
if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd3, sizeof(oncore_cmd_Gd3)); /* M12+T */
+ oncore_sendmsg(instance, oncore_cmd_Gd3, sizeof(oncore_cmd_Gd3)); /* M12+T */
else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At2, sizeof(oncore_cmd_At2)); /* not GT, arg not VP */
+ oncore_sendmsg(instance, oncore_cmd_At2, sizeof(oncore_cmd_At2)); /* not GT, arg not VP */
break;
}
/* Read back PPS Offset for Output */
/* Nb. This will fail silently for early UT (no plus) and M12 models */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ayx, sizeof(oncore_cmd_Ayx));
+ oncore_sendmsg(instance, 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, oncore_cmd_Azx, sizeof(oncore_cmd_Azx));
/* Read back Satellite Mask Angle for Output */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Agx, sizeof(oncore_cmd_Agx));
+ oncore_sendmsg(instance, oncore_cmd_Agx, sizeof(oncore_cmd_Agx));
}
@@ -2091,13 +2249,13 @@ oncore_msg_BaEaHa(
if (instance->count1++ > 5 || instance->BEHa[130]&0x10) {
instance->count1 = 0;
if (instance->BEHa[130]&0x10) {
- record_clock_stats(&(instance->peer->srcadr),
+ oncore_log(instance, LOG_NOTICE,
"Initiating hardware 3D site survey");
- record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_HW");
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_HW");
instance->site_survey = ONCORE_SS_HW;
} else {
- record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_SW");
instance->site_survey = ONCORE_SS_SW;
}
}
@@ -2124,19 +2282,20 @@ oncore_msg_BaEaHa(
* We will have to do it ourselves (done above)
*/
- sprintf(Msg, "Initiating software 3D site survey (%d samples)",
- POS_HOLD_AVERAGE);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Initiating software 3D site survey (%d samples)",
+ POS_HOLD_AVERAGE);
+ oncore_log(instance, LOG_INFO, Msg);
- record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_SW");
instance->site_survey = ONCORE_SS_SW;
instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* disable */
+ oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* disable */
else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* disable */
+ oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
+ oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* disable */
}
}
}
@@ -2208,7 +2367,7 @@ oncore_msg_BaEaHa(
instance->traim = 0;
instance->traim_delay = 0;
cp = "ONCORE: Did not detect TRAIM response, TRAIM = OFF";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_INFO, cp);
oncore_set_traim(instance);
} else
@@ -2249,8 +2408,7 @@ oncore_msg_BaEaHa(
/* if not, and non-zero offset, zero the offset, and send message */
if (!instance->saw_Ay && instance->offset) {
- cp = "No @@Ay command, PPS OFFSET ignored";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_INFO, "No @@Ay command, PPS OFFSET ignored");
instance->offset = 0;
}
}
@@ -2286,9 +2444,11 @@ oncore_msg_Bd(
{
char Msg[160];
- sprintf(Msg, "Bd: Almanac %s, week = %d, t = %d, %d SVs: %x",
- ((buf[4]) ? "LOADED" : "(NONE)"), buf[5], buf[6], buf[7], w32(&buf[8]) );
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Bd: Almanac %s, week = %d, t = %d, %d SVs: %x",
+ ((buf[4]) ? "LOADED" : "(NONE)"), buf[5], buf[6],
+ buf[7], w32(&buf[8]));
+ oncore_log(instance, LOG_NOTICE, Msg);
}
@@ -2313,6 +2473,8 @@ oncore_msg_Bj(
{
const char *cp;
+ instance->saw_Bj = 1;
+
switch(buf[4]) {
case 1:
instance->pp->leap = LEAP_ADDSECOND;
@@ -2328,12 +2490,131 @@ oncore_msg_Bj(
cp = "Set pp.leap to LEAP_NOWARNING";
break;
}
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, cp);
}
static void
+oncore_msg_Bl(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ int chan, id, subframe, valid, page, i, j, tow;
+ int day_now, day_lsf;
+ char *cp, Msg[120];
+ enum {
+ WARN_NOT_YET,
+ WARN_0,
+ WARN_PLUS,
+ WARN_MINUS
+ } warn;
+
+ day_now = day_lsf = 0;
+ cp = NULL; /* keep gcc happy */
+
+ chan = buf[4] & 0377;
+ id = buf[5] & 0377;
+ subframe = buf[6] & 017;
+ valid = (buf[6] >> 4) & 017;
+ page = buf[7];
+
+ if ((!instance->Bl.lsf_flg && !instance->Bl.wn_flg) && (subframe == 4 && page == 18 && valid == 10)) {
+ instance->Bl.dt_ls = buf[32];
+ instance->Bl.WN_lsf = buf[33];
+ instance->Bl.DN_lsf = buf[34];
+ instance->Bl.dt_lsf = buf[35];
+ instance->Bl.lsf_flg++;
+ }
+ if ((instance->Bl.lsf_flg && !instance->Bl.wn_flg) && (subframe == 1 && valid == 10)) {
+ i = (buf[7+7]<<8) + buf[7+8];
+ instance->Bl.WN = i >> 6;
+ tow = (buf[7+4]<<16) + (buf[7+5]<<8) + buf[7+6];
+ tow >>= 7;
+ tow = tow & 0377777;
+ tow <<= 2;
+ instance->Bl.DN = tow/57600L + 1;
+ instance->Bl.wn_flg++;
+ }
+ if (instance->Bl.wn_flg && instance->Bl.lsf_flg) {
+ instance->Bl.wn_flg = instance->Bl.lsf_flg = 0;
+ oncore_cmd_Bl[2] = 0;
+ oncore_sendmsg(instance, oncore_cmd_Bl, sizeof oncore_cmd_Bl);
+ oncore_cmd_Bl[2] = 1;
+
+ i = instance->Bl.WN&01400;
+ instance->Bl.WN_lsf |= i;
+
+ /* have everything I need, doit */
+
+ i = (instance->Bl.WN_lsf - instance->Bl.WN);
+ if (i < 0)
+ i += 1024;
+ day_now = instance->Bl.DN;
+ day_lsf = 7*i + instance->Bl.DN_lsf;
+
+ /* ignore if in past or more than a month in future */
+
+ warn = WARN_NOT_YET;
+ if (day_lsf >= day_now && day_lsf - day_now < 32) {
+ /* if < 28d, doit, if 28-31, ck day-of-month < 20 (not at end of prev month) */
+ if (day_lsf - day_now < 28 || instance->BEHa[5] < 20) {
+ i = instance->Bl.dt_lsf - instance->Bl.dt_ls;
+ switch (i) {
+ case -1:
+ warn = WARN_MINUS;
+ break;
+ case 0:
+ warn = WARN_0;
+ break;
+ case 1:
+ warn = WARN_PLUS;
+ break;
+ }
+ }
+ }
+
+ switch (warn) {
+ case WARN_0:
+ case WARN_NOT_YET:
+ instance->peer->leap = LEAP_NOWARNING;
+ cp = "Set peer.leap to LEAP_NOWARNING";
+ break;
+ case WARN_MINUS:
+ instance->peer->leap = LEAP_DELSECOND;
+ cp = "Set peer.leap to LEAP_DELSECOND";
+ break;
+ case WARN_PLUS:
+ instance->peer->leap = LEAP_ADDSECOND;
+ cp = "Set peer.leap to LEAP_ADDSECOND";
+ break;
+ }
+ oncore_log(instance, LOG_NOTICE, cp);
+
+ i = instance->Bl.dt_lsf-instance->Bl.dt_ls;
+ if (i) {
+ j = (i >= 0) ? i : -i; /* abs(i) */
+ snprintf(Msg, sizeof(Msg),
+ "see Leap_Second (%c%d) in %d days",
+ ((i >= 0) ? '+' : '-'), j,
+ day_lsf-day_now);
+ oncore_log(instance, LOG_NOTICE, Msg);
+ }
+ }
+ snprintf(Msg, sizeof(Msg),
+ "dt_ls = %d dt_lsf = %d WN = %d DN = %d WN_lsf = %d DNlsf = %d wn_flg = %d lsf_flg = %d Bl_day = %d",
+ instance->Bl.dt_ls, instance->Bl.dt_lsf,
+ instance->Bl.WN, instance->Bl.DN,
+ instance->Bl.WN_lsf, instance->Bl.DN_lsf,
+ instance->Bl.wn_flg, instance->Bl.lsf_flg,
+ instance->Bl.Bl_day);
+ oncore_log(instance, LOG_INFO, Msg);
+}
+
+
+static void
oncore_msg_BnEnHn(
struct instance *instance,
u_char *buf,
@@ -2341,7 +2622,6 @@ oncore_msg_BnEnHn(
)
{
long dt1, dt2;
- char *cp;
if (instance->o_state != ONCORE_RUN)
return;
@@ -2349,8 +2629,7 @@ oncore_msg_BnEnHn(
if (instance->traim_delay) { /* flag that @@Bn/@@En/Hn returned */
instance->traim_ck = 1;
instance->traim_delay = 0;
- cp = "ONCORE: Detected TRAIM, TRAIM = ON";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "ONCORE: Detected TRAIM, TRAIM = ON");
oncore_set_traim(instance);
}
@@ -2363,8 +2642,10 @@ oncore_msg_BnEnHn(
/* If Time RAIM doesn't like it, don't trust it */
if (buf[2] == 'H') {
- if (instance->BEHn[6]) /* bad TRAIM */
+ if (instance->BEHn[6]) { /* bad TRAIM */
+ oncore_log(instance, LOG_WARNING, "BAD TRAIM");
return;
+ }
dt1 = instance->saw_tooth + instance->offset; /* dt this time step */
instance->saw_tooth = (s_char) instance->BEHn[14]; /* update for next time Hn[14] */
@@ -2406,7 +2687,7 @@ oncore_msg_CaFaIa(
size_t len
)
{
- char *cp;
+ char Msg[120];
int i;
if (instance->o_state == ONCORE_TEST_SENT) {
@@ -2414,12 +2695,17 @@ oncore_msg_CaFaIa(
instance->timeout = 0;
-#ifdef DEBUG
+#if ONCORE_VERBOSE_SELF_TEST
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]);
+ snprintf(Msg, sizeof(Msg),
+ ">>@@%ca %x %x %x", buf[2],
+ buf[4], buf[5], buf[6]);
else
- printf("ONCORE[%d]: >>@@%ca %x %x\n", instance->unit, buf[2], buf[4], buf[5]);
+ snprintf(Msg, sizeof(Msg),
+ ">>@@%ca %x %x", buf[2],
+ buf[4], buf[5]);
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
@@ -2429,15 +2715,18 @@ oncore_msg_CaFaIa(
i = buf[4] || buf[5];
if (buf[2] == 'I') i = i || buf[6];
if (i) {
- if (buf[2] == 'I') {
- msyslog(LOG_ERR, "ONCORE[%d]: self test failed: result %02x %02x %02x",
- instance->unit, buf[4], buf[5], buf[6]);
- } else {
- msyslog(LOG_ERR, "ONCORE[%d]: self test failed: result %02x %02x",
- instance->unit, buf[4], buf[5]);
- }
- cp = "ONCORE: self test failed, shutting down driver";
- record_clock_stats(&instance->peer->srcadr, cp);
+ if (buf[2] == 'I')
+ snprintf(Msg, sizeof(Msg),
+ "self test failed: result %02x %02x %02x",
+ buf[4], buf[5], buf[6]);
+ else
+ snprintf(Msg, sizeof(Msg),
+ "self test failed: result %02x %02x",
+ buf[4], buf[5]);
+ oncore_log(instance, LOG_ERR, Msg);
+
+ oncore_log(instance, LOG_ERR,
+ "ONCORE: self test failed, shutting down driver");
refclock_report(instance->peer, CEVNT_FAULT);
oncore_shutdown(instance->unit, instance->peer);
@@ -2449,11 +2738,10 @@ oncore_msg_CaFaIa(
oncore_antenna_report(instance, antenna);
instance->o_state = ONCORE_INIT;
- cp = "state = ONCORE_INIT";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_INIT");
instance->timeout = 4;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
}
}
@@ -2484,10 +2772,7 @@ oncore_msg_Cb(
else if (buf[4] == 4 && buf[5] == 25)
i = 34;
else {
- char *cp;
-
- cp = "Cb: Response is NO ALMANAC";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "Cb: Response is NO ALMANAC");
return;
}
@@ -2495,11 +2780,13 @@ oncore_msg_Cb(
instance->shmem[instance->shmem_Cb + i + 2]++;
memcpy(instance->shmem + instance->shmem_Cb + i + 3, buf, (size_t) (len + 3));
-#if 1
+#ifdef ONCORE_VERBOSE_MSG_CB
{
- char Msg[160];
- sprintf(Msg, "See Cb [%d,%d]", buf[4], buf[5]);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ char Msg[160];
+
+ snprintf(Msg, sizeof(Msg), "See Cb [%d,%d]", buf[4],
+ buf[5]);
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
}
@@ -2518,16 +2805,13 @@ oncore_msg_Cf(
size_t len
)
{
- const char *cp;
-
if (instance->o_state == ONCORE_RESET_SENT) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to Posn Fix mode */
+ oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to Posn Fix mode */
/* Reset set VP to IDLE */
instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_TEST_SENT");
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
}
}
@@ -2556,7 +2840,6 @@ oncore_msg_Cj(
)
{
int mode;
- char *cp;
memcpy(instance->Cj, buf, len);
@@ -2568,23 +2851,21 @@ oncore_msg_Cj(
mode = instance->init_type;
if (mode == 3 || mode == 4) { /* Cf will return here to check for TEST */
instance->o_state = ONCORE_RESET_SENT;
- cp = "state = ONCORE_RESET_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_RESET_SENT");
+ oncore_sendmsg(instance, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
} else {
instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_TEST_SENT");
}
}
if (instance->o_state == ONCORE_TEST_SENT) {
if (instance->chan == 6)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
+ oncore_sendmsg(instance, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
else if (instance->chan == 8)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
+ oncore_sendmsg(instance, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
else if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
+ oncore_sendmsg(instance, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
} else if (instance->o_state == ONCORE_INIT)
oncore_msg_Cj_init(instance, buf, len);
}
@@ -2620,7 +2901,7 @@ oncore_msg_Cj_id(
if (!cp1)
cp1 = (char *)&instance->Cj[294];
*cp1 = '\0';
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, cp);
*cp1 = '\r';
cp = cp1+2;
}
@@ -2681,8 +2962,10 @@ oncore_msg_Cj_id(
/* use MODEL to set CHAN and TRAIM and possibly zero SHMEM */
- sprintf(Msg, "This looks like an Oncore %s with version %d.%d firmware.", cp, instance->version, instance->revision);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "This looks like an Oncore %s with version %d.%d firmware.",
+ cp, instance->version, instance->revision);
+ oncore_log(instance, LOG_INFO, Msg);
instance->chan_id = 8; /* default */
if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
@@ -2700,9 +2983,14 @@ oncore_msg_Cj_id(
else if (instance->model == ONCORE_M12)
instance->traim_id = -1;
- sprintf(Msg, "Channels = %d, TRAIM = %s", instance->chan_id,
- ((instance->traim_id < 0) ? "UNKNOWN" : ((instance->traim_id > 0) ? "ON" : "OFF")));
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Channels = %d, TRAIM = %s",
+ instance->chan_id,
+ ((instance->traim_id < 0)
+ ? "UNKNOWN"
+ : (instance->traim_id > 0)
+ ? "ON"
+ : "OFF"));
+ oncore_log(instance, LOG_INFO, Msg);
}
@@ -2720,8 +3008,8 @@ oncore_msg_Cj_init(
size_t len
)
{
- char *cp, Msg[160];
- u_char Cmd[20];
+ char Msg[160];
+ u_char Cmd[20];
int mode;
@@ -2733,17 +3021,19 @@ oncore_msg_Cj_init(
if (instance->chan == 12) {
instance->shmem_bad_Ea = 1;
- sprintf(Msg, "*** SHMEM partially enabled for ONCORE M12 s/w v%d.%d ***", instance->version, instance->revision);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "*** SHMEM partially enabled for ONCORE M12 s/w v%d.%d ***",
+ instance->version, instance->revision);
+ oncore_log(instance, LOG_NOTICE, Msg);
}
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to Posn Fix mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof(oncore_cmd_Bb)); /* turn on for shmem (6/8/12) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof(oncore_cmd_Ek)); /* turn off (VP) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof(oncore_cmd_Aw)); /* UTC time (6/8/12) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof(oncore_cmd_AB)); /* Appl type static (VP) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Be, sizeof(oncore_cmd_Be)); /* Tell us the Almanac for shmem (6/8/12) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bd, sizeof(oncore_cmd_Bd)); /* Tell us when Almanac changes */
+ oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to Posn Fix mode */
+ oncore_sendmsg(instance, oncore_cmd_Bb, sizeof(oncore_cmd_Bb)); /* turn on for shmem (6/8/12) */
+ oncore_sendmsg(instance, oncore_cmd_Ek, sizeof(oncore_cmd_Ek)); /* turn off (VP) */
+ oncore_sendmsg(instance, oncore_cmd_Aw, sizeof(oncore_cmd_Aw)); /* UTC time (6/8/12) */
+ oncore_sendmsg(instance, oncore_cmd_AB, sizeof(oncore_cmd_AB)); /* Appl type static (VP) */
+ oncore_sendmsg(instance, oncore_cmd_Be, sizeof(oncore_cmd_Be)); /* Tell us the Almanac for shmem (6/8/12) */
+ oncore_sendmsg(instance, oncore_cmd_Bd, sizeof(oncore_cmd_Bd)); /* Tell us when Almanac changes */
mode = instance->init_type;
@@ -2753,23 +3043,23 @@ oncore_msg_Cj_init(
*/
if (instance->posn_set) {
- record_clock_stats(&(instance->peer->srcadr), "Setting Posn from input data");
+ oncore_log(instance, LOG_INFO, "Setting Posn from input data");
oncore_set_posn(instance); /* this should print posn indirectly thru the As cmd */
} else /* must issue an @@At here to check on 6/8 Position Hold, set_posn would have */
if (instance->chan != 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Atx, sizeof(oncore_cmd_Atx));
+ oncore_sendmsg(instance, oncore_cmd_Atx, sizeof(oncore_cmd_Atx));
if (mode != 0) {
/* cable delay in ns */
memcpy(Cmd, oncore_cmd_Az, (size_t) sizeof(oncore_cmd_Az));
w32_buf(&Cmd[-2+4], instance->delay);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Az)); /* 6,8,12 */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Az)); /* 6,8,12 */
/* PPS offset in ns */
if (instance->offset) {
memcpy(Cmd, oncore_cmd_Ay, (size_t) sizeof(oncore_cmd_Ay)); /* some have it, some don't */
w32_buf(&Cmd[-2+4], instance->offset); /* will check for hw response */
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ay));
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ay));
}
/* Satellite mask angle */
@@ -2777,7 +3067,7 @@ oncore_msg_Cj_init(
if (instance->Ag != 0xff) { /* will have 0xff in it if not set by user */
memcpy(Cmd, oncore_cmd_Ag, (size_t) sizeof(oncore_cmd_Ag));
Cmd[-2+4] = instance->Ag;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ag));
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ag));
}
}
@@ -2789,29 +3079,28 @@ oncore_msg_Cj_init(
*/
if (instance->chan == 6) { /* start 6chan, kill 8,12chan commands, possibly testing VP in 6chan mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En0, sizeof(oncore_cmd_En0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba, sizeof(oncore_cmd_Ba ));
+ oncore_sendmsg(instance, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
+ oncore_sendmsg(instance, oncore_cmd_En0, sizeof(oncore_cmd_En0));
+ oncore_sendmsg(instance, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
+ oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
+ oncore_sendmsg(instance, oncore_cmd_Ba, sizeof(oncore_cmd_Ba ));
} else if (instance->chan == 8) { /* start 8chan, kill 6,12chan commands */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof(oncore_cmd_Ea ));
+ oncore_sendmsg(instance, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
+ oncore_sendmsg(instance, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
+ oncore_sendmsg(instance, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
+ oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
+ oncore_sendmsg(instance, oncore_cmd_Ea, sizeof(oncore_cmd_Ea ));
} else if (instance->chan == 12){ /* start 12chan, kill 6,12chan commands */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En0, sizeof(oncore_cmd_En0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha, sizeof(oncore_cmd_Ha ));
+ oncore_sendmsg(instance, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
+ oncore_sendmsg(instance, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
+ oncore_sendmsg(instance, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
+ oncore_sendmsg(instance, oncore_cmd_En0, sizeof(oncore_cmd_En0));
+ oncore_sendmsg(instance, 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);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_ALMANAC");
}
@@ -2843,8 +3132,10 @@ oncore_msg_Ga(
Ht /= 100;
- sprintf(Msg, "Ga Posn Lat = %.7f, Lon = %.7f, Ht = %.2f", Lat, Lon, Ht);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Ga Posn Lat = %.7f, Lon = %.7f, Ht = %.2f", Lat,
+ Lon, Ht);
+ oncore_log(instance, LOG_NOTICE, Msg);
instance->ss_lat = lat;
instance->ss_long = lon;
@@ -2879,9 +3170,10 @@ oncore_msg_Gb(
gmth = buf[12];
gmtm = buf[13];
- sprintf(Msg, "Date/Time set to: %d%s%d %2d:%02d:%02d GMT (GMT offset is %s%02d:%02d)",
- d, Month[mo-1], y, h, m, s, gmts, gmth, gmtm);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Date/Time set to: %d%s%d %2d:%02d:%02d GMT (GMT offset is %s%02d:%02d)",
+ d, Month[mo-1], y, h, m, s, gmts, gmth, gmtm);
+ oncore_log(instance, LOG_NOTICE, Msg);
}
@@ -2905,20 +3197,21 @@ oncore_msg_Gj(
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
+ snprintf(Msg, sizeof(Msg),
+ "Leap Sec Msg: %d %d %d %d %d %d %d %d %d %d", 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]);
+ oncore_log(instance, LOG_INFO, Msg);
+
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]-1], 256*buf[6]+buf[7],
- buf[15], buf[16], buf[17]);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Leap second (%d) scheduled for %d%s%d at %d:%d:%d",
+ dt, buf[9], Month[buf[8] - 1],
+ 256 * buf[6] + buf[7], buf[15], buf[16],
+ buf[17]);
+ oncore_log(instance, LOG_NOTICE, Msg);
}
/* Only raise warning within a month of the leap second */
@@ -2938,7 +3231,7 @@ oncore_msg_Gj(
}
}
}
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_INFO, cp);
}
@@ -2952,11 +3245,8 @@ oncore_msg_Sz(
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_log(instance, LOG_ERR, "Oncore: System Failure at Power On");
oncore_shutdown(instance->unit, instance->peer);
}
}
@@ -2983,7 +3273,7 @@ oncore_antenna_report(
}
instance->ant_state = new_state;
- record_clock_stats(&instance->peer->srcadr, cp);
+ oncore_log(instance, LOG_NOTICE, cp);
}
@@ -2993,8 +3283,6 @@ oncore_chan_test(
struct instance *instance
)
{
- char *cp;
-
/* subroutine oncore_Cj_id has determined the number of channels from the
* model number of the attached oncore. This is not always correct since
* the oncore could have non-standard firmware. Here we check (independently) by
@@ -3005,13 +3293,12 @@ oncore_chan_test(
*/
instance->o_state = ONCORE_CHECK_CHAN;
- cp = "state = ONCORE_CHECK_CHAN";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_CHECK_CHAN");
instance->count3 = 1;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha, sizeof(oncore_cmd_Ha));
+ oncore_sendmsg(instance, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
+ oncore_sendmsg(instance, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
+ oncore_sendmsg(instance, oncore_cmd_Ha, sizeof(oncore_cmd_Ha));
}
@@ -3043,17 +3330,21 @@ oncore_check_almanac(
instance->count5 = 2;
instance->count5_set = 1;
}
-#if 0
-{
- char Msg[160];
-
- sprintf(Msg, "ONCORE[%d]: DEBUG BITS: (%x %x), (%x %x %x), %x %x %x %x %x\n",
- instance->unit,
- instance->BEHa[129], instance->BEHa[130], bits1, bits2, bits3, instance->mode == MODE_0D,
- instance->mode == MODE_2D, instance->mode == MODE_3D,
- instance->rsm.bad_almanac, instance->rsm.bad_fix);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
+#ifdef ONCORE_VERBOSE_CHECK_ALMANAC
+ {
+ char Msg[160];
+
+ snprintf(Msg, sizeof(Msg),
+ "DEBUG BITS: (%x %x), (%x %x %x), %x %x %x %x %x",
+ instance->BEHa[129],
+ instance->BEHa[130], bits1, bits2,
+ bits3, instance->mode == MODE_0D,
+ instance->mode == MODE_2D,
+ instance->mode == MODE_3D,
+ instance->rsm.bad_almanac,
+ instance->rsm.bad_fix);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ }
#endif
}
}
@@ -3108,19 +3399,21 @@ oncore_check_leap_sec(
struct instance *instance
)
{
- if (instance->Bj_day != instance->BEHa[5]) { /* do this 1/day */
+ oncore_cmd_Bl[2] = 1; /* just to be sure */
+ if (instance->Bj_day != instance->BEHa[5]) { /* do this 1/day */
instance->Bj_day = instance->BEHa[5];
if (instance->saw_Gj < 0) { /* -1 DONT have Gj use Bj */
if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
+ oncore_sendmsg(instance, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
+ oncore_sendmsg(instance, oncore_cmd_Bl, sizeof(oncore_cmd_Bl));
return;
}
if (instance->saw_Gj == 0) /* 0 is dont know if we have Gj */
instance->count4 = 1;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
+ oncore_sendmsg(instance, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
return;
}
@@ -3135,7 +3428,8 @@ oncore_check_leap_sec(
instance->saw_Gj = -1; /* didnt see it, will use Bj */
instance->count4 = 0;
if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
+ oncore_sendmsg(instance, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
+ oncore_sendmsg(instance, oncore_cmd_Bl, sizeof(oncore_cmd_Bl));
}
}
}
@@ -3189,8 +3483,9 @@ oncore_compute_dH(
/* if MSL is not set, the calculation is meaningless */
if (MSL) { /* not set ! */
- sprintf(Msg, "dH = (GPS - MSL) = %.2fm", instance->dH);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "dH = (GPS - MSL) = %.2fm",
+ instance->dH);
+ oncore_log(instance, LOG_INFO, Msg);
}
}
@@ -3213,44 +3508,43 @@ oncore_load_almanac(
if (!instance->shmem)
return;
-#if 1
- for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
+#ifndef ONCORE_VERBOSE_LOAD_ALMANAC
+ for (cp = instance->shmem + 4; (n = 256 * (*(cp-3)) + *(cp-2));
+ cp += (n + 3)) {
if (!strncmp((char *) cp, "@@Cb", 4) &&
oncore_checksum_ok(cp, 33) &&
(*(cp+4) == 4 || *(cp+4) == 5)) {
write(instance->ttyfd, cp, n);
-#if 1
oncore_print_Cb(instance, cp);
-#endif
}
}
-#else
-/************DEBUG************/
- for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
+#else /* ONCORE_VERBOSE_LOAD_ALMANAC follows */
+ for (cp = instance->shmem + 4; (n = 256 * (*(cp-3)) + *(cp-2));
+ cp += (n+3)) {
char Msg[160];
- sprintf(Msg, "See %c%c%c%c %d", *(cp), *(cp+1), *(cp+2), *(cp+3), *(cp+4));
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "See %c%c%c%c %d", *(cp),
+ *(cp+1), *(cp+2), *(cp+3), *(cp+4));
+ oncore_log(instance, LOG_DEBUG, Msg);
if (!strncmp(cp, "@@Cb", 4)) {
oncore_print_Cb(instance, cp);
if (oncore_checksum_ok(cp, 33)) {
if (*(cp+4) == 4 || *(cp+4) == 5) {
- record_clock_stats(&(instance->peer->srcadr), "GOOD SF");
+ oncore_log(instance, LOG_DEBUG, "GOOD SF");
write(instance->ttyfd, cp, n);
} else
- record_clock_stats(&(instance->peer->srcadr), "BAD SF");
+ oncore_log(instance, LOG_DEBUG, "BAD SF");
} else
- record_clock_stats(&(instance->peer->srcadr), "BAD CHECKSUM");
+ oncore_log(instance, LOG_DEBUG, "BAD CHECKSUM");
}
}
-/************DEBUG************/
#endif
/* Must load position and time or the Almanac doesn't do us any good */
if (!instance->posn_set) { /* if we input a posn use it, else from SHMEM */
- record_clock_stats(&(instance->peer->srcadr), "Loading Posn from SHMEM");
+ oncore_log(instance, LOG_NOTICE, "Loading Posn from SHMEM");
for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
if ((instance->chan == 6 && (!strncmp((char *) cp, "@@Ba", 4) && oncore_checksum_ok(cp, 68))) ||
(instance->chan == 8 && (!strncmp((char *) cp, "@@Ea", 4) && oncore_checksum_ok(cp, 76))) ||
@@ -3261,12 +3555,15 @@ oncore_load_almanac(
ii = buf_w32(cp + 15);
jj = buf_w32(cp + 19);
kk = buf_w32(cp + 23);
-#if 0
-{
-char Msg[160];
-sprintf(Msg, "SHMEM posn = %ld (%d, %d, %d)", (long) (cp-instance->shmem), ii, jj, kk);
-record_clock_stats(&(instance->peer->srcadr), Msg);
-}
+#ifdef ONCORE_VERBOSE_LOAD_ALMANAC
+ {
+ char Msg[160];
+ snprintf(Msg, sizeof(Msg),
+ "SHMEM posn = %ld (%d, %d, %d)",
+ (long)(cp-instance->shmem),
+ ii, jj, kk);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ }
#endif
if (ii != 0 || jj != 0 || kk != 0) { /* phk asked for this test */
instance->ss_lat = ii;
@@ -3280,14 +3577,16 @@ record_clock_stats(&(instance->peer->srcadr), Msg);
/* and set time to time from Computer clock */
- gettimeofday(&tv, 0);
+ GETTIMEOFDAY(&tv, 0);
tm = gmtime((const time_t *) &tv.tv_sec);
-#if 1
+
+#ifdef ONCORE_VERBOSE_LOAD_ALMANAC
{
- char Msg[160];
- sprintf(Msg, "DATE %d %d %d, %d %d %d", 1900+tm->tm_year, tm->tm_mon, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ char Msg[160];
+ snprintf(Msg, sizeof(Msg), "DATE %d %d %d, %d %d %d",
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (instance->chan == 12) {
@@ -3302,27 +3601,27 @@ record_clock_stats(&(instance->peer->srcadr), Msg);
Cmd[-2+11] = 0;
Cmd[-2+12] = 0;
Cmd[-2+13] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Gb));
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Gb));
} else {
/* First set GMT offset to zero */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ab, sizeof(oncore_cmd_Ab));
+ oncore_sendmsg(instance, oncore_cmd_Ab, sizeof(oncore_cmd_Ab));
memcpy(Cmd, oncore_cmd_Ac, (size_t) sizeof(oncore_cmd_Ac));
Cmd[-2+4] = tm->tm_mon + 1;
Cmd[-2+5] = tm->tm_mday;
Cmd[-2+6] = (1900+tm->tm_year)/256;
Cmd[-2+7] = (1900+tm->tm_year)%256;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ac));
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ac));
memcpy(Cmd, oncore_cmd_Aa, (size_t) sizeof(oncore_cmd_Aa));
Cmd[-2+4] = tm->tm_hour;
Cmd[-2+5] = tm->tm_min;
Cmd[-2+6] = tm->tm_sec;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Aa));
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Aa));
}
- record_clock_stats(&(instance->peer->srcadr), "Setting Posn and Time after Loading Almanac");
+ oncore_log(instance, LOG_INFO, "Setting Posn and Time after Loading Almanac");
}
@@ -3335,18 +3634,24 @@ oncore_print_Cb(
u_char *cp
)
{
-#if 0
+#ifdef ONCORE_VERBOSE_CB
int ii;
- char Msg[160];
-
- printf("DEBUG: See: %c%c%c%c\n", *(cp), *(cp+1), *(cp+2), *(cp+3));
- printf("DEBUG: Cb: [%d,%d]", *(cp+4), *(cp+5));
- for(ii=0; ii<33; ii++)
- printf(" %d", *(cp+ii));
- printf("\n");
+ char Msg[160], Msg2[10];
+
+ snprintf(Msg, sizeof(Msg), "DEBUG: See: %c%c%c%c", *(cp),
+ *(cp+1), *(cp+2), *(cp+3));
+ oncore_log(instance, LOG_DEBUG, Msg);
+ snprintf(Msg, sizeof(Msg), "DEBUG: Cb: [%d,%d]", *(cp+4),
+ *(cp+5));
+ for(ii = 0; ii < 33; ii++) {
+ snprintf(Msg2, sizeof(Msg2), " %d", *(cp+ii));
+ strncat(Msg, Msg2, sizeof(Msg));
+ }
+ oncore_log(instance, LOG_DEBUG, Msg);
- sprintf(Msg, "Debug: Cb: [%d,%d]", *(cp+4), *(cp+5));
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Debug: Cb: [%d,%d]", *(cp+4),
+ *(cp+5));
+ oncore_log(instance, LOG_DEBUG, Msg);
#endif
}
@@ -3384,7 +3689,7 @@ oncore_print_posn(
int idx, idy, is, imx, imy;
long lat, lon;
- record_clock_stats(&(instance->peer->srcadr), "Posn:");
+ oncore_log(instance, LOG_INFO, "Posn:");
ew = 'E';
lon = instance->ss_long;
if (lon < 0) {
@@ -3404,8 +3709,10 @@ oncore_print_posn(
xd = lat/3600000.; /* lat, lon in int msec arc, ht in cm. */
yd = lon/3600000.;
- sprintf(Msg, "Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) GPS", ns, xd, ew, yd, hm, hft);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) GPS",
+ ns, xd, ew, yd, hm, hft);
+ oncore_log(instance, LOG_INFO, Msg);
idx = xd;
idy = yd;
@@ -3413,9 +3720,9 @@ oncore_print_posn(
imy = lon%3600000;
xm = imx/60000.;
ym = imy/60000.;
- sprintf(Msg,
+ snprintf(Msg, sizeof(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);
+ oncore_log(instance, LOG_INFO, Msg);
imx = xm;
imy = ym;
@@ -3423,9 +3730,10 @@ oncore_print_posn(
xs = is/1000.;
is = lon%60000;
ys = is/1000.;
- sprintf(Msg,
- "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %7.2fm (%7.2fft) GPS", ns, idx, imx, xs, ew, idy, imy, ys, hm, hft);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(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);
+ oncore_log(instance, LOG_INFO, Msg);
}
@@ -3436,16 +3744,23 @@ oncore_print_posn(
static void
oncore_sendmsg(
- int fd,
+ struct instance *instance,
u_char *ptr,
size_t len
)
{
+ int fd;
u_char cs = 0;
-#ifdef DEBUG
- if (debug > 4)
- printf("ONCORE: Send @@%c%c %d\n", ptr[0], ptr[1], (int) len);
+ fd = instance->ttyfd;
+#ifdef ONCORE_VERBOSE_SENDMSG
+ if (debug > 4) {
+ char Msg[120];
+
+ snprintf(Msg, sizeof(Msg), "ONCORE: Send @@%c%c %d",
+ ptr[0], ptr[1], (int)len);
+ oncore_log(instance, LOG_DEBUG, Msg);
+ }
#endif
write(fd, "@@", (size_t) 2);
write(fd, ptr, len);
@@ -3469,10 +3784,10 @@ oncore_set_posn(
will get set ON in @@Ea later */
if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* (12) */
+ oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* (12) */
else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* (6/8) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* (6/8) */
+ oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* (6/8) */
+ oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* (6/8) */
}
mode = instance->init_type;
@@ -3483,12 +3798,12 @@ oncore_set_posn(
w32_buf(&Cmd[-2+8], (int) instance->ss_long);
w32_buf(&Cmd[-2+12], (int) instance->ss_ht);
Cmd[-2+16] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_As)); /* posn hold 3D posn (6/8/12) */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_As)); /* posn hold 3D posn (6/8/12) */
memcpy(Cmd, oncore_cmd_Au, (size_t) sizeof(oncore_cmd_Au));
w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
Cmd[-2+8] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Au)); /* altitude hold (6/8/12 not UT, M12T) */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Au)); /* altitude hold (6/8/12 not UT, M12T) */
/* next set current position */
@@ -3498,28 +3813,28 @@ oncore_set_posn(
w32_buf(&Cmd[-2+8], (int) instance->ss_long);
w32_buf(&Cmd[-2+12],(int) instance->ss_ht);
Cmd[-2+16] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ga)); /* 3d posn (12) */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ga)); /* 3d posn (12) */
} else {
memcpy(Cmd, oncore_cmd_Ad, (size_t) sizeof(oncore_cmd_Ad));
w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ad)); /* lat (6/8) */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ad)); /* lat (6/8) */
memcpy(Cmd, oncore_cmd_Ae, (size_t) sizeof(oncore_cmd_Ae));
w32_buf(&Cmd[-2+4], (int) instance->ss_long);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ae)); /* long (6/8) */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ae)); /* long (6/8) */
memcpy(Cmd, oncore_cmd_Af, (size_t) sizeof(oncore_cmd_Af));
w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
Cmd[-2+8] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Af)); /* ht (6/8) */
+ oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Af)); /* ht (6/8) */
}
/* Finally, turn on position hold */
if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
+ oncore_sendmsg(instance, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1));
+ oncore_sendmsg(instance, oncore_cmd_At1, sizeof(oncore_cmd_At1));
}
}
@@ -3537,25 +3852,29 @@ oncore_set_traim(
else
instance->traim = instance->traim_ck;
- sprintf(Msg, "Input says TRAIM = %d", instance->traim_in);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Model # says TRAIM = %d", instance->traim_id);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Testing says TRAIM = %d", instance->traim_ck);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Using TRAIM = %d", instance->traim);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg), "Input says TRAIM = %d",
+ instance->traim_in);
+ oncore_log(instance, LOG_INFO, Msg);
+ snprintf(Msg, sizeof(Msg), "Model # says TRAIM = %d",
+ instance->traim_id);
+ oncore_log(instance, LOG_INFO, Msg);
+ snprintf(Msg, sizeof(Msg), "Testing says TRAIM = %d",
+ instance->traim_ck);
+ oncore_log(instance, LOG_INFO, Msg);
+ snprintf(Msg, sizeof(Msg), "Using TRAIM = %d",
+ instance->traim);
+ oncore_log(instance, LOG_INFO, Msg);
if (instance->traim_ck == 1 && instance->traim == 0) {
/* if it should be off, and I turned it on during testing,
then turn it off again */
if (instance->chan == 6)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bnx, sizeof(oncore_cmd_Bnx));
+ oncore_sendmsg(instance, oncore_cmd_Bnx, sizeof(oncore_cmd_Bnx));
else if (instance->chan == 8)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Enx, sizeof(oncore_cmd_Enx));
+ oncore_sendmsg(instance, oncore_cmd_Enx, sizeof(oncore_cmd_Enx));
else /* chan == 12 */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ge0, sizeof(oncore_cmd_Ge0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
+ oncore_sendmsg(instance, oncore_cmd_Ge0, sizeof(oncore_cmd_Ge0));
+ oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
}
}
@@ -3574,28 +3893,28 @@ oncore_shmem_get_3D(
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 */
+ oncore_sendmsg(instance, oncore_cmd_Gd2, sizeof(oncore_cmd_Gd2)); /* 2D */
else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* 3D */
+ oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* 3D */
} else {
if (instance->saw_At) { /* out of 0D -> 3D mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0));
+ oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0));
if (instance->shmem_Posn == 2) /* 3D -> 2D mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
} else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
+ oncore_sendmsg(instance, 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 */
+ oncore_sendmsg(instance, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1)); /* 0D */
else {
if (instance->saw_At) {
if (instance->mode == MODE_2D) /* 2D -> 3D or 0D mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1)); /* to 0D mode */
+ oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
+ oncore_sendmsg(instance, oncore_cmd_At1, sizeof(oncore_cmd_At1)); /* to 0D mode */
} else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
}
}
}
@@ -3614,7 +3933,7 @@ oncore_ss(
struct instance *instance
)
{
- char *cp, Msg[160];
+ char Msg[160];
double lat, lon, ht;
@@ -3625,15 +3944,14 @@ oncore_ss(
if ((instance->chan == 8 && !(instance->BEHa[37] & 0x20)) ||
(instance->chan == 12 && !(instance->BEHa[130] & 0x10))) {
- record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
+ oncore_log(instance, LOG_INFO, "Now in 0D mode");
if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gax, sizeof(oncore_cmd_Gax));
+ oncore_sendmsg(instance, oncore_cmd_Gax, sizeof(oncore_cmd_Gax));
else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
+ oncore_sendmsg(instance, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
- cp = "SSstate = ONCORE_SS_DONE";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
instance->site_survey = ONCORE_SS_DONE;
}
} else {
@@ -3659,22 +3977,24 @@ oncore_ss(
instance->ss_long /= POS_HOLD_AVERAGE;
instance->ss_ht /= POS_HOLD_AVERAGE;
- sprintf(Msg, "Surveyed posn: lat %.3f (mas) long %.3f (mas) ht %.3f (cm)",
- instance->ss_lat, instance->ss_long, instance->ss_ht);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Surveyed posn: lat %.3f (mas) long %.3f (mas) ht %.3f (cm)",
+ instance->ss_lat, instance->ss_long,
+ instance->ss_ht);
+ oncore_log(instance, LOG_NOTICE, Msg);
lat = instance->ss_lat/3600000.;
lon = instance->ss_long/3600000.;
ht = instance->ss_ht/100;
- sprintf(Msg, "Surveyed posn: lat %.7f (deg) long %.7f (deg) ht %.2f (m)",
- lat, lon, ht);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ snprintf(Msg, sizeof(Msg),
+ "Surveyed posn: lat %.7f (deg) long %.7f (deg) ht %.2f (m)",
+ lat, lon, ht);
+ oncore_log(instance, LOG_NOTICE, Msg);
oncore_set_posn(instance);
- record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
+ oncore_log(instance, LOG_INFO, "Now in 0D mode");
- cp = "SSstate = ONCORE_SS_DONE";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
instance->site_survey = ONCORE_SS_DONE;
}
}
@@ -3687,10 +4007,9 @@ oncore_wait_almanac(
)
{
if (instance->rsm.bad_almanac) {
-#ifdef DEBUG
- if (debug)
- printf("ONCORE[%d]: waiting for almanac\n", instance->unit);
-#endif
+ instance->counta++;
+ if (instance->counta%5 == 0)
+ oncore_log(instance, LOG_INFO, "Waiting for Almanac");
/*
* If we get here (first time) then we don't have an almanac in memory.
@@ -3707,26 +4026,71 @@ oncore_wait_almanac(
(5sec) and wait for things to settle down */
if (instance->chan == 6)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn, sizeof(oncore_cmd_Bn));
+ oncore_sendmsg(instance, oncore_cmd_Bn, sizeof(oncore_cmd_Bn));
else if (instance->chan == 8)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En, sizeof(oncore_cmd_En));
+ oncore_sendmsg(instance, oncore_cmd_En, sizeof(oncore_cmd_En));
else if (instance->chan == 12) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gc, sizeof(oncore_cmd_Gc)); /* 1PPS on, continuous */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ge, sizeof(oncore_cmd_Ge)); /* TRAIM on */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn, sizeof(oncore_cmd_Hn)); /* TRAIM status 1/s */
+ oncore_sendmsg(instance, oncore_cmd_Gc, sizeof(oncore_cmd_Gc)); /* 1PPS on, continuous */
+ oncore_sendmsg(instance, oncore_cmd_Ge, sizeof(oncore_cmd_Ge)); /* TRAIM on */
+ oncore_sendmsg(instance, oncore_cmd_Hn, sizeof(oncore_cmd_Hn)); /* TRAIM status 1/s */
}
instance->traim_delay = 1;
- record_clock_stats(&(instance->peer->srcadr), "Have now loaded an ALMANAC");
+ oncore_log(instance, LOG_NOTICE, "Have now loaded an ALMANAC");
instance->o_state = ONCORE_RUN;
- record_clock_stats(&(instance->peer->srcadr), "state = ONCORE_RUN");
+ oncore_log(instance, LOG_NOTICE, "state = ONCORE_RUN");
}
return(0);
}
+static void
+oncore_log (
+ struct instance *instance,
+ int log_level,
+ const char *msg
+ )
+{
+ int i;
+ char Msg[200];
+
+ snprintf(Msg, sizeof(Msg), "ONCORE[%d]: %s", instance->unit,
+ msg);
+ syslog(log_level, Msg);
+
+ i = strlen(msg);
+
+ if (i > 127) {
+ snprintf(Msg, sizeof(Msg),
+ "Internal Error: max error msg length exceeded in clockstats file (%d)",
+ i);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ record_clock_stats(&(instance->peer->srcadr), "Start of message was");
+ strncpy(Msg, msg, 120);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ } else { /* now put ONCORE[n]: ahead of message if it will fit */
+ if (i < 110) {
+ snprintf(Msg, sizeof(Msg), "ONCORE[%d]: %s",
+ instance->unit, msg);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ } else
+ record_clock_stats(&(instance->peer->srcadr), msg);
+ }
+
+#ifdef ONCORE_VERBOSE_ONCORE_LOG
+ instance->max_len = max(i, instance->max_len);
+ instance->max_count++;
+ if (instance->max_count % 100 == 0) {
+ snprintf(Msg, sizeof(Msg),
+ "Max Message Length so far is %d",
+ instance->max_len);
+ oncore_log(instance, LOG_INFO, Msg);
+ }
+#endif
+}
+
#else
int refclock_oncore_bs;
-#endif /* REFCLOCK */
+#endif /* REFCLOCK && CLOCK_ONCORE */
diff --git a/ntpd/refclock_palisade.c b/ntpd/refclock_palisade.c
index adb4659f97bb..ffe520d01d40 100644
--- a/ntpd/refclock_palisade.c
+++ b/ntpd/refclock_palisade.c
@@ -50,13 +50,28 @@
*
* Version 2.45; July 14, 1999
*
+ *
+ *
+ * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock.
+ * Contact: Fernando Pablo Hauscarriaga
+ * E-mail: fernandoph@iar.unlp.edu.ar
+ * Home page: www.iar.unlp.edu.ar/~fernandoph
+ * Instituto Argentino de Radioastronomia
+ * www.iar.unlp.edu.ar
+ *
+ * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed
+ * now we use mode 2 for decode thunderbolt packets.
+ * Fernando P. Hauscarriaga
+ *
+ * 30/08/09: Added support for Trimble Acutime Gold Receiver.
+ * Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar)
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
-#if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
+#if defined(REFCLOCK) && defined(CLOCK_PALISADE)
#ifdef SYS_WINNT
extern int async_write(int, const void *, unsigned int);
@@ -72,11 +87,11 @@ const int days_of_year [12] = {
#ifdef DEBUG
const char * Tracking_Status[15][15] = {
- { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
- {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
- { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
- { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
- { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
+ { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
+ {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
+ { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
+ { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
+ { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
#endif
/*
@@ -92,7 +107,7 @@ struct refclock refclock_palisade = {
NOFLAGS /* not used */
};
-int day_of_year P((char *dt));
+int day_of_year (char *dt);
/* Extract the clock type from the mode setting */
#define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
@@ -100,49 +115,170 @@ int day_of_year P((char *dt));
/* Supported clock types */
#define CLK_TRIMBLE 0 /* Trimble Palisade */
#define CLK_PRAECIS 1 /* Endrun Technologies Praecis */
+#define CLK_THUNDERBOLT 2 /* Trimble Thunderbolt GPS Receiver */
+#define CLK_ACUTIME 3 /* Trimble Acutime Gold */
+#define CLK_ACUTIMEB 4 /* Trimble Actutime Gold Port B */
int praecis_msg;
static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
+/* These routines are for sending packets to the Thunderbolt receiver
+ * They are taken from Markus Prosch
+ */
+
+#ifdef PALISADE_SENDCMD_RESURRECTED
+/*
+ * sendcmd - Build data packet for sending
+ */
+static void
+sendcmd (
+ struct packettx *buffer,
+ int c
+ )
+{
+ *buffer->data = DLE;
+ *(buffer->data + 1) = (unsigned char)c;
+ buffer->size = 2;
+}
+#endif /* PALISADE_SENDCMD_RESURRECTED */
+
+/*
+ * sendsupercmd - Build super data packet for sending
+ */
+static void
+sendsupercmd (
+ struct packettx *buffer,
+ int c1,
+ int c2
+ )
+{
+ *buffer->data = DLE;
+ *(buffer->data + 1) = (unsigned char)c1;
+ *(buffer->data + 2) = (unsigned char)c2;
+ buffer->size = 3;
+}
+
+/*
+ * sendbyte -
+ */
+static void
+sendbyte (
+ struct packettx *buffer,
+ int b
+ )
+{
+ if (b == DLE)
+ *(buffer->data+buffer->size++) = DLE;
+ *(buffer->data+buffer->size++) = (unsigned char)b;
+}
+
+/*
+ * sendint -
+ */
+static void
+sendint (
+ struct packettx *buffer,
+ int a
+ )
+{
+ sendbyte(buffer, (unsigned char)((a>>8) & 0xff));
+ sendbyte(buffer, (unsigned char)(a & 0xff));
+}
+
+/*
+ * sendetx - Send packet or super packet to the device
+ */
+static int
+sendetx (
+ struct packettx *buffer,
+ int fd
+ )
+{
+ int result;
+
+ *(buffer->data+buffer->size++) = DLE;
+ *(buffer->data+buffer->size++) = ETX;
+ result = write(fd, buffer->data, (unsigned long)buffer->size);
+
+ if (result != -1)
+ return (result);
+ else
+ return (-1);
+}
+
+/*
+ * init_thunderbolt - Prepares Thunderbolt receiver to be used with
+ * NTP (also taken from Markus Prosch).
+ */
+static void
+init_thunderbolt (
+ int fd
+ )
+{
+ struct packettx tx;
+
+ tx.size = 0;
+ tx.data = (u_char *) malloc(100);
+
+ /* set UTC time */
+ sendsupercmd (&tx, 0x8E, 0xA2);
+ sendbyte (&tx, 0x3);
+ sendetx (&tx, fd);
+
+ /* activate packets 0x8F-AB and 0x8F-AC */
+ sendsupercmd (&tx, 0x8F, 0xA5);
+ sendint (&tx, 0x5);
+ sendetx (&tx, fd);
+
+ free(tx.data);
+}
+
+/*
+ * init_acutime - Prepares Acutime Receiver to be used with NTP
+ */
+static void
+init_acutime (
+ int fd
+ )
+{
+ /* Disable all outputs, Enable Event-Polling on PortA so
+ we can ask for time packets */
+ struct packettx tx;
+
+ tx.size = 0;
+ tx.data = (u_char *) malloc(100);
+
+ sendsupercmd(&tx, 0x8E, 0xA5);
+ sendbyte(&tx, 0x02);
+ sendbyte(&tx, 0x00);
+ sendbyte(&tx, 0x00);
+ sendbyte(&tx, 0x00);
+ sendetx(&tx, fd);
+
+ free(tx.data);
+}
+
/*
* palisade_start - open the devices and initialize data for processing
*/
static int
palisade_start (
-#ifdef PALISADE
- unit, peer
- )
- int unit;
- struct peer *peer;
-#else /* ANSI */
int unit,
struct peer *peer
)
-#endif
{
struct palisade_unit *up;
struct refclockproc *pp;
int fd;
char gpsdev[20];
-
struct termios tio;
-#ifdef SYS_WINNT
- (void) sprintf(gpsdev, "COM%d:", unit);
-#else
- (void) sprintf(gpsdev, DEVICE, unit);
-#endif
+
+ snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
+
/*
* Open serial port.
*/
-#if defined PALISADE
- fd = open(gpsdev, O_RDWR
-#ifdef O_NONBLOCK
- | O_NONBLOCK
-#endif
- );
-#else /* NTP 4.x */
fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
-#endif
if (fd <= 0) {
#ifdef DEBUG
printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
@@ -153,75 +289,56 @@ palisade_start (
msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
gpsdev);
-#if defined PALISADE
- tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
- tio.c_iflag = (IGNBRK);
- tio.c_oflag = (0);
- tio.c_lflag = (0);
-
- if (cfsetispeed(&tio, SPEED232) == -1) {
- msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit);
-#endif
- return 0;
- }
- if (cfsetospeed(&tio, SPEED232) == -1) {
-#ifdef DEBUG
- printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit);
-#endif
- msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit);
- return 0;
- }
-#else /* NTP 4.x */
- if (tcgetattr(fd, &tio) < 0) {
- msyslog(LOG_ERR,
+ if (tcgetattr(fd, &tio) < 0) {
+ msyslog(LOG_ERR,
"Palisade(%d) tcgetattr(fd, &tio): %m",unit);
#ifdef DEBUG
- printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
+ printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
#endif
- return (0);
- }
+ close(fd);
+ return (0);
+ }
- tio.c_cflag |= (PARENB|PARODD);
- tio.c_iflag &= ~ICRNL;
-#endif /* NTP 4.x */
-
- if (tcsetattr(fd, TCSANOW, &tio) == -1) {
- msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
-#endif
- return 0;
- }
+ tio.c_cflag |= (PARENB|PARODD);
+ tio.c_iflag &= ~ICRNL;
/*
* Allocate and initialize unit structure
*/
up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit));
-
- if (!(up)) {
- msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) emalloc\n",unit);
-#endif
- (void) close(fd);
- return (0);
- }
memset((char *)up, 0, sizeof(struct palisade_unit));
up->type = CLK_TYPE(peer);
switch (up->type) {
- case CLK_TRIMBLE:
- /* Normal mode, do nothing */
- break;
- case CLK_PRAECIS:
- msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled\n",unit);
- break;
- default:
- msyslog(LOG_NOTICE, "Palisade(%d) mode unknown\n",unit);
- break;
+ case CLK_TRIMBLE:
+ /* Normal mode, do nothing */
+ break;
+ case CLK_PRAECIS:
+ msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled\n"
+ ,unit);
+ break;
+ case CLK_THUNDERBOLT:
+ msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled\n"
+ ,unit);
+ tio.c_cflag = (CS8|CLOCAL|CREAD);
+ break;
+ case CLK_ACUTIME:
+ msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled\n"
+ ,unit);
+ break;
+ default:
+ msyslog(LOG_NOTICE, "Palisade(%d) mode unknown\n",unit);
+ break;
+ }
+ if (tcsetattr(fd, TCSANOW, &tio) == -1) {
+ msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
+#ifdef DEBUG
+ printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
+#endif
+ close(fd);
+ free(up);
+ return 0;
}
pp = peer->procptr;
@@ -231,9 +348,10 @@ palisade_start (
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
#ifdef DEBUG
- printf("Palisade(%d) io_addclock\n",unit);
+ printf("Palisade(%d) io_addclock\n",unit);
#endif
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -253,7 +371,12 @@ palisade_start (
up->leap_status = 0;
up->unit = (short) unit;
up->rpt_status = TSIP_PARSED_EMPTY;
- up->rpt_cnt = 0;
+ up->rpt_cnt = 0;
+
+ if (up->type == CLK_THUNDERBOLT)
+ init_thunderbolt(fd);
+ if (up->type == CLK_ACUTIME)
+ init_acutime(fd);
return 1;
}
@@ -264,23 +387,18 @@ palisade_start (
*/
static void
palisade_shutdown (
-#ifdef PALISADE
- unit, peer
- )
- int unit;
- struct peer *peer;
-#else /* ANSI */
int unit,
struct peer *peer
)
-#endif
{
struct palisade_unit *up;
struct refclockproc *pp;
pp = peer->procptr;
up = (struct palisade_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -290,29 +408,23 @@ palisade_shutdown (
*/
int
day_of_year (
-#ifdef PALISADE
- dt
- )
- char * dt;
-#else
char * dt
)
-#endif
{
int day, mon, year;
mon = dt[1];
- /* Check month is inside array bounds */
- if ((mon < 1) || (mon > 12))
+ /* Check month is inside array bounds */
+ if ((mon < 1) || (mon > 12))
return -1;
day = dt[0] + days_of_year[mon - 1];
year = getint((u_char *) (dt + 2));
if ( !(year % 4) && ((year % 100) ||
- (!(year % 100) && !(year%400)))
- &&(mon > 2))
- day ++; /* leap year and March or later */
+ (!(year % 100) && !(year%400)))
+ &&(mon > 2))
+ day ++; /* leap year and March or later */
return day;
}
@@ -323,14 +435,8 @@ day_of_year (
*/
int
TSIP_decode (
-#ifdef PALISADE
- peer
- )
- struct peer *peer;
-#else
struct peer *peer
)
-#endif
{
int st;
long secint;
@@ -350,182 +456,430 @@ TSIP_decode (
* proper format, declare bad format and exit.
*/
- if ((up->rpt_buf[0] == (char) 0x41) ||
- (up->rpt_buf[0] == (char) 0x46) ||
- (up->rpt_buf[0] == (char) 0x54) ||
- (up->rpt_buf[0] == (char) 0x4B) ||
- (up->rpt_buf[0] == (char) 0x6D)) {
+ if ((up->type != CLK_THUNDERBOLT) & (up->type != CLK_ACUTIME)){
+ if ((up->rpt_buf[0] == (char) 0x41) ||
+ (up->rpt_buf[0] == (char) 0x46) ||
+ (up->rpt_buf[0] == (char) 0x54) ||
+ (up->rpt_buf[0] == (char) 0x4B) ||
+ (up->rpt_buf[0] == (char) 0x6D)) {
- /* standard time packet - GPS time and GPS week number */
+ /* standard time packet - GPS time and GPS week number */
#ifdef DEBUG
printf("Palisade Port B packets detected. Connect to Port A\n");
#endif
- return 0;
+ return 0;
+ }
}
/*
* We cast both to u_char to as 0x8f uses the sign bit on a char
*/
if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
- /*
- * Superpackets
- */
- event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
- if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
- /* Ignore Packet */
+ /*
+ * Superpackets
+ */
+ event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
+ if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
+ /* Ignore Packet */
return 0;
- switch (mb(0) & 0xff) {
- int GPS_UTC_Offset;
- case PACKET_8F0B:
+ switch (mb(0) & 0xff) {
+ int GPS_UTC_Offset;
+ long tow;
- if (up->polled <= 0)
- return 0;
+ case PACKET_8F0B:
- if (up->rpt_cnt != LENCODE_8F0B) /* check length */
- break;
+ if (up->polled <= 0)
+ return 0;
+
+ if (up->rpt_cnt != LENCODE_8F0B) /* check length */
+ break;
#ifdef DEBUG
-if (debug > 1) {
- int ts;
- double lat, lon, alt;
- lat = getdbl((u_char *) &mb(42)) * R2D;
- lon = getdbl((u_char *) &mb(50)) * R2D;
- alt = getdbl((u_char *) &mb(58));
-
- printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
- up->unit, lat,lon,alt);
- printf("TSIP_decode: unit %d: Sats:", up->unit);
- for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) {
- if (mb(st) > 0) ts++;
- printf(" %02d", mb(st));
- }
- printf(" : Tracking %d\n", ts);
- }
+ if (debug > 1) {
+ int ts;
+ double lat, lon, alt;
+ lat = getdbl((u_char *) &mb(42)) * R2D;
+ lon = getdbl((u_char *) &mb(50)) * R2D;
+ alt = getdbl((u_char *) &mb(58));
+
+ printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
+ up->unit, lat,lon,alt);
+ printf("TSIP_decode: unit %d: Sats:",
+ up->unit);
+ for (st = 66, ts = 0; st <= 73; st++)
+ if (mb(st)) {
+ if (mb(st) > 0) ts++;
+ printf(" %02d", mb(st));
+ }
+ printf(" : Tracking %d\n", ts);
+ }
#endif
- GPS_UTC_Offset = getint((u_char *) &mb(16));
- if (GPS_UTC_Offset == 0) { /* Check UTC offset */
+ GPS_UTC_Offset = getint((u_char *) &mb(16));
+ if (GPS_UTC_Offset == 0) { /* Check UTC offset */
#ifdef DEBUG
- printf("TSIP_decode: UTC Offset Unknown\n");
+ printf("TSIP_decode: UTC Offset Unknown\n");
#endif
- break;
- }
+ break;
+ }
- secs = getdbl((u_char *) &mb(3));
- secint = (long) secs;
- secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
+ secs = getdbl((u_char *) &mb(3));
+ secint = (long) secs;
+ secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
- pp->nsec = (long) (secfrac * 1000000000);
+ pp->nsec = (long) (secfrac * 1000000000);
- secint %= 86400; /* Only care about today */
- pp->hour = secint / 3600;
- secint %= 3600;
- pp->minute = secint / 60;
- secint %= 60;
- pp->second = secint % 60;
+ secint %= 86400; /* Only care about today */
+ pp->hour = secint / 3600;
+ secint %= 3600;
+ pp->minute = secint / 60;
+ secint %= 60;
+ pp->second = secint % 60;
- if ((pp->day = day_of_year(&mb(11))) < 0) break;
+ if ((pp->day = day_of_year(&mb(11))) < 0) break;
- pp->year = getint((u_char *) &mb(13));
+ pp->year = getint((u_char *) &mb(13));
#ifdef DEBUG
- if (debug > 1)
- printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
- up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
- pp->second, pp->nsec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
+ if (debug > 1)
+ printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
+ up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
+ pp->second, pp->nsec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
#endif
- /* Only use this packet when no
- * 8F-AD's are being received
- */
+ /* Only use this packet when no
+ * 8F-AD's are being received
+ */
- if (up->leap_status) {
- up->leap_status = 0;
- return 0;
- }
+ if (up->leap_status) {
+ up->leap_status = 0;
+ return 0;
+ }
- return 2;
- break;
+ return 2;
+ break;
- case PACKET_NTP:
- /* Palisade-NTP Packet */
+ case PACKET_NTP:
+ /* Palisade-NTP Packet */
- if (up->rpt_cnt != LENCODE_NTP) /* check length */
- break;
+ if (up->rpt_cnt != LENCODE_NTP) /* check length */
+ break;
- up->leap_status = mb(19);
+ up->leap_status = mb(19);
- if (up->polled <= 0)
- return 0;
+ if (up->polled <= 0)
+ return 0;
- /* Check Tracking Status */
- st = mb(18);
- if (st < 0 || st > 14) st = 14;
- if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
+ /* Check Tracking Status */
+ st = mb(18);
+ if (st < 0 || st > 14)
+ st = 14;
+ if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
#ifdef DEBUG
- printf("TSIP_decode: Not Tracking Sats : %s\n",
- *Tracking_Status[st]);
+ printf("TSIP_decode: Not Tracking Sats : %s\n",
+ *Tracking_Status[st]);
#endif
- refclock_report(peer, CEVNT_BADTIME);
- up->polled = -1;
- return 0;
- break;
- }
+ refclock_report(peer, CEVNT_BADTIME);
+ up->polled = -1;
+ return 0;
+ break;
+ }
- if (up->leap_status & PALISADE_LEAP_PENDING) {
- if (up->leap_status & PALISADE_UTC_TIME)
- pp->leap = LEAP_ADDSECOND;
- else
- pp->leap = LEAP_DELSECOND;
- }
- else if (up->leap_status)
- pp->leap = LEAP_NOWARNING;
+ if (up->leap_status & PALISADE_LEAP_PENDING) {
+ if (up->leap_status & PALISADE_UTC_TIME)
+ pp->leap = LEAP_ADDSECOND;
+ else
+ pp->leap = LEAP_DELSECOND;
+ }
+ else if (up->leap_status)
+ pp->leap = LEAP_NOWARNING;
- else { /* UTC flag is not set:
- * Receiver may have been reset, and lost
- * its UTC almanac data */
- pp->leap = LEAP_NOTINSYNC;
+ else { /* UTC flag is not set:
+ * Receiver may have been reset, and lost
+ * its UTC almanac data */
+ pp->leap = LEAP_NOTINSYNC;
#ifdef DEBUG
- printf("TSIP_decode: UTC Almanac unavailable: %d\n",
- mb(19));
+ printf("TSIP_decode: UTC Almanac unavailable: %d\n",
+ mb(19));
#endif
- refclock_report(peer, CEVNT_BADTIME);
- up->polled = -1;
+ refclock_report(peer, CEVNT_BADTIME);
+ up->polled = -1;
+ return 0;
+ }
+
+ pp->nsec = (long) (getdbl((u_char *) &mb(3))
+ * 1000000000);
+
+ if ((pp->day = day_of_year(&mb(14))) < 0)
+ break;
+ pp->year = getint((u_char *) &mb(16));
+ pp->hour = mb(11);
+ pp->minute = mb(12);
+ pp->second = mb(13);
+
+#ifdef DEBUG
+ if (debug > 1)
+ printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
+ up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
+ pp->second, pp->nsec, mb(15), mb(14), pp->year,
+ mb(19), *Tracking_Status[st]);
+#endif
+ return 1;
+ break;
+
+ case PACKET_8FAC:
+ if (up->polled <= 0)
+ return 0;
+
+ if (up->rpt_cnt != LENCODE_8FAC)/* check length */
+ break;
+
+#ifdef DEBUG
+ if (debug > 1) {
+ double lat, lon, alt;
+ lat = getdbl((u_char *) &mb(36)) * R2D;
+ lon = getdbl((u_char *) &mb(44)) * R2D;
+ alt = getdbl((u_char *) &mb(52));
+
+ printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
+ up->unit, lat,lon,alt);
+ printf("TSIP_decode: unit %d\n", up->unit);
+ }
+#endif
+ if (getint((u_char *) &mb(10)) & 0x80)
+ pp->leap = LEAP_ADDSECOND; /* we ASSUME addsecond */
+ else
+ pp->leap = LEAP_NOWARNING;
+
+#ifdef DEBUG
+ if (debug > 1)
+ printf("TSIP_decode: unit %d: 0x%02x leap %d\n",
+ up->unit, mb(0) & 0xff, pp->leap);
+ if (debug > 1) {
+ printf("Receiver MODE: 0x%02X\n", (u_char)mb(1));
+ if (mb(1) == 0x00)
+ printf(" AUTOMATIC\n");
+ if (mb(1) == 0x01)
+ printf(" SINGLE SATELLITE\n");
+ if (mb(1) == 0x03)
+ printf(" HORIZONTAL(2D)\n");
+ if (mb(1) == 0x04)
+ printf(" FULL POSITION(3D)\n");
+ if (mb(1) == 0x05)
+ printf(" DGPR REFERENCE\n");
+ if (mb(1) == 0x06)
+ printf(" CLOCK HOLD(2D)\n");
+ if (mb(1) == 0x07)
+ printf(" OVERDETERMINED CLOCK\n");
+
+ printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2));
+ if (mb(2) == 0x00)
+ printf(" NORMAL\n");
+ if (mb(2) == 0x01)
+ printf(" POWER-UP\n");
+ if (mb(2) == 0x02)
+ printf(" AUTO HOLDOVER\n");
+ if (mb(2) == 0x03)
+ printf(" MANUAL HOLDOVER\n");
+ if (mb(2) == 0x04)
+ printf(" RECOVERY\n");
+ if (mb(2) == 0x06)
+ printf(" DISCIPLINING DISABLED\n");
+ }
+#endif
return 0;
- }
+ break;
+
+ case PACKET_8FAB:
+ /* Thunderbolt Primary Timing Packet */
+
+ if (up->rpt_cnt != LENCODE_8FAB) /* check length */
+ break;
+
+ if (up->polled <= 0)
+ return 0;
- pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000000);
+ GPS_UTC_Offset = getint((u_char *) &mb(7));
- if ((pp->day = day_of_year(&mb(14))) < 0)
+ if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
+#ifdef DEBUG
+ printf("TSIP_decode: UTC Offset Unknown\n");
+#endif
+ break;
+ }
+
+
+ if ((mb(9) & 0x1d) == 0x0) {
+ /* if we know the GPS time and the UTC offset,
+ we expect UTC timing information !!! */
+
+ pp->leap = LEAP_NOTINSYNC;
+ refclock_report(peer, CEVNT_BADTIME);
+ up->polled = -1;
+ return 0;
+ }
+
+ pp->nsec = 0;
+#ifdef DEBUG
+ printf("\nTiming Flags are:\n");
+ printf("Timing flag value is: 0x%X\n", mb(9));
+ if ((mb(9) & 0x01) != 0)
+ printf (" Getting UTC time\n");
+ else
+ printf (" Getting GPS time\n");
+ if ((mb(9) & 0x02) != 0)
+ printf (" PPS is from UTC\n");
+ else
+ printf (" PPS is from GPS\n");
+ if ((mb(9) & 0x04) != 0)
+ printf (" Time is not Set\n");
+ else
+ printf (" Time is Set\n");
+ if ((mb(9) & 0x08) != 0)
+ printf(" I dont have UTC info\n");
+ else
+ printf (" I have UTC info\n");
+ if ((mb(9) & 0x10) != 0)
+ printf (" Time is from USER\n\n");
+ else
+ printf (" Time is from GPS\n\n");
+#endif
+
+ if ((pp->day = day_of_year(&mb(13))) < 0)
+ break;
+ tow = getlong((u_char *) &mb(1));
+#ifdef DEBUG
+ if (debug > 1) {
+ printf("pp->day: %d\n", pp->day);
+ printf("TOW: %ld\n", tow);
+ printf("DAY: %d\n", mb(13));
+ }
+#endif
+ pp->year = getint((u_char *) &mb(15));
+ pp->hour = mb(12);
+ pp->minute = mb(11);
+ pp->second = mb(10);
+
+
+#ifdef DEBUG
+ if (debug > 1)
+ printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d ",up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, pp->nsec, mb(14), mb(13), pp->year);
+#endif
+ return 1;
break;
- pp->year = getint((u_char *) &mb(16));
- pp->hour = mb(11);
- pp->minute = mb(12);
- pp->second = mb(13);
+ default:
+ /* Ignore Packet */
+ return 0;
+ } /* switch */
+ } /* if 8F packets */
+
+ else if (up->rpt_buf[0] == (u_char)0x42) {
+ printf("0x42\n");
+ return 0;
+ }
+ else if (up->rpt_buf[0] == (u_char)0x43) {
+ printf("0x43\n");
+ return 0;
+ }
+ else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){
+ printf("Undocumented 0x41 packet on Thunderbolt\n");
+ return 0;
+ }
+ else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) {
#ifdef DEBUG
- if (debug > 1)
-printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
- up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
- pp->second, pp->nsec, mb(15), mb(14), pp->year,
- mb(19), *Tracking_Status[st]);
+ printf("GPS TOW: %ld\n", getlong((u_char *) &mb(0)));
+ printf("GPS WN: %d\n", getint((u_char *) &mb(4)));
+ printf("GPS UTC-GPS Offser: %ld\n", getlong((u_char *) &mb(6)));
#endif
- return 1;
- break;
+ return 0;
+ }
- default:
- /* Ignore Packet */
+ /* Health Status for Acutime Receiver */
+ else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) {
+#ifdef DEBUG
+ if (debug > 1)
+ /* Status Codes */
+ switch (mb(0)) {
+ case 0x00:
+ printf ("Doing Position Fixes\n");
+ break;
+ case 0x01:
+ printf ("Do no have GPS time yet\n");
+ break;
+ case 0x03:
+ printf ("PDOP is too high\n");
+ break;
+ case 0x08:
+ printf ("No usable satellites\n");
+ break;
+ case 0x09:
+ printf ("Only 1 usable satellite\n");
+ break;
+ case 0x0A:
+ printf ("Only 2 usable satellites\n");
+ break;
+ case 0x0B:
+ printf ("Only 3 usable satellites\n");
+ break;
+ case 0x0C:
+ printf("The Chosen satellite is unusable\n");
+ break;
+ }
+#endif
+ /* Error Codes */
+ if (mb(1) != 0) {
+
+ refclock_report(peer, CEVNT_BADTIME);
+ up->polled = -1;
+#ifdef DEBUG
+ if (debug > 1) {
+ if (mb(1) && 0x01)
+ printf ("Signal Processor Error, reset unit.\n");
+ if (mb(1) && 0x02)
+ printf ("Alignment error, channel or chip 1, reset unit.\n");
+ if (mb(1) && 0x03)
+ printf ("Alignment error, channel or chip 2, reset unit.\n");
+ if (mb(1) && 0x04)
+ printf ("Antenna feed line fault (open or short)\n");
+ if (mb(1) && 0x05)
+ printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
+ }
+#endif
+
+ return 0;
+ }
+ }
+ else if (up->rpt_buf[0] == 0x54)
return 0;
- } /* switch */
- }/* if 8F packets */
+ else if (up->rpt_buf[0] == PACKET_6D) {
+#ifdef DEBUG
+ int sats;
+
+ if ((mb(0) & 0x01) && (mb(0) & 0x02))
+ printf("2d Fix Dimension\n");
+ if (mb(0) & 0x04)
+ printf("3d Fix Dimension\n");
+
+ if (mb(0) & 0x08)
+ printf("Fix Mode is MANUAL\n");
+ else
+ printf("Fix Mode is AUTO\n");
+
+ sats = mb(0) & 0xF0;
+ sats = sats >> 4;
+ printf("Tracking %d Satellites\n", sats);
+#endif
+ return 0;
+ } /* else if not super packet */
refclock_report(peer, CEVNT_BADREPLY);
up->polled = -1;
#ifdef DEBUG
printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
- up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
- event, up->rpt_cnt);
+ up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
+ event, up->rpt_cnt);
#endif
return 0;
}
@@ -536,14 +890,8 @@ printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %
static void
palisade_receive (
-#ifdef PALISADE
- peer
- )
- struct peer * peer;
-#else /* ANSI */
struct peer * peer
)
-#endif
{
struct palisade_unit *up;
struct refclockproc *pp;
@@ -557,14 +905,14 @@ palisade_receive (
if (! TSIP_decode(peer)) return;
if (up->polled <= 0)
- return; /* no poll pending, already received or timeout */
+ return; /* no poll pending, already received or timeout */
up->polled = 0; /* Poll reply received */
pp->lencode = 0; /* clear time code */
#ifdef DEBUG
if (debug)
printf(
- "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
+ "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
up->unit, pp->year, pp->day, pp->hour, pp->minute,
pp->second, pp->nsec);
#endif
@@ -575,23 +923,18 @@ palisade_receive (
* report and process
*/
- (void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
- pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->nsec);
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
+ "%4d %03d %02d:%02d:%02d.%06ld",
+ pp->year, pp->day,
+ pp->hour,pp->minute, pp->second, pp->nsec);
pp->lencode = 24;
-#ifdef PALISADE
- pp->lasttime = current_time;
-#endif
- if (!refclock_process(pp
-#ifdef PALISADE
- , PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5
-#endif
- )) {
+ if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
#ifdef DEBUG
printf("palisade_receive: unit %d: refclock_process failed!\n",
- up->unit);
+ up->unit);
#endif
return;
}
@@ -600,16 +943,11 @@ palisade_receive (
#ifdef DEBUG
if (debug)
- printf("palisade_receive: unit %d: %s\n",
- up->unit, prettydate(&pp->lastrec));
+ printf("palisade_receive: unit %d: %s\n",
+ up->unit, prettydate(&pp->lastrec));
#endif
pp->lastref = pp->lastrec;
- refclock_receive(peer
-#ifdef PALISADE
- , &pp->offset, 0, pp->dispersion,
- &pp->lastrec, &pp->lastrec, pp->leap
-#endif
- );
+ refclock_receive(peer);
}
@@ -619,16 +957,9 @@ palisade_receive (
*/
static void
palisade_poll (
-#ifdef PALISADE
- unit, peer
- )
- int unit;
- struct peer *peer;
-#else
int unit,
struct peer *peer
)
-#endif
{
struct palisade_unit *up;
struct refclockproc *pp;
@@ -638,19 +969,19 @@ palisade_poll (
pp->polls++;
if (up->polled > 0) /* last reply never arrived or error */
- refclock_report(peer, CEVNT_TIMEOUT);
+ refclock_report(peer, CEVNT_TIMEOUT);
up->polled = 2; /* synchronous packet + 1 event */
#ifdef DEBUG
if (debug)
- printf("palisade_poll: unit %d: polling %s\n", unit,
- (pp->sloppyclockflag & CLK_FLAG2) ?
- "synchronous packet" : "event");
+ printf("palisade_poll: unit %d: polling %s\n", unit,
+ (pp->sloppyclockflag & CLK_FLAG2) ?
+ "synchronous packet" : "event");
#endif
if (pp->sloppyclockflag & CLK_FLAG2)
- return; /* using synchronous packet input */
+ return; /* using synchronous packet input */
if(up->type == CLK_PRAECIS) {
if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
@@ -662,11 +993,14 @@ palisade_poll (
}
if (HW_poll(pp) < 0)
- refclock_report(peer, CEVNT_FAULT);
+ refclock_report(peer, CEVNT_FAULT);
}
static void
-praecis_parse(struct recvbuf *rbufp, struct peer *peer)
+praecis_parse (
+ struct recvbuf *rbufp,
+ struct peer *peer
+ )
{
static char buf[100];
static int p = 0;
@@ -692,14 +1026,8 @@ praecis_parse(struct recvbuf *rbufp, struct peer *peer)
static void
palisade_io (
-#ifdef PALISADE
- rbufp
- )
- struct recvbuf *rbufp;
-#else /* ANSI */
struct recvbuf *rbufp
)
-#endif
{
/*
* Initialize pointers and read the timecode and timestamp.
@@ -748,21 +1076,21 @@ palisade_io (
case TSIP_PARSED_DATA:
if (*c == DLE)
- up->rpt_status = TSIP_PARSED_DLE_2;
+ up->rpt_status = TSIP_PARSED_DLE_2;
else
- mb(up->rpt_cnt++) = *c;
+ mb(up->rpt_cnt++) = *c;
break;
case TSIP_PARSED_DLE_2:
if (*c == DLE) {
up->rpt_status = TSIP_PARSED_DATA;
mb(up->rpt_cnt++) =
- *c;
- }
+ *c;
+ }
else if (*c == ETX)
- up->rpt_status = TSIP_PARSED_FULL;
+ up->rpt_status = TSIP_PARSED_FULL;
else {
- /* error: start new report packet */
+ /* error: start new report packet */
up->rpt_status = TSIP_PARSED_DLE_1;
up->rpt_buf[0] = *c;
}
@@ -771,23 +1099,23 @@ palisade_io (
case TSIP_PARSED_FULL:
case TSIP_PARSED_EMPTY:
default:
- if ( *c != DLE)
- up->rpt_status = TSIP_PARSED_EMPTY;
- else
- up->rpt_status = TSIP_PARSED_DLE_1;
- break;
+ if ( *c != DLE)
+ up->rpt_status = TSIP_PARSED_EMPTY;
+ else
+ up->rpt_status = TSIP_PARSED_DLE_1;
+ break;
}
c++;
if (up->rpt_status == TSIP_PARSED_DLE_1) {
- up->rpt_cnt = 0;
+ up->rpt_cnt = 0;
if (pp->sloppyclockflag & CLK_FLAG2)
- /* stamp it */
- get_systime(&pp->lastrec);
+ /* stamp it */
+ get_systime(&pp->lastrec);
}
else if (up->rpt_status == TSIP_PARSED_EMPTY)
- up->rpt_cnt = 0;
+ up->rpt_cnt = 0;
else if (up->rpt_cnt > BMAX)
up->rpt_status =TSIP_PARSED_EMPTY;
@@ -807,14 +1135,8 @@ palisade_io (
*/
long
HW_poll (
-#ifdef PALISADE
- pp /* pointer to unit structure */
- )
- struct refclockproc * pp; /* pointer to unit structure */
-#else
struct refclockproc * pp /* pointer to unit structure */
)
-#endif
{
int x; /* state before & after RTS set */
struct palisade_unit *up;
@@ -824,8 +1146,8 @@ HW_poll (
/* read the current status, so we put things back right */
if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
#ifdef DEBUG
- if (debug)
- printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
+ if (debug)
+ printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
#endif
msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
up->unit);
@@ -835,10 +1157,13 @@ HW_poll (
x |= TIOCM_RTS; /* turn on RTS */
/* Edge trigger */
+ if (up->type == CLK_ACUTIME)
+ write (pp->io.fd, "", 1);
+
if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
#ifdef DEBUG
- if (debug)
- printf("Palisade HW_poll: unit %d: SET \n", up->unit);
+ if (debug)
+ printf("Palisade HW_poll: unit %d: SET \n", up->unit);
#endif
msyslog(LOG_ERR,
"Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
@@ -853,8 +1178,8 @@ HW_poll (
if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
#ifdef DEBUG
- if (debug)
- printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
+ if (debug)
+ printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
#endif
msyslog(LOG_ERR,
"Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
@@ -871,14 +1196,8 @@ HW_poll (
*/
float
getfloat (
-#ifdef PALISADE
- bp
- )
- u_char *bp;
-#else
u_char *bp
)
-#endif
{
float sval;
#ifdef WORDS_BIGENDIAN
@@ -901,14 +1220,8 @@ getfloat (
*/
double
getdbl (
-#ifdef PALISADE
- bp
- )
- u_char *bp;
-#else
u_char *bp
)
-#endif
{
double dval;
#ifdef WORDS_BIGENDIAN
@@ -938,18 +1251,26 @@ getdbl (
*/
short
getint (
-#ifdef PALISADE
- bp
+ u_char *bp
)
- u_char *bp;
-#else
+{
+ return (short) (bp[1] + (bp[0] << 8));
+}
+
+/*
+ * cast a 32 bit character array into a long (32 bit) int
+ */
+long
+getlong(
u_char *bp
)
-#endif
{
-return (short) (bp[1] + (bp[0] << 8));
+ return (long) (bp[0] << 24) |
+ (bp[1] << 16) |
+ (bp[2] << 8) |
+ bp[3];
}
-#else
-int refclock_palisade_bs;
-#endif /* REFCLOCK */
+#else /* REFCLOCK && CLOCK_PALISADE*/
+int refclock_palisade_c_notempty;
+#endif
diff --git a/ntpd/refclock_palisade.h b/ntpd/refclock_palisade.h
index e63f3da36452..c2d4476a9833 100644
--- a/ntpd/refclock_palisade.h
+++ b/ntpd/refclock_palisade.h
@@ -71,6 +71,7 @@
# define _SVID3
# endif
# include <termios.h>
+# include <sys/stat.h>
# ifdef TERMIOS_NEEDS__SVID3
# undef _SVID3
# endif
@@ -108,10 +109,23 @@
#define LENCODE_8F0B 74 /* Length of TSIP 8F-0B Packet & header */
#define LENCODE_NTP 22 /* Length of Palisade NTP Packet */
+#define LENCODE_8FAC 68 /* Length of Thunderbolt 8F-AC Position Packet*/
+#define LENCODE_8FAB 17 /* Length of Thunderbolt Primary Timing Packet*/
+
/* Allowed Sub-Packet ID's */
#define PACKET_8F0B 0x0B
#define PACKET_NTP 0xAD
+/* Thunderbolt Packets */
+#define PACKET_8FAC 0xAC /* Supplementary Thunderbolt Time Packet */
+#define PACKET_8FAB 0xAB /* Primary Thunderbolt Time Packet */
+#define PACKET_6D 0x6D /* Supplementary Thunderbolt Tracking Stats */
+#define PACKET_41 0x41 /* Thunderbolt I dont know what this packet is, it's not documented on my manual*/
+
+/* Acutime Packets */
+#define PACKET_41A 0x41 /* GPS time */
+#define PACKET_46 0x46 /* Receiver Health */
+
#define DLE 0x10
#define ETX 0x03
@@ -139,6 +153,16 @@
#define R2D (180.0/GPS_PI)
/*
+ * Structure for build data packets for send (thunderbolt uses it only)
+ * taken from Markus Prosch
+ */
+struct packettx
+{
+ short size;
+ u_char *data;
+};
+
+/*
* Palisade unit control structure.
*/
struct palisade_unit {
@@ -147,7 +171,7 @@ struct palisade_unit {
char leap_status; /* leap second flag */
char rpt_status; /* TSIP Parser State */
short rpt_cnt; /* TSIP packet length so far */
- char rpt_buf[BMAX]; /* packet assembly buffer */
+ char rpt_buf[BMAX]; /* packet assembly buffer */
int type; /* Clock mode type */
};
@@ -155,16 +179,27 @@ struct palisade_unit {
* Function prototypes
*/
-static int palisade_start P((int, struct peer *));
-static void palisade_shutdown P((int, struct peer *));
-static void palisade_receive P((struct peer *));
-static void palisade_poll P((int, struct peer *));
-static void palisade_io P((struct recvbuf *));
-int palisade_configure P((int, struct peer *));
-int TSIP_decode P((struct peer *));
-long HW_poll P((struct refclockproc *));
-float getfloat P((u_char *));
-double getdbl P((u_char *));
-short getint P((u_char *));
-
+static int palisade_start (int, struct peer *);
+static void palisade_shutdown (int, struct peer *);
+static void palisade_receive (struct peer *);
+static void palisade_poll (int, struct peer *);
+static void palisade_io (struct recvbuf *);
+int palisade_configure (int, struct peer *);
+int TSIP_decode (struct peer *);
+long HW_poll (struct refclockproc *);
+float getfloat (u_char *);
+double getdbl (u_char *);
+short getint (u_char *);
+long getlong (u_char *);
+
+
+#ifdef PALISADE_SENDCMD_RESURRECTED
+static void sendcmd (struct packettx *buffer, int c);
+#endif
+static void sendsupercmd (struct packettx *buffer, int c1, int c2);
+static void sendbyte (struct packettx *buffer, int b);
+static void sendint (struct packettx *buffer, int a);
+static int sendetx (struct packettx *buffer, int fd);
+static void init_thunderbolt (int fd);
+static void init_acutime (int fd);
#endif /* PALISADE_H */
diff --git a/ntpd/refclock_parse.c b/ntpd/refclock_parse.c
index 0b0109cf6ffc..75d5fe2a8a3c 100644
--- a/ntpd/refclock_parse.c
+++ b/ntpd/refclock_parse.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
+ * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A
*
- * refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
+ * refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A
*
* generic reference clock driver for several DCF/GPS/MSF/... receivers
*
@@ -15,7 +15,7 @@
* Currently the STREAMS module is only available for Suns running
* SunOS 4.x and SunOS5.x.
*
- * Copyright (c) 1995-2007 by Frank Kardel <kardel <AT> ntp.org>
+ * Copyright (c) 1995-2009 by Frank Kardel <kardel <AT> ntp.org>
* Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
*
* Redistribution and use in source and binary forms, with or without
@@ -141,6 +141,7 @@
#ifdef HAVE_PPSAPI
# include "ppsapi_timepps.h"
+# include "refclock_atom.h"
#endif
#ifdef PPS
@@ -188,16 +189,16 @@
#include "ieee754io.h"
#include "recvbuff.h"
-static char rcsid[] = "refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp";
+static char rcsid[] = "refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A+POWERUPTRUST";
/**===========================================================================
** external interface to ntp mechanism
**/
-static int parse_start P((int, struct peer *));
-static void parse_shutdown P((int, struct peer *));
-static void parse_poll P((int, struct peer *));
-static void parse_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
+static int parse_start (int, struct peer *);
+static void parse_shutdown (int, struct peer *);
+static void parse_poll (int, struct peer *);
+static void parse_control (int, struct refclockstat *, struct refclockstat *, struct peer *);
struct refclock refclock_parse = {
parse_start,
@@ -231,16 +232,16 @@ struct parseunit; /* to keep inquiring minds happy */
typedef struct bind
{
const char *bd_description; /* name of type of binding */
- int (*bd_init) P((struct parseunit *)); /* initialize */
- void (*bd_end) P((struct parseunit *)); /* end */
- int (*bd_setcs) P((struct parseunit *, parsectl_t *)); /* set character size */
- int (*bd_disable) P((struct parseunit *)); /* disable */
- int (*bd_enable) P((struct parseunit *)); /* enable */
- int (*bd_getfmt) P((struct parseunit *, parsectl_t *)); /* get format */
- int (*bd_setfmt) P((struct parseunit *, parsectl_t *)); /* setfmt */
- int (*bd_timecode) P((struct parseunit *, parsectl_t *)); /* get time code */
- void (*bd_receive) P((struct recvbuf *)); /* receive operation */
- int (*bd_io_input) P((struct recvbuf *)); /* input operation */
+ int (*bd_init) (struct parseunit *); /* initialize */
+ void (*bd_end) (struct parseunit *); /* end */
+ int (*bd_setcs) (struct parseunit *, parsectl_t *); /* set character size */
+ int (*bd_disable) (struct parseunit *); /* disable */
+ int (*bd_enable) (struct parseunit *); /* enable */
+ int (*bd_getfmt) (struct parseunit *, parsectl_t *); /* get format */
+ int (*bd_setfmt) (struct parseunit *, parsectl_t *); /* setfmt */
+ int (*bd_timecode) (struct parseunit *, parsectl_t *); /* get time code */
+ void (*bd_receive) (struct recvbuf *); /* receive operation */
+ int (*bd_io_input) (struct recvbuf *); /* input operation */
} bind_t;
#define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)
@@ -252,12 +253,11 @@ typedef struct bind
#define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
/*
- * io modes
+ * special handling flags
*/
-#define PARSE_F_PPSPPS 0x0001 /* use loopfilter PPS code (CIOGETEV) */
-#define PARSE_F_PPSONSECOND 0x0002 /* PPS pulses are on second */
-
-
+#define PARSE_F_PPSONSECOND 0x00000001 /* PPS pulses are on second */
+#define PARSE_F_POWERUPTRUST 0x00000100 /* POWERUP state ist trusted for */
+ /* trusttime after SYNC was seen */
/**===========================================================================
** error message regression handling
**
@@ -405,9 +405,8 @@ struct parseunit
u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
int ppsfd; /* fd to ise for PPS io */
#ifdef HAVE_PPSAPI
- pps_handle_t ppshandle; /* store PPSAPI handle */
- pps_params_t ppsparams; /* current PPS parameters */
int hardppsstate; /* current hard pps state */
+ struct refclock_atom atom; /* PPSAPI structure */
#endif
parsetime_t timedata; /* last (parse module) data */
void *localdata; /* optional local, receiver-specific data */
@@ -423,9 +422,9 @@ struct parseunit
** includes NTP parameters, TTY parameters and IO handling parameters
**/
-static void poll_dpoll P((struct parseunit *));
-static void poll_poll P((struct peer *));
-static int poll_init P((struct parseunit *));
+static void poll_dpoll (struct parseunit *);
+static void poll_poll (struct peer *);
+static int poll_init (struct parseunit *);
typedef struct poll_info
{
@@ -536,8 +535,8 @@ typedef struct poll_info
/*
* Meinberg GPS16X receiver
*/
-static void gps16x_message P((struct parseunit *, parsetime_t *));
-static int gps16x_poll_init P((struct parseunit *));
+static void gps16x_message (struct parseunit *, parsetime_t *);
+static int gps16x_poll_init (struct parseunit *);
#define GPS16X_ROOTDELAY 0.0 /* nothing here */
#define GPS16X_BASEDELAY 0.001968 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
@@ -677,16 +676,18 @@ static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
* RAWDCF receivers that need to be powered from DTR
* (like Expert mouse clock)
*/
-static int rawdcf_init_1 P((struct parseunit *));
+static int rawdcf_init_1 (struct parseunit *);
#define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)"
+#define RAWDCFDTRSET75_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR @ 75 baud)"
#define RAWDCFDTRSET_INIT rawdcf_init_1
/*
* RAWDCF receivers that need to be powered from
* DTR CLR and RTS SET
*/
-static int rawdcf_init_2 P((struct parseunit *));
+static int rawdcf_init_2 (struct parseunit *);
#define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)"
+#define RAWDCFDTRCLRRTSSET75_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET @ 75 baud)"
#define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2
/*
@@ -700,17 +701,17 @@ static int rawdcf_init_2 P((struct parseunit *));
#define TRIM_TAIPCMDSIZE (sizeof(TRIM_TAIPPOLLCMD)-1)
static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
-static int trimbletaip_init P((struct parseunit *));
-static void trimbletaip_event P((struct parseunit *, int));
+static int trimbletaip_init (struct parseunit *);
+static void trimbletaip_event (struct parseunit *, int);
/* query time & UTC correction data */
static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX };
static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) };
-static int trimbletsip_init P((struct parseunit *));
-static void trimbletsip_end P((struct parseunit *));
-static void trimbletsip_message P((struct parseunit *, parsetime_t *));
-static void trimbletsip_event P((struct parseunit *, int));
+static int trimbletsip_init (struct parseunit *);
+static void trimbletsip_end (struct parseunit *);
+static void trimbletsip_message (struct parseunit *, parsetime_t *);
+static void trimbletsip_event (struct parseunit *, int);
#define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */
#define TRIMBLE_RESET_HOLDOFF TRIMBLETSIP_IDLE_TIME
@@ -857,12 +858,12 @@ static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE }
static struct parse_clockinfo
{
- u_long cl_flags; /* operation flags (io modes) */
- void (*cl_poll) P((struct parseunit *)); /* active poll routine */
- int (*cl_init) P((struct parseunit *)); /* active poll init routine */
- void (*cl_event) P((struct parseunit *, int)); /* special event handling (e.g. reset clock) */
- void (*cl_end) P((struct parseunit *)); /* active poll end routine */
- void (*cl_message) P((struct parseunit *, parsetime_t *)); /* process a lower layer message */
+ u_long cl_flags; /* operation flags (PPS interpretation, trust handling) */
+ void (*cl_poll) (struct parseunit *); /* active poll routine */
+ int (*cl_init) (struct parseunit *); /* active poll init routine */
+ void (*cl_event) (struct parseunit *, int); /* special event handling (e.g. reset clock) */
+ void (*cl_end) (struct parseunit *); /* active poll end routine */
+ void (*cl_message) (struct parseunit *, parsetime_t *); /* process a lower layer message */
void *cl_data; /* local data area for "poll" mechanism */
double cl_rootdelay; /* rootdelay */
double cl_basedelay; /* current offset by which the RS232
@@ -1351,6 +1352,99 @@ static struct parse_clockinfo
RAWDCF_SAMPLES,
RAWDCF_KEEP
},
+ { /* mode 20, like mode 14 but driven by 75 baud */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ RAWDCFDTRSET_INIT,
+ NO_EVENT,
+ NO_END,
+ NO_MESSAGE,
+ NO_LCLDATA,
+ RAWDCF_ROOTDELAY,
+ RAWDCF_BASEDELAY,
+ DCF_A_ID,
+ RAWDCFDTRSET75_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ B75,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG,
+ RAWDCF_SAMPLES,
+ RAWDCF_KEEP
+ },
+ { /* mode 21, like mode 16 but driven by 75 baud
+ - RAWDCF RTS set, DTR clr */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ RAWDCFDTRCLRRTSSET_INIT,
+ NO_EVENT,
+ NO_END,
+ NO_MESSAGE,
+ NO_LCLDATA,
+ RAWDCF_ROOTDELAY,
+ RAWDCF_BASEDELAY,
+ DCF_A_ID,
+ RAWDCFDTRCLRRTSSET75_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ B75,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG,
+ RAWDCF_SAMPLES,
+ RAWDCF_KEEP
+ },
+ { /* mode 22 - like 2 with POWERUP trust */
+ MBG_FLAGS | PARSE_F_POWERUPTRUST,
+ NO_POLL,
+ NO_INIT,
+ NO_EVENT,
+ NO_END,
+ NO_MESSAGE,
+ NO_LCLDATA,
+ DCFUA31_ROOTDELAY,
+ DCFUA31_BASEDELAY,
+ DCF_A_ID,
+ DCFUA31_DESCRIPTION,
+ DCFUA31_FORMAT,
+ DCF_TYPE,
+ DCFUA31_MAXUNSYNC,
+ DCFUA31_SPEED,
+ DCFUA31_CFLAG,
+ DCFUA31_IFLAG,
+ DCFUA31_OFLAG,
+ DCFUA31_LFLAG,
+ DCFUA31_SAMPLES,
+ DCFUA31_KEEP
+ },
+ { /* mode 23 - like 7 with POWERUP trust */
+ MBG_FLAGS | PARSE_F_POWERUPTRUST,
+ GPS16X_POLL,
+ GPS16X_INIT,
+ NO_EVENT,
+ GPS16X_END,
+ GPS16X_MESSAGE,
+ GPS16X_DATA,
+ GPS16X_ROOTDELAY,
+ GPS16X_BASEDELAY,
+ GPS16X_ID,
+ GPS16X_DESCRIPTION,
+ GPS16X_FORMAT,
+ GPS_TYPE,
+ GPS16X_MAXUNSYNC,
+ GPS16X_SPEED,
+ GPS16X_CFLAG,
+ GPS16X_IFLAG,
+ GPS16X_OFLAG,
+ GPS16X_LFLAG,
+ GPS16X_SAMPLES,
+ GPS16X_KEEP
+ },
};
static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
@@ -1371,11 +1465,11 @@ static int notice = 0;
#define PARSE_STATETIME(parse, i) ((parse->generic->currentstatus == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
-static void parse_event P((struct parseunit *, int));
-static void parse_process P((struct parseunit *, parsetime_t *));
-static void clear_err P((struct parseunit *, u_long));
-static int list_err P((struct parseunit *, u_long));
-static char * l_mktime P((u_long));
+static void parse_event (struct parseunit *, int);
+static void parse_process (struct parseunit *, parsetime_t *);
+static void clear_err (struct parseunit *, u_long);
+static int list_err (struct parseunit *, u_long);
+static char * l_mktime (u_long);
/**===========================================================================
** implementation error message regression module
@@ -1474,10 +1568,10 @@ mkreadable(
)
{
char *b = buffer;
- char *endb = (char *)0;
+ char *endb = NULL;
if (blen < 4)
- return (char *)0; /* don't bother with mini buffers */
+ return NULL; /* don't bother with mini buffers */
endb = buffer + blen - 4;
@@ -1515,7 +1609,7 @@ mkreadable(
}
else
{
- sprintf(buffer, "\\x%02x", *src++);
+ snprintf(buffer, blen, "\\x%02x", *src++);
blen -= 4;
buffer += 4;
}
@@ -1554,27 +1648,27 @@ mkascii(
* define possible io handling methods
*/
#ifdef STREAM
-static int ppsclock_init P((struct parseunit *));
-static int stream_init P((struct parseunit *));
-static void stream_end P((struct parseunit *));
-static int stream_enable P((struct parseunit *));
-static int stream_disable P((struct parseunit *));
-static int stream_setcs P((struct parseunit *, parsectl_t *));
-static int stream_getfmt P((struct parseunit *, parsectl_t *));
-static int stream_setfmt P((struct parseunit *, parsectl_t *));
-static int stream_timecode P((struct parseunit *, parsectl_t *));
-static void stream_receive P((struct recvbuf *));
+static int ppsclock_init (struct parseunit *);
+static int stream_init (struct parseunit *);
+static void stream_end (struct parseunit *);
+static int stream_enable (struct parseunit *);
+static int stream_disable (struct parseunit *);
+static int stream_setcs (struct parseunit *, parsectl_t *);
+static int stream_getfmt (struct parseunit *, parsectl_t *);
+static int stream_setfmt (struct parseunit *, parsectl_t *);
+static int stream_timecode (struct parseunit *, parsectl_t *);
+static void stream_receive (struct recvbuf *);
#endif
-static int local_init P((struct parseunit *));
-static void local_end P((struct parseunit *));
-static int local_nop P((struct parseunit *));
-static int local_setcs P((struct parseunit *, parsectl_t *));
-static int local_getfmt P((struct parseunit *, parsectl_t *));
-static int local_setfmt P((struct parseunit *, parsectl_t *));
-static int local_timecode P((struct parseunit *, parsectl_t *));
-static void local_receive P((struct recvbuf *));
-static int local_input P((struct recvbuf *));
+static int local_init (struct parseunit *);
+static void local_end (struct parseunit *);
+static int local_nop (struct parseunit *);
+static int local_setcs (struct parseunit *, parsectl_t *);
+static int local_getfmt (struct parseunit *, parsectl_t *);
+static int local_setfmt (struct parseunit *, parsectl_t *);
+static int local_timecode (struct parseunit *, parsectl_t *);
+static void local_receive (struct recvbuf *);
+static int local_input (struct recvbuf *);
static bind_t io_bindings[] =
{
@@ -2073,7 +2167,7 @@ local_input(
pps_timeout.tv_sec = 0;
pps_timeout.tv_nsec = 0;
- if (time_pps_fetch(parse->ppshandle, PPS_TSFMT_TSPEC, &pps_info,
+ if (time_pps_fetch(parse->atom.handle, PPS_TSFMT_TSPEC, &pps_info,
&pps_timeout) == 0)
{
if (pps_info.assert_sequence + pps_info.clear_sequence != parse->ppsserial)
@@ -2621,7 +2715,7 @@ parse_shutdown(
#ifdef HAVE_PPSAPI
if (parse->flags & PARSE_PPSCLOCK)
{
- (void)time_pps_destroy(parse->ppshandle);
+ (void)time_pps_destroy(parse->atom.handle);
}
#endif
if (parse->generic->io.fd != parse->ppsfd && parse->ppsfd != -1)
@@ -2684,7 +2778,7 @@ parse_hardpps(
i = PPS_CAPTUREASSERT;
}
- if (time_pps_kcbind(parse->ppshandle, PPS_KC_HARDPPS, i,
+ if (time_pps_kcbind(parse->atom.handle, PPS_KC_HARDPPS, i,
PPS_TSFMT_TSPEC) < 0) {
msyslog(LOG_ERR, "PARSE receiver #%d: time_pps_kcbind failed: %m",
CLK_UNIT(parse->peer));
@@ -2711,23 +2805,30 @@ parse_ppsapi(
struct parseunit *parse
)
{
- int cap, mode, mode1;
+ int cap, mode_ppsoffset;
char *cp;
parse->flags &= ~PARSE_PPSCLOCK;
- if (time_pps_getcap(parse->ppshandle, &cap) < 0) {
+ /*
+ * collect PPSAPI offset capability - should move into generic handling
+ */
+ if (time_pps_getcap(parse->atom.handle, &cap) < 0) {
msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getcap failed: %m",
CLK_UNIT(parse->peer));
return 0;
}
- if (time_pps_getparams(parse->ppshandle, &parse->ppsparams) < 0) {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getparams failed: %m",
- CLK_UNIT(parse->peer));
+ /*
+ * initialize generic PPSAPI interface
+ *
+ * we leave out CLK_FLAG3 as time_pps_kcbind()
+ * is handled here for now. Ideally this should also
+ * be part of the generic PPSAPI interface
+ */
+ if (!refclock_params(parse->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG4), &parse->atom))
return 0;
- }
/* nb. only turn things on, if someone else has turned something
* on before we get here, leave it alone!
@@ -2735,47 +2836,36 @@ parse_ppsapi(
if (parse->flags & PARSE_CLEAR) {
cp = "CLEAR";
- mode = PPS_CAPTURECLEAR;
- mode1 = PPS_OFFSETCLEAR;
+ mode_ppsoffset = PPS_OFFSETCLEAR;
} else {
cp = "ASSERT";
- mode = PPS_CAPTUREASSERT;
- mode1 = PPS_OFFSETASSERT;
+ mode_ppsoffset = PPS_OFFSETASSERT;
}
msyslog(LOG_INFO, "PARSE receiver #%d: initializing PPS to %s",
CLK_UNIT(parse->peer), cp);
- if (!(mode & cap)) {
- msyslog(LOG_ERR, "PARSE receiver #%d: FAILED to initialize PPS to %s (PPS API capabilities=0x%x)",
- CLK_UNIT(parse->peer), cp, cap);
-
- return 0;
- }
-
- if (!(mode1 & cap)) {
+ if (!(mode_ppsoffset & cap)) {
msyslog(LOG_WARNING, "PARSE receiver #%d: Cannot set PPS_%sCLEAR, this will increase jitter (PPS API capabilities=0x%x)",
CLK_UNIT(parse->peer), cp, cap);
- mode1 = 0;
+ mode_ppsoffset = 0;
} else {
- if (mode1 == PPS_OFFSETCLEAR)
+ if (mode_ppsoffset == PPS_OFFSETCLEAR)
{
- parse->ppsparams.clear_offset.tv_sec = -parse->ppsphaseadjust;
- parse->ppsparams.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
+ parse->atom.pps_params.clear_offset.tv_sec = -parse->ppsphaseadjust;
+ parse->atom.pps_params.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
}
- if (mode1 == PPS_OFFSETASSERT)
+ if (mode_ppsoffset == PPS_OFFSETASSERT)
{
- parse->ppsparams.assert_offset.tv_sec = -parse->ppsphaseadjust;
- parse->ppsparams.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
+ parse->atom.pps_params.assert_offset.tv_sec = -parse->ppsphaseadjust;
+ parse->atom.pps_params.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
}
}
- /* only set what is legal */
+ parse->atom.pps_params.mode |= mode_ppsoffset;
- parse->ppsparams.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
-
- if (time_pps_setparams(parse->ppshandle, &parse->ppsparams) < 0) {
+ if (time_pps_setparams(parse->atom.handle, &parse->atom.pps_params) < 0) {
msyslog(LOG_ERR, "PARSE receiver #%d: FAILED set PPS parameters: %m",
CLK_UNIT(parse->peer));
return 0;
@@ -2817,7 +2907,7 @@ parse_start(
if (!notice)
{
NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2006, Frank Kardel");
+ msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2009, Frank Kardel");
notice = 1;
}
@@ -3033,7 +3123,7 @@ parse_start(
parse->hardppsstate = PARSE_HARDPPS_DISABLE;
if (CLK_PPS(parse->peer))
{
- if (time_pps_create(parse->ppsfd, &parse->ppshandle) < 0)
+ if (!refclock_ppsapi(parse->ppsfd, &parse->atom))
{
msyslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: could not set up PPS: %m", CLK_UNIT(parse->peer));
}
@@ -3716,7 +3806,7 @@ parse_process(
* for PARSE Meinberg DCF77 receivers the lost synchronisation
* is true as it is the powerup state and the time is taken
* from a crude real time clock chip
- * for the PZF series this is only partly true, as
+ * for the PZF/GPS series this is only partly true, as
* PARSE_POWERUP only means that the pseudo random
* phase shift sequence cannot be found. this is only
* bad, if we have never seen the clock in the SYNC
@@ -3734,11 +3824,14 @@ parse_process(
* interval. fortunately powerdowns last usually longer than 64
* seconds and the receiver is at least 2 minutes in the
* POWERUP or NOSYNC state before switching to SYNC
+ * for GPS receivers this can mean antenna problems and other causes.
+ * the additional grace period can be enables by a clock
+ * mode having the PARSE_F_POWERUPTRUST flag in cl_flag set.
*/
parse_event(parse, CEVNT_FAULT);
NLOG(NLOG_CLOCKSTATUS)
ERR(ERR_BADSTATUS)
- msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED",
+ msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED/RECEIVER PROBLEMS",
CLK_UNIT(parse->peer));
}
else
@@ -3811,7 +3904,7 @@ parse_process(
/*
* set fudge = 0.0 if already included in PPS time stamps
*/
- if (parse->ppsparams.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
+ if (parse->atom.pps_params.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
{
ppsphaseadjust = 0.0;
}
@@ -3944,13 +4037,14 @@ parse_process(
* we have seen the clock in sync at least once
* after the last time we didn't see an expected data telegram
* at startup being not in sync is also bad just like
- * POWERUP state
+ * POWERUP state unless PARSE_F_POWERUPTRUST is set
* see the clock states section above for more reasoning
*/
- if (((current_time - parse->lastsync) > parse->maxunsync) ||
- (parse->lastsync < parse->lastmissed) ||
+ if (((current_time - parse->lastsync) > parse->maxunsync) ||
+ (parse->lastsync < parse->lastmissed) ||
((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
- PARSE_POWERUP(parsetime->parse_state))
+ (((parse->parse_type->cl_flags & PARSE_F_POWERUPTRUST) == 0) &&
+ PARSE_POWERUP(parsetime->parse_state)))
{
parse->generic->leap = LEAP_NOTINSYNC;
parse->lastsync = 0; /* wait for full sync again */
@@ -3996,16 +4090,32 @@ parse_process(
refclock_process_offset(parse->generic, reftime, rectime, fudge);
+#ifdef HAVE_PPSAPI
/*
* pass PPS information on to PPS clock
*/
if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
{
- (void) pps_sample(&parse->timedata.parse_ptime.fp);
+ /* refclock_pps includes fudgetime1 - we keep the RS232 offset in there :-( */
+ double savedtime1 = parse->generic->fudgetime1;
+
+ parse->generic->fudgetime1 = fudge;
+
+ if (refclock_pps(parse->peer, &parse->atom,
+ parse->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4))) {
+ parse->peer->flags |= FLAG_PPS;
+ } else {
+ parse->peer->flags &= ~FLAG_PPS;
+ }
+
+ parse->generic->fudgetime1 = savedtime1;
+
parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
}
+#endif
} else {
parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
+ parse->peer->flags &= ~FLAG_PPS;
}
/*
@@ -4834,11 +4944,11 @@ struct txbuf
u_char *txt; /* pointer to actual data buffer */
};
-void sendcmd P((struct txbuf *buf, int c));
-void sendbyte P((struct txbuf *buf, int b));
-void sendetx P((struct txbuf *buf, struct parseunit *parse));
-void sendint P((struct txbuf *buf, int a));
-void sendflt P((struct txbuf *buf, double a));
+void sendcmd (struct txbuf *buf, int c);
+void sendbyte (struct txbuf *buf, int b);
+void sendetx (struct txbuf *buf, struct parseunit *parse);
+void sendint (struct txbuf *buf, int a);
+void sendflt (struct txbuf *buf, double a);
void
sendcmd(
@@ -4851,11 +4961,11 @@ sendcmd(
buf->idx = 2;
}
-void sendcmd P((struct txbuf *buf, int c));
-void sendbyte P((struct txbuf *buf, int b));
-void sendetx P((struct txbuf *buf, struct parseunit *parse));
-void sendint P((struct txbuf *buf, int a));
-void sendflt P((struct txbuf *buf, double a));
+void sendcmd (struct txbuf *buf, int c);
+void sendbyte (struct txbuf *buf, int b);
+void sendetx (struct txbuf *buf, struct parseunit *parse);
+void sendint (struct txbuf *buf, int a);
+void sendflt (struct txbuf *buf, double a);
void
sendbyte(
@@ -5058,7 +5168,7 @@ trimbletsip_end(
parse->localdata = (void *)0;
}
parse->peer->nextaction = 0;
- parse->peer->action = (void (*) P((struct peer *)))0;
+ parse->peer->action = (void (*) (struct peer *))0;
}
/*--------------------------------------------------
@@ -5744,6 +5854,9 @@ int refclock_parse_bs;
* History:
*
* refclock_parse.c,v
+ * Revision 4.81 2009/05/01 10:15:29 kardel
+ * use new refclock_ppsapi interface
+ *
* Revision 4.80 2007/08/11 12:06:29 kardel
* update comments wrt/ to PPS
*
diff --git a/ntpd/refclock_pcf.c b/ntpd/refclock_pcf.c
index d4e9fd17a015..fcc12be0706a 100644
--- a/ntpd/refclock_pcf.c
+++ b/ntpd/refclock_pcf.c
@@ -38,9 +38,9 @@
/*
* Function prototypes
*/
-static int pcf_start P((int, struct peer *));
-static void pcf_shutdown P((int, struct peer *));
-static void pcf_poll P((int, struct peer *));
+static int pcf_start (int, struct peer *);
+static void pcf_shutdown (int, struct peer *);
+static void pcf_poll (int, struct peer *);
/*
* Transfer vector
@@ -72,10 +72,10 @@ pcf_start(
/*
* Open device file for reading.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
fd = open(device, O_RDONLY);
if (fd == -1) {
- (void)sprintf(device, OLDDEVICE, unit);
+ snprintf(device, sizeof(device), OLDDEVICE, unit);
fd = open(device, O_RDONLY);
}
#ifdef DEBUG
@@ -144,6 +144,8 @@ pcf_poll(
return;
}
+ memset(&tm, 0, sizeof(tm));
+
tm.tm_mday = buf[11] * 10 + buf[10];
tm.tm_mon = buf[13] * 10 + buf[12] - 1;
tm.tm_year = buf[15] * 10 + buf[14];
diff --git a/ntpd/refclock_pst.c b/ntpd/refclock_pst.c
index 776e28eaf43d..bd208c72590f 100644
--- a/ntpd/refclock_pst.c
+++ b/ntpd/refclock_pst.c
@@ -91,10 +91,10 @@ struct pstunit {
/*
* Function prototypes
*/
-static int pst_start P((int, struct peer *));
-static void pst_shutdown P((int, struct peer *));
-static void pst_receive P((struct recvbuf *));
-static void pst_poll P((int, struct peer *));
+static int pst_start (int, struct peer *);
+static void pst_shutdown (int, struct peer *);
+static void pst_receive (struct recvbuf *);
+static void pst_poll (int, struct peer *);
/*
* Transfer vector
@@ -127,25 +127,23 @@ pst_start(
/*
* Open serial port. Use CLK line discipline, if available.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
return (0);
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct pstunit *)emalloc(sizeof(struct pstunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct pstunit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = pst_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -176,8 +174,10 @@ pst_shutdown(
pp = peer->procptr;
up = (struct pstunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
diff --git a/ntpd/refclock_ripencc.c b/ntpd/refclock_ripencc.c
index d9fa2044cd51..3ce3a73750b3 100644
--- a/ntpd/refclock_ripencc.c
+++ b/ntpd/refclock_ripencc.c
@@ -90,7 +90,7 @@
#define TSIP_PARSED_DATA 3
#define TSIP_PARSED_DLE_2 4
-#define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */
+#define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */
#define UTCF_LEAP_SCHD (unsigned char) (1<<4) /* Leap scheduled */
#define UTCF_LEAP_PNDG (unsigned char) (1<<5) /* Leap pending, will occur at end of day */
@@ -109,128 +109,128 @@
/* TSIP packets have the following structure, whether report or command. */
typedef struct {
short
- counter, /* counter */
- len; /* size of buf; < MAX_RPTBUF unsigned chars */
+ counter, /* counter */
+ len; /* size of buf; < MAX_RPTBUF unsigned chars */
unsigned char
- status, /* TSIP packet format/parse status */
- code, /* TSIP code */
- buf[MAX_RPTBUF];/* report or command string */
+ status, /* TSIP packet format/parse status */
+ code, /* TSIP code */
+ buf[MAX_RPTBUF]; /* report or command string */
} TSIPPKT;
/* TSIP binary data structures */
typedef struct {
unsigned char
- t_oa_raw, SV_health;
+ t_oa_raw, SV_health;
float
- e, t_oa, i_0, OMEGADOT, sqrt_A,
- OMEGA_0, omega, M_0, a_f0, a_f1,
- Axis, n, OMEGA_n, ODOT_n, t_zc;
+ e, t_oa, i_0, OMEGADOT, sqrt_A,
+ OMEGA_0, omega, M_0, a_f0, a_f1,
+ Axis, n, OMEGA_n, ODOT_n, t_zc;
short
- weeknum, wn_oa;
+ weeknum, wn_oa;
} ALM_INFO;
-typedef struct { /* Almanac health page (25) parameters */
+typedef struct { /* Almanac health page (25) parameters */
unsigned char
- WN_a, SV_health[32], t_oa;
+ WN_a, SV_health[32], t_oa;
} ALH_PARMS;
-typedef struct { /* Universal Coordinated Time (UTC) parms */
+typedef struct { /* Universal Coordinated Time (UTC) parms */
double
- A_0;
+ A_0;
float
- A_1;
+ A_1;
short
- delta_t_LS;
+ delta_t_LS;
float
- t_ot;
+ t_ot;
short
- WN_t, WN_LSF, DN, delta_t_LSF;
+ WN_t, WN_LSF, DN, delta_t_LSF;
} UTC_INFO;
-typedef struct { /* Ionospheric info (float) */
+typedef struct { /* Ionospheric info (float) */
float
- alpha_0, alpha_1, alpha_2, alpha_3,
- beta_0, beta_1, beta_2, beta_3;
+ alpha_0, alpha_1, alpha_2, alpha_3,
+ beta_0, beta_1, beta_2, beta_3;
} ION_INFO;
-typedef struct { /* Subframe 1 info (float) */
+typedef struct { /* Subframe 1 info (float) */
short
- weeknum;
+ weeknum;
unsigned char
- codeL2, L2Pdata, SVacc_raw, SV_health;
+ codeL2, L2Pdata, SVacc_raw, SV_health;
short
- IODC;
+ IODC;
float
- T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
+ T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
} EPHEM_CLOCK;
-typedef struct { /* Ephemeris info (float) */
+typedef struct { /* Ephemeris info (float) */
unsigned char
- IODE, fit_interval;
+ IODE, fit_interval;
float
- C_rs, delta_n;
+ C_rs, delta_n;
double
- M_0;
+ M_0;
float
- C_uc;
+ C_uc;
double
- e;
+ e;
float
- C_us;
+ C_us;
double
- sqrt_A;
+ sqrt_A;
float
- t_oe, C_ic;
+ t_oe, C_ic;
double
- OMEGA_0;
+ OMEGA_0;
float
- C_is;
+ C_is;
double
- i_0;
+ i_0;
float
- C_rc;
+ C_rc;
double
- omega;
+ omega;
float
- OMEGADOT, IDOT;
+ OMEGADOT, IDOT;
double
- Axis, n, r1me2, OMEGA_n, ODOT_n;
+ Axis, n, r1me2, OMEGA_n, ODOT_n;
} EPHEM_ORBIT;
-typedef struct { /* Navigation data structure */
+typedef struct { /* Navigation data structure */
short
- sv_number; /* SV number (0 = no entry) */
+ sv_number; /* SV number (0 = no entry) */
float
- t_ephem; /* time of ephemeris collection */
+ t_ephem; /* time of ephemeris collection */
EPHEM_CLOCK
- ephclk; /* subframe 1 data */
+ ephclk; /* subframe 1 data */
EPHEM_ORBIT
- ephorb; /* ephemeris data */
+ ephorb; /* ephemeris data */
} NAV_INFO;
typedef struct {
unsigned char
- bSubcode,
- operating_mode,
- dgps_mode,
- dyn_code,
- trackmode;
+ bSubcode,
+ operating_mode,
+ dgps_mode,
+ dyn_code,
+ trackmode;
float
- elev_mask,
- cno_mask,
- dop_mask,
- dop_switch;
+ elev_mask,
+ cno_mask,
+ dop_mask,
+ dop_switch;
unsigned char
- dgps_age_limit;
+ dgps_age_limit;
} TSIP_RCVR_CFG;
#ifdef TRIMBLE_OUTPUT_FUNC
static char
- *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
+ *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
*st_baud_text_app [] = {"", "", " 300", " 600", " 1200", " 2400",
- " 4800", " 9600", "19200", "38400"},
+ " 4800", " 9600", "19200", "38400"},
*old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
*parity_text [] = {"NONE", "ODD", "EVEN"},
*old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
@@ -240,12 +240,12 @@ static char
*rcvr_port_text [] = { "Port A ", "Port B ", "Current Port"},
*dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
*NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
- "3-D", "", "", "OverDetermined Time"},
+ "3-D", "", "", "OverDetermined Time"},
*PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
*PPSPolarityText[] = {"Positive", "Negative"},
*MaskText[] = { "Almanac ", "Ephemeris", "UTC ", "Iono ",
- "GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select",
- "Ext Event", "Pos Fix ", "Raw Meas "};
+ "GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select",
+ "Ext Event", "Pos Fix ", "Raw Meas "};
#endif /* TRIMBLE_OUTPUT_FUNC */
@@ -272,116 +272,116 @@ struct ripencc_unit {
/* prototypes for report parsing primitives */
short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
- unsigned char *rx_baud_index, unsigned char *char_format_index,
- unsigned char *stop_bits, unsigned char *tx_mode_index,
- unsigned char *rx_mode_index);
+ unsigned char *rx_baud_index, unsigned char *char_format_index,
+ unsigned char *stop_bits, unsigned char *tx_mode_index,
+ unsigned char *rx_mode_index);
short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
- float *t_zc, float *eccentricity, float *t_oa, float *i_0,
- float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
- float *M_0);
+ float *t_zc, float *eccentricity, float *t_oa, float *i_0,
+ float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
+ float *M_0);
short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
- short *week_num);
+ short *week_num);
short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
- float *time_of_fix);
+ float *time_of_fix);
short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
- unsigned char *minor_nav_version, unsigned char *nav_day,
- unsigned char *nav_month, unsigned char *nav_year,
- unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
- unsigned char *dsp_day, unsigned char *dsp_month,
- unsigned char *dsp_year);
+ unsigned char *minor_nav_version, unsigned char *nav_day,
+ unsigned char *nav_month, unsigned char *nav_year,
+ unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
+ unsigned char *dsp_day, unsigned char *dsp_month,
+ unsigned char *dsp_year);
short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
- float *snr);
+ float *snr);
short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
- float *clock_bias, float *time_of_fix);
+ float *clock_bias, float *time_of_fix);
short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
- unsigned char *alt_flag);
+ unsigned char *alt_flag);
short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
- unsigned char *status3, unsigned char *status4);
+ unsigned char *status3, unsigned char *status4);
short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
- float *snr_mask, float *dop_mask, float *dop_switch);
+ float *snr_mask, float *dop_mask, float *dop_switch);
short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
- short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
+ short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
- float *time_of_fix);
+ float *time_of_fix);
short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
- unsigned char *time_code, unsigned char *aux_code);
+ unsigned char *time_code, unsigned char *aux_code);
short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
- float *time_of_fix);
+ float *time_of_fix);
short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
- unsigned char *diag_code, short *week_num, float *time_of_fix);
+ unsigned char *diag_code, short *week_num, float *time_of_fix);
short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
- unsigned char *sv_prn, unsigned char *data_length,
- unsigned char *data_packet);
+ unsigned char *sv_prn, unsigned char *data_length,
+ unsigned char *data_packet);
short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
- unsigned char status_code[32]);
+ unsigned char status_code[32]);
short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
- float *signal_level, float *code_phase, float *Doppler,
- double *time_of_fix);
+ float *signal_level, float *code_phase, float *Doppler,
+ double *time_of_fix);
short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
- unsigned char *sv_iode, unsigned char *fit_interval_flag,
- float *time_of_collection, float *time_of_eph, float *sv_accy);
+ unsigned char *sv_iode, unsigned char *fit_interval_flag,
+ float *time_of_collection, float *time_of_eph, float *sv_accy);
short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
- unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
- float *signal_level, float *time_of_last_msmt, float *elev,
- float *azim, unsigned char *old_msmt_flag,
- unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
- unsigned char *data_collect_flag);
+ unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
+ float *signal_level, float *time_of_last_msmt, float *elev,
+ float *azim, unsigned char *old_msmt_flag,
+ unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
+ unsigned char *data_collect_flag);
short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
- unsigned char *ndim, unsigned char sv_prn[], float *pdop,
- float *hdop, float *vdop, float *tdop);
+ unsigned char *ndim, unsigned char sv_prn[], float *pdop,
+ float *hdop, float *vdop, float *tdop);
short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
- float *time_of_fix);
+ float *time_of_fix);
short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
- double *clock_bias, float *time_of_fix);
+ double *clock_bias, float *time_of_fix);
short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
short rpt_0xBC (TSIPPKT *rpt, unsigned char *port_num,
- unsigned char *in_baud, unsigned char *out_baud,
- unsigned char *data_bits, unsigned char *parity,
- unsigned char *stop_bits, unsigned char *flow_control,
- unsigned char *protocols_in, unsigned char *protocols_out,
- unsigned char *reserved);
+ unsigned char *in_baud, unsigned char *out_baud,
+ unsigned char *data_bits, unsigned char *parity,
+ unsigned char *stop_bits, unsigned char *flow_control,
+ unsigned char *protocols_in, unsigned char *protocols_out,
+ unsigned char *reserved);
/* prototypes for superpacket parsers */
short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
- unsigned char *date, unsigned char *month, short *year,
- unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
- float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
- char sv_id[8]);
+ unsigned char *date, unsigned char *month, short *year,
+ unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
+ float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
+ char sv_id[8]);
short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
- double *lon, double *alt, double vel_enu[], double *time_of_fix,
- short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
- short sv_IODC[], short *datum_index);
+ double *lon, double *alt, double vel_enu[], double *time_of_fix,
+ short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
+ short sv_IODC[], short *datum_index);
short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
- unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
- unsigned char *bBuildYear, unsigned char *bBuildMonth,
- unsigned char *bBuildDay, unsigned char *bBuildHour,
- float *fOscOffset, unsigned short *iTestCodeId);
+ unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
+ unsigned char *bBuildYear, unsigned char *bBuildMonth,
+ unsigned char *bBuildDay, unsigned char *bBuildHour,
+ float *fOscOffset, unsigned short *iTestCodeId);
short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
- unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
- unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
- unsigned short *iPremiumOptions, unsigned short *iMachineID,
- unsigned short *iKey);
+ unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
+ unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
+ unsigned short *iPremiumOptions, unsigned short *iMachineID,
+ unsigned short *iKey);
short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
- unsigned char *pps_timebase, unsigned char *pos_polarity,
- double *pps_offset, float *bias_unc_threshold);
+ unsigned char *pps_timebase, unsigned char *pos_polarity,
+ double *pps_offset, float *bias_unc_threshold);
short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
- unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
- unsigned char *Day, unsigned char *Month, unsigned short *Year,
- unsigned char *Status, unsigned char *Flags);
+ unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
+ unsigned char *Day, unsigned char *Month, unsigned short *Year,
+ unsigned char *Status, unsigned char *Flags);
/**/
/* prototypes for command-encode primitives with suffix convention: */
@@ -390,11 +390,11 @@ void cmd_0x1F (TSIPPKT *cmd);
void cmd_0x26 (TSIPPKT *cmd);
void cmd_0x2F (TSIPPKT *cmd);
void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
- unsigned char time_code, unsigned char opts_code);
+ unsigned char time_code, unsigned char opts_code);
void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn);
void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
- unsigned char char_code, unsigned char stopbitcode,
- unsigned char output_mode, unsigned char input_mode);
+ unsigned char char_code, unsigned char stopbitcode,
+ unsigned char output_mode, unsigned char input_mode);
void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
/* prototypes 8E commands */
@@ -403,7 +403,7 @@ void cmd_0x8E41q (TSIPPKT *cmd);
void cmd_0x8E42q (TSIPPKT *cmd);
void cmd_0x8E4Aq (TSIPPKT *cmd);
void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
- unsigned char Polarity, double PPSOffset, float Uncertainty);
+ unsigned char Polarity, double PPSOffset, float Uncertainty);
void cmd_0x8E4Bq (TSIPPKT *cmd);
void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
void cmd_0x8EADq (TSIPPKT *cmd);
@@ -411,33 +411,33 @@ void cmd_0x8EADq (TSIPPKT *cmd);
/* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
/* Trimble parse functions */
-static int parse0x8FAD P((TSIPPKT *, struct peer *));
-static int parse0x8F0B P((TSIPPKT *, struct peer *));
+static int parse0x8FAD (TSIPPKT *, struct peer *);
+static int parse0x8F0B (TSIPPKT *, struct peer *);
#ifdef TRIMBLE_OUTPUT_FUNC
-static int parseany P((TSIPPKT *, struct peer *));
-static void TranslateTSIPReportToText P((TSIPPKT *, char *));
+static int parseany (TSIPPKT *, struct peer *);
+static void TranslateTSIPReportToText (TSIPPKT *, char *);
#endif /* TRIMBLE_OUTPUT_FUNC */
-static int parse0x5C P((TSIPPKT *, struct peer *));
-static int parse0x4F P((TSIPPKT *, struct peer *));
-static void tsip_input_proc P((TSIPPKT *, int));
+static int parse0x5C (TSIPPKT *, struct peer *);
+static int parse0x4F (TSIPPKT *, struct peer *);
+static void tsip_input_proc (TSIPPKT *, int);
/* Trimble helper functions */
-static void bPutFloat P((float *, unsigned char *));
-static void bPutDouble P((double *, unsigned char *));
-static void bPutULong P((unsigned long *, unsigned char *));
-static int print_msg_table_header P((int rptcode, char *HdrStr, int force));
-static char * show_time P((float time_of_week));
+static void bPutFloat (float *, unsigned char *);
+static void bPutDouble (double *, unsigned char *);
+static void bPutULong (unsigned long *, unsigned char *);
+static int print_msg_table_header (int rptcode, char *HdrStr, int force);
+static char * show_time (float time_of_week);
/* RIPE NCC functions */
-static void ripencc_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
-static int ripencc_ppsapi P((struct peer *, int, int));
-static int ripencc_get_pps_ts P((struct ripencc_unit *, l_fp *));
-static int ripencc_start P((int, struct peer *));
-static void ripencc_shutdown P((int, struct peer *));
-static void ripencc_poll P((int, struct peer *));
-static void ripencc_send P((struct peer *, TSIPPKT spt));
-static void ripencc_receive P((struct recvbuf *));
+static void ripencc_control (int, const struct refclockstat *,
+ struct refclockstat *, struct peer *);
+static int ripencc_ppsapi (struct peer *, int, int);
+static int ripencc_get_pps_ts (struct ripencc_unit *, l_fp *);
+static int ripencc_start (int, struct peer *);
+static void ripencc_shutdown (int, struct peer *);
+static void ripencc_poll (int, struct peer *);
+static void ripencc_send (struct peer *, TSIPPKT spt);
+static void ripencc_receive (struct recvbuf *);
/* fill in reflock structure for our clock */
struct refclock refclock_ripencc = {
@@ -471,12 +471,18 @@ ripencc_start(int unit, struct peer *peer)
struct termios tio;
TSIPPKT spt;
+ pp = peer->procptr;
+
/*
* Open serial port
*/
(void)snprintf(device, sizeof(device), DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_RAW)))
+ if (!(fd = refclock_open(device, SPEED232, LDISC_RAW))) {
+ pp->io.fd = -1;
return (0);
+ }
+
+ pp->io.fd = fd;
/* from refclock_palisade.c */
if (tcgetattr(fd, &tio) < 0) {
@@ -498,17 +504,17 @@ ripencc_start(int unit, struct peer *peer)
* Allocate and initialize unit structure
*/
if (!(up = (struct ripencc_unit *)
- emalloc(sizeof(struct ripencc_unit)))) {
+ emalloc(sizeof(struct ripencc_unit)))) {
(void) close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct ripencc_unit));
- pp = peer->procptr;
+
pp->io.clock_recv = ripencc_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
- pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
+ pp->io.fd = -1;
(void) close(fd);
free(up);
return (0);
@@ -548,47 +554,47 @@ ripencc_start(int unit, struct peer *peer)
/* i/o opts */ /* trimble manual page A30 */
cmd_0x35s(&spt,
- 0x1C, /* position */
- 0x00, /* velocity */
- 0x05, /* timing */
- 0x0a); /* auxilary */
+ 0x1C, /* position */
+ 0x00, /* velocity */
+ 0x05, /* timing */
+ 0x0a); /* auxilary */
ripencc_send(peer, spt);
/* turn off port A */
cmd_0x3Ds (&spt,
- 0x0B, /* baud_out */
- 0x0B, /* baud_inp */
- 0x07, /* char_code */
- 0x07, /* stopbitcode */
- 0x01, /* output_mode */
- 0x00); /* input_mode */
+ 0x0B, /* baud_out */
+ 0x0B, /* baud_inp */
+ 0x07, /* char_code */
+ 0x07, /* stopbitcode */
+ 0x01, /* output_mode */
+ 0x00); /* input_mode */
ripencc_send(peer, spt);
/* set i/o options */
cmd_0x8E4As (&spt,
- 0x01, /* PPS on */
- 0x01, /* Timebase UTC */
- 0x00, /* polarity positive */
- 0., /* 100 ft. cable XXX make flag */
- 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */
+ 0x01, /* PPS on */
+ 0x01, /* Timebase UTC */
+ 0x00, /* polarity positive */
+ 0., /* 100 ft. cable XXX make flag */
+ 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */
ripencc_send(peer,spt);
/* all outomatic packet output off */
cmd_0x8E4Ds(&spt,
- 0x00000000); /* AutoOutputMask */
+ 0x00000000); /* AutoOutputMask */
ripencc_send(peer, spt);
cmd_0xBBq (&spt,
- 0x00); /* query primary configuration */
+ 0x00); /* query primary configuration */
ripencc_send(peer,spt);
/* query PPS parameters */
- cmd_0x8E4Aq (&spt); /* query PPS params */
+ cmd_0x8E4Aq (&spt); /* query PPS params */
ripencc_send(peer,spt);
/* query survey limit */
- cmd_0x8E4Bq (&spt); /* query survey limit */
+ cmd_0x8E4Bq (&spt); /* query survey limit */
ripencc_send(peer,spt);
#ifdef DEBUG_NCC
@@ -615,7 +621,7 @@ ripencc_start(int unit, struct peer *peer)
static void
ripencc_control(
int unit, /* unit (not used) */
- struct refclockstat *in, /* input parameters (not used) */
+ const struct refclockstat *in, /* input parameters (not used) */
struct refclockstat *out, /* output parameters (not used) */
struct peer *peer /* peer structure pointer */
)
@@ -628,7 +634,7 @@ ripencc_control(
pp = peer->procptr;
ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
- pp->sloppyclockflag & CLK_FLAG3);
+ pp->sloppyclockflag & CLK_FLAG3);
}
@@ -650,7 +656,7 @@ ripencc_ppsapi(
up = (struct ripencc_unit *)pp->unitptr;
if (time_pps_getcap(up->handle, &capability) < 0) {
msyslog(LOG_ERR,
- "refclock_ripencc: time_pps_getcap failed: %m");
+ "refclock_ripencc: time_pps_getcap failed: %m");
return (0);
}
memset(&up->pps_params, 0, sizeof(pps_params_t));
@@ -660,14 +666,14 @@ ripencc_ppsapi(
up->pps_params.mode = capability & PPS_CAPTUREASSERT;
if (!up->pps_params.mode) {
msyslog(LOG_ERR,
- "refclock_ripencc: invalid capture edge %d",
- !enb_clear);
+ "refclock_ripencc: invalid capture edge %d",
+ !enb_clear);
return (0);
}
up->pps_params.mode |= PPS_TSFMT_TSPEC;
if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
msyslog(LOG_ERR,
- "refclock_ripencc: time_pps_setparams failed: %m");
+ "refclock_ripencc: time_pps_setparams failed: %m");
return (0);
}
if (enb_hardpps) {
@@ -675,7 +681,7 @@ ripencc_ppsapi(
up->pps_params.mode & ~PPS_TSFMT_TSPEC,
PPS_TSFMT_TSPEC) < 0) {
msyslog(LOG_ERR,
- "refclock_ripencc: time_pps_kcbind failed: %m");
+ "refclock_ripencc: time_pps_kcbind failed: %m");
return (0);
}
pps_enable = 1;
@@ -686,9 +692,9 @@ ripencc_ppsapi(
if (debug) {
time_pps_getparams(up->handle, &up->pps_params);
printf(
- "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
- capability, up->pps_params.api_version,
- up->pps_params.mode, enb_hardpps);
+ "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
+ capability, up->pps_params.api_version,
+ up->pps_params.mode, enb_hardpps);
}
#endif /* DEBUG_NCC */
@@ -726,7 +732,7 @@ ripencc_get_pps_ts(
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)
+ &timeout) < 0)
return (0);
if (up->pps_params.mode & PPS_CAPTUREASSERT) {
if (pps_info.assert_sequence ==
@@ -770,12 +776,15 @@ ripencc_shutdown(int unit, struct peer *peer)
pp = peer->procptr;
up = (struct ripencc_unit *)pp->unitptr;
- if (up->handle != 0)
- time_pps_destroy(up->handle);
-
- io_closeclock(&pp->io);
+ if (up != NULL) {
+ if (up->handle != 0)
+ time_pps_destroy(up->handle);
+ free(up);
+ }
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
- free(up);
+ return;
}
/*
@@ -843,7 +852,7 @@ ripencc_send(struct peer *peer, TSIPPKT spt)
return;
}
- if (*ip == 0x10) /* byte stuffing */
+ if (*ip == 0x10) /* byte stuffing */
*op++ = 0x10;
*op++ = *ip++;
}
@@ -867,7 +876,7 @@ ripencc_send(struct peer *peer, TSIPPKT spt)
#endif /* DEBUG_RAW */
if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
- refclock_report(peer, CEVNT_FAULT);
+ refclock_report(peer, CEVNT_FAULT);
}
}
@@ -884,12 +893,12 @@ ripencc_receive(struct recvbuf *rbufp)
register struct ripencc_unit *up;
register struct refclockproc *pp;
struct peer *peer;
- static TSIPPKT rpt; /* structure for current incoming TSIP report */
- TSIPPKT spt; /* send packet */
+ static TSIPPKT rpt; /* for current incoming TSIP report */
+ TSIPPKT spt; /* send packet */
int ns_since_pps;
int i;
char *cp;
- /* Use these variables to hold data until we decide its worth keeping */
+ /* these variables hold data until we decide it's worth keeping */
char rd_lastcode[BMAX];
l_fp rd_tmp;
u_short rd_lencode;
@@ -910,12 +919,14 @@ ripencc_receive(struct recvbuf *rbufp)
#endif /* DEBUG_RAW */
#ifdef DEBUG_RAW
- if (debug) { /* print raw packet */
+ if (debug) { /* print raw packet */
int i;
unsigned char *cp;
printf("ripencc_receive: len %d\n", rbufp->recv_length);
- for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) {
+ for (i=1, cp=(char*)&rbufp->recv_space;
+ i <= rbufp->recv_length;
+ i++, cp++) {
printf(" %02X", *cp);
if (i%10 == 0)
printf("\n");
@@ -927,7 +938,7 @@ ripencc_receive(struct recvbuf *rbufp)
cp = (char*) &rbufp->recv_space;
i=rbufp->recv_length;
- while (i--) { /* loop over received chars */
+ while (i--) { /* loop over received chars */
tsip_input_proc(&rpt, (unsigned char) *cp++);
@@ -936,30 +947,32 @@ ripencc_receive(struct recvbuf *rbufp)
switch (rpt.code) {
- case 0x8F: /* superpacket */
+ case 0x8F: /* superpacket */
switch (rpt.buf[0]) {
- case 0xAD: /* UTC Time */
+ case 0xAD: /* UTC Time */
/*
- * When polling on port B the timecode
- * is the time of the previous PPS.
- * If we completed receiving the packet
- * less than 150ms after the turn of the second,
- * it may have the code of the previous second.
- * We do not trust that and simply poll again
- * without even parsing it.
- *
- * More elegant would be to re-schedule the poll,
- * but I do not know (yet) how to do that cleanly.
- *
- */
+ ** When polling on port B the timecode is
+ ** the time of the previous PPS. If we
+ ** completed receiving the packet less than
+ ** 150ms after the turn of the second, it
+ ** may have the code of the previous second.
+ ** We do not trust that and simply poll
+ ** again without even parsing it.
+ **
+ ** More elegant would be to re-schedule the
+ ** poll, but I do not know (yet) how to do
+ ** that cleanly.
+ **
+ */
/* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
/* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
- ns_since_pps=200;
+ ns_since_pps = 200;
if (up->polled && ns_since_pps < 150) {
- msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__);
+ msyslog(LOG_INFO, "%s(): up->polled",
+ __FUNCTION__);
ripencc_poll(up->unit, peer);
break;
}
@@ -970,9 +983,9 @@ ripencc_receive(struct recvbuf *rbufp)
* from results.
*/
if (parse0x8FAD(&rpt, peer) < 0) {
- msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
- refclock_report(peer, CEVNT_BADREPLY);
- break;
+ msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
+ refclock_report(peer, CEVNT_BADREPLY);
+ break;
}
/*
* If the PPSAPI is working, rather use its
@@ -1009,9 +1022,10 @@ ripencc_receive(struct recvbuf *rbufp)
}
/*
- * Process the new sample in the median filter and determine the
- * reference clock offset and dispersion.
- */
+ ** Process the new sample in the median
+ ** filter and determine the reference clock
+ ** offset and dispersion.
+ */
if (!refclock_process(pp)) {
msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
refclock_report(peer, CEVNT_BADTIME);
@@ -1021,13 +1035,14 @@ ripencc_receive(struct recvbuf *rbufp)
refclock_receive(peer);
break;
- case 0x0B: /* comprehensive time packet */
+ case 0x0B: /* comprehensive time packet */
parse0x8F0B(&rpt, peer);
break;
- default: /* other superpackets */
+ default: /* other superpackets */
#ifdef DEBUG_NCC
- msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);
+ msyslog(LOG_INFO, "%s(): calling parseany",
+ __FUNCTION__);
#endif /* DEBUG_NCC */
#ifdef TRIMBLE_OUTPUT_FUNC
parseany(&rpt, peer);
@@ -1036,15 +1051,15 @@ ripencc_receive(struct recvbuf *rbufp)
}
break;
- case 0x4F: /* UTC parameters, for leap info */
+ case 0x4F: /* UTC parameters, for leap info */
parse0x4F(&rpt, peer);
break;
- case 0x5C: /* sat tracking data */
+ case 0x5C: /* sat tracking data */
parse0x5C(&rpt, peer);
break;
- default: /* other packets */
+ default: /* other packets */
#ifdef TRIMBLE_OUTPUT_FUNC
parseany(&rpt, peer);
#endif /* TRIMBLE_OUTPUT_FUNC */
@@ -1059,33 +1074,45 @@ ripencc_receive(struct recvbuf *rbufp)
* (so not from parseany)
*/
-void cmd_0x1F (TSIPPKT *cmd)
/* request software versions */
+void
+cmd_0x1F(
+ TSIPPKT *cmd
+ )
{
cmd->len = 0;
cmd->code = 0x1F;
}
-void cmd_0x26 (TSIPPKT *cmd)
/* request receiver health */
+void
+cmd_0x26(
+ TSIPPKT *cmd
+ )
{
cmd->len = 0;
cmd->code = 0x26;
}
-
-
-
-void cmd_0x2F (TSIPPKT *cmd)
/* request UTC params */
+void
+cmd_0x2F(
+ TSIPPKT *cmd
+ )
{
cmd->len = 0;
cmd->code = 0x2F;
}
-void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
- unsigned char time_code, unsigned char opts_code)
/* set serial I/O options */
+void
+cmd_0x35s(
+ TSIPPKT *cmd,
+ unsigned char pos_code,
+ unsigned char vel_code,
+ unsigned char time_code,
+ unsigned char opts_code
+ )
{
cmd->buf[0] = pos_code;
cmd->buf[1] = vel_code;
@@ -1094,24 +1121,34 @@ void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
cmd->len = 4;
cmd->code = 0x35;
}
-void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn)
+
/* request tracking status */
+void
+cmd_0x3C(
+ TSIPPKT *cmd,
+ unsigned char sv_prn
+ )
{
cmd->buf[0] = sv_prn;
cmd->len = 1;
cmd->code = 0x3C;
}
-
-void cmd_0x3Ds (TSIPPKT *cmd,
- unsigned char baud_out, unsigned char baud_inp,
- unsigned char char_code, unsigned char stopbitcode,
- unsigned char output_mode, unsigned char input_mode)
/* set Channel A configuration for dual-port operation */
+void
+cmd_0x3Ds(
+ TSIPPKT *cmd,
+ unsigned char baud_out,
+ unsigned char baud_inp,
+ unsigned char char_code,
+ unsigned char stopbitcode,
+ unsigned char output_mode,
+ unsigned char input_mode
+ )
{
cmd->buf[0] = baud_out; /* XMT baud rate */
cmd->buf[1] = baud_inp; /* RCV baud rate */
- cmd->buf[2] = char_code; /* parity and #bits per byte */
+ cmd->buf[2] = char_code; /* parity and #bits per byte */
cmd->buf[3] = stopbitcode; /* number of stop bits code */
cmd->buf[4] = output_mode; /* Ch. A transmission mode */
cmd->buf[5] = input_mode; /* Ch. A reception mode */
@@ -1121,10 +1158,12 @@ void cmd_0x3Ds (TSIPPKT *cmd,
/* query primary configuration */
-void cmd_0xBBq (TSIPPKT *cmd,
- unsigned char subcode)
+void
+cmd_0xBBq(
+ TSIPPKT *cmd,
+ unsigned char subcode
+ )
{
-
cmd->len = 1;
cmd->code = 0xBB;
cmd->buf[0] = subcode;
@@ -1132,36 +1171,47 @@ void cmd_0xBBq (TSIPPKT *cmd,
/**** Superpackets ****/
-void cmd_0x8E0Bq (TSIPPKT *cmd)
/* 8E-0B to query 8F-0B controls */
+void
+cmd_0x8E0Bq(
+ TSIPPKT *cmd
+ )
{
-
cmd->len = 1;
cmd->code = 0x8E;
cmd->buf[0] = 0x0B;
}
-void cmd_0x8E41q (TSIPPKT *cmd)
/* 8F-41 to query board serial number */
+void
+cmd_0x8E41q(
+ TSIPPKT *cmd
+ )
{
-
cmd->len = 1;
cmd->code = 0x8E;
cmd->buf[0] = 0x41;
}
-void cmd_0x8E42q (TSIPPKT *cmd)
/* 8F-42 to query product serial number */
+void
+cmd_0x8E42q(
+ TSIPPKT *cmd
+ )
{
-
cmd->len = 1;
cmd->code = 0x8E;
cmd->buf[0] = 0x42;
}
-void cmd_0x8E4Aq (TSIPPKT *cmd)
+
+
/* 8F-4A to query PPS parameters */
+void
+cmd_0x8E4Aq(
+ TSIPPKT *cmd
+ )
{
cmd->len = 1;
cmd->code = 0x8E;
@@ -1170,12 +1220,15 @@ void cmd_0x8E4Aq (TSIPPKT *cmd)
/* set i/o options */
-void cmd_0x8E4As (TSIPPKT *cmd,
- unsigned char PPSOnOff,
- unsigned char TimeBase,
- unsigned char Polarity,
- double PPSOffset,
- float Uncertainty)
+void
+cmd_0x8E4As(
+ TSIPPKT *cmd,
+ unsigned char PPSOnOff,
+ unsigned char TimeBase,
+ unsigned char Polarity,
+ double PPSOffset,
+ float Uncertainty
+ )
{
cmd->len = 16;
cmd->code = 0x8E;
@@ -1186,18 +1239,24 @@ void cmd_0x8E4As (TSIPPKT *cmd,
bPutDouble (&PPSOffset, &cmd->buf[4]);
bPutFloat (&Uncertainty, &cmd->buf[12]);
}
-void cmd_0x8E4Bq (TSIPPKT *cmd)
+
/* 8F-4B query survey limit */
+void
+cmd_0x8E4Bq(
+ TSIPPKT *cmd
+ )
{
cmd->len = 1;
cmd->code = 0x8E;
cmd->buf[0] = 0x4B;
}
-
/* poll for UTC superpacket */
-void cmd_0x8EADq (TSIPPKT *cmd)
/* 8E-AD to query 8F-AD controls */
+void
+cmd_0x8EADq(
+ TSIPPKT *cmd
+ )
{
cmd->len = 1;
cmd->code = 0x8E;
@@ -1205,8 +1264,11 @@ void cmd_0x8EADq (TSIPPKT *cmd)
}
/* all outomatic packet output off */
-void cmd_0x8E4Ds (TSIPPKT *cmd,
- unsigned long AutoOutputMask)
+void
+cmd_0x8E4Ds(
+ TSIPPKT *cmd,
+ unsigned long AutoOutputMask
+ )
{
cmd->len = 5;
cmd->code = 0x8E;
@@ -1215,88 +1277,106 @@ void cmd_0x8E4Ds (TSIPPKT *cmd,
}
-
-
-/* for DOS machines, reverse order of bytes as they come through the
- * serial port. */
+/*
+ * for DOS machines, reverse order of bytes as they come through the
+ * serial port.
+ */
#ifdef BYTESWAP
-static short bGetShort (unsigned char *bp)
+static short
+bGetShort(
+ unsigned char *bp
+ )
{
short outval;
- unsigned char *optr;
+ unsigned char *optr;
- optr = (unsigned char*)&outval + 1;
- *optr-- = *bp++;
- *optr = *bp;
+ optr = (unsigned char*)&outval + 1;
+ *optr-- = *bp++;
+ *optr = *bp;
return outval;
}
#ifdef TRIMBLE_OUTPUT_FUNC
-static unsigned short bGetUShort (unsigned char *bp)
+static unsigned short
+bGetUShort(
+ unsigned char *bp
+ )
{
unsigned short outval;
- unsigned char *optr;
+ unsigned char *optr;
- optr = (unsigned char*)&outval + 1;
- *optr-- = *bp++;
- *optr = *bp;
+ optr = (unsigned char*)&outval + 1;
+ *optr-- = *bp++;
+ *optr = *bp;
return outval;
}
-static long bGetLong (unsigned char *bp)
+static long
+bGetLong(
+ unsigned char *bp
+ )
{
long outval;
- unsigned char *optr;
+ unsigned char *optr;
- optr = (unsigned char*)&outval + 3;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
+ optr = (unsigned char*)&outval + 3;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr = *bp;
return outval;
}
-static unsigned long bGetULong (unsigned char *bp)
+static unsigned long
+bGetULong(
+ unsigned char *bp
+ )
{
unsigned long outval;
- unsigned char *optr;
+ unsigned char *optr;
- optr = (unsigned char*)&outval + 3;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
+ optr = (unsigned char*)&outval + 3;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr = *bp;
return outval;
}
#endif /* TRIMBLE_OUTPUT_FUNC */
-static float bGetSingle (unsigned char *bp)
+static float
+bGetSingle(
+ unsigned char *bp
+ )
{
float outval;
- unsigned char *optr;
+ unsigned char *optr;
- optr = (unsigned char*)&outval + 3;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
+ optr = (unsigned char*)&outval + 3;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr = *bp;
return outval;
}
-static double bGetDouble (unsigned char *bp)
+static double
+bGetDouble(
+ unsigned char *bp
+ )
{
double outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 7;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
+ unsigned char *optr;
+
+ optr = (unsigned char*)&outval + 7;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr-- = *bp++;
+ *optr = *bp;
return outval;
}
@@ -1316,43 +1396,52 @@ static double bGetDouble (unsigned char *bp)
#ifdef BYTESWAP
void
-bPutFloat (float *in, unsigned char *out)
+bPutFloat(
+ float *in,
+ unsigned char *out
+ )
{
unsigned char *inptr;
- inptr = (unsigned char*)in + 3;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out = *inptr;
+ inptr = (unsigned char*)in + 3;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out = *inptr;
}
static void
-bPutULong (unsigned long *in, unsigned char *out)
+bPutULong(
+ unsigned long *in,
+ unsigned char *out
+ )
{
unsigned char *inptr;
- inptr = (unsigned char*)in + 3;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out = *inptr;
+ inptr = (unsigned char*)in + 3;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out = *inptr;
}
static void
-bPutDouble (double *in, unsigned char *out)
+bPutDouble(
+ double *in,
+ unsigned char *out
+ )
{
unsigned char *inptr;
- inptr = (unsigned char*)in + 7;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out = *inptr;
+ inptr = (unsigned char*)in + 7;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out++ = *inptr--;
+ *out = *inptr;
}
#else /* not BYTESWAP */
@@ -1374,9 +1463,10 @@ void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
*/
static int
-parse0x8FAD(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
+parse0x8FAD(
+ TSIPPKT *rpt,
+ struct peer *peer
+ )
{
register struct refclockproc *pp;
register struct ripencc_unit *up;
@@ -1403,7 +1493,6 @@ parse0x8FAD(rpt, peer)
return(-1);
}
-
if (bGetDouble(&buf[3]) != 0.0) {
#ifdef DEBUG_NCC
if (debug)
@@ -1412,14 +1501,14 @@ parse0x8FAD(rpt, peer)
return(-1);
}
- hour = (unsigned int) buf[11];
- minute = (unsigned int) buf[12];
- second = (unsigned int) buf[13];
+ hour = (unsigned int) buf[11];
+ minute = (unsigned int) buf[12];
+ second = (unsigned int) buf[13];
day = (unsigned int) buf[14];
month = (unsigned int) buf[15];
year = bGetShort(&buf[16]);
- trackstat = buf[18];
- utcflags = buf[19];
+ trackstat = buf[18];
+ utcflags = buf[19];
sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
@@ -1438,7 +1527,7 @@ parse0x8FAD(rpt, peer)
/* poll for UTC parameters once and then if UTC flag changed */
up = (struct ripencc_unit *) pp->unitptr;
if (utcflags != up->utcflags) {
- TSIPPKT spt; /* local structure for send packet */
+ TSIPPKT spt; /* local structure for send packet */
cmd_0x2F (&spt); /* request UTC params */
ripencc_send(peer,spt);
up->utcflags = utcflags;
@@ -1458,7 +1547,7 @@ parse0x8FAD(rpt, peer)
if (month < 1 || month > 12 || day < 1 || day > 31)
return(-1);
- if (pp->year % 4) {
+ if (pp->year % 4) { /* XXX: use is_leapyear() ? */
if (day > day1tab[month - 1])
return(-1);
for (i = 0; i < month - 1; i++)
@@ -1476,7 +1565,9 @@ parse0x8FAD(rpt, peer)
pp->nsec = 0;
if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
- pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND);
+ pp-> leap = (up->leapdelta > 0)
+ ? LEAP_ADDSECOND
+ : LEAP_DELSECOND;
else
pp-> leap = LEAP_NOWARNING;
@@ -1486,13 +1577,15 @@ parse0x8FAD(rpt, peer)
/*
* Parse comprehensive time packet
*
- * 0 = success
+ * 0 = success
* -1 = errors
*/
-int parse0x8F0B(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
+int
+parse0x8F0B(
+ TSIPPKT *rpt,
+ struct peer *peer
+ )
{
register struct refclockproc *pp;
@@ -1539,7 +1632,6 @@ int parse0x8F0B(rpt, peer)
hour = (unsigned int )fmod(tow / 3600., 24.);
}
-
day = (unsigned int) buf[11];
month = (unsigned int) buf[12];
year = bGetShort(&buf[13]);
@@ -1587,9 +1679,10 @@ int parse0x8F0B(rpt, peer)
sprintf(logbuf, "C1 %02d%02d%04d %02d%02d%02d %d %7.0f %.1f %.0f %.1f %d %02d%09.6f %c %02d%09.6f %c %.0f %d %d %d %d %d %d %d %d",
- day, month, year, hour, minute, second, mode, bias, biasunc, rate, rateunc, utcoff,
- lat_deg, lat_min, north_south, lon_deg, lon_min, east_west, alt,
- sv[0], sv[1], sv[2], sv[3], sv[4], sv[5], sv[6], sv[7]);
+ day, month, year, hour, minute, second, mode, bias, biasunc,
+ rate, rateunc, utcoff, lat_deg, lat_min, north_south, lon_deg,
+ lon_min, east_west, alt, sv[0], sv[1], sv[2], sv[3], sv[4],
+ sv[5], sv[6], sv[7]);
#ifdef DEBUG_NCC
if (debug)
@@ -1605,9 +1698,11 @@ int parse0x8F0B(rpt, peer)
/*
* Parse any packet using Trimble machinery
*/
-int parseany(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
+int
+parseany(
+ TSIPPKT *rpt,
+ struct peer *peer
+ )
{
static char logbuf[1024]; /* logging string buffer */
@@ -1631,9 +1726,11 @@ int parseany(rpt, peer)
* -1 = errors
*/
-int parse0x4F(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
+int
+parse0x4F(
+ TSIPPKT *rpt,
+ struct peer *peer
+ )
{
register struct ripencc_unit *up;
@@ -1680,9 +1777,11 @@ int parse0x4F(rpt, peer)
* -1 = errors
*/
-int parse0x5C(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
+int
+parse0x5C(
+ TSIPPKT *rpt,
+ struct peer *peer
+ )
{
unsigned char prn, channel, aqflag, ephstat;
float snr, azinuth, elevation;
@@ -1784,13 +1883,15 @@ int parse0x5C(rpt, peer)
*/
-/**/
-static void tsip_input_proc (
- TSIPPKT *rpt,
- int inbyte)
-/* reads bytes until serial buffer is empty or a complete report
+/*
+ * reads bytes until serial buffer is empty or a complete report
* has been received; end of report is signified by DLE ETX.
*/
+static void
+tsip_input_proc(
+ TSIPPKT *rpt,
+ int inbyte
+ )
{
unsigned char newbyte;
@@ -1799,71 +1900,71 @@ static void tsip_input_proc (
newbyte = (unsigned char)(inbyte);
switch (rpt->status)
{
- case TSIP_PARSED_DLE_1:
+ case TSIP_PARSED_DLE_1:
switch (newbyte)
{
- case 0:
- case ETX:
- /* illegal TSIP IDs */
- rpt->len = 0;
+ case 0:
+ case ETX:
+ /* illegal TSIP IDs */
+ rpt->len = 0;
rpt->status = TSIP_PARSED_EMPTY;
break;
- case DLE:
- /* try normal message start again */
+ case DLE:
+ /* try normal message start again */
rpt->len = 0;
rpt->status = TSIP_PARSED_DLE_1;
break;
- default:
- /* legal TSIP ID; start message */
+ default:
+ /* legal TSIP ID; start message */
rpt->code = newbyte;
- rpt->len = 0;
+ rpt->len = 0;
rpt->status = TSIP_PARSED_DATA;
break;
}
break;
- case TSIP_PARSED_DATA:
+ case TSIP_PARSED_DATA:
switch (newbyte) {
- case DLE:
- /* expect DLE or ETX next */
+ case DLE:
+ /* expect DLE or ETX next */
rpt->status = TSIP_PARSED_DLE_2;
break;
- default:
- /* normal data byte */
+ default:
+ /* normal data byte */
rpt->buf[rpt->len] = newbyte;
rpt->len++;
- /* no change in rpt->status */
+ /* no change in rpt->status */
break;
}
break;
- case TSIP_PARSED_DLE_2:
+ case TSIP_PARSED_DLE_2:
switch (newbyte) {
- case DLE:
- /* normal data byte */
+ case DLE:
+ /* normal data byte */
rpt->buf[rpt->len] = newbyte;
rpt->len++;
rpt->status = TSIP_PARSED_DATA;
break;
- case ETX:
+ case ETX:
/* end of message; return TRUE here. */
rpt->status = TSIP_PARSED_FULL;
break;
- default:
+ default:
/* error: treat as TSIP_PARSED_DLE_1; start new report packet */
rpt->code = newbyte;
- rpt->len = 0;
+ rpt->len = 0;
rpt->status = TSIP_PARSED_DATA;
}
break;
- case TSIP_PARSED_FULL:
- case TSIP_PARSED_EMPTY:
- default:
+ case TSIP_PARSED_FULL:
+ case TSIP_PARSED_EMPTY:
+ default:
switch (newbyte) {
- case DLE:
- /* normal message start */
+ case DLE:
+ /* normal message start */
rpt->len = 0;
rpt->status = TSIP_PARSED_DLE_1;
break;
- default:
+ default:
/* error: ignore newbyte */
rpt->len = 0;
rpt->status = TSIP_PARSED_EMPTY;
@@ -1880,14 +1981,17 @@ static void tsip_input_proc (
#ifdef TRIMBLE_OUTPUT_FUNC
/**/
-short rpt_0x3D (TSIPPKT *rpt,
- unsigned char *tx_baud_index,
- unsigned char *rx_baud_index,
- unsigned char *char_format_index,
- unsigned char *stop_bits,
- unsigned char *tx_mode_index,
- unsigned char *rx_mode_index)
/* Channel A configuration for dual port operation */
+short
+rpt_0x3D(
+ TSIPPKT *rpt,
+ unsigned char *tx_baud_index,
+ unsigned char *rx_baud_index,
+ unsigned char *char_format_index,
+ unsigned char *stop_bits,
+ unsigned char *tx_mode_index,
+ unsigned char *rx_mode_index
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -1903,19 +2007,22 @@ short rpt_0x3D (TSIPPKT *rpt,
}
/**/
-short rpt_0x40 (TSIPPKT *rpt,
- unsigned char *sv_prn,
- short *week_num,
- float *t_zc,
- float *eccentricity,
- float *t_oa,
- float *i_0,
- float *OMEGA_dot,
- float *sqrt_A,
- float *OMEGA_0,
- float *omega,
- float *M_0)
/* almanac data for specified satellite */
+short
+rpt_0x40(
+ TSIPPKT *rpt,
+ unsigned char *sv_prn,
+ short *week_num,
+ float *t_zc,
+ float *eccentricity,
+ float *t_oa,
+ float *i_0,
+ float *OMEGA_dot,
+ float *sqrt_A,
+ float *OMEGA_0,
+ float *omega,
+ float *M_0
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -1935,11 +2042,14 @@ short rpt_0x40 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x41 (TSIPPKT *rpt,
- float *time_of_week,
- float *UTC_offset,
- short *week_num)
/* GPS time */
+short
+rpt_0x41(
+ TSIPPKT *rpt,
+ float *time_of_week,
+ float *UTC_offset,
+ short *week_num
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -1951,10 +2061,13 @@ short rpt_0x41 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x42 (TSIPPKT *rpt,
- float pos_ECEF[3],
- float *time_of_fix)
/* position in ECEF, single precision */
+short
+rpt_0x42(
+ TSIPPKT *rpt,
+ float pos_ECEF[3],
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -1967,11 +2080,14 @@ short rpt_0x42 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x43 (TSIPPKT *rpt,
- float ECEF_vel[3],
- float *freq_offset,
- float *time_of_fix)
/* velocity in ECEF, single precision */
+short
+rpt_0x43(
+ TSIPPKT *rpt,
+ float ECEF_vel[3],
+ float *freq_offset,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -1985,18 +2101,21 @@ short rpt_0x43 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x45 (TSIPPKT *rpt,
- unsigned char *major_nav_version,
- unsigned char *minor_nav_version,
- unsigned char *nav_day,
- unsigned char *nav_month,
- unsigned char *nav_year,
- unsigned char *major_dsp_version,
- unsigned char *minor_dsp_version,
- unsigned char *dsp_day,
- unsigned char *dsp_month,
- unsigned char *dsp_year)
/* software versions */
+short
+rpt_0x45(
+ TSIPPKT *rpt,
+ unsigned char *major_nav_version,
+ unsigned char *minor_nav_version,
+ unsigned char *nav_day,
+ unsigned char *nav_month,
+ unsigned char *nav_year,
+ unsigned char *major_dsp_version,
+ unsigned char *minor_dsp_version,
+ unsigned char *dsp_day,
+ unsigned char *dsp_month,
+ unsigned char *dsp_year
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2015,10 +2134,13 @@ short rpt_0x45 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x46 (TSIPPKT *rpt,
- unsigned char *status1,
- unsigned char *status2)
/* receiver health and status */
+short
+rpt_0x46(
+ TSIPPKT *rpt,
+ unsigned char *status1,
+ unsigned char *status2
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2029,10 +2151,14 @@ short rpt_0x46 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x47 (TSIPPKT *rpt,
- unsigned char *nsvs, unsigned char *sv_prn,
- float *snr)
/* signal levels for all satellites tracked */
+short
+rpt_0x47(
+ TSIPPKT *rpt,
+ unsigned char *nsvs,
+ unsigned char *sv_prn,
+ float *snr
+ )
{
short isv;
unsigned char *buf;
@@ -2047,9 +2173,12 @@ short rpt_0x47 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x48 (TSIPPKT *rpt,
- unsigned char *message)
/* GPS system message */
+short
+rpt_0x48(
+ TSIPPKT *rpt,
+ unsigned char *message
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2060,9 +2189,12 @@ short rpt_0x48 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x49 (TSIPPKT *rpt,
- unsigned char *sv_health)
/* health for all satellites from almanac health page */
+short
+rpt_0x49(
+ TSIPPKT *rpt,
+ unsigned char *sv_health
+ )
{
short i;
unsigned char *buf;
@@ -2073,13 +2205,16 @@ short rpt_0x49 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4A (TSIPPKT *rpt,
- float *lat,
- float *lon,
- float *alt,
- float *clock_bias,
- float *time_of_fix)
/* position in lat-lon-alt, single precision */
+short
+rpt_0x4A(
+ TSIPPKT *rpt,
+ float *lat,
+ float *lon,
+ float *alt,
+ float *clock_bias,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2093,9 +2228,14 @@ short rpt_0x4A (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4A_2 (TSIPPKT *rpt,
- float *alt, float *dummy , unsigned char *alt_flag)
/* reference altitude parameters */
+short
+rpt_0x4A_2(
+ TSIPPKT *rpt,
+ float *alt,
+ float *dummy,
+ unsigned char *alt_flag
+ )
{
unsigned char *buf;
@@ -2108,11 +2248,14 @@ short rpt_0x4A_2 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4B (TSIPPKT *rpt,
- unsigned char *machine_id,
- unsigned char *status3,
- unsigned char *status4)
/* machine ID code, status */
+short
+rpt_0x4B(
+ TSIPPKT *rpt,
+ unsigned char *machine_id,
+ unsigned char *status3,
+ unsigned char *status4
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2124,13 +2267,16 @@ short rpt_0x4B (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4C (TSIPPKT *rpt,
- unsigned char *dyn_code,
- float *el_mask,
- float *snr_mask,
- float *dop_mask,
- float *dop_switch)
/* operating parameters and masks */
+short
+rpt_0x4C(
+ TSIPPKT *rpt,
+ unsigned char *dyn_code,
+ float *el_mask,
+ float *snr_mask,
+ float *dop_mask,
+ float *dop_switch
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2144,9 +2290,12 @@ short rpt_0x4C (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4D (TSIPPKT *rpt,
- float *osc_offset)
/* oscillator offset */
+short
+rpt_0x4D(
+ TSIPPKT *rpt,
+ float *osc_offset
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2156,9 +2305,12 @@ short rpt_0x4D (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4E (TSIPPKT *rpt,
- unsigned char *response)
/* yes/no response to command to set GPS time */
+short
+rpt_0x4E(
+ TSIPPKT *rpt,
+ unsigned char *response
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2168,16 +2320,19 @@ short rpt_0x4E (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x4F (TSIPPKT *rpt,
- double *a0,
- float *a1,
- float *time_of_data,
- short *dt_ls,
- short *wn_t,
- short *wn_lsf,
- short *dn,
- short *dt_lsf)
/* UTC data */
+short
+rpt_0x4F(
+ TSIPPKT *rpt,
+ double *a0,
+ float *a1,
+ float *time_of_data,
+ short *dt_ls,
+ short *wn_t,
+ short *wn_lsf,
+ short *dn,
+ short *dt_lsf
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2195,11 +2350,14 @@ short rpt_0x4F (TSIPPKT *rpt,
}
/**/
-short rpt_0x54 (TSIPPKT *rpt,
- float *clock_bias,
- float *freq_offset,
- float *time_of_fix)
/* clock offset and frequency offset in 1-SV (0-D) mode */
+short
+rpt_0x54(
+ TSIPPKT *rpt,
+ float *clock_bias,
+ float *freq_offset,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2211,12 +2369,15 @@ short rpt_0x54 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x55 (TSIPPKT *rpt,
- unsigned char *pos_code,
- unsigned char *vel_code,
- unsigned char *time_code,
- unsigned char *aux_code)
/* I/O serial options */
+short
+rpt_0x55(
+ TSIPPKT *rpt,
+ unsigned char *pos_code,
+ unsigned char *vel_code,
+ unsigned char *time_code,
+ unsigned char *aux_code
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2229,9 +2390,14 @@ short rpt_0x55 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x56 (TSIPPKT *rpt,
- float vel_ENU[3], float *freq_offset, float *time_of_fix)
/* velocity in east-north-up coordinates */
+short
+rpt_0x56(
+ TSIPPKT *rpt,
+ float vel_ENU[3],
+ float *freq_offset,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2248,11 +2414,15 @@ short rpt_0x56 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x57 (TSIPPKT *rpt,
- unsigned char *source_code, unsigned char *diag_code,
- short *week_num,
- float *time_of_fix)
/* info about last computed fix */
+short
+rpt_0x57(
+ TSIPPKT *rpt,
+ unsigned char *source_code,
+ unsigned char *diag_code,
+ short *week_num,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2265,10 +2435,16 @@ short rpt_0x57 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x58 (TSIPPKT *rpt,
- unsigned char *op_code, unsigned char *data_type, unsigned char *sv_prn,
- unsigned char *data_length, unsigned char *data_packet)
/* GPS system data or acknowledgment of GPS system data load */
+short
+rpt_0x58(
+ TSIPPKT *rpt,
+ unsigned char *op_code,
+ unsigned char *data_type,
+ unsigned char *sv_prn,
+ unsigned char *data_length,
+ unsigned char *data_packet
+ )
{
unsigned char *buf, *buf4;
short dl;
@@ -2294,7 +2470,7 @@ short rpt_0x58 (TSIPPKT *rpt,
*data_length = (unsigned char)dl;
buf4 = &buf[4];
switch (*data_type) {
- case 2:
+ case 2:
/* Almanac */
if (*data_length != sizeof (ALM_INFO)) return TRUE;
alminfo = (ALM_INFO*)data_packet;
@@ -2319,7 +2495,7 @@ short rpt_0x58 (TSIPPKT *rpt,
alminfo->wn_oa = bGetShort(&buf4[64]);
break;
- case 3:
+ case 3:
/* Almanac health page */
if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE;
@@ -2327,7 +2503,7 @@ short rpt_0x58 (TSIPPKT *rpt,
memcpy (data_packet, buf4, dl);
break;
- case 4:
+ case 4:
/* Ionosphere */
if (*data_length != sizeof (ION_INFO) + 8) return TRUE;
ioninfo = (ION_INFO*)data_packet;
@@ -2341,7 +2517,7 @@ short rpt_0x58 (TSIPPKT *rpt,
ioninfo->beta_3 = bGetSingle (&buf4[36]);
break;
- case 5:
+ case 5:
/* UTC */
if (*data_length != sizeof (UTC_INFO) + 13) return TRUE;
utcinfo = (UTC_INFO*)data_packet;
@@ -2355,7 +2531,7 @@ short rpt_0x58 (TSIPPKT *rpt,
utcinfo->delta_t_LSF = bGetShort (&buf4[37]);
break;
- case 6:
+ case 6:
/* Ephemeris */
if (*data_length != sizeof (NAV_INFO) - 1) return TRUE;
@@ -2406,10 +2582,13 @@ short rpt_0x58 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x59 (TSIPPKT *rpt,
- unsigned char *code_type,
- unsigned char status_code[32])
/* satellite enable/disable or health heed/ignore list */
+short
+rpt_0x59(
+ TSIPPKT *rpt,
+ unsigned char *code_type,
+ unsigned char status_code[32]
+ )
{
short iprn;
unsigned char *buf;
@@ -2422,14 +2601,17 @@ short rpt_0x59 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x5A (TSIPPKT *rpt,
- unsigned char *sv_prn,
- float *sample_length,
- float *signal_level,
- float *code_phase,
- float *Doppler,
- double *time_of_fix)
/* raw measurement data - code phase/Doppler */
+short
+rpt_0x5A(
+ TSIPPKT *rpt,
+ unsigned char *sv_prn,
+ float *sample_length,
+ float *signal_level,
+ float *code_phase,
+ float *Doppler,
+ double *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2444,15 +2626,18 @@ short rpt_0x5A (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x5B (TSIPPKT *rpt,
- unsigned char *sv_prn,
- unsigned char *sv_health,
- unsigned char *sv_iode,
- unsigned char *fit_interval_flag,
- float *time_of_collection,
- float *time_of_eph,
- float *sv_accy)
/* satellite ephorb status */
+short
+rpt_0x5B(
+ TSIPPKT *rpt,
+ unsigned char *sv_prn,
+ unsigned char *sv_health,
+ unsigned char *sv_iode,
+ unsigned char *fit_interval_flag,
+ float *time_of_collection,
+ float *time_of_eph,
+ float *sv_accy
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2468,21 +2653,24 @@ short rpt_0x5B (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x5C (TSIPPKT *rpt,
- unsigned char *sv_prn,
- unsigned char *slot,
- unsigned char *chan,
- unsigned char *acq_flag,
- unsigned char *eph_flag,
- float *signal_level,
- float *time_of_last_msmt,
- float *elev,
- float *azim,
- unsigned char *old_msmt_flag,
- unsigned char *integer_msec_flag,
- unsigned char *bad_data_flag,
- unsigned char *data_collect_flag)
/* satellite tracking status */
+short
+rpt_0x5C(
+ TSIPPKT *rpt,
+ unsigned char *sv_prn,
+ unsigned char *slot,
+ unsigned char *chan,
+ unsigned char *acq_flag,
+ unsigned char *eph_flag,
+ float *signal_level,
+ float *time_of_last_msmt,
+ float *elev,
+ float *azim,
+ unsigned char *old_msmt_flag,
+ unsigned char *integer_msec_flag,
+ unsigned char *bad_data_flag,
+ unsigned char *data_collect_flag
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2507,16 +2695,19 @@ short rpt_0x5C (TSIPPKT *rpt,
}
/**/
-short rpt_0x6D (TSIPPKT *rpt,
- unsigned char *manual_mode,
- unsigned char *nsvs,
- unsigned char *ndim,
- unsigned char sv_prn[],
- float *pdop,
- float *hdop,
- float *vdop,
- float *tdop)
/* over-determined satellite selection for position fixes, PDOP, fix mode */
+short
+rpt_0x6D(
+ TSIPPKT *rpt,
+ unsigned char *manual_mode,
+ unsigned char *nsvs,
+ unsigned char *ndim,
+ unsigned char sv_prn[],
+ float *pdop,
+ float *hdop,
+ float *vdop,
+ float *tdop
+ )
{
short islot;
unsigned char *buf;
@@ -2538,9 +2729,12 @@ short rpt_0x6D (TSIPPKT *rpt,
}
/**/
-short rpt_0x82 (TSIPPKT *rpt,
- unsigned char *diff_mode)
/* differential fix mode */
+short
+rpt_0x82(
+ TSIPPKT *rpt,
+ unsigned char *diff_mode
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2550,11 +2744,14 @@ short rpt_0x82 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x83 (TSIPPKT *rpt,
- double ECEF_pos[3],
- double *clock_bias,
- float *time_of_fix)
/* position, ECEF double precision */
+short
+rpt_0x83(
+ TSIPPKT *rpt,
+ double ECEF_pos[3],
+ double *clock_bias,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2568,13 +2765,16 @@ short rpt_0x83 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_0x84 (TSIPPKT *rpt,
- double *lat,
- double *lon,
- double *alt,
- double *clock_bias,
- float *time_of_fix)
/* position, lat-lon-alt double precision */
+short
+rpt_0x84(
+ TSIPPKT *rpt,
+ double *lat,
+ double *lon,
+ double *alt,
+ double *clock_bias,
+ float *time_of_fix
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2588,39 +2788,44 @@ short rpt_0x84 (TSIPPKT *rpt,
return FALSE;
}
-short rpt_Paly0xBB(TSIPPKT *rpt,
- TSIP_RCVR_CFG *TsipxBB)
+short
+rpt_Paly0xBB(
+ TSIPPKT *rpt,
+ TSIP_RCVR_CFG *TsipxBB
+ )
{
-
unsigned char *buf;
buf = rpt->buf;
- /* Palisade is inconsistent with other TSIP, which has a kength of 40 */
+ /* Palisade is inconsistent with other TSIP, which has a length of 40 */
/* if (rpt->len != 40) return TRUE; */
if (rpt->len != 43) return TRUE;
- TsipxBB->bSubcode = buf[0];
- TsipxBB->operating_mode = buf[1] ;
- TsipxBB->dyn_code = buf[3] ;
- TsipxBB->elev_mask = bGetSingle (&buf[5]);
- TsipxBB->cno_mask = bGetSingle (&buf[9]);
- TsipxBB->dop_mask = bGetSingle (&buf[13]);
+ TsipxBB->bSubcode = buf[0];
+ TsipxBB->operating_mode = buf[1];
+ TsipxBB->dyn_code = buf[3];
+ TsipxBB->elev_mask = bGetSingle (&buf[5]);
+ TsipxBB->cno_mask = bGetSingle (&buf[9]);
+ TsipxBB->dop_mask = bGetSingle (&buf[13]);
TsipxBB->dop_switch = bGetSingle (&buf[17]);
return FALSE;
}
-short rpt_0xBC (TSIPPKT *rpt,
- unsigned char *port_num,
- unsigned char *in_baud,
- unsigned char *out_baud,
- unsigned char *data_bits,
- unsigned char *parity,
- unsigned char *stop_bits,
- unsigned char *flow_control,
- unsigned char *protocols_in,
- unsigned char *protocols_out,
- unsigned char *reserved)
/* Receiver serial port configuration */
+short
+rpt_0xBC(
+ TSIPPKT *rpt,
+ unsigned char *port_num,
+ unsigned char *in_baud,
+ unsigned char *out_baud,
+ unsigned char *data_bits,
+ unsigned char *parity,
+ unsigned char *stop_bits,
+ unsigned char *flow_control,
+ unsigned char *protocols_in,
+ unsigned char *protocols_out,
+ unsigned char *reserved
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2642,51 +2847,57 @@ short rpt_0xBC (TSIPPKT *rpt,
/**** Superpackets ****/
-short rpt_0x8F0B(TSIPPKT *rpt,
- unsigned short *event,
- double *tow,
- unsigned char *date,
- unsigned char *month,
- short *year,
- unsigned char *dim_mode,
- short *utc_offset,
- double *bias,
- double *drift,
- float *bias_unc,
- float *dr_unc,
- double *lat,
- double *lon,
- double *alt,
- char sv_id[8])
-{
- short local_index;
- unsigned char *buf;
+short
+rpt_0x8F0B(
+ TSIPPKT *rpt,
+ unsigned short *event,
+ double *tow,
+ unsigned char *date,
+ unsigned char *month,
+ short *year,
+ unsigned char *dim_mode,
+ short *utc_offset,
+ double *bias,
+ double *drift,
+ float *bias_unc,
+ float *dr_unc,
+ double *lat,
+ double *lon,
+ double *alt,
+ char sv_id[8]
+ )
+{
+ short local_index;
+ unsigned char *buf;
buf = rpt->buf;
- if (rpt->len != 74) return TRUE;
- *event = bGetShort(&buf[1]);
- *tow = bGetDouble(&buf[3]);
- *date = buf[11];
- *month = buf[12];
- *year = bGetShort(&buf[13]);
- *dim_mode = buf[15];
- *utc_offset = bGetShort(&buf[16]);
- *bias = bGetDouble(&buf[18]);
- *drift = bGetDouble(&buf[26]);
- *bias_unc = bGetSingle(&buf[34]);
- *dr_unc = bGetSingle(&buf[38]);
- *lat = bGetDouble(&buf[42]);
- *lon = bGetDouble(&buf[50]);
- *alt = bGetDouble(&buf[58]);
-
- for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
- return FALSE;
-}
-
-short rpt_0x8F14 (TSIPPKT *rpt,
- short *datum_idx,
- double datum_coeffs[5])
-/* datum index and coefficients */
+ if (rpt->len != 74) return TRUE;
+ *event = bGetShort(&buf[1]);
+ *tow = bGetDouble(&buf[3]);
+ *date = buf[11];
+ *month = buf[12];
+ *year = bGetShort(&buf[13]);
+ *dim_mode = buf[15];
+ *utc_offset = bGetShort(&buf[16]);
+ *bias = bGetDouble(&buf[18]);
+ *drift = bGetDouble(&buf[26]);
+ *bias_unc = bGetSingle(&buf[34]);
+ *dr_unc = bGetSingle(&buf[38]);
+ *lat = bGetDouble(&buf[42]);
+ *lon = bGetDouble(&buf[50]);
+ *alt = bGetDouble(&buf[58]);
+
+ for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
+ return FALSE;
+}
+
+/* datum index and coefficients */
+short
+rpt_0x8F14(
+ TSIPPKT *rpt,
+ short *datum_idx,
+ double datum_coeffs[5]
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2702,10 +2913,13 @@ short rpt_0x8F14 (TSIPPKT *rpt,
}
-short rpt_0x8F15 (TSIPPKT *rpt,
- short *datum_idx,
- double datum_coeffs[5])
-/* datum index and coefficients */
+/* datum index and coefficients */
+short
+rpt_0x8F15(
+ TSIPPKT *rpt,
+ short *datum_idx,
+ double datum_coeffs[5]
+ )
{
unsigned char *buf;
buf = rpt->buf;
@@ -2723,29 +2937,32 @@ short rpt_0x8F15 (TSIPPKT *rpt,
#define MAX_LONG (2147483648.) /* 2**31 */
-short rpt_0x8F20 (TSIPPKT *rpt,
- unsigned char *info,
- double *lat,
- double *lon,
- double *alt,
- double vel_enu[],
- double *time_of_fix,
- short *week_num,
- unsigned char *nsvs,
- unsigned char sv_prn[],
- short sv_IODC[],
- short *datum_index)
+short
+rpt_0x8F20(
+ TSIPPKT *rpt,
+ unsigned char *info,
+ double *lat,
+ double *lon,
+ double *alt,
+ double vel_enu[],
+ double *time_of_fix,
+ short *week_num,
+ unsigned char *nsvs,
+ unsigned char sv_prn[],
+ short sv_IODC[],
+ short *datum_index
+ )
{
short
- isv;
+ isv;
unsigned char
- *buf, prnx, iode;
+ *buf, prnx, iode;
unsigned long
- ulongtemp;
+ ulongtemp;
long
- longtemp;
+ longtemp;
double
- vel_scale;
+ vel_scale;
buf = rpt->buf;
@@ -2774,24 +2991,27 @@ short rpt_0x8F20 (TSIPPKT *rpt,
for (isv = 0; isv < 8; isv++) {
prnx = buf[32+2*isv];
sv_prn[isv] = (unsigned char)(prnx&0x3F);
- iode = buf[33+2*isv];
+ iode = buf[33+2*isv];
sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8));
}
return FALSE;
}
-short rpt_0x8F41 (TSIPPKT *rpt,
- unsigned char *bSearchRange,
- unsigned char *bBoardOptions,
- unsigned long *iiSerialNumber,
- unsigned char *bBuildYear,
- unsigned char *bBuildMonth,
- unsigned char *bBuildDay,
- unsigned char *bBuildHour,
- float *fOscOffset,
- unsigned short *iTestCodeId)
+short
+rpt_0x8F41(
+ TSIPPKT *rpt,
+ unsigned char *bSearchRange,
+ unsigned char *bBoardOptions,
+ unsigned long *iiSerialNumber,
+ unsigned char *bBuildYear,
+ unsigned char *bBuildMonth,
+ unsigned char *bBuildDay,
+ unsigned char *bBuildHour,
+ float *fOscOffset,
+ unsigned short *iTestCodeId
+ )
{
- if(rpt->len != 17) return FALSE;
+ if (rpt->len != 17) return FALSE;
*bSearchRange = rpt->buf[1];
*bBoardOptions = rpt->buf[2];
*iiSerialNumber = bGetLong(&rpt->buf[3]);
@@ -2805,17 +3025,20 @@ short rpt_0x8F41 (TSIPPKT *rpt,
return TRUE;
}
-short rpt_0x8F42 (TSIPPKT *rpt,
- unsigned char *bProdOptionsPre,
- unsigned char *bProdNumberExt,
- unsigned short *iCaseSerialNumberPre,
- unsigned long *iiCaseSerialNumber,
- unsigned long *iiProdNumber,
- unsigned short *iPremiumOptions,
- unsigned short *iMachineID,
- unsigned short *iKey)
+short
+rpt_0x8F42(
+ TSIPPKT *rpt,
+ unsigned char *bProdOptionsPre,
+ unsigned char *bProdNumberExt,
+ unsigned short *iCaseSerialNumberPre,
+ unsigned long *iiCaseSerialNumber,
+ unsigned long *iiProdNumber,
+ unsigned short *iPremiumOptions,
+ unsigned short *iMachineID,
+ unsigned short *iKey
+ )
{
- if(rpt->len != 19) return FALSE;
+ if (rpt->len != 19) return FALSE;
*bProdOptionsPre = rpt->buf[1];
*bProdNumberExt = rpt->buf[2];
*iCaseSerialNumberPre = bGetShort(&rpt->buf[3]);
@@ -2827,100 +3050,117 @@ short rpt_0x8F42 (TSIPPKT *rpt,
return TRUE;
}
-short rpt_0x8F45(TSIPPKT *rpt,
- unsigned char *bSegMask)
+short
+rpt_0x8F45(
+ TSIPPKT *rpt,
+ unsigned char *bSegMask
+ )
{
- if(rpt->len != 2) return FALSE;
+ if (rpt->len != 2) return FALSE;
*bSegMask = rpt->buf[1];
return TRUE;
}
-short rpt_0x8F4A_16(TSIPPKT *rpt,
- unsigned char *pps_enabled,
- unsigned char *pps_timebase,
- unsigned char *pos_polarity,
- double *pps_offset,
- float *bias_unc_threshold)
/* Stinger PPS definition */
+short
+rpt_0x8F4A_16(
+ TSIPPKT *rpt,
+ unsigned char *pps_enabled,
+ unsigned char *pps_timebase,
+ unsigned char *pos_polarity,
+ double *pps_offset,
+ float *bias_unc_threshold
+ )
{
unsigned char
- *buf;
-
- buf = rpt->buf;
- if (rpt->len != 16) return TRUE;
- *pps_enabled = buf[1];
- *pps_timebase = buf[2];
- *pos_polarity = buf[3];
- *pps_offset = bGetDouble(&buf[4]);
- *bias_unc_threshold = bGetSingle(&buf[12]);
+ *buf;
+
+ buf = rpt->buf;
+ if (rpt->len != 16) return TRUE;
+ *pps_enabled = buf[1];
+ *pps_timebase = buf[2];
+ *pos_polarity = buf[3];
+ *pps_offset = bGetDouble(&buf[4]);
+ *bias_unc_threshold = bGetSingle(&buf[12]);
return FALSE;
}
-short rpt_0x8F4B(TSIPPKT *rpt,
- unsigned long *decorr_max)
+short
+rpt_0x8F4B(
+ TSIPPKT *rpt,
+ unsigned long *decorr_max
+ )
{
unsigned char
- *buf;
+ *buf;
- buf = rpt->buf;
- if (rpt->len != 5) return TRUE;
- *decorr_max = bGetLong(&buf[1]);
- return FALSE;
+ buf = rpt->buf;
+ if (rpt->len != 5) return TRUE;
+ *decorr_max = bGetLong(&buf[1]);
+ return FALSE;
}
-short rpt_0x8F4D(TSIPPKT *rpt,
- unsigned long *event_mask)
+short
+rpt_0x8F4D(
+ TSIPPKT *rpt,
+ unsigned long *event_mask
+ )
{
unsigned char
- *buf;
+ *buf;
- buf = rpt->buf;
- if (rpt->len != 5) return TRUE;
- *event_mask = bGetULong (&buf[1]);
- return FALSE;
+ buf = rpt->buf;
+ if (rpt->len != 5) return TRUE;
+ *event_mask = bGetULong (&buf[1]);
+ return FALSE;
}
-short rpt_0x8FA5(TSIPPKT *rpt,
- unsigned char *spktmask)
+short
+rpt_0x8FA5(
+ TSIPPKT *rpt,
+ unsigned char *spktmask
+ )
{
unsigned char
- *buf;
-
- buf = rpt->buf;
- if (rpt->len != 5) return TRUE;
- spktmask[0] = buf[1];
- spktmask[1] = buf[2];
- spktmask[2] = buf[3];
- spktmask[3] = buf[4];
- return FALSE;
-}
-
-short rpt_0x8FAD (TSIPPKT *rpt,
- unsigned short *COUNT,
- double *FracSec,
- unsigned char *Hour,
- unsigned char *Minute,
- unsigned char *Second,
- unsigned char *Day,
- unsigned char *Month,
- unsigned short *Year,
- unsigned char *Status,
- unsigned char *Flags)
-{
+ *buf;
+ buf = rpt->buf;
+ if (rpt->len != 5) return TRUE;
+ spktmask[0] = buf[1];
+ spktmask[1] = buf[2];
+ spktmask[2] = buf[3];
+ spktmask[3] = buf[4];
+ return FALSE;
+}
+
+short
+rpt_0x8FAD(
+ TSIPPKT *rpt,
+ unsigned short *COUNT,
+ double *FracSec,
+ unsigned char *Hour,
+ unsigned char *Minute,
+ unsigned char *Second,
+ unsigned char *Day,
+ unsigned char *Month,
+ unsigned short *Year,
+ unsigned char *Status,
+ unsigned char *Flags
+ )
+{
if (rpt->len != 22) return TRUE;
- *COUNT = bGetUShort(&rpt->buf[1]);
- *FracSec = bGetDouble(&rpt->buf[3]);
- *Hour = rpt->buf[11];
- *Minute = rpt->buf[12];
- *Second = rpt->buf[13];
- *Day = rpt->buf[14];
- *Month = rpt->buf[15];
- *Year = bGetUShort(&rpt->buf[16]);
- *Status = rpt->buf[18];
- *Flags = rpt->buf[19];
- return FALSE;
+ *COUNT = bGetUShort(&rpt->buf[1]);
+ *FracSec = bGetDouble(&rpt->buf[3]);
+ *Hour = rpt->buf[11];
+ *Minute = rpt->buf[12];
+ *Second = rpt->buf[13];
+ *Day = rpt->buf[14];
+ *Month = rpt->buf[15];
+ *Year = bGetUShort(&rpt->buf[16]);
+ *Status = rpt->buf[18];
+ *Flags = rpt->buf[19];
+ return FALSE;
}
@@ -2976,31 +3216,34 @@ short rpt_0x8FAD (TSIPPKT *rpt,
/* pbuf is the pointer to the current location of the text output */
static char
- *pbuf;
+*pbuf;
/* keep track of whether the message has been successfully parsed */
static short
- parsed;
+parsed;
/* convert time of week into day-hour-minute-second and print */
-char* show_time (float time_of_week)
+char *
+show_time(
+ float time_of_week
+ )
{
short days, hours, minutes;
float seconds;
double tow = 0;
- static char timestring [80];
+ static char timestring [80];
if (time_of_week == -1.0)
- {
+ {
sprintf(timestring, " <No time yet> ");
}
else if ((time_of_week >= 604800.0) || (time_of_week < 0.0))
- {
+ {
sprintf(timestring, " <Bad time> ");
}
- else
- {
+ else
+ {
if (time_of_week < 604799.9)
tow = time_of_week + .00000001;
seconds = (float)fmod(tow, 60.);
@@ -3008,42 +3251,45 @@ char* show_time (float time_of_week)
hours = (short)fmod(tow / 3600., 24.);
days = (short)(tow / 86400.0);
sprintf(timestring, " %s %02d:%02d:%05.2f ",
- dayname[days], hours, minutes, seconds);
- }
- return timestring;
+ dayname[days], hours, minutes, seconds);
+ }
+ return timestring;
}
/**/
/* 0x3D */
-static void rpt_chan_A_config (TSIPPKT *rpt)
+static void
+rpt_chan_A_config(
+ TSIPPKT *rpt
+ )
{
unsigned char
- tx_baud_index, rx_baud_index,
- char_format_index, stop_bits,
- tx_mode_index, rx_mode_index,
- databits, parity;
+ tx_baud_index, rx_baud_index,
+ char_format_index, stop_bits,
+ tx_mode_index, rx_mode_index,
+ databits, parity;
int
- i, nbaud;
+ i, nbaud;
/* unload rptbuf */
if (rpt_0x3D (rpt,
- &tx_baud_index, &rx_baud_index, &char_format_index,
- &stop_bits, &tx_mode_index, &rx_mode_index)) {
+ &tx_baud_index, &rx_baud_index, &char_format_index,
+ &stop_bits, &tx_mode_index, &rx_mode_index)) {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nChannel A Configuration");
- nbaud = sizeof(old_baudnum);
+ nbaud = sizeof(old_baudnum);
for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break;
pbuf += sprintf(pbuf, "\n Transmit speed: %s at %s",
- old_output_ch[tx_mode_index], st_baud_text_app[i]);
+ old_output_ch[tx_mode_index], st_baud_text_app[i]);
for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break;
pbuf += sprintf(pbuf, "\n Receive speed: %s at %s",
- old_input_ch[rx_mode_index], st_baud_text_app[i]);
+ old_input_ch[rx_mode_index], st_baud_text_app[i]);
databits = (unsigned char)((char_format_index & 0x03) + 5);
@@ -3051,43 +3297,46 @@ static void rpt_chan_A_config (TSIPPKT *rpt)
if (parity > 4) parity = 2;
pbuf += sprintf(pbuf, "\n Character format (bits/char, parity, stop bits): %d-%s-%d",
- databits, old_parity_text[parity], stop_bits);
+ databits, old_parity_text[parity], stop_bits);
}
/**/
/* 0x40 */
-static void rpt_almanac_data_page (TSIPPKT *rpt)
+static void
+rpt_almanac_data_page(
+ TSIPPKT *rpt
+ )
{
unsigned char
- sv_prn;
+ sv_prn;
short
- week_num;
+ week_num;
float
- t_zc,
- eccentricity,
- t_oa,
- i_0,
- OMEGA_dot,
- sqrt_A,
- OMEGA_0,
- omega,
- M_0;
+ t_zc,
+ eccentricity,
+ t_oa,
+ i_0,
+ OMEGA_dot,
+ sqrt_A,
+ OMEGA_0,
+ omega,
+ M_0;
/* unload rptbuf */
if (rpt_0x40 (rpt,
- &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
- &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
+ &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
+ &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn);
pbuf += sprintf(pbuf, "\n Captured:%15.0f %s",
- t_zc, show_time (t_zc));
+ t_zc, show_time (t_zc));
pbuf += sprintf(pbuf, "\n week:%15d", week_num);
pbuf += sprintf(pbuf, "\n Eccentricity:%15g", eccentricity);
pbuf += sprintf(pbuf, "\n T_oa:%15.0f %s",
- t_oa, show_time (t_oa));
+ t_oa, show_time (t_oa));
pbuf += sprintf(pbuf, "\n i 0:%15g", i_0);
pbuf += sprintf(pbuf, "\n OMEGA dot:%15g", OMEGA_dot);
pbuf += sprintf(pbuf, "\n sqrt A:%15g", sqrt_A);
@@ -3097,12 +3346,15 @@ static void rpt_almanac_data_page (TSIPPKT *rpt)
}
/* 0x41 */
-static void rpt_GPS_time (TSIPPKT *rpt)
+static void
+rpt_GPS_time(
+ TSIPPKT *rpt
+ )
{
float
- time_of_week, UTC_offset;
+ time_of_week, UTC_offset;
short
- week_num;
+ week_num;
/* unload rptbuf */
if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) {
@@ -3111,15 +3363,18 @@ static void rpt_GPS_time (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d UTC offset %.1f",
- show_time(time_of_week), week_num, UTC_offset);
+ show_time(time_of_week), week_num, UTC_offset);
}
/* 0x42 */
-static void rpt_single_ECEF_position (TSIPPKT *rpt)
+static void
+rpt_single_ECEF_position(
+ TSIPPKT *rpt
+ )
{
float
- ECEF_pos[3], time_of_fix;
+ ECEF_pos[3], time_of_fix;
/* unload rptbuf */
if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) {
@@ -3128,16 +3383,19 @@ static void rpt_single_ECEF_position (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\nSXYZ: %15.0f %15.0f %15.0f %s",
- ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
- show_time(time_of_fix));
+ ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
+ show_time(time_of_fix));
}
/* 0x43 */
-static void rpt_single_ECEF_velocity (TSIPPKT *rpt)
+static void
+rpt_single_ECEF_velocity(
+ TSIPPKT *rpt
+ )
{
float
- ECEF_vel[3], freq_offset, time_of_fix;
+ ECEF_vel[3], freq_offset, time_of_fix;
/* unload rptbuf */
if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) {
@@ -3146,54 +3404,63 @@ static void rpt_single_ECEF_velocity (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\nVelECEF: %11.3f %11.3f %11.3f %12.3f%s",
- ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
- show_time(time_of_fix));
+ ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
+ show_time(time_of_fix));
}
/* 0x45 */
-static void rpt_SW_version (TSIPPKT *rpt) {
+static void
+rpt_SW_version(
+ TSIPPKT *rpt
+ )
+{
unsigned char
- major_nav_version, minor_nav_version,
- nav_day, nav_month, nav_year,
- major_dsp_version, minor_dsp_version,
- dsp_day, dsp_month, dsp_year;
+ major_nav_version, minor_nav_version,
+ nav_day, nav_month, nav_year,
+ major_dsp_version, minor_dsp_version,
+ dsp_day, dsp_month, dsp_year;
/* unload rptbuf */
if (rpt_0x45 (rpt,
- &major_nav_version, &minor_nav_version,
- &nav_day, &nav_month, &nav_year,
- &major_dsp_version, &minor_dsp_version,
- &dsp_day, &dsp_month, &dsp_year)) {
+ &major_nav_version, &minor_nav_version,
+ &nav_day, &nav_month, &nav_year,
+ &major_dsp_version, &minor_dsp_version,
+ &dsp_day, &dsp_month, &dsp_year)) {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf,
-"\nFW Versions: Nav Proc %2d.%02d %2d/%2d/%2d Sig Proc %2d.%02d %2d/%2d/%2d",
- major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
- major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
+ "\nFW Versions: Nav Proc %2d.%02d %2d/%2d/%2d Sig Proc %2d.%02d %2d/%2d/%2d",
+ major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
+ major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
}
/* 0x46 */
-static void rpt_rcvr_health (TSIPPKT *rpt)
+static void
+rpt_rcvr_health(
+ TSIPPKT *rpt
+ )
{
unsigned char
- status1, status2;
- static char
- *sc_text[] = {
- "Doing position fixes",
- "Don't have GPS time yet",
- "Waiting for almanac collection",
- "DOP too high ",
- "No satellites available",
- "Only 1 satellite available",
- "Only 2 satellites available",
- "Only 3 satellites available",
- "No satellites usable ",
- "Only 1 satellite usable",
- "Only 2 satellites usable",
- "Only 3 satellites usable",
- "Chosen satellite unusable"};
+ status1, status2;
+ const char
+ *text;
+ static const char const
+ *sc_text[] = {
+ "Doing position fixes",
+ "Don't have GPS time yet",
+ "Waiting for almanac collection",
+ "DOP too high ",
+ "No satellites available",
+ "Only 1 satellite available",
+ "Only 2 satellites available",
+ "Only 3 satellites available",
+ "No satellites usable ",
+ "Only 1 satellite usable",
+ "Only 2 satellites usable",
+ "Only 3 satellites usable",
+ "Chosen satellite unusable"};
/* unload rptbuf */
@@ -3203,49 +3470,58 @@ static void rpt_rcvr_health (TSIPPKT *rpt)
return;
}
+ text = (status1 < COUNTOF(sc_text))
+ ? sc_text[status1]
+ : "(out of range)";
pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ",
- sc_text[rpt->buf[0]], status1);
+ text, status1);
pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)",
- (status2 & 0x01)?"No BBRAM":"BBRAM OK",
- (status2 & 0x10)?"No Ant":"Ant OK",
- status2);
+ (status2 & 0x01)?"No BBRAM":"BBRAM OK",
+ (status2 & 0x10)?"No Ant":"Ant OK",
+ status2);
}
/* 0x47 */
-static void rpt_SNR_all_SVs (TSIPPKT *rpt)
+static void
+rpt_SNR_all_SVs(
+ TSIPPKT *rpt
+ )
{
unsigned char
- nsvs, sv_prn[12];
+ nsvs, sv_prn[12];
short
- isv;
+ isv;
float
- snr[12];
+ snr[12];
/* unload rptbuf */
if (rpt_0x47 (rpt, &nsvs, sv_prn, snr))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs);
for (isv = 0; isv < nsvs; isv++)
- {
+ {
pbuf += sprintf(pbuf, "\n SV %02d %6.2f",
- sv_prn[isv], snr[isv]);
+ sv_prn[isv], snr[isv]);
}
}
/* 0x48 */
-static void rpt_GPS_system_message (TSIPPKT *rpt)
+static void
+rpt_GPS_system_message(
+ TSIPPKT *rpt
+ )
{
unsigned char
- message[23];
+ message[23];
/* unload rptbuf */
if (rpt_0x48 (rpt, message))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
@@ -3254,43 +3530,50 @@ static void rpt_GPS_system_message (TSIPPKT *rpt)
}
/* 0x49 */
-static void rpt_almanac_health_page (TSIPPKT *rpt)
+static void
+rpt_almanac_health_page(
+ TSIPPKT *rpt
+ )
{
short
- iprn;
+ iprn;
unsigned char
- sv_health [32];
+ sv_health [32];
/* unload rptbuf */
if (rpt_0x49 (rpt, sv_health))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nAlmanac health page:");
for (iprn = 0; iprn < 32; iprn++)
- {
+ {
if (!(iprn%5)) *pbuf++ = '\n';
pbuf += sprintf(pbuf, " SV%02d %2X",
- (iprn+1) , sv_health[iprn]);
+ (iprn+1) , sv_health[iprn]);
}
}
/* 0x4A */
-static void rpt_single_lla_position (TSIPPKT *rpt) {
+static void
+rpt_single_lla_position(
+ TSIPPKT *rpt
+ )
+{
short
- lat_deg, lon_deg;
+ lat_deg, lon_deg;
float
- lat, lon,
- alt, clock_bias, time_of_fix;
+ lat, lon,
+ alt, clock_bias, time_of_fix;
double lat_min, lon_min;
unsigned char
- north_south, east_west;
+ north_south, east_west;
if (rpt_0x4A (rpt,
- &lat, &lon, &alt, &clock_bias, &time_of_fix))
- {
+ &lat, &lon, &alt, &clock_bias, &time_of_fix))
+ {
parsed = BADLEN_PARSE;
return;
}
@@ -3299,7 +3582,7 @@ static void rpt_single_lla_position (TSIPPKT *rpt) {
lat *= (float)R2D;
north_south = 'N';
if (lat < 0.0)
- {
+ {
north_south = 'S';
lat = -lat;
}
@@ -3309,7 +3592,7 @@ static void rpt_single_lla_position (TSIPPKT *rpt) {
lon *= (float)R2D;
east_west = 'E';
if (lon < 0.0)
- {
+ {
east_west = 'W';
lon = -lon;
}
@@ -3317,136 +3600,152 @@ static void rpt_single_lla_position (TSIPPKT *rpt) {
lon_min = (lon - lon_deg) * 60.0;
pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f %c%5d:%06.3f %c%10.2f %12.2f%s",
- lat_deg, lat_min, north_south,
- lon_deg, lon_min, east_west,
- alt, clock_bias,
- show_time(time_of_fix));
+ lat_deg, lat_min, north_south,
+ lon_deg, lon_min, east_west,
+ alt, clock_bias,
+ show_time(time_of_fix));
}
/* 0x4A */
-static void rpt_ref_alt (TSIPPKT *rpt) {
-
+static void
+rpt_ref_alt(
+ TSIPPKT *rpt
+ )
+{
float
- alt, dummy;
+ alt, dummy;
unsigned char
- alt_flag;
+ alt_flag;
- if (rpt_0x4A_2 (rpt,
- &alt, &dummy, &alt_flag))
- {
+ if (rpt_0x4A_2 (rpt, &alt, &dummy, &alt_flag))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nReference Alt: %.1f m; %s",
- alt, alt_flag?"ON":"OFF");
+ alt, alt_flag?"ON":"OFF");
}
/* 0x4B */
-static void rpt_rcvr_id_and_status (TSIPPKT *rpt)
+static void
+rpt_rcvr_id_and_status(
+ TSIPPKT *rpt
+ )
{
unsigned char
- machine_id, status3, status4;
+ machine_id, status3, status4;
/* unload rptbuf */
if (rpt_0x4B (rpt, &machine_id, &status3, &status4))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)",
- machine_id,
- (status3 & 0x02)?"No RTC":"RTC OK",
- (status3 & 0x08)?"No Alm":"Alm OK",
- status3);
+ machine_id,
+ (status3 & 0x02)?"No RTC":"RTC OK",
+ (status3 & 0x08)?"No Alm":"Alm OK",
+ status3);
}
/* 0x4C */
-static void rpt_operating_parameters (TSIPPKT *rpt)
+static void
+rpt_operating_parameters(
+ TSIPPKT *rpt
+ )
{
unsigned char
- dyn_code;
+ dyn_code;
float
- el_mask, snr_mask, dop_mask, dop_switch;
+ el_mask, snr_mask, dop_mask, dop_switch;
/* unload rptbuf */
if (rpt_0x4C (rpt, &dyn_code, &el_mask,
- &snr_mask, &dop_mask, &dop_switch))
- {
+ &snr_mask, &dop_mask, &dop_switch))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nOperating Parameters:");
pbuf += sprintf(pbuf, "\n Dynamics code = %d %s",
- dyn_code, dyn_text[dyn_code]);
- pbuf += sprintf(pbuf, "\n Elevation mask = %.2fø", el_mask * R2D);
+ dyn_code, dyn_text[dyn_code]);
+ pbuf += sprintf(pbuf, "\n Elevation mask = %.2f", el_mask * R2D);
pbuf += sprintf(pbuf, "\n SNR mask = %.2f", snr_mask);
pbuf += sprintf(pbuf, "\n DOP mask = %.2f", dop_mask);
pbuf += sprintf(pbuf, "\n DOP switch = %.2f", dop_switch);
}
/* 0x4D */
-static void rpt_oscillator_offset (TSIPPKT *rpt)
+static void
+rpt_oscillator_offset(
+ TSIPPKT *rpt
+ )
{
float
- osc_offset;
+ osc_offset;
/* unload rptbuf */
if (rpt_0x4D (rpt, &osc_offset))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM",
- osc_offset, osc_offset/1575.42);
+ osc_offset, osc_offset/1575.42);
}
/* 0x4E */
-static void rpt_GPS_time_set_response (TSIPPKT *rpt)
+static void
+rpt_GPS_time_set_response(
+ TSIPPKT *rpt
+ )
{
-
unsigned char
- response;
+ response;
/* unload rptbuf */
if (rpt_0x4E (rpt, &response))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
switch (response)
- {
- case 'Y':
+ {
+ case 'Y':
pbuf += sprintf(pbuf, "\nTime set accepted");
break;
- case 'N':
+ case 'N':
pbuf += sprintf(pbuf, "\nTime set rejected or not required");
break;
- default:
+ default:
parsed = BADDATA_PARSE;
}
}
/* 0x4F */
-static void rpt_UTC_offset (TSIPPKT *rpt)
+static void
+rpt_UTC_offset(
+ TSIPPKT *rpt
+ )
{
double
- a0;
+ a0;
float
- a1, time_of_data;
+ a1, time_of_data;
short
- dt_ls, wn_t, wn_lsf, dn, dt_lsf;
+ dt_ls, wn_t, wn_lsf, dn, dt_lsf;
/* unload rptbuf */
if (rpt_0x4F (rpt, &a0, &a1, &time_of_data,
- &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
+ &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
parsed = BADLEN_PARSE;
return;
}
@@ -3464,10 +3763,13 @@ static void rpt_UTC_offset (TSIPPKT *rpt)
/**/
/* 0x54 */
-static void rpt_1SV_bias (TSIPPKT *rpt)
+static void
+rpt_1SV_bias(
+ TSIPPKT *rpt
+ )
{
float
- clock_bias, freq_offset, time_of_fix;
+ clock_bias, freq_offset, time_of_fix;
/* unload rptbuf */
if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) {
@@ -3476,25 +3778,28 @@ static void rpt_1SV_bias (TSIPPKT *rpt)
}
pbuf += sprintf (pbuf, "\nTime Fix Clock Bias: %6.2f m Freq Bias: %6.2f m/s%s",
- clock_bias, freq_offset, show_time (time_of_fix));
+ clock_bias, freq_offset, show_time (time_of_fix));
}
/* 0x55 */
-static void rpt_io_opt (TSIPPKT *rpt)
+static void
+rpt_io_opt(
+ TSIPPKT *rpt
+ )
{
unsigned char
- pos_code, vel_code, time_code, aux_code;
+ pos_code, vel_code, time_code, aux_code;
/* unload rptbuf */
if (rpt_0x55 (rpt,
- &pos_code, &vel_code, &time_code, &aux_code)) {
+ &pos_code, &vel_code, &time_code, &aux_code)) {
parsed = BADLEN_PARSE;
return;
}
/* rptbuf unloaded */
pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X",
- pos_code, vel_code, time_code, aux_code);
+ pos_code, vel_code, time_code, aux_code);
if (pos_code & 0x01) {
pbuf += sprintf(pbuf, "\n ECEF XYZ position output");
@@ -3505,16 +3810,16 @@ static void rpt_io_opt (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, (pos_code & 0x04)?
- "\n MSL altitude output (Geoid height) ":
- "\n WGS-84 altitude output");
+ "\n MSL altitude output (Geoid height) ":
+ "\n WGS-84 altitude output");
pbuf += sprintf(pbuf, (pos_code & 0x08)?
- "\n MSL altitude input":
- "\n WGS-84 altitude input");
+ "\n MSL altitude input":
+ "\n WGS-84 altitude input");
pbuf += sprintf(pbuf, (pos_code & 0x10)?
- "\n Double precision":
- "\n Single precision");
+ "\n Double precision":
+ "\n Single precision");
if (pos_code & 0x20) {
pbuf += sprintf(pbuf, "\n All Enabled Superpackets");
@@ -3529,8 +3834,8 @@ static void rpt_io_opt (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, (time_code & 0x01)?
- "\n Time tags in UTC":
- "\n Time tags in GPS time");
+ "\n Time tags in UTC":
+ "\n Time tags in GPS time");
if (time_code & 0x02) {
pbuf += sprintf(pbuf, "\n Fixes delayed to integer seconds");
@@ -3548,9 +3853,9 @@ static void rpt_io_opt (TSIPPKT *rpt)
pbuf += sprintf(pbuf, "\n Minimize measurement propagation");
}
- pbuf += sprintf(pbuf, (time_code & 0x20) ?
- "\n PPS output at all times" :
- "\n PPS output during fixes");
+ pbuf += sprintf(pbuf, (time_code & 0x20) ?
+ "\n PPS output at all times" :
+ "\n PPS output during fixes");
if (aux_code & 0x01) {
pbuf += sprintf(pbuf, "\n Raw measurement output");
@@ -3565,15 +3870,18 @@ static void rpt_io_opt (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, (aux_code & 0x08)?
- "\n Signal Strength Output as dBHz" :
- "\n Signal Strength Output as AMU");
+ "\n Signal Strength Output as dBHz" :
+ "\n Signal Strength Output as AMU");
}
/* 0x56 */
-static void rpt_ENU_velocity (TSIPPKT *rpt)
+static void
+rpt_ENU_velocity(
+ TSIPPKT *rpt
+ )
{
float
- vel_ENU[3], freq_offset, time_of_fix;
+ vel_ENU[3], freq_offset, time_of_fix;
/* unload rptbuf */
if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) {
@@ -3582,19 +3890,22 @@ static void rpt_ENU_velocity (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\nVel ENU: %11.3f %11.3f %11.3f %12.3f%s",
- vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
- show_time (time_of_fix));
+ vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
+ show_time (time_of_fix));
}
/* 0x57 */
-static void rpt_last_fix_info (TSIPPKT *rpt)
+static void
+rpt_last_fix_info(
+ TSIPPKT *rpt
+ )
{
unsigned char
- source_code, diag_code;
+ source_code, diag_code;
short
- week_num;
+ week_num;
float
- time_of_fix;
+ time_of_fix;
/* unload rptbuf */
if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) {
@@ -3603,61 +3914,64 @@ static void rpt_last_fix_info (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\n source code %d; diag code: %2Xh",
- source_code, diag_code);
+ source_code, diag_code);
pbuf += sprintf(pbuf, "\n Time of last fix:%s", show_time(time_of_fix));
pbuf += sprintf(pbuf, "\n Week of last fix: %d", week_num);
}
/* 0x58 */
-static void rpt_GPS_system_data (TSIPPKT *rpt)
+static void
+rpt_GPS_system_data(
+ TSIPPKT *rpt
+ )
{
unsigned char
- iprn,
- op_code, data_type, sv_prn,
- data_length, data_packet[250];
+ iprn,
+ op_code, data_type, sv_prn,
+ data_length, data_packet[250];
ALM_INFO
- *almanac;
+ *almanac;
ALH_PARMS
- *almh;
+ *almh;
UTC_INFO
- *utc;
+ *utc;
ION_INFO
- *ionosphere;
+ *ionosphere;
EPHEM_CLOCK
- *cdata;
+ *cdata;
EPHEM_ORBIT
- *edata;
+ *edata;
NAV_INFO
- *nav_data;
+ *nav_data;
unsigned char
- curr_t_oa;
+ curr_t_oa;
unsigned short
- curr_wn_oa;
+ curr_wn_oa;
static char
- *datname[] =
- {"", "", "Almanac Orbit",
- "Health Page & Ref Time", "Ionosphere", "UTC ",
- "Ephemeris"};
+ *datname[] =
+ {"", "", "Almanac Orbit",
+ "Health Page & Ref Time", "Ionosphere", "UTC ",
+ "Ephemeris"};
/* unload rptbuf */
if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn,
- &data_length, data_packet))
- {
+ &data_length, data_packet))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nSystem data [%d]: %s SV%02d",
- data_type, datname[data_type], sv_prn);
+ data_type, datname[data_type], sv_prn);
switch (op_code)
{
- case 1:
+ case 1:
pbuf += sprintf(pbuf, " Acknowledgment");
break;
- case 2:
+ case 2:
pbuf += sprintf(pbuf, " length = %d bytes", data_length);
switch (data_type) {
- case 2:
+ case 2:
/* Almanac */
if (sv_prn == 0 || sv_prn > 32) {
pbuf += sprintf(pbuf, " Binary PRN invalid");
@@ -3665,57 +3979,57 @@ static void rpt_GPS_system_data (TSIPPKT *rpt)
}
almanac = (ALM_INFO*)data_packet;
pbuf += sprintf(pbuf, "\n t_oa_raw = % -12d SV_hlth = % -12d ",
- almanac->t_oa_raw , almanac->SV_health );
+ almanac->t_oa_raw , almanac->SV_health );
pbuf += sprintf(pbuf, "\n e = % -12g t_oa = % -12g ",
- almanac->e , almanac->t_oa );
+ almanac->e , almanac->t_oa );
pbuf += sprintf(pbuf, "\n i_0 = % -12g OMEGADOT = % -12g ",
- almanac->i_0 , almanac->OMEGADOT );
+ almanac->i_0 , almanac->OMEGADOT );
pbuf += sprintf(pbuf, "\n sqrt_A = % -12g OMEGA_0 = % -12g ",
- almanac->sqrt_A , almanac->OMEGA_0 );
+ almanac->sqrt_A , almanac->OMEGA_0 );
pbuf += sprintf(pbuf, "\n omega = % -12g M_0 = % -12g ",
- almanac->omega , almanac->M_0 );
+ almanac->omega , almanac->M_0 );
pbuf += sprintf(pbuf, "\n a_f0 = % -12g a_f1 = % -12g ",
- almanac->a_f0 , almanac->a_f1 );
+ almanac->a_f0 , almanac->a_f1 );
pbuf += sprintf(pbuf, "\n Axis = % -12g n = % -12g ",
- almanac->Axis , almanac->n );
+ almanac->Axis , almanac->n );
pbuf += sprintf(pbuf, "\n OMEGA_n = % -12g ODOT_n = % -12g ",
- almanac->OMEGA_n , almanac->ODOT_n );
+ almanac->OMEGA_n , almanac->ODOT_n );
pbuf += sprintf(pbuf, "\n t_zc = % -12g weeknum = % -12d ",
- almanac->t_zc , almanac->weeknum );
+ almanac->t_zc , almanac->weeknum );
pbuf += sprintf(pbuf, "\n wn_oa = % -12d", almanac->wn_oa );
break;
- case 3:
+ case 3:
/* Almanac health page */
almh = (ALH_PARMS*)data_packet;
pbuf += sprintf(pbuf, "\n t_oa = %d, wn_oa&0xFF = %d ",
- almh->t_oa, almh->WN_a);
+ almh->t_oa, almh->WN_a);
pbuf += sprintf(pbuf, "\nAlmanac health page:");
for (iprn = 0; iprn < 32; iprn++) {
if (!(iprn%5)) *pbuf++ = '\n';
pbuf += sprintf(pbuf, " SV%02d %2X",
- (iprn+1) , almh->SV_health[iprn]);
+ (iprn+1) , almh->SV_health[iprn]);
}
curr_t_oa = data_packet[34];
curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]);
pbuf += sprintf(pbuf, "\n current t_oa = %d, wn_oa = %d ",
- curr_t_oa, curr_wn_oa);
+ curr_t_oa, curr_wn_oa);
break;
- case 4:
+ case 4:
/* Ionosphere */
ionosphere = (ION_INFO*)data_packet;
pbuf += sprintf(pbuf, "\n alpha_0 = % -12g alpha_1 = % -12g ",
- ionosphere->alpha_0, ionosphere->alpha_1);
+ ionosphere->alpha_0, ionosphere->alpha_1);
pbuf += sprintf(pbuf, "\n alpha_2 = % -12g alpha_3 = % -12g ",
- ionosphere->alpha_2, ionosphere->alpha_3);
+ ionosphere->alpha_2, ionosphere->alpha_3);
pbuf += sprintf(pbuf, "\n beta_0 = % -12g beta_1 = % -12g ",
- ionosphere->beta_0, ionosphere->beta_1);
+ ionosphere->beta_0, ionosphere->beta_1);
pbuf += sprintf(pbuf, "\n beta_2 = % -12g beta_3 = % -12g ",
- ionosphere->beta_2, ionosphere->beta_3);
+ ionosphere->beta_2, ionosphere->beta_3);
break;
- case 5:
+ case 5:
/* UTC */
utc = (UTC_INFO*)data_packet;
pbuf += sprintf(pbuf, "\n A_0 = %g ", utc->A_0);
@@ -3728,7 +4042,7 @@ static void rpt_GPS_system_data (TSIPPKT *rpt)
pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", utc->delta_t_LSF );
break;
- case 6: /* Ephemeris */
+ case 6: /* Ephemeris */
if (sv_prn == 0 || sv_prn > 32) {
pbuf += sprintf(pbuf, " Binary PRN invalid");
return;
@@ -3736,45 +4050,45 @@ static void rpt_GPS_system_data (TSIPPKT *rpt)
nav_data = (NAV_INFO*)data_packet;
pbuf += sprintf(pbuf, "\n SV_PRN = % -12d . t_ephem = % -12g . ",
- nav_data->sv_number , nav_data->t_ephem );
+ nav_data->sv_number , nav_data->t_ephem );
cdata = &(nav_data->ephclk);
pbuf += sprintf(pbuf,
- "\n weeknum = % -12d . codeL2 = % -12d . L2Pdata = % -12d",
- cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
+ "\n weeknum = % -12d . codeL2 = % -12d . L2Pdata = % -12d",
+ cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
pbuf += sprintf(pbuf,
- "\n SVacc_raw = % -12d .SV_health = % -12d . IODC = % -12d",
- cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
+ "\n SVacc_raw = % -12d .SV_health = % -12d . IODC = % -12d",
+ cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
pbuf += sprintf(pbuf,
- "\n T_GD = % -12g . t_oc = % -12g . a_f2 = % -12g",
- cdata->T_GD, cdata->t_oc, cdata->a_f2 );
+ "\n T_GD = % -12g . t_oc = % -12g . a_f2 = % -12g",
+ cdata->T_GD, cdata->t_oc, cdata->a_f2 );
pbuf += sprintf(pbuf,
- "\n a_f1 = % -12g . a_f0 = % -12g . SVacc = % -12g",
- cdata->a_f1, cdata->a_f0, cdata->SVacc );
+ "\n a_f1 = % -12g . a_f0 = % -12g . SVacc = % -12g",
+ cdata->a_f1, cdata->a_f0, cdata->SVacc );
edata = &(nav_data->ephorb);
pbuf += sprintf(pbuf,
- "\n IODE = % -12d .fit_intvl = % -12d . C_rs = % -12g",
- edata->IODE, edata->fit_interval, edata->C_rs );
+ "\n IODE = % -12d .fit_intvl = % -12d . C_rs = % -12g",
+ edata->IODE, edata->fit_interval, edata->C_rs );
pbuf += sprintf(pbuf,
- "\n delta_n = % -12g . M_0 = % -12g . C_uc = % -12g",
- edata->delta_n, edata->M_0, edata->C_uc );
+ "\n delta_n = % -12g . M_0 = % -12g . C_uc = % -12g",
+ edata->delta_n, edata->M_0, edata->C_uc );
pbuf += sprintf(pbuf,
- "\n ecc = % -12g . C_us = % -12g . sqrt_A = % -12g",
- edata->e, edata->C_us, edata->sqrt_A );
+ "\n ecc = % -12g . C_us = % -12g . sqrt_A = % -12g",
+ edata->e, edata->C_us, edata->sqrt_A );
pbuf += sprintf(pbuf,
- "\n t_oe = % -12g . C_ic = % -12g . OMEGA_0 = % -12g",
- edata->t_oe, edata->C_ic, edata->OMEGA_0 );
+ "\n t_oe = % -12g . C_ic = % -12g . OMEGA_0 = % -12g",
+ edata->t_oe, edata->C_ic, edata->OMEGA_0 );
pbuf += sprintf(pbuf,
- "\n C_is = % -12g . i_0 = % -12g . C_rc = % -12g",
- edata->C_is, edata->i_0, edata->C_rc );
+ "\n C_is = % -12g . i_0 = % -12g . C_rc = % -12g",
+ edata->C_is, edata->i_0, edata->C_rc );
pbuf += sprintf(pbuf,
- "\n omega = % -12g . OMEGADOT = % -12g . IDOT = % -12g",
- edata->omega, edata->OMEGADOT, edata->IDOT );
+ "\n omega = % -12g . OMEGADOT = % -12g . IDOT = % -12g",
+ edata->omega, edata->OMEGADOT, edata->IDOT );
pbuf += sprintf(pbuf,
- "\n Axis = % -12g . n = % -12g . r1me2 = % -12g",
- edata->Axis, edata->n, edata->r1me2 );
+ "\n Axis = % -12g . n = % -12g . r1me2 = % -12g",
+ edata->Axis, edata->n, edata->r1me2 );
pbuf += sprintf(pbuf,
- "\n OMEGA_n = % -12g . ODOT_n = % -12g",
- edata->OMEGA_n, edata->ODOT_n );
+ "\n OMEGA_n = % -12g . ODOT_n = % -12g",
+ edata->OMEGA_n, edata->ODOT_n );
break;
}
}
@@ -3782,173 +4096,191 @@ static void rpt_GPS_system_data (TSIPPKT *rpt)
/* 0x59: */
-static void rpt_SVs_enabled (TSIPPKT *rpt)
+static void
+rpt_SVs_enabled(
+ TSIPPKT *rpt
+ )
{
unsigned char
- numsvs,
- code_type,
- status_code[32];
+ numsvs,
+ code_type,
+ status_code[32];
short
- iprn;
+ iprn;
/* unload rptbuf */
if (rpt_0x59 (rpt, &code_type, status_code))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
- switch (code_type)
- {
- case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
- case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
- default: return;
- }
- numsvs = 0;
- for (iprn=0; iprn<32; iprn++)
- {
- if (status_code[iprn])
- {
- pbuf += sprintf(pbuf, " %02d", iprn+1);
- numsvs++;
- }
- }
- if (numsvs == 0) pbuf += sprintf(pbuf, "None");
+ switch (code_type)
+ {
+ case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
+ case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
+ default: return;
+ }
+ numsvs = 0;
+ for (iprn = 0; iprn < 32; iprn++)
+ {
+ if (status_code[iprn])
+ {
+ pbuf += sprintf(pbuf, " %02d", iprn+1);
+ numsvs++;
+ }
+ }
+ if (numsvs == 0) pbuf += sprintf(pbuf, "None");
}
/* 0x5A */
-static void rpt_raw_msmt (TSIPPKT *rpt)
+static void
+rpt_raw_msmt(
+ TSIPPKT *rpt
+ )
{
unsigned char
- sv_prn;
+ sv_prn;
float
- sample_length, signal_level, code_phase, Doppler;
+ sample_length, signal_level, code_phase, Doppler;
double
- time_of_fix;
+ time_of_fix;
/* unload rptbuf */
if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level,
- &code_phase, &Doppler, &time_of_fix))
- {
+ &code_phase, &Doppler, &time_of_fix))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\n %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s",
- sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
- show_time ((float)time_of_fix));
+ sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
+ show_time ((float)time_of_fix));
}
/* 0x5B */
-static void rpt_SV_ephemeris_status (TSIPPKT *rpt)
+static void
+rpt_SV_ephemeris_status(
+ TSIPPKT *rpt
+ )
{
unsigned char
- sv_prn, sv_health, sv_iode, fit_interval_flag;
+ sv_prn, sv_health, sv_iode, fit_interval_flag;
float
- time_of_collection, time_of_eph, sv_accy;
+ time_of_collection, time_of_eph, sv_accy;
/* unload rptbuf */
if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag,
- &time_of_collection, &time_of_eph, &sv_accy))
- {
+ &time_of_collection, &time_of_eph, &sv_accy))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\n SV%02d %s %2Xh %2Xh ",
- sv_prn, show_time (time_of_collection), sv_health, sv_iode);
+ sv_prn, show_time (time_of_collection), sv_health, sv_iode);
/* note: cannot use show_time twice in same call */
pbuf += sprintf(pbuf, "%s %1d %4.1f",
- show_time (time_of_eph), fit_interval_flag, sv_accy);
+ show_time (time_of_eph), fit_interval_flag, sv_accy);
}
/* 0x5C */
-static void rpt_SV_tracking_status (TSIPPKT *rpt)
+static void
+rpt_SV_tracking_status(
+ TSIPPKT *rpt
+ )
{
unsigned char
- sv_prn, chan, slot, acq_flag, eph_flag,
- old_msmt_flag, integer_msec_flag, bad_data_flag,
- data_collect_flag;
+ sv_prn, chan, slot, acq_flag, eph_flag,
+ old_msmt_flag, integer_msec_flag, bad_data_flag,
+ data_collect_flag;
float
- signal_level, time_of_last_msmt,
- elev, azim;
+ signal_level, time_of_last_msmt,
+ elev, azim;
/* unload rptbuf */
if (rpt_0x5C (rpt,
- &sv_prn, &slot, &chan, &acq_flag, &eph_flag,
- &signal_level, &time_of_last_msmt, &elev, &azim,
- &old_msmt_flag, &integer_msec_flag, &bad_data_flag,
- &data_collect_flag))
- {
+ &sv_prn, &slot, &chan, &acq_flag, &eph_flag,
+ &signal_level, &time_of_last_msmt, &elev, &azim,
+ &old_msmt_flag, &integer_msec_flag, &bad_data_flag,
+ &data_collect_flag))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf,
-"\n SV%2d %1d %1d %1d %4.1f %s %5.1f %5.1f",
- sv_prn, chan,
- acq_flag, eph_flag, signal_level,
- show_time(time_of_last_msmt),
- elev*R2D, azim*R2D);
+ "\n SV%2d %1d %1d %1d %4.1f %s %5.1f %5.1f",
+ sv_prn, chan,
+ acq_flag, eph_flag, signal_level,
+ show_time(time_of_last_msmt),
+ elev*R2D, azim*R2D);
}
/**/
/* 0x6D */
-static void rpt_allSV_selection (TSIPPKT *rpt)
+static void
+rpt_allSV_selection(
+ TSIPPKT *rpt
+ )
{
unsigned char
- manual_mode, nsvs, sv_prn[8], ndim;
+ manual_mode, nsvs, sv_prn[8], ndim;
short
- islot;
+ islot;
float
- pdop, hdop, vdop, tdop;
+ pdop, hdop, vdop, tdop;
/* unload rptbuf */
if (rpt_0x6D (rpt,
- &manual_mode, &nsvs, &ndim, sv_prn,
- &pdop, &hdop, &vdop, &tdop))
- {
+ &manual_mode, &nsvs, &ndim, sv_prn,
+ &pdop, &hdop, &vdop, &tdop))
+ {
parsed = BADLEN_PARSE;
return;
}
switch (ndim)
- {
- case 0:
+ {
+ case 0:
pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs);
- break;
- case 1:
+ break;
+ case 1:
pbuf += sprintf(pbuf, "\nMode: One-SV Timing:");
- break;
- case 3: case 4:
+ break;
+ case 3: case 4:
pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:",
- manual_mode ? 'M' : 'A', ndim - 1, nsvs);
- break;
- case 5:
+ manual_mode ? 'M' : 'A', ndim - 1, nsvs);
+ break;
+ case 5:
pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs);
- break;
- default:
+ break;
+ default:
pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim);
- break;
- }
+ break;
+ }
for (islot = 0; islot < nsvs; islot++)
- {
+ {
if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]);
}
- if (ndim == 3 || ndim == 4)
- {
+ if (ndim == 3 || ndim == 4)
+ {
pbuf += sprintf(pbuf, "; DOPs: P %.1f H %.1f V %.1f T %.1f",
- pdop, hdop, vdop, tdop);
- }
+ pdop, hdop, vdop, tdop);
+ }
}
/**/
/* 0x82 */
-static void rpt_DGPS_position_mode (TSIPPKT *rpt)
+static void
+rpt_DGPS_position_mode(
+ TSIPPKT *rpt
+ )
{
unsigned char
- diff_mode;
+ diff_mode;
/* unload rptbuf */
if (rpt_0x82 (rpt, &diff_mode)) {
@@ -3957,49 +4289,54 @@ static void rpt_DGPS_position_mode (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode) (%d)",
- (diff_mode&1) ? "" : " not",
- (diff_mode&2) ? "auto" : "manual",
- diff_mode);
+ (diff_mode&1) ? "" : " not",
+ (diff_mode&2) ? "auto" : "manual",
+ diff_mode);
}
/* 0x83 */
-static void rpt_double_ECEF_position (TSIPPKT *rpt)
+static void
+rpt_double_ECEF_position(
+ TSIPPKT *rpt
+ )
{
-
double
- ECEF_pos[3], clock_bias;
+ ECEF_pos[3], clock_bias;
float
- time_of_fix;
+ time_of_fix;
/* unload rptbuf */
if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nDXYZ:%12.2f %13.2f %13.2f %12.2f%s",
- ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
- show_time(time_of_fix));
+ ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
+ show_time(time_of_fix));
}
/* 0x84 */
-static void rpt_double_lla_position (TSIPPKT *rpt)
+static void
+rpt_double_lla_position(
+ TSIPPKT *rpt
+ )
{
short
- lat_deg, lon_deg;
+ lat_deg, lon_deg;
double
- lat, lon, lat_min, lon_min,
- alt, clock_bias;
+ lat, lon, lat_min, lon_min,
+ alt, clock_bias;
float
- time_of_fix;
+ time_of_fix;
unsigned char
- north_south, east_west;
+ north_south, east_west;
/* unload rptbuf */
if (rpt_0x84 (rpt,
- &lat, &lon, &alt, &clock_bias, &time_of_fix))
- {
+ &lat, &lon, &alt, &clock_bias, &time_of_fix))
+ {
parsed = BADLEN_PARSE;
return;
}
@@ -4024,14 +4361,17 @@ static void rpt_double_lla_position (TSIPPKT *rpt)
lon_deg = (short)lon;
lon_min = (lon - lon_deg) * 60.0;
pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s",
- lat_deg, lat_min, north_south,
- lon_deg, lon_min, east_west,
- alt, clock_bias,
- show_time(time_of_fix));
+ lat_deg, lat_min, north_south,
+ lon_deg, lon_min, east_west,
+ alt, clock_bias,
+ show_time(time_of_fix));
}
/* 0xBB */
-static void rpt_complete_rcvr_config (TSIPPKT *rpt)
+static void
+rpt_complete_rcvr_config(
+ TSIPPKT *rpt
+ )
{
TSIP_RCVR_CFG TsipxBB ;
/* unload rptbuf */
@@ -4042,49 +4382,52 @@ static void rpt_complete_rcvr_config (TSIPPKT *rpt)
}
pbuf += sprintf(pbuf, "\n operating mode: %s",
- NavModeText0xBB[TsipxBB.operating_mode]);
+ NavModeText0xBB[TsipxBB.operating_mode]);
pbuf += sprintf(pbuf, "\n dynamics: %s",
- dyn_text[TsipxBB.dyn_code]);
+ dyn_text[TsipxBB.dyn_code]);
pbuf += sprintf(pbuf, "\n elev angle mask: %g deg",
- TsipxBB.elev_mask * R2D);
+ TsipxBB.elev_mask * R2D);
pbuf += sprintf(pbuf, "\n SNR mask: %g AMU",
- TsipxBB.cno_mask);
+ TsipxBB.cno_mask);
pbuf += sprintf(pbuf, "\n DOP mask: %g",
- TsipxBB.dop_mask);
+ TsipxBB.dop_mask);
pbuf += sprintf(pbuf, "\n DOP switch: %g",
- TsipxBB.dop_switch);
+ TsipxBB.dop_switch);
return ;
}
/* 0xBC */
-static void rpt_rcvr_serial_port_config (TSIPPKT *rpt)
+static void
+rpt_rcvr_serial_port_config(
+ TSIPPKT *rpt
+ )
{
unsigned char
- port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
- protocols_in, protocols_out, reserved;
+ port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
+ protocols_in, protocols_out, reserved;
unsigned char known;
/* unload rptbuf */
if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity,
- &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
+ &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
parsed = BADLEN_PARSE;
return;
}
/* rptbuf unloaded */
pbuf += sprintf(pbuf, "\n RECEIVER serial port %s config:",
- rcvr_port_text[port_num]);
+ rcvr_port_text[port_num]);
pbuf += sprintf(pbuf, "\n I/O Baud %s/%s, %d - %s - %d",
- st_baud_text_app[in_baud],
- st_baud_text_app[out_baud],
- data_bits+5,
- parity_text[parity],
- stop_bits=1);
+ st_baud_text_app[in_baud],
+ st_baud_text_app[out_baud],
+ data_bits+5,
+ parity_text[parity],
+ stop_bits=1);
pbuf += sprintf(pbuf, "\n Input protocols: ");
known = FALSE;
if (protocols_in&B_TSIP)
- {
+ {
pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]);
known = TRUE;
}
@@ -4093,98 +4436,101 @@ static void rpt_rcvr_serial_port_config (TSIPPKT *rpt)
pbuf += sprintf(pbuf, "\n Output protocols: ");
known = FALSE;
if (protocols_out&B_TSIP)
- {
+ {
pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]);
known = TRUE;
}
if (protocols_out&B_NMEA)
- {
+ {
pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]);
known = TRUE;
}
if (known == FALSE) pbuf += sprintf(pbuf, "No known");
reserved = reserved;
- }
+}
/* 0x8F */
/* 8F0B */
-static void rpt_8F0B(TSIPPKT *rpt)
+static void
+rpt_8F0B(
+ TSIPPKT *rpt
+ )
{
const char
- *oprtng_dim[7] = {
- "horizontal (2-D)",
- "full position (3-D)",
- "single satellite (0-D)",
- "automatic",
- "N/A",
- "N/A",
- "overdetermined clock"};
- char
- sv_id[8];
- unsigned char
- month,
- date,
- dim_mode,
- north_south,
- east_west;
- unsigned short
- event;
- short
- utc_offset,
- year,
- local_index;
+ *oprtng_dim[7] = {
+ "horizontal (2-D)",
+ "full position (3-D)",
+ "single satellite (0-D)",
+ "automatic",
+ "N/A",
+ "N/A",
+ "overdetermined clock"};
+ char
+ sv_id[8];
+ unsigned char
+ month,
+ date,
+ dim_mode,
+ north_south,
+ east_west;
+ unsigned short
+ event;
+ short
+ utc_offset,
+ year,
+ local_index;
short
- lat_deg,
- lon_deg;
- float
- bias_unc,
- dr_unc;
- double
- tow,
- bias,
- drift,
- lat,
- lon,
- alt,
- lat_min,
- lon_min;
- int
- numfix,
- numnotfix;
+ lat_deg,
+ lon_deg;
+ float
+ bias_unc,
+ dr_unc;
+ double
+ tow,
+ bias,
+ drift,
+ lat,
+ lon,
+ alt,
+ lat_min,
+ lon_min;
+ int
+ numfix,
+ numnotfix;
if (rpt_0x8F0B(rpt,
- &event,
- &tow,
- &date,
- &month,
- &year,
- &dim_mode,
- &utc_offset,
- &bias,
- &drift,
- &bias_unc,
- &dr_unc,
- &lat,
- &lon,
- &alt,
- sv_id))
- {
+ &event,
+ &tow,
+ &date,
+ &month,
+ &year,
+ &dim_mode,
+ &utc_offset,
+ &bias,
+ &drift,
+ &bias_unc,
+ &dr_unc,
+ &lat,
+ &lon,
+ &alt,
+ sv_id))
+ {
parsed = BADLEN_PARSE;
return;
}
if (event == 0)
- {
- pbuf += sprintf(pbuf, "\nNew partial+full meas");
+ {
+ pbuf += sprintf(pbuf, "\nNew partial+full meas");
}
- else
- {
+ else
+ {
pbuf += sprintf(pbuf, "\nEvent count: %5d", event);
- }
+ }
pbuf += sprintf(pbuf, "\nGPS time : %s %2d/%2d/%2d (DMY)",
- show_time(tow), date, month, year);
+ show_time(tow), date, month, year);
pbuf += sprintf(pbuf, "\nMode : %s", oprtng_dim[dim_mode]);
pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset);
pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias);
@@ -4195,24 +4541,24 @@ static void rpt_8F0B(TSIPPKT *rpt)
lat *= R2D; /* convert from radians to degrees */
lon *= R2D;
if (lat < 0.0)
- {
+ {
north_south = 'S';
lat = -lat;
}
- else
- {
+ else
+ {
north_south = 'N';
}
lat_deg = (short)lat;
lat_min = (lat - lat_deg) * 60.0;
if (lon < 0.0)
- {
+ {
east_west = 'W';
lon = -lon;
}
- else
- {
+ else
+ {
east_west = 'E';
}
@@ -4223,79 +4569,85 @@ static void rpt_8F0B(TSIPPKT *rpt)
pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west);
pbuf += sprintf(pbuf, " %10.2f", alt);
- numfix = numnotfix = 0;
+ numfix = numnotfix = 0;
for (local_index=0; local_index<8; local_index++)
- {
+ {
if (sv_id[local_index] < 0) numnotfix++;
if (sv_id[local_index] > 0) numfix++;
- }
- if (numfix > 0)
- {
+ }
+ if (numfix > 0)
+ {
pbuf += sprintf(pbuf, "\nSVs used in fix : ");
for (local_index=0; local_index<8; local_index++)
- {
+ {
if (sv_id[local_index] > 0)
- {
- pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
- }
- }
- }
- if (numnotfix > 0)
- {
+ {
+ pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
+ }
+ }
+ }
+ if (numnotfix > 0)
+ {
pbuf += sprintf(pbuf, "\nOther SVs tracked: ");
for (local_index=0; local_index<8; local_index++)
- {
+ {
if (sv_id[local_index] < 0)
- {
- pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
- }
- }
- }
+ {
+ pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
+ }
+ }
+ }
}
/* 0x8F14 */
-static void rpt_8F14 (TSIPPKT *rpt)
/* Datum parameters */
+static void
+rpt_8F14(
+ TSIPPKT *rpt
+ )
{
double
- datum_coeffs[5];
+ datum_coeffs[5];
short
- datum_idx;
+ datum_idx;
/* unload rptbuf */
if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs))
- {
+ {
parsed = BADLEN_PARSE;
return;
}
if (datum_idx == -1)
- {
- pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
+ {
+ pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
- }
- else if (datum_idx == 0)
- {
- pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
- }
- else
- {
- pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
- }
+ }
+ else if (datum_idx == 0)
+ {
+ pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
+ }
+ else
+ {
+ pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
+ }
}
/* 0x8F15 */
-static void rpt_8F15 (TSIPPKT *rpt)
/* Datum parameters */
+static void
+rpt_8F15(
+ TSIPPKT *rpt
+ )
{
double
- datum_coeffs[5];
+ datum_coeffs[5];
short
- datum_idx;
+ datum_idx;
/* unload rptbuf */
if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) {
@@ -4304,22 +4656,22 @@ static void rpt_8F15 (TSIPPKT *rpt)
}
if (datum_idx == -1)
- {
- pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
+ {
+ pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
- }
- else if (datum_idx == 0)
- {
- pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
- }
- else
- {
- pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
- }
+ }
+ else if (datum_idx == 0)
+ {
+ pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
+ }
+ else
+ {
+ pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
+ }
}
/* 0x8F20 */
@@ -4327,72 +4679,75 @@ static void rpt_8F15 (TSIPPKT *rpt)
#define INFO_2D 0x04
#define INFO_ALTSET 0x08
#define INFO_FILTERED 0x10
-static void rpt_8F20 (TSIPPKT *rpt)
+static void
+rpt_8F20(
+ TSIPPKT *rpt
+ )
{
unsigned char
- info, nsvs, sv_prn[32];
+ info, nsvs, sv_prn[32];
short
- week_num, datum_index, sv_IODC[32];
+ week_num, datum_index, sv_IODC[32];
double
- lat, lon, alt, time_of_fix;
+ lat, lon, alt, time_of_fix;
double
- londeg, latdeg, vel[3];
+ londeg, latdeg, vel[3];
short
- isv;
- char
- datum_string[20];
+ isv;
+ char
+ datum_string[20];
/* unload rptbuf */
if (rpt_0x8F20 (rpt,
- &info, &lat, &lon, &alt, vel,
- &time_of_fix,
- &week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
+ &info, &lat, &lon, &alt, vel,
+ &time_of_fix,
+ &week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
{
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf,
- "\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds) FixType: %s%s%s",
- week_num,
- dayname[(short)(time_of_fix/86400.0)],
- (short)fmod(time_of_fix/3600., 24.),
- (short)fmod(time_of_fix/60., 60.),
- fmod(time_of_fix, 60.),
- (char)rpt->buf[29], /* UTC offset */
- (info & INFO_DGPS)?"Diff":"",
- (info & INFO_2D)?"2D":"3D",
- (info & INFO_FILTERED)?"-Filtrd":"");
-
- if (datum_index > 0)
- {
+ "\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds) FixType: %s%s%s",
+ week_num,
+ dayname[(short)(time_of_fix/86400.0)],
+ (short)fmod(time_of_fix/3600., 24.),
+ (short)fmod(time_of_fix/60., 60.),
+ fmod(time_of_fix, 60.),
+ (char)rpt->buf[29], /* UTC offset */
+ (info & INFO_DGPS)?"Diff":"",
+ (info & INFO_2D)?"2D":"3D",
+ (info & INFO_FILTERED)?"-Filtrd":"");
+
+ if (datum_index > 0)
+ {
sprintf(datum_string, "Datum%3d", datum_index);
- }
- else if (datum_index)
- {
+ }
+ else if (datum_index)
+ {
sprintf(datum_string, "Unknown ");
- }
- else
- {
+ }
+ else
+ {
sprintf(datum_string, "WGS-84");
- }
+ }
/* convert from radians to degrees */
latdeg = R2D * fabs(lat);
londeg = R2D * fabs(lon);
pbuf += sprintf(pbuf,
- "\n Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
- (short)latdeg, fmod (latdeg, 1.)*60.0,
- (lat<0.0)?'S':'N',
- (short)londeg, fmod (londeg, 1.)*60.0,
- (lon<0.0)?'W':'E',
- alt,
- datum_string);
+ "\n Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
+ (short)latdeg, fmod (latdeg, 1.)*60.0,
+ (lat<0.0)?'S':'N',
+ (short)londeg, fmod (londeg, 1.)*60.0,
+ (lon<0.0)?'W':'E',
+ alt,
+ datum_string);
pbuf += sprintf(pbuf,
- "\n Vel: %9.3f E %9.3f N %9.3f U (m/sec)",
- vel[0], vel[1], vel[2]);
+ "\n Vel: %9.3f E %9.3f N %9.3f U (m/sec)",
+ vel[0], vel[1], vel[2]);
pbuf += sprintf(pbuf,
- "\n SVs: ");
+ "\n SVs: ");
for (isv = 0; isv < nsvs; isv++) {
pbuf += sprintf(pbuf, " %02d", sv_prn[isv]);
}
@@ -4404,361 +4759,394 @@ static void rpt_8F20 (TSIPPKT *rpt)
}
/* 0x8F41 */
-static void rpt_8F41(TSIPPKT *rpt)
+static void
+rpt_8F41(
+ TSIPPKT *rpt
+ )
{
unsigned char
- bSearchRange,
- bBoardOptions,
- bBuildYear,
- bBuildMonth,
- bBuildDay,
- bBuildHour;
+ bSearchRange,
+ bBoardOptions,
+ bBuildYear,
+ bBuildMonth,
+ bBuildDay,
+ bBuildHour;
float
- fOscOffset;
+ fOscOffset;
unsigned short
- iTestCodeId;
+ iTestCodeId;
unsigned long
- iiSerialNumber;
-
- if (!rpt_0x8F41(rpt,
- &bSearchRange,
- &bBoardOptions,
- &iiSerialNumber,
- &bBuildYear,
- &bBuildMonth,
- &bBuildDay,
- &bBuildHour,
- &fOscOffset,
- &iTestCodeId))
- {
+ iiSerialNumber;
+
+ if (!rpt_0x8F41(rpt,
+ &bSearchRange,
+ &bBoardOptions,
+ &iiSerialNumber,
+ &bBuildYear,
+ &bBuildMonth,
+ &bBuildDay,
+ &bBuildHour,
+ &fOscOffset,
+ &iTestCodeId))
+ {
parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n search range: %d",
- bSearchRange);
- pbuf += sprintf(pbuf, "\n board options: %d",
- bBoardOptions);
- pbuf += sprintf(pbuf, "\n board serial #: %ld",
- iiSerialNumber);
- pbuf += sprintf(pbuf, "\n build date/hour: %02d/%02d/%02d %02d:00",
- bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
- pbuf += sprintf(pbuf, "\n osc offset: %.3f PPM (%.0f Hz)",
- fOscOffset/1575.42, fOscOffset);
- pbuf += sprintf(pbuf, "\n test code: %d",
- iTestCodeId);
+ return;
+ }
+
+ pbuf += sprintf(pbuf, "\n search range: %d",
+ bSearchRange);
+ pbuf += sprintf(pbuf, "\n board options: %d",
+ bBoardOptions);
+ pbuf += sprintf(pbuf, "\n board serial #: %ld",
+ iiSerialNumber);
+ pbuf += sprintf(pbuf, "\n build date/hour: %02d/%02d/%02d %02d:00",
+ bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
+ pbuf += sprintf(pbuf, "\n osc offset: %.3f PPM (%.0f Hz)",
+ fOscOffset/1575.42, fOscOffset);
+ pbuf += sprintf(pbuf, "\n test code: %d",
+ iTestCodeId);
}
/* 0x8F42 */
-static void rpt_8F42(TSIPPKT *rpt)
+static void
+rpt_8F42(
+ TSIPPKT *rpt
+ )
{
unsigned char
- bProdOptionsPre,
- bProdNumberExt;
+ bProdOptionsPre,
+ bProdNumberExt;
unsigned short
- iCaseSerialNumberPre,
- iPremiumOptions,
- iMachineID,
- iKey;
+ iCaseSerialNumberPre,
+ iPremiumOptions,
+ iMachineID,
+ iKey;
unsigned long
- iiCaseSerialNumber,
- iiProdNumber;
-
- if (!rpt_0x8F42(rpt,
- &bProdOptionsPre,
- &bProdNumberExt,
- &iCaseSerialNumberPre,
- &iiCaseSerialNumber,
- &iiProdNumber,
- &iPremiumOptions,
- &iMachineID,
- &iKey))
- {
+ iiCaseSerialNumber,
+ iiProdNumber;
+
+ if (!rpt_0x8F42(rpt,
+ &bProdOptionsPre,
+ &bProdNumberExt,
+ &iCaseSerialNumberPre,
+ &iiCaseSerialNumber,
+ &iiProdNumber,
+ &iPremiumOptions,
+ &iMachineID,
+ &iKey))
+ {
parsed = BADLEN_PARSE;
- return;
- }
+ return;
+ }
pbuf += sprintf(pbuf, "\nProduct ID 8F42");
- pbuf += sprintf(pbuf, "\n extension: %d", bProdNumberExt);
- pbuf += sprintf(pbuf, "\n case serial # prefix: %d", iCaseSerialNumberPre);
- pbuf += sprintf(pbuf, "\n case serial #: %ld", iiCaseSerialNumber);
- pbuf += sprintf(pbuf, "\n prod. #: %ld", iiProdNumber);
+ pbuf += sprintf(pbuf, "\n extension: %d", bProdNumberExt);
+ pbuf += sprintf(pbuf, "\n case serial # prefix: %d", iCaseSerialNumberPre);
+ pbuf += sprintf(pbuf, "\n case serial #: %ld", iiCaseSerialNumber);
+ pbuf += sprintf(pbuf, "\n prod. #: %ld", iiProdNumber);
pbuf += sprintf(pbuf, "\n premium options: %Xh", iPremiumOptions);
- pbuf += sprintf(pbuf, "\n machine ID: %d", iMachineID);
- pbuf += sprintf(pbuf, "\n key: %Xh", iKey);
+ pbuf += sprintf(pbuf, "\n machine ID: %d", iMachineID);
+ pbuf += sprintf(pbuf, "\n key: %Xh", iKey);
}
/* 0x8F45 */
-static void rpt_8F45(TSIPPKT *rpt)
+static void
+rpt_8F45(
+ TSIPPKT *rpt
+ )
{
- unsigned char bSegMask;
+ unsigned char bSegMask;
- if (!rpt_0x8F45(rpt,
- &bSegMask))
- {
+ if (!rpt_0x8F45(rpt,
+ &bSegMask))
+ {
parsed = BADLEN_PARSE;
return;
}
pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask);
}
-static void rpt_8F4A(TSIPPKT *rpt)
/* Stinger PPS def */
+static void
+rpt_8F4A(
+ TSIPPKT *rpt
+ )
{
unsigned char
- pps_enabled,
- pps_timebase,
- pps_polarity;
- float
- bias_unc_threshold;
- double
- pps_offset;
+ pps_enabled,
+ pps_timebase,
+ pps_polarity;
+ float
+ bias_unc_threshold;
+ double
+ pps_offset;
if (rpt_0x8F4A_16 (rpt,
- &pps_enabled,
- &pps_timebase,
- &pps_polarity,
- &pps_offset,
- &bias_unc_threshold))
- {
- parsed = BADLEN_PARSE;
- return;
- }
+ &pps_enabled,
+ &pps_timebase,
+ &pps_polarity,
+ &pps_offset,
+ &bias_unc_threshold))
+ {
+ parsed = BADLEN_PARSE;
+ return;
+ }
pbuf += sprintf(pbuf, "\nPPS is %s", pps_enabled?"enabled":"disabled");
- pbuf += sprintf(pbuf, "\n timebase: %s", PPSTimeBaseText[pps_timebase]);
- pbuf += sprintf(pbuf, "\n polarity: %s", PPSPolarityText[pps_polarity]);
- pbuf += sprintf(pbuf, "\n offset: %.1f ns, ", pps_offset*1.e9);
- pbuf += sprintf(pbuf, "\n biasunc: %.1f ns", bias_unc_threshold/GPS_C*1.e9);
+ pbuf += sprintf(pbuf, "\n timebase: %s", PPSTimeBaseText[pps_timebase]);
+ pbuf += sprintf(pbuf, "\n polarity: %s", PPSPolarityText[pps_polarity]);
+ pbuf += sprintf(pbuf, "\n offset: %.1f ns, ", pps_offset*1.e9);
+ pbuf += sprintf(pbuf, "\n biasunc: %.1f ns", bias_unc_threshold/GPS_C*1.e9);
}
-static void rpt_8F4B(TSIPPKT *rpt)
/* fast-SA decorrolation time for self-survey */
+static void
+rpt_8F4B(
+ TSIPPKT *rpt
+ )
{
unsigned long
- decorr_max;
+ decorr_max;
- if (rpt_0x8F4B(rpt, &decorr_max))
- {
+ if (rpt_0x8F4B(rpt, &decorr_max))
+ {
parsed = BADLEN_PARSE;
- return;
- }
+ return;
+ }
- pbuf += sprintf(pbuf,
- "\nMax # of position fixes for self-survey : %ld",
- decorr_max);
+ pbuf += sprintf(pbuf,
+ "\nMax # of position fixes for self-survey : %ld",
+ decorr_max);
}
-static void rpt_8F4D(TSIPPKT *rpt)
+static void
+rpt_8F4D(
+ TSIPPKT *rpt
+ )
{
static char
- *linestart;
+ *linestart;
unsigned long
- OutputMask;
- static unsigned long
- MaskBit[] = {
- 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
- 0x00000100L, 0x00000800L, 0x00001000L,
- 0x40000000L, 0x80000000L};
- int
- ichoice,
- numchoices;
-
- if (rpt_0x8F4D(rpt, &OutputMask))
- {
+ OutputMask;
+ static unsigned long
+ MaskBit[] = {
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
+ 0x00000020,
+ 0x00000100L, 0x00000800L, 0x00001000L,
+ 0x40000000L, 0x80000000L};
+ int
+ ichoice,
+ numchoices;
+
+ if (rpt_0x8F4D(rpt, &OutputMask))
+ {
parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
- (unsigned char)(OutputMask>>24),
- (unsigned char)(OutputMask>>16),
- (unsigned char)(OutputMask>>8),
- (unsigned char)OutputMask);
-
- numchoices = sizeof(MaskText)/sizeof(char*);
- pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
- linestart = pbuf;
- for (ichoice=0; ichoice<numchoices; ichoice++)
- {
- if (OutputMask&MaskBit[ichoice])
- {
- pbuf += sprintf(pbuf, "%s %s",
- (pbuf==linestart)?"\n ":",",
- MaskText[ichoice]);
+ return;
+ }
+
+ pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
+ (unsigned char)(OutputMask>>24),
+ (unsigned char)(OutputMask>>16),
+ (unsigned char)(OutputMask>>8),
+ (unsigned char)OutputMask);
+
+ numchoices = sizeof(MaskText)/sizeof(char*);
+ pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
+ linestart = pbuf;
+ for (ichoice = 0; ichoice < numchoices; ichoice++)
+ {
+ if (OutputMask&MaskBit[ichoice])
+ {
+ pbuf += sprintf(pbuf, "%s %s",
+ (pbuf==linestart)?"\n ":",",
+ MaskText[ichoice]);
if (pbuf-linestart > 60) linestart = pbuf;
- }
- }
-
- pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
- linestart = pbuf;
- for (ichoice=0; ichoice<numchoices; ichoice++)
- {
- if (OutputMask&MaskBit[ichoice]) continue;
+ }
+ }
+
+ pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
+ linestart = pbuf;
+ for (ichoice = 0; ichoice < numchoices; ichoice++)
+ {
+ if (OutputMask&MaskBit[ichoice]) continue;
pbuf += sprintf(pbuf, "%s %s",
- (pbuf==linestart)?"\n ":",",
- MaskText[ichoice]);
+ (pbuf==linestart)?"\n ":",",
+ MaskText[ichoice]);
if (pbuf-linestart > 60) linestart = pbuf;
- }
+ }
}
-static void rpt_8FA5(TSIPPKT *rpt)
+static void
+rpt_8FA5(
+ TSIPPKT *rpt
+ )
{
unsigned char
- spktmask[4];
+ spktmask[4];
- if (rpt_0x8FA5(rpt, spktmask))
- {
+ if (rpt_0x8FA5(rpt, spktmask))
+ {
parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
- spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
-
- if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n PPS 8F-0B");
- if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n Event 8F-0B");
- if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n PPS 8F-AD");
- if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n Event 8F-AD");
- if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n ppos Fix 8F-20");
-}
-
-static void rpt_8FAD (TSIPPKT *rpt)
-{
- unsigned short
- Count,
- Year;
- double
- FracSec;
- unsigned char
- Hour,
- Minute,
- Second,
- Day,
- Month,
- Status,
- Flags;
+ return;
+ }
+
+ pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
+ spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
+
+ if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n PPS 8F-0B");
+ if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n Event 8F-0B");
+ if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n PPS 8F-AD");
+ if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n Event 8F-AD");
+ if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n ppos Fix 8F-20");
+}
+
+static void
+rpt_8FAD(
+ TSIPPKT *rpt
+ )
+{
+ unsigned short
+ Count,
+ Year;
+ double
+ FracSec;
+ unsigned char
+ Hour,
+ Minute,
+ Second,
+ Day,
+ Month,
+ Status,
+ Flags;
static char* Status8FADText[] = {
- "CODE_DOING_FIXES",
- "CODE_GOOD_1_SV",
- "CODE_APPX_1SV",
- "CODE_NEED_TIME",
- "CODE_NEED_INITIALIZATION",
- "CODE_PDOP_HIGH",
- "CODE_BAD_1SV",
- "CODE_0SVS",
- "CODE_1SV",
- "CODE_2SVS",
- "CODE_3SVS",
- "CODE_NO_INTEGRITY",
- "CODE_DCORR_GEN",
- "CODE_OVERDET_CLK",
- "Invalid Status"},
- *LeapStatusText[] = {
- " UTC Avail", " ", " ", " ",
- " Scheduled", " Pending", " Warning", " In Progress"};
- int i;
+ "CODE_DOING_FIXES",
+ "CODE_GOOD_1_SV",
+ "CODE_APPX_1SV",
+ "CODE_NEED_TIME",
+ "CODE_NEED_INITIALIZATION",
+ "CODE_PDOP_HIGH",
+ "CODE_BAD_1SV",
+ "CODE_0SVS",
+ "CODE_1SV",
+ "CODE_2SVS",
+ "CODE_3SVS",
+ "CODE_NO_INTEGRITY",
+ "CODE_DCORR_GEN",
+ "CODE_OVERDET_CLK",
+ "Invalid Status"},
+ *LeapStatusText[] = {
+ " UTC Avail", " ", " ", " ",
+ " Scheduled", " Pending", " Warning", " In Progress"};
+ int i;
if (rpt_0x8FAD (rpt,
- &Count,
- &FracSec,
- &Hour,
- &Minute,
- &Second,
- &Day,
- &Month,
- &Year,
- &Status,
- &Flags))
- {
+ &Count,
+ &FracSec,
+ &Hour,
+ &Minute,
+ &Second,
+ &Day,
+ &Month,
+ &Year,
+ &Status,
+ &Flags))
+ {
parsed = BADLEN_PARSE;
return;
- }
+ }
pbuf += sprintf(pbuf, "\n8FAD Count: %d Status: %s",
- Count, Status8FADText[Status]);
-
- pbuf += sprintf(pbuf, "\n Leap Flags:");
- if (Flags)
- {
- for (i=0; i<8; i++)
- {
- if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
- }
- }
- else
- {
- pbuf += sprintf(pbuf, " UTC info not available");
- }
+ Count, Status8FADText[Status]);
+
+ pbuf += sprintf(pbuf, "\n Leap Flags:");
+ if (Flags)
+ {
+ for (i=0; i<8; i++)
+ {
+ if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
+ }
+ }
+ else
+ {
+ pbuf += sprintf(pbuf, " UTC info not available");
+ }
pbuf += sprintf(pbuf, "\n %02d/%02d/%04d (DMY) %02d:%02d:%02d.%09ld UTC",
- Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
+ Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
}
-int print_msg_table_header (int rptcode, char *HdrStr, int force)
+int
+print_msg_table_header(
+ int rptcode,
+ char *HdrStr,
+ int force
+ )
{
/* force header is to help auto-output function */
/* last_rptcode is to determine whether to print a header */
/* for the first occurrence of a series of reports */
static int
- last_rptcode = 0;
- int
- numchars;
+ last_rptcode = 0;
+ int
+ numchars;
- numchars = 0;
+ numchars = 0;
if (force || rptcode!=last_rptcode)
- {
+ {
/* supply a header in console output */
- switch (rptcode)
+ switch (rptcode)
{
- case 0x5A:
+ case 0x5A:
numchars = sprintf(HdrStr, "\nRaw Measurement Data");
numchars += sprintf(HdrStr+numchars,
- "\n SV Sample SNR Code Phase Doppler Seconds Time of Meas");
+ "\n SV Sample SNR Code Phase Doppler Seconds Time of Meas");
break;
- case 0x5B:
+ case 0x5B:
numchars = sprintf(HdrStr, "\nEphemeris Status");
numchars += sprintf(HdrStr+numchars,
- "\n SV Time collected Health IODE t oe Fit URA");
+ "\n SV Time collected Health IODE t oe Fit URA");
break;
- case 0x5C:
+ case 0x5C:
numchars = sprintf(HdrStr, "\nTracking Info");
numchars += sprintf(HdrStr+numchars,
- "\n SV C Acq Eph SNR Time of Meas Elev Azim ");
+ "\n SV C Acq Eph SNR Time of Meas Elev Azim ");
break;
- }
+ }
}
last_rptcode = rptcode;
- return (short)numchars;
+ return (short)numchars;
}
-static void unknown_rpt (TSIPPKT *rpt)
+static void
+unknown_rpt(
+ TSIPPKT *rpt
+ )
{
int i;
/* app-specific rpt packets */
if (parsed == BADLEN_PARSE)
- {
+ {
pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length",
- rpt->code, rpt->len);
- }
+ rpt->code, rpt->len);
+ }
if (parsed == BADID_PARSE)
- {
+ {
pbuf += sprintf(pbuf,
- "\nTSIP report packet ID %2Xh, length %d: translation not supported",
- rpt->code, rpt->len);
- }
+ "\nTSIP report packet ID %2Xh, length %d: translation not supported",
+ rpt->code, rpt->len);
+ }
if (parsed == BADDATA_PARSE)
- {
+ {
pbuf += sprintf(pbuf,
- "\nTSIP report packet ID %2Xh, length %d: data content incorrect",
- rpt->code, rpt->len);
- }
+ "\nTSIP report packet ID %2Xh, length %d: data content incorrect",
+ rpt->code, rpt->len);
+ }
for (i = 0; i < rpt->len; i++) {
if ((i % 20) == 0) *pbuf++ = '\n';
@@ -4766,96 +5154,101 @@ static void unknown_rpt (TSIPPKT *rpt)
}
}
/**/
+
/*
** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit()
*/
-void TranslateTSIPReportToText (TSIPPKT *rpt, char *TextOutputBuffer)
+void
+TranslateTSIPReportToText(
+ TSIPPKT *rpt,
+ char *TextOutputBuffer
+ )
{
/* pbuf is the pointer to the current location of the text output */
pbuf = TextOutputBuffer;
- /* keep track of whether the message has been successfully parsed */
+ /* keep track of whether the message has been successfully parsed */
parsed = GOOD_PARSE;
/* print a header if this is the first of a series of messages */
pbuf += print_msg_table_header (rpt->code, pbuf, FALSE);
- /* process incoming TSIP report according to code */
+ /* process incoming TSIP report according to code */
switch (rpt->code)
- {
- case 0x3D: rpt_chan_A_config (rpt); break;
- case 0x40: rpt_almanac_data_page (rpt); break;
- case 0x41: rpt_GPS_time (rpt); break;
- case 0x42: rpt_single_ECEF_position (rpt); break;
- case 0x43: rpt_single_ECEF_velocity (rpt); break;
- case 0x45: rpt_SW_version (rpt); break;
- case 0x46: rpt_rcvr_health (rpt); break;
- case 0x47: rpt_SNR_all_SVs (rpt); break;
- case 0x48: rpt_GPS_system_message (rpt); break;
- case 0x49: rpt_almanac_health_page (rpt); break;
- case 0x4A: switch (rpt->len) {
- /*
- ** special case (=slip-up) in the TSIP protocol;
- ** parsing method depends on length
- */
- case 20: rpt_single_lla_position (rpt); break;
- case 9: rpt_ref_alt (rpt); break;
+ {
+ case 0x3D: rpt_chan_A_config (rpt); break;
+ case 0x40: rpt_almanac_data_page (rpt); break;
+ case 0x41: rpt_GPS_time (rpt); break;
+ case 0x42: rpt_single_ECEF_position (rpt); break;
+ case 0x43: rpt_single_ECEF_velocity (rpt); break;
+ case 0x45: rpt_SW_version (rpt); break;
+ case 0x46: rpt_rcvr_health (rpt); break;
+ case 0x47: rpt_SNR_all_SVs (rpt); break;
+ case 0x48: rpt_GPS_system_message (rpt); break;
+ case 0x49: rpt_almanac_health_page (rpt); break;
+ case 0x4A: switch (rpt->len) {
+ /*
+ ** special case (=slip-up) in the TSIP protocol;
+ ** parsing method depends on length
+ */
+ case 20: rpt_single_lla_position (rpt); break;
+ case 9: rpt_ref_alt (rpt); break;
} break;
- case 0x4B: rpt_rcvr_id_and_status (rpt);break;
- case 0x4C: rpt_operating_parameters (rpt); break;
- case 0x4D: rpt_oscillator_offset (rpt); break;
- case 0x4E: rpt_GPS_time_set_response (rpt); break;
- case 0x4F: rpt_UTC_offset (rpt); break;
- case 0x54: rpt_1SV_bias (rpt); break;
- case 0x55: rpt_io_opt (rpt); break;
- case 0x56: rpt_ENU_velocity (rpt); break;
- case 0x57: rpt_last_fix_info (rpt); break;
- case 0x58: rpt_GPS_system_data (rpt); break;
- case 0x59: rpt_SVs_enabled (rpt); break;
- case 0x5A: rpt_raw_msmt (rpt); break;
- case 0x5B: rpt_SV_ephemeris_status (rpt); break;
- case 0x5C: rpt_SV_tracking_status (rpt); break;
- case 0x6D: rpt_allSV_selection (rpt); break;
- case 0x82: rpt_DGPS_position_mode (rpt); break;
- case 0x83: rpt_double_ECEF_position (rpt); break;
- case 0x84: rpt_double_lla_position (rpt); break;
- case 0xBB: rpt_complete_rcvr_config (rpt); break;
- case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
-
- case 0x8F: switch (rpt->buf[0])
- {
- /* superpackets; parsed according to subcodes */
- case 0x0B: rpt_8F0B(rpt); break;
- case 0x14: rpt_8F14(rpt); break;
- case 0x15: rpt_8F15(rpt); break;
- case 0x20: rpt_8F20(rpt); break;
- case 0x41: rpt_8F41(rpt); break;
- case 0x42: rpt_8F42(rpt); break;
- case 0x45: rpt_8F45(rpt); break;
- case 0x4A: rpt_8F4A(rpt); break;
- case 0x4B: rpt_8F4B(rpt); break;
- case 0x4D: rpt_8F4D(rpt); break;
- case 0xA5: rpt_8FA5(rpt); break;
- case 0xAD: rpt_8FAD(rpt); break;
- default: parsed = BADID_PARSE; break;
+ case 0x4B: rpt_rcvr_id_and_status (rpt);break;
+ case 0x4C: rpt_operating_parameters (rpt); break;
+ case 0x4D: rpt_oscillator_offset (rpt); break;
+ case 0x4E: rpt_GPS_time_set_response (rpt); break;
+ case 0x4F: rpt_UTC_offset (rpt); break;
+ case 0x54: rpt_1SV_bias (rpt); break;
+ case 0x55: rpt_io_opt (rpt); break;
+ case 0x56: rpt_ENU_velocity (rpt); break;
+ case 0x57: rpt_last_fix_info (rpt); break;
+ case 0x58: rpt_GPS_system_data (rpt); break;
+ case 0x59: rpt_SVs_enabled (rpt); break;
+ case 0x5A: rpt_raw_msmt (rpt); break;
+ case 0x5B: rpt_SV_ephemeris_status (rpt); break;
+ case 0x5C: rpt_SV_tracking_status (rpt); break;
+ case 0x6D: rpt_allSV_selection (rpt); break;
+ case 0x82: rpt_DGPS_position_mode (rpt); break;
+ case 0x83: rpt_double_ECEF_position (rpt); break;
+ case 0x84: rpt_double_lla_position (rpt); break;
+ case 0xBB: rpt_complete_rcvr_config (rpt); break;
+ case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
+
+ case 0x8F: switch (rpt->buf[0])
+ {
+ /* superpackets; parsed according to subcodes */
+ case 0x0B: rpt_8F0B(rpt); break;
+ case 0x14: rpt_8F14(rpt); break;
+ case 0x15: rpt_8F15(rpt); break;
+ case 0x20: rpt_8F20(rpt); break;
+ case 0x41: rpt_8F41(rpt); break;
+ case 0x42: rpt_8F42(rpt); break;
+ case 0x45: rpt_8F45(rpt); break;
+ case 0x4A: rpt_8F4A(rpt); break;
+ case 0x4B: rpt_8F4B(rpt); break;
+ case 0x4D: rpt_8F4D(rpt); break;
+ case 0xA5: rpt_8FA5(rpt); break;
+ case 0xAD: rpt_8FAD(rpt); break;
+ default: parsed = BADID_PARSE; break;
}
break;
- default: parsed = BADID_PARSE; break;
+ default: parsed = BADID_PARSE; break;
}
if (parsed != GOOD_PARSE)
{
- /*
- **The message has TSIP structure (DLEs, etc.)
- ** but could not be parsed by above routines
- */
+ /*
+ **The message has TSIP structure (DLEs, etc.)
+ ** but could not be parsed by above routines
+ */
unknown_rpt (rpt);
}
- /* close TextOutputBuffer */
- pbuf = '\0';
+ /* close TextOutputBuffer */
+ pbuf = '\0';
}
#endif /* TRIMBLE_OUTPUT_FUNC */
diff --git a/ntpd/refclock_shm.c b/ntpd/refclock_shm.c
index 7be263d1ba33..b73e899766d3 100644
--- a/ntpd/refclock_shm.c
+++ b/ntpd/refclock_shm.c
@@ -39,6 +39,9 @@
* This driver supports a reference clock attached thru shared memory
*/
+/* Temp hack to simplify testing of the old mode. */
+#define OLDWAY 0
+
/*
* SHM interface definitions
*/
@@ -51,9 +54,12 @@
/*
* Function prototypes
*/
-static int shm_start (int, struct peer *);
-static void shm_shutdown (int, struct peer *);
-static void shm_poll (int unit, struct peer *);
+static int shm_start (int unit, struct peer *peer);
+static void shm_shutdown (int unit, struct peer *peer);
+static void shm_poll (int unit, struct peer *peer);
+static void shm_timer (int unit, struct peer *peer);
+ int shm_peek (int unit, struct peer *peer);
+ void shm_clockstats (int unit, struct peer *peer);
/*
* Transfer vector
@@ -61,12 +67,13 @@ static void shm_poll (int unit, struct peer *);
struct refclock refclock_shm = {
shm_start, /* start up driver */
shm_shutdown, /* shut down driver */
- shm_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
+ shm_poll, /* transmit poll message */
+ noentry, /* not used: control */
+ noentry, /* not used: init */
+ noentry, /* not used: buginfo */
+ shm_timer, /* once per second */
};
+
struct shmTime {
int mode; /* 0 - if valid set
* use values,
@@ -88,15 +95,30 @@ struct shmTime {
int dummy[10];
};
+struct shmunit {
+ struct shmTime *shm; /* pointer to shared memory segment */
+
+ /* debugging/monitoring counters - reset when printed */
+ int ticks; /* number of attempts to read data*/
+ int good; /* number of valid samples */
+ int notready; /* number of peeks without data ready */
+ int bad; /* number of invalid samples */
+ int clash; /* number of access clashes while reading */
+};
+
+
struct shmTime *getShmTime(int);
struct shmTime *getShmTime (int unit) {
#ifndef SYS_WINNT
int shmid=0;
- assert (unit<10); /* MAXUNIT is 4, so should never happen */
+ /* 0x4e545030 is NTP0.
+ * Big units will give non-ascii but that's OK
+ * as long as everybody does it the same way.
+ */
shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
- IPC_CREAT|(unit<2?0700:0777));
+ IPC_CREAT|(unit<2?0600:0666));
if (shmid==-1) { /*error */
msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
return 0;
@@ -115,8 +137,8 @@ struct shmTime *getShmTime (int unit) {
HANDLE shmid=0;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
- sprintf (buf,"NTP%d",unit);
- if (unit>=2) { /* world access */
+ snprintf(buf, sizeof(buf), "NTP%d", unit);
+ if (unit >= 2) { /* world access */
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
return 0;
@@ -163,22 +185,29 @@ shm_start(
)
{
struct refclockproc *pp;
+ struct shmunit *up;
+
pp = peer->procptr;
pp->io.clock_recv = noentry;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = -1;
- pp->unitptr = (caddr_t)getShmTime(unit);
+
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
+ pp->unitptr = (caddr_t)up;
+
+ up->shm = getShmTime(unit);
/*
* Initialize miscellaneous peer variables
*/
memcpy((char *)&pp->refid, REFID, 4);
- if (pp->unitptr!=0) {
- ((struct shmTime*)pp->unitptr)->precision=PRECISION;
- peer->precision = ((struct shmTime*)pp->unitptr)->precision;
- ((struct shmTime*)pp->unitptr)->valid=0;
- ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
+ if (up->shm != 0) {
+ up->shm->precision = PRECISION;
+ peer->precision = up->shm->precision;
+ up->shm->valid=0;
+ up->shm->nsamples=NSAMPLES;
pp->clockdesc = DESCRIPTION;
return (1);
}
@@ -197,17 +226,34 @@ shm_shutdown(
struct peer *peer
)
{
- register struct shmTime *up;
struct refclockproc *pp;
+ struct shmunit *up;
pp = peer->procptr;
- up = (struct shmTime *)pp->unitptr;
+ up = (struct shmunit *)pp->unitptr;
+
+ if (NULL == up)
+ return;
#ifndef SYS_WINNT
/* HMS: shmdt()wants char* or const void * */
- (void) shmdt (up);
+ (void) shmdt ((char *)up->shm);
#else
- UnmapViewOfFile (up);
+ UnmapViewOfFile (up->shm);
#endif
+ free(up);
+}
+
+
+/*
+ * shm_timer - called every second
+ */
+static void
+shm_timer(int unit, struct peer *peer)
+{
+ if (OLDWAY)
+ return;
+
+ shm_peek(unit, peer);
}
@@ -220,26 +266,60 @@ shm_poll(
struct peer *peer
)
{
- register struct shmTime *up;
struct refclockproc *pp;
+ int ok;
+
+ pp = peer->procptr;
+
+ if (OLDWAY) {
+ ok = shm_peek(unit, peer);
+ if (!ok) return;
+ }
+
+ /*
+ * Process median filter samples. If none received, declare a
+ * timeout and keep going.
+ */
+ if (pp->coderecv == pp->codeproc) {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ shm_clockstats(unit, peer);
+ return;
+ }
+ pp->lastref = pp->lastrec;
+ refclock_receive(peer);
+ shm_clockstats(unit, peer);
+}
+
+/*
+ * shm_peek - try to grab a sample
+ */
+int shm_peek(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ struct shmunit *up;
+ struct shmTime *shm;
/*
* This is the main routine. It snatches the time from the shm
* board and tacks on a local timestamp.
*/
pp = peer->procptr;
- up = (struct shmTime*)pp->unitptr;
- if (up==0) { /* try to map again - this may succeed if meanwhile some-
- body has ipcrm'ed the old (unaccessible) shared mem
- segment */
- pp->unitptr = (caddr_t)getShmTime(unit);
- up = (struct shmTime*)pp->unitptr;
+ up = (struct shmunit*)pp->unitptr;
+ up->ticks++;
+ if (up->shm == 0) {
+ /* try to map again - this may succeed if meanwhile some-
+ body has ipcrm'ed the old (unaccessible) shared mem segment */
+ up->shm = getShmTime(unit);
}
- if (up==0) {
+ shm = up->shm;
+ if (shm == 0) {
refclock_report(peer, CEVNT_FAULT);
- return;
+ return(0);
}
- if (up->valid) {
+ if (shm->valid) {
struct timeval tvr;
struct timeval tvt;
struct tm *t;
@@ -248,27 +328,27 @@ shm_poll(
tvr.tv_usec = 0;
tvt.tv_sec = 0;
tvt.tv_usec = 0;
- switch (up->mode) {
+ switch (shm->mode) {
case 0: {
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
+ tvr.tv_sec=shm->receiveTimeStampSec;
+ tvr.tv_usec=shm->receiveTimeStampUSec;
+ tvt.tv_sec=shm->clockTimeStampSec;
+ tvt.tv_usec=shm->clockTimeStampUSec;
}
break;
case 1: {
- int cnt=up->count;
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
- ok=(cnt==up->count);
+ int cnt=shm->count;
+ tvr.tv_sec=shm->receiveTimeStampSec;
+ tvr.tv_usec=shm->receiveTimeStampUSec;
+ tvt.tv_sec=shm->clockTimeStampSec;
+ tvt.tv_usec=shm->clockTimeStampUSec;
+ ok=(cnt==shm->count);
}
break;
default:
- msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
+ msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",shm->mode);
}
- up->valid=0;
+ shm->valid=0;
if (ok) {
time_t help; /* XXX NetBSD has incompatible tv_sec */
@@ -283,28 +363,53 @@ shm_poll(
pp->minute=t->tm_min;
pp->second=t->tm_sec;
pp->nsec=tvt.tv_usec * 1000;
- peer->precision=up->precision;
- pp->leap=up->leap;
+ peer->precision=shm->precision;
+ pp->leap=shm->leap;
}
else {
refclock_report(peer, CEVNT_FAULT);
msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
- return;
+ up->clash++;
+ return(0);
}
}
else {
refclock_report(peer, CEVNT_TIMEOUT);
- /*
- msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
- */
- return;
+ up->notready++;
+ return(0);
}
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
- return;
+ up->bad++;
+ return(0);
}
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
+ up->good++;
+ return(1);
+}
+
+/*
+ * shm_clockstats - dump and reset counters
+ */
+void shm_clockstats(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ struct shmunit *up;
+ char logbuf[256];
+
+ pp = peer->procptr;
+ up = (struct shmunit*)pp->unitptr;
+
+ if (!(pp->sloppyclockflag & CLK_FLAG4)) return;
+
+ snprintf(logbuf, sizeof(logbuf), "%3d %3d %3d %3d %3d",
+ up->ticks, up->good, up->notready, up->bad, up->clash);
+ record_clock_stats(&peer->srcadr, logbuf);
+
+ up->ticks = up->good = up->notready =up->bad = up->clash = 0;
+
}
#else
diff --git a/ntpd/refclock_tpro.c b/ntpd/refclock_tpro.c
index 3c425684ec7a..86764d3f7a25 100644
--- a/ntpd/refclock_tpro.c
+++ b/ntpd/refclock_tpro.c
@@ -42,9 +42,9 @@ struct tprounit {
/*
* Function prototypes
*/
-static int tpro_start P((int, struct peer *));
-static void tpro_shutdown P((int, struct peer *));
-static void tpro_poll P((int unit, struct peer *));
+static int tpro_start (int, struct peer *);
+static void tpro_shutdown (int, struct peer *);
+static void tpro_poll (int unit, struct peer *);
/*
* Transfer vector
@@ -77,7 +77,7 @@ tpro_start(
/*
* Open TPRO device
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
fd = open(device, O_RDONLY | O_NDELAY, 0777);
if (fd == -1) {
msyslog(LOG_ERR, "tpro_start: open of %s: %m", device);
@@ -87,11 +87,8 @@ tpro_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct tprounit *) emalloc(sizeof(struct tprounit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct tprounit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = noentry;
pp->io.srcclock = (caddr_t)peer;
@@ -125,7 +122,8 @@ tpro_shutdown(
pp = peer->procptr;
up = (struct tprounit *)pp->unitptr;
io_closeclock(&pp->io);
- free(up);
+ if (NULL != up)
+ free(up);
}
@@ -170,13 +168,13 @@ tpro_poll(
* we could pad the written string appropriately and read the
* resulting value in already scaled.
*/
- sprintf(pp->a_lastcode,
- "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
- tp->day100, tp->day10, tp->day1, tp->hour10, tp->hour1,
- tp->min10, tp->min1, tp->sec10, tp->sec1, tp->ms100,
- tp->ms10, tp->ms1, tp->usec100, tp->usec10, tp->usec1,
- tp->status);
- pp->lencode = strlen(pp->a_lastcode);
+ snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
+ "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
+ tp->day100, tp->day10, tp->day1, tp->hour10, tp->hour1,
+ tp->min10, tp->min1, tp->sec10, tp->sec1, tp->ms100,
+ tp->ms10, tp->ms1, tp->usec100, tp->usec10, tp->usec1,
+ tp->status);
+ pp->lencode = strlen(pp->a_lastcode);
#ifdef DEBUG
if (debug)
printf("tpro: time %s timecode %d %s\n",
@@ -204,7 +202,6 @@ tpro_poll(
refclock_report(peer, CEVNT_TIMEOUT);
return;
}
- refclock_receive(peer);
pp->lastref = pp->lastrec;
record_clock_stats(&peer->srcadr, pp->a_lastcode);
refclock_receive(peer);
diff --git a/ntpd/refclock_trak.c b/ntpd/refclock_trak.c
index 3a4a54e653eb..ddb86de845b0 100644
--- a/ntpd/refclock_trak.c
+++ b/ntpd/refclock_trak.c
@@ -147,7 +147,7 @@ trak_start(
* timestamp following the "*" on-time character of the
* timecode.
*/
- (void)sprintf(device, DEVICE, unit);
+ snprintf(device, sizeof(device), DEVICE, unit);
if (
#ifdef PPS
!(fd = refclock_open(device, SPEED232, LDISC_CLK))
@@ -160,12 +160,8 @@ trak_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct trakunit *)
- emalloc(sizeof(struct trakunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct trakunit));
+ up = emalloc(sizeof(*up));
+ memset(up, 0, sizeof(*up));
pp = peer->procptr;
pp->io.clock_recv = trak_receive;
pp->io.srcclock = (caddr_t)peer;
@@ -173,6 +169,7 @@ trak_start(
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
(void) close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
@@ -214,8 +211,10 @@ trak_shutdown(
pp = peer->procptr;
up = (struct trakunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
diff --git a/ntpd/refclock_true.c b/ntpd/refclock_true.c
index dd355d90273b..e2520c0dc1c3 100644
--- a/ntpd/refclock_true.c
+++ b/ntpd/refclock_true.c
@@ -21,6 +21,12 @@
#include <stdio.h>
#include <ctype.h>
+#ifdef SYS_WINNT
+extern int async_write(int, const void *, unsigned int);
+#undef write
+#define write(fd, data, octets) async_write(fd, data, octets)
+#endif
+
/* 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
@@ -167,15 +173,15 @@ struct true_unit {
/*
* Function prototypes
*/
-static int true_start P((int, struct peer *));
-static void true_shutdown P((int, struct peer *));
-static void true_receive P((struct recvbuf *));
-static void true_poll P((int, struct peer *));
-static void true_send P((struct peer *, const char *));
-static void true_doevent P((struct peer *, enum true_event));
+static int true_start (int, struct peer *);
+static void true_shutdown (int, struct peer *);
+static void true_receive (struct recvbuf *);
+static void true_poll (int, struct peer *);
+static void true_send (struct peer *, const char *);
+static void true_doevent (struct peer *, enum true_event);
#ifdef CLOCK_PPS720
-static u_long true_sample720 P((void));
+static u_long true_sample720 (void);
#endif
/*
@@ -235,6 +241,7 @@ true_debug(struct peer *peer, const char *fmt, ...)
fprintf(up->debug, "true%d: ", up->unit);
vfprintf(up->debug, fmt, ap);
}
+ va_end(ap);
}
#endif /*STDC*/
@@ -289,7 +296,16 @@ true_start(
up->pollcnt = 2;
up->type = t_unknown;
up->state = s_Base;
+
+ /*
+ * Send a CTRL-C character at the start,
+ * just in case the clock is already
+ * sending timecodes
+ */
+ true_send(peer, "\03\r");
+
true_doevent(peer, e_Init);
+
return (1);
}
@@ -480,7 +496,8 @@ 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 == '?'
+ || synced == 'X')
pp->leap = LEAP_NOTINSYNC;
else
pp->leap = LEAP_NOWARNING;
diff --git a/ntpd/refclock_tt560.c b/ntpd/refclock_tt560.c
index f3d7bc17a701..7aa2180e756f 100644
--- a/ntpd/refclock_tt560.c
+++ b/ntpd/refclock_tt560.c
@@ -47,9 +47,9 @@ typedef union byteswap_u
/*
* Function prototypes
*/
-static int tt560_start P((int, struct peer *));
-static void tt560_shutdown P((int, struct peer *));
-static void tt560_poll P((int unit, struct peer *));
+static int tt560_start (int, struct peer *);
+static void tt560_shutdown (int, struct peer *);
+static void tt560_poll (int unit, struct peer *);
/*
* Transfer vector
diff --git a/ntpd/refclock_ulink.c b/ntpd/refclock_ulink.c
index d7a62fef3a4b..5b7f46f03816 100644
--- a/ntpd/refclock_ulink.c
+++ b/ntpd/refclock_ulink.c
@@ -106,10 +106,10 @@ struct ulinkunit {
/*
* Function prototypes
*/
-static int ulink_start P((int, struct peer *));
-static void ulink_shutdown P((int, struct peer *));
-static void ulink_receive P((struct recvbuf *));
-static void ulink_poll P((int, struct peer *));
+static int ulink_start (int, struct peer *);
+static void ulink_shutdown (int, struct peer *);
+static void ulink_receive (struct recvbuf *);
+static void ulink_poll (int, struct peer *);
/*
* Transfer vector
diff --git a/ntpd/refclock_wwv.c b/ntpd/refclock_wwv.c
index b7e0d9a6b1df..b03cfe128702 100644
--- a/ntpd/refclock_wwv.c
+++ b/ntpd/refclock_wwv.c
@@ -39,11 +39,12 @@
* tuned automatically using this program as propagation conditions
* change throughout the weasons, both day and night.
*
- * The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a workstation running Solaris, SunOS
- * FreeBSD or Linux, and with a little help, other workstations with
- * similar codecs or sound cards. In this implementation, only one audio
- * driver and codec can be supported on a single machine.
+ * The driver requires an audio codec or sound card with sampling rate 8
+ * kHz and mu-law companding. This is the same standard as used by the
+ * telephone industry and is supported by most hardware and operating
+ * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
+ * implementation, only one audio driver and codec can be supported on a
+ * single machine.
*
* The demodulation and decoding algorithms used in this driver are
* based on those developed for the TAPR DSP93 development board and the
@@ -68,6 +69,10 @@
* It does not seem useful to select the compact disc player port. Fudge
* flag3 enables audio monitoring of the input signal. For this purpose,
* the monitor gain is set to a default value.
+ *
+ * CEVNT_BADTIME invalid date or time
+ * CEVNT_PROP propagation failure - no stations heard
+ * CEVNT_TIMEOUT timeout (see newgame() below)
*/
/*
* General definitions. These ordinarily do not need to be changed.
@@ -92,6 +97,7 @@
#define TCKSIZ (TCKCYC * MS) /* tick filter size */
#define NCHAN 5 /* number of radio channels */
#define AUDIO_PHI 5e-6 /* dispersion growth factor */
+#define TBUF 128 /* max monitor line length */
/*
* Tunable parameters. The DGAIN parameter can be changed to fit the
@@ -102,12 +108,10 @@
* radio is not tunable, the DCHAN parameter can be changed to fit the
* expected best propagation frequency: higher if further from the
* transmitter, lower if nearer. The compromise value works for the US
- * right coast. The FREQ_OFFSET parameter can be used as a frequency
- * vernier to correct codec requency if greater than MAXFREQ.
+ * right coast.
*/
#define DCHAN 3 /* default radio channel (15 Mhz) */
#define DGAIN 5. /* subcarrier gain */
-#define FREQ_OFFSET 0. /* codec frequency correction (PPM) */
/*
* General purpose status bits (status)
@@ -133,6 +137,7 @@
#define FGATE 0x0010 /* frequency gate */
#define DGATE 0x0020 /* data pulse amplitude error */
#define BGATE 0x0040 /* data pulse width error */
+#define METRIC 0x0080 /* one or more stations heard */
#define LEPSEC 0x1000 /* leap minute */
/*
@@ -150,10 +155,10 @@
* These bits indicate various alarm conditions, which are decoded to
* form the quality character included in the timecode.
*/
-#define CMPERR 1 /* digit or misc bit compare error */
-#define LOWERR 2 /* low bit or digit amplitude or SNR */
-#define NINERR 4 /* less than nine digits in minute */
-#define SYNERR 8 /* not tracking second sync */
+#define CMPERR 0x1 /* digit or misc bit compare error */
+#define LOWERR 0x2 /* low bit or digit amplitude or SNR */
+#define NINERR 0x4 /* less than nine digits in minute */
+#define SYNERR 0x8 /* not tracking second sync */
/*
* Watchcat timeouts (watch)
@@ -225,15 +230,21 @@
#define SECWAR 0x40 /* 3 leap second warning */
/*
- * The on-time synchronization point for the driver is the second epoch
- * sync pulse produced by the FIR matched filters. As the 5-ms delay of
- * these filters is compensated, the program delay is 1.1 ms due to the
- * 600-Hz IIR bandpass filter. The measured receiver delay is 4.7 ms and
- * the codec delay less than 0.2 ms. The additional propagation delay
- * specific to each receiver location can be programmed in the fudge
- * time1 and time2 values for WWV and WWVH, respectively.
+ * The on-time synchronization point is the positive-going zero crossing
+ * of the first cycle of the 5-ms second pulse. The IIR baseband filter
+ * phase delay is 0.91 ms, while the receiver delay is approximately 4.7
+ * ms at 1000 Hz. The fudge value -0.45 ms due to the codec and other
+ * causes was determined by calibrating to a PPS signal from a GPS
+ * receiver. The additional propagation delay specific to each receiver
+ * location can be programmed in the fudge time1 and time2 values for
+ * WWV and WWVH, respectively.
+ *
+ * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
+ * generally within .02 ms short-term with .02 ms jitter. The long-term
+ * offsets vary up to 0.3 ms due to ionosperhic layer height variations.
+ * The processor load due to the driver is 5.8 percent.
*/
-#define PDELAY (.0011 + .0047 + .0002) /* net system delay (s) */
+#define PDELAY ((.91 + 4.7 - 0.45) / 1000) /* system delay (s) */
/*
* Table of sine values at 4.5-degree increments. This is used by the
@@ -365,7 +376,7 @@ struct progx progx[] = {
};
/*
- * BCD coefficients for maximum likelihood digit decode
+ * BCD coefficients for maximum-likelihood digit decode
*/
#define P15 1. /* max positive number */
#define N15 -1. /* max negative number */
@@ -447,14 +458,13 @@ char dstcod[] = {
/*
* The decoding matrix consists of nine row vectors, one for each digit
* of the timecode. The digits are stored from least to most significant
- * order. The maximum likelihood timecode is formed from the digits
- * corresponding to the maximum likelihood values reading in the
+ * order. The maximum-likelihood timecode is formed from the digits
+ * corresponding to the maximum-likelihood values reading in the
* opposite order: yy ddd hh:mm.
*/
struct decvec {
int radix; /* radix (3, 4, 6, 10) */
int digit; /* current clock digit */
- int mldigit; /* maximum likelihood digit */
int count; /* match count */
double digprb; /* max digit probability */
double digsnr; /* likelihood function (dB) */
@@ -503,6 +513,7 @@ struct wwvunit {
l_fp tick; /* audio sample increment */
double phase, freq; /* logical clock phase and frequency */
double monitor; /* audio monitor point */
+ double pdelay; /* propagation delay (s) */
#ifdef ICOM
int fd_icom; /* ICOM file descriptor */
#endif /* ICOM */
@@ -513,7 +524,7 @@ struct wwvunit {
* Audio codec variables
*/
double comp[SIZE]; /* decompanding table */
- int port; /* codec port */
+ int port; /* codec port */
int gain; /* codec gain */
int mongain; /* codec monitor gain */
int clipcnt; /* sample clipped count */
@@ -568,32 +579,32 @@ struct wwvunit {
/*
* Function prototypes
*/
-static int wwv_start P((int, struct peer *));
-static void wwv_shutdown P((int, struct peer *));
-static void wwv_receive P((struct recvbuf *));
-static void wwv_poll P((int, struct peer *));
+static int wwv_start (int, struct peer *);
+static void wwv_shutdown (int, struct peer *);
+static void wwv_receive (struct recvbuf *);
+static void wwv_poll (int, struct peer *);
/*
* More function prototypes
*/
-static void wwv_epoch P((struct peer *));
-static void wwv_rf P((struct peer *, double));
-static void wwv_endpoc P((struct peer *, int));
-static void wwv_rsec P((struct peer *, double));
-static void wwv_qrz P((struct peer *, struct sync *, int));
-static void wwv_corr4 P((struct peer *, struct decvec *,
- double [], double [][4]));
-static void wwv_gain P((struct peer *));
-static void wwv_tsec P((struct peer *));
-static int timecode P((struct wwvunit *, char *));
-static double wwv_snr P((double, double));
-static int carry P((struct decvec *));
-static int wwv_newchan P((struct peer *));
-static void wwv_newgame P((struct peer *));
-static double wwv_metric P((struct sync *));
-static void wwv_clock P((struct peer *));
+static void wwv_epoch (struct peer *);
+static void wwv_rf (struct peer *, double);
+static void wwv_endpoc (struct peer *, int);
+static void wwv_rsec (struct peer *, double);
+static void wwv_qrz (struct peer *, struct sync *, int);
+static void wwv_corr4 (struct peer *, struct decvec *,
+ double [], double [][4]);
+static void wwv_gain (struct peer *);
+static void wwv_tsec (struct peer *);
+static int timecode (struct wwvunit *, char *);
+static double wwv_snr (double, double);
+static int carry (struct decvec *);
+static int wwv_newchan (struct peer *);
+static void wwv_newgame (struct peer *);
+static double wwv_metric (struct sync *);
+static void wwv_clock (struct peer *);
#ifdef ICOM
-static int wwv_qsy P((struct peer *, int));
+static int wwv_qsy (struct peer *, int);
#endif /* ICOM */
static double qsy[NCHAN] = {2.5, 5, 10, 15, 20}; /* frequencies (MHz) */
@@ -705,7 +716,9 @@ wwv_start(
/*
* Initialize autotune if available. Note that the ICOM select
* code must be less than 128, so the high order bit can be used
- * to select the line speed 0 (9600 bps) or 1 (1200 bps).
+ * to select the line speed 0 (9600 bps) or 1 (1200 bps). Note
+ * we don't complain if the ICOM device is not there; but, if it
+ * is, the radio better be working.
*/
temp = 0;
#ifdef DEBUG
@@ -719,25 +732,14 @@ wwv_start(
else
up->fd_icom = icom_init("/dev/icom", B9600,
temp);
- if (up->fd_icom < 0) {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: %m");
- up->errflg = CEVNT_FAULT;
- }
}
if (up->fd_icom > 0) {
if (wwv_qsy(peer, DCHAN) != 0) {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: radio not found");
- up->errflg = CEVNT_FAULT;
+ msyslog(LOG_NOTICE, "icom: radio not found");
close(up->fd_icom);
up->fd_icom = 0;
} else {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: autotune enabled");
+ msyslog(LOG_NOTICE, "icom: autotune enabled");
}
}
#endif /* ICOM */
@@ -837,8 +839,7 @@ wwv_receive(
* per second, which results in a frequency change of
* 125 PPM.
*/
- up->phase += up->freq / SECOND;
- up->phase += FREQ_OFFSET / 1e6;
+ up->phase += (up->freq + clock_codec) / SECOND;
if (up->phase >= .5) {
up->phase -= 1.;
} else if (up->phase < -.5) {
@@ -884,8 +885,6 @@ wwv_poll(
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
- if (pp->coderecv == pp->codeproc)
- up->errflg = CEVNT_TIMEOUT;
if (up->errflg)
refclock_report(peer, up->errflg);
up->errflg = 0;
@@ -974,7 +973,6 @@ wwv_rf(
static int epopos; /* epoch second sync position buffer */
static int iniflg; /* initialization flag */
- int pdelay; /* propagation delay (samples) */
int epoch; /* comb filter index */
double dtemp;
int i;
@@ -1012,7 +1010,7 @@ wwv_rf(
* compensate for the radio audio response at 100 Hz.
*
* Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
- * passband ripple, -50 dB stopband ripple.
+ * passband ripple, -50 dB stopband ripple, phase delay 0.97 ms.
*/
data = (lpf[4] = lpf[3]) * 8.360961e-01;
data += (lpf[3] = lpf[2]) * -3.481740e+00;
@@ -1056,7 +1054,7 @@ wwv_rf(
* tones and most of the noise and voice modulation components.
*
* Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB
- * passband ripple, -50 dB stopband ripple.
+ * passband ripple, -50 dB stopband ripple, phase delay 0.91 ms.
*/
syncx = (bpf[8] = bpf[7]) * 4.897278e-01;
syncx += (bpf[7] = bpf[6]) * -2.765914e+00;
@@ -1174,10 +1172,6 @@ wwv_rf(
*/
if (!wwv_newchan(peer))
up->watch = 0;
-#ifdef ICOM
- if (up->fd_icom > 0)
- wwv_qsy(peer, up->dchan);
-#endif /* ICOM */
} else {
/*
@@ -1212,7 +1206,8 @@ wwv_rf(
wwv_epoch(peer);
} else if (up->sptr != NULL) {
sp = up->sptr;
- if (sp->metric >= TTHR && epoch == sp->mepoch % SECOND) {
+ if (sp->metric >= TTHR && epoch == sp->mepoch % SECOND)
+ {
up->rsec = (60 - sp->mepoch / SECOND) % 60;
up->rphase = 0;
up->status |= MSYNC;
@@ -1232,18 +1227,14 @@ wwv_rf(
* provides a resolution of one sample (125 us). The filters run
* only if the station has been reliably determined.
*/
- if (up->status & SELV) {
- pdelay = (int)(pp->fudgetime1 * SECOND);
+ if (up->status & SELV)
mfsync = sqrt(csiamp * csiamp + csqamp * csqamp) /
TCKCYC;
- } else if (up->status & SELH) {
- pdelay = (int)(pp->fudgetime2 * SECOND);
+ else if (up->status & SELH)
mfsync = sqrt(hsiamp * hsiamp + hsqamp * hsqamp) /
TCKCYC;
- } else {
- pdelay = 0;
+ else
mfsync = 0;
- }
/*
* Enhance the seconds sync pulse using a 1-s (8000-sample) comb
@@ -1271,7 +1262,7 @@ wwv_rf(
if (epoch == 0) {
up->epomax = epomax;
up->eposnr = wwv_snr(epomax, nxtmax);
- epopos -= pdelay + TCKCYC * MS;
+ epopos -= TCKCYC * MS;
if (epopos < 0)
epopos += SECOND;
wwv_endpoc(peer, epopos);
@@ -1313,7 +1304,7 @@ wwv_qrz(
{
struct refclockproc *pp;
struct wwvunit *up;
- char tbuf[80]; /* monitor buffer */
+ char tbuf[TBUF]; /* monitor buffer */
long epoch;
pp = peer->procptr;
@@ -1365,7 +1356,7 @@ wwv_qrz(
sp->metric = wwv_metric(sp);
if (pp->sloppyclockflag & CLK_FLAG4) {
sprintf(tbuf,
- "wwv8 %04x %3d %s %04x %.0f %.0f/%.1f %4ld %4ld",
+ "wwv8 %04x %3d %s %04x %.0f %.0f/%.1f %ld %ld",
up->status, up->gain, sp->refid,
sp->reach & 0xffff, sp->metric, sp->synmax,
sp->synsnr, sp->pos % SECOND, epoch);
@@ -1413,7 +1404,7 @@ wwv_endpoc(
static int avgcnt; /* averaging interval counter */
static int avginc; /* averaging ratchet */
static int iniflg; /* initialization flag */
- char tbuf[80]; /* monitor buffer */
+ char tbuf[TBUF]; /* monitor buffer */
double dtemp;
int tmp2;
@@ -1489,8 +1480,8 @@ wwv_endpoc(
mepoch = xepoch;
syncnt = 0;
}
- if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & MSYNC))
- {
+ if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
+ MSYNC)) {
sprintf(tbuf,
"wwv1 %04x %3d %4d %5.0f %5.1f %5d %4d %4d %4d",
up->status, up->gain, tepoch, up->epomax,
@@ -1768,7 +1759,7 @@ wwv_rsec(
struct wwvunit *up;
struct chan *cp;
struct sync *sp, *rp;
- char tbuf[80]; /* monitor buffer */
+ char tbuf[TBUF]; /* monitor buffer */
int sw, arg, nsec;
pp = peer->procptr;
@@ -1887,35 +1878,28 @@ wwv_rsec(
up->errcnt = up->digcnt = up->alarm = 0;
/*
- * We now begin the minute scan. If not yet synchronized
- * to a station, restart if the units digit has not been
- * found within the DATA timeout (15 m) or if not
- * synchronized within the SYNCH timeout (40 m). After
- * synchronizing to a station, restart if no stations
- * are found within the PANIC timeout (2 days).
+ * If synchronized to a station, restart if no stations
+ * have been heard within the PANIC timeout (2 days). If
+ * not and the minute digit has been found, restart if
+ * not synchronized withing the SYNCH timeout (40 m). If
+ * not, restart if the unit digit has not been found
+ * within the DATA timeout (15 m).
*/
if (up->status & INSYNC) {
if (up->watch > PANIC) {
wwv_newgame(peer);
return;
}
- } else {
- if (!(up->status & DSYNC)) {
- if (up->watch > DATA) {
- wwv_newgame(peer);
- return;
- }
- }
+ } else if (up->status & DSYNC) {
if (up->watch > SYNCH) {
wwv_newgame(peer);
return;
}
+ } else if (up->watch > DATA) {
+ wwv_newgame(peer);
+ return;
}
wwv_newchan(peer);
-#ifdef ICOM
- if (up->fd_icom > 0)
- wwv_qsy(peer, up->dchan);
-#endif /* ICOM */
break;
/*
@@ -1987,7 +1971,7 @@ wwv_rsec(
/*
* Save the data channel gain, then QSY to the probe channel and
- * dim the seconds comb filters. The newchan() routine will
+ * dim the seconds comb filters. The www_newchan() routine will
* light them back up.
*/
case MSC21: /* 58 */
@@ -2107,7 +2091,7 @@ wwv_clock(
pp->disp = 0;
pp->lastref = up->timestamp;
refclock_process_offset(pp, offset,
- up->timestamp, PDELAY);
+ up->timestamp, PDELAY + up->pdelay);
refclock_receive(peer);
}
}
@@ -2122,12 +2106,12 @@ wwv_clock(
/*
- * wwv_corr4 - determine maximum likelihood digit
+ * wwv_corr4 - determine maximum-likelihood digit
*
* This routine correlates the received digit vector with the BCD
* coefficient vectors corresponding to all valid digits at the given
* position in the decoding matrix. The maximum value corresponds to the
- * maximum likelihood digit, while the ratio of this value to the next
+ * maximum-likelihood digit, while the ratio of this value to the next
* lower value determines the likelihood function. Note that, if the
* digit is invalid, the likelihood vector is averaged toward a miss.
*/
@@ -2143,7 +2127,7 @@ wwv_corr4(
struct wwvunit *up;
double topmax, nxtmax; /* metrics */
double acc; /* accumulator */
- char tbuf[80]; /* monitor buffer */
+ char tbuf[TBUF]; /* monitor buffer */
int mldigit; /* max likelihood digit */
int i, j;
@@ -2176,9 +2160,9 @@ wwv_corr4(
vp->digsnr = wwv_snr(topmax, nxtmax);
/*
- * The current maximum likelihood digit is compared to the last
- * maximum likelihood digit. If different, the compare counter
- * and maximum likelihood digit are reset. When the compare
+ * The current maximum-likelihood digit is compared to the last
+ * maximum-likelihood digit. If different, the compare counter
+ * and maximum-likelihood digit are reset. When the compare
* counter reaches the BCMP threshold (3), the digit is assumed
* correct. When the compare counter of all nine digits have
* reached threshold, the clock is assumed correct.
@@ -2188,26 +2172,23 @@ wwv_corr4(
* not considered correct until all nine clock digits have
* reached threshold. This is intended as eye candy, but avoids
* mistakes when the signal is low and the SNR is very marginal.
- * once correctly set, the maximum likelihood digit is ignored
- * on the assumption the clock will always be correct unless for
- * some reason it drifts to a different second.
*/
- vp->mldigit = mldigit;
if (vp->digprb < BTHR || vp->digsnr < BSNR) {
- vp->count = 0;
up->status |= BGATE;
} else {
- up->status |= DSYNC;
if (vp->digit != mldigit) {
- vp->count = 0;
up->alarm |= CMPERR;
- if (!(up->status & INSYNC))
+ if (vp->count > 0)
+ vp->count--;
+ if (vp->count == 0)
vp->digit = mldigit;
} else {
if (vp->count < BCMP)
vp->count++;
- else
+ if (vp->count == BCMP) {
+ up->status |= DSYNC;
up->digcnt++;
+ }
}
}
if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
@@ -2215,7 +2196,7 @@ wwv_corr4(
sprintf(tbuf,
"wwv4 %2d %04x %3d %4d %5.0f %2d %d %d %d %5.0f %5.1f",
up->rsec - 1, up->status, up->gain, up->yepoch,
- up->epomax, vp->radix, vp->digit, vp->mldigit,
+ up->epomax, vp->radix, vp->digit, mldigit,
vp->count, vp->digprb, vp->digsnr);
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
@@ -2326,7 +2307,7 @@ wwv_tsec(
* This routine rotates a likelihood vector one position and increments
* the clock digit modulo the radix. It returns the new clock digit or
* zero if a carry occurred. Once synchronized, the clock digit will
- * match the maximum likelihood digit corresponding to that position.
+ * match the maximum-likelihood digit corresponding to that position.
*/
static int
carry(
@@ -2420,16 +2401,14 @@ wwv_newchan(
struct wwvunit *up;
struct sync *sp, *rp;
double rank, dtemp;
- int i, j;
+ int i, j, rval;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
/*
* Search all five station pairs looking for the channel with
- * maximum metric. If no station is found above thresholds, tune
- * to WWV on 15 MHz, set the reference ID to NONE and wait for
- * hotter ions.
+ * maximum metric.
*/
sp = NULL;
j = 0;
@@ -2453,39 +2432,57 @@ wwv_newchan(
/*
* If the strongest signal is less than the MTHR threshold (13),
- * we are beneath the waves, so squelch the second sync. If the
- * strongest signal is greater than the threshold, tune to that
- * frequency and transmitter QTH.
+ * we are beneath the waves, so squelch the second sync and
+ * advance to the next station. This makes sure all stations are
+ * scanned when the ions grow dim. If the strongest signal is
+ * greater than the threshold, tune to that frequency and
+ * transmitter QTH.
*/
+ up->status &= ~(SELV | SELH);
if (rank < MTHR) {
up->dchan = (up->dchan + 1) % NCHAN;
- up->status &= ~(SELV | SELH);
- return (FALSE);
+ if (up->status & METRIC) {
+ up->status &= ~METRIC;
+ refclock_report(peer, CEVNT_PROP);
+ }
+ rval = FALSE;
+ } else {
+ up->dchan = j;
+ up->sptr = sp;
+ memcpy(&pp->refid, sp->refid, 4);
+ peer->refid = pp->refid;
+ up->status |= METRIC;
+ if (sp->select & SELV) {
+ up->status |= SELV;
+ up->pdelay = pp->fudgetime1;
+ } else if (sp->select & SELH) {
+ up->status |= SELH;
+ up->pdelay = pp->fudgetime2;
+ } else {
+ up->pdelay = 0;
+ }
+ rval = TRUE;
}
- up->dchan = j;
- up->status |= SELV | SELH;
- up->sptr = sp;
- memcpy(&pp->refid, sp->refid, 4);
- peer->refid = pp->refid;
- return (TRUE);
+#ifdef ICOM
+ if (up->fd_icom > 0)
+ wwv_qsy(peer, up->dchan);
+#endif /* ICOM */
+ return (rval);
}
/*
* wwv_newgame - reset and start over
*
- * There are four conditions resulting in a new game:
+ * There are three conditions resulting in a new game:
*
- * 1 During initial acquisition (MSYNC dark) going 6 minutes (ACQSN)
- * without reliably finding the minute pulse (MSYNC lit).
- *
- * 2 After finding the minute pulse (MSYNC lit), going 15 minutes
+ * 1 After finding the minute pulse (MSYNC lit), going 15 minutes
* (DATA) without finding the unit seconds digit.
*
- * 3 After finding good data (DATA lit), going more than 40 minutes
+ * 2 After finding good data (DSYNC lit), going more than 40 minutes
* (SYNCH) without finding station sync (INSYNC lit).
*
- * 4 After finding station sync (INSYNC lit), going more than 2 days
+ * 3 After finding station sync (INSYNC lit), going more than 2 days
* (PANIC) without finding any station.
*/
static void
@@ -2505,6 +2502,8 @@ wwv_newgame(
* Initialize strategic values. Note we set the leap bits
* NOTINSYNC and the refid "NONE".
*/
+ if (up->status)
+ up->errflg = CEVNT_TIMEOUT;
peer->leap = LEAP_NOTINSYNC;
up->watch = up->status = up->alarm = 0;
up->avgint = MINAVG;
@@ -2514,7 +2513,8 @@ wwv_newgame(
/*
* Initialize the station processes for audio gain, select bit,
* station/frequency identifier and reference identifier. Start
- * probing at the next channel after the data channel.
+ * probing at the strongest channel or the default channel if
+ * nothing heard.
*/
memset(up->mitig, 0, sizeof(up->mitig));
for (i = 0; i < NCHAN; i++) {
@@ -2525,13 +2525,9 @@ wwv_newgame(
cp->wwvh.select = SELH;
sprintf(cp->wwvh.refid, "WH%.0f", floor(qsy[i]));
}
- up->dchan = (DCHAN + NCHAN - 1) % NCHAN;;
+ up->dchan = (DCHAN + NCHAN - 1) % NCHAN;
wwv_newchan(peer);
- up->achan = up->schan = up->dchan;
-#ifdef ICOM
- if (up->fd_icom > 0)
- wwv_qsy(peer, up->dchan);
-#endif /* ICOM */
+ up->schan = up->dchan;
}
/*
@@ -2668,7 +2664,8 @@ timecode(
* there are no clips, the gain is bumped up; if there are more than
* MAXCLP clips (100), it is bumped down. The decoder is relatively
* insensitive to amplitude, so this crudity works just peachy. The
- * input port is set and the error flag is cleared, mostly to be ornery.
+ * routine also jiggles the input port and selectively mutes the
+ * monitor.
*/
static void
wwv_gain(
diff --git a/ntpd/refclock_wwvb.c b/ntpd/refclock_wwvb.c
index 7bddd3a375fc..10bb63f6e389 100644
--- a/ntpd/refclock_wwvb.c
+++ b/ntpd/refclock_wwvb.c
@@ -17,6 +17,11 @@
#include <stdio.h>
#include <ctype.h>
+#ifdef HAVE_PPSAPI
+#include "ppsapi_timepps.h"
+#include "refclock_atom.h"
+#endif /* HAVE_PPSAPI */
+
/*
* This driver supports the Spectracom Model 8170 and Netclock/2 WWVB
* Synchronized Clocks and the Netclock/GPS Master Clock. Both the WWVB
@@ -49,7 +54,7 @@
* hh:mm:ss = hours, minutes, seconds
* i = synchronization flag (' ' = in synch, '?' = out of synch)
*
- * The alarm condition is indicated by other than ' ' at a, which occurs
+ * The alarm condition is indicated by other than ' ' at i, which occurs
* during initial synchronization and when received signal is lost for
* about ten hours.
*
@@ -64,7 +69,7 @@
* ddd = day of year
* hh:mm:ss.fff = hours, minutes, seconds, milliseconds
*
- * The alarm condition is indicated by other than ' ' at a, which occurs
+ * The alarm condition is indicated by other than ' ' at i, which occurs
* during initial synchronization and when received signal is lost for
* about ten hours. The unlock condition is indicated by other than ' '
* at q.
@@ -84,6 +89,16 @@
* makes no attempt to correct for the intrinsic jitter of the radio
* itself, which is a known problem with the older radios.
*
+ * PPS Signal Processing
+ *
+ * When PPS signal processing is enabled, and when the system clock has
+ * been set by this or another driver and the PPS signal offset is
+ * within 0.4 s of the system clock offset, the PPS signal replaces the
+ * timecode for as long as the PPS signal is active. If for some reason
+ * the PPS signal fails for one or more poll intervals, the driver
+ * reverts to the timecode. If the timecode fails for one or more poll
+ * intervals, the PPS signal is disconnected.
+ *
* Fudge Factors
*
* This driver can retrieve a table of quality data maintained
@@ -100,20 +115,28 @@
#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 PPS_PRECISION (-13) /* precision assumed (about 100 us) */
#define REFID "WWVB" /* reference ID */
#define DESCRIPTION "Spectracom WWVB/GPS Receiver" /* WRU */
#define LENWWVB0 22 /* format 0 timecode length */
-#define LENWWVB1 22 /* format 1 timecode length */
#define LENWWVB2 24 /* format 2 timecode length */
-#define LENWWVB3 29 /* format 3 timecode length */
+#define LENWWVB3 29 /* format 3 timecode length */
#define MONLIN 15 /* number of monitoring lines */
/*
* WWVB unit control structure
*/
struct wwvbunit {
- l_fp laststamp; /* last receive timestamp */
+#ifdef HAVE_PPSAPI
+ struct refclock_atom atom; /* PPSAPI structure */
+ int ppsapi_tried; /* attempt PPSAPI once */
+ int ppsapi_lit; /* time_pps_create() worked */
+ int tcount; /* timecode sample counter */
+ int pcount; /* PPS sample counter */
+#endif /* HAVE_PPSAPI */
+ l_fp laststamp; /* last <CR> timestamp */
+ int prev_eol_cr; /* was last EOL <CR> (not <LF>)? */
u_char lasthour; /* last hour (for monitor) */
u_char linect; /* count ignored lines (for monitor */
};
@@ -121,11 +144,18 @@ struct wwvbunit {
/*
* Function prototypes
*/
-static int wwvb_start P((int, struct peer *));
-static void wwvb_shutdown P((int, struct peer *));
-static void wwvb_receive P((struct recvbuf *));
-static void wwvb_poll P((int, struct peer *));
-static void wwvb_timer P((int, struct peer *));
+static int wwvb_start (int, struct peer *);
+static void wwvb_shutdown (int, struct peer *);
+static void wwvb_receive (struct recvbuf *);
+static void wwvb_poll (int, struct peer *);
+static void wwvb_timer (int, struct peer *);
+#ifdef HAVE_PPSAPI
+static void wwvb_control (int, const struct refclockstat *,
+ struct refclockstat *, struct peer *);
+#define WWVB_CONTROL wwvb_control
+#else
+#define WWVB_CONTROL noentry
+#endif /* HAVE_PPSAPI */
/*
* Transfer vector
@@ -134,7 +164,7 @@ struct refclock refclock_wwvb = {
wwvb_start, /* start up driver */
wwvb_shutdown, /* shut down driver */
wwvb_poll, /* transmit poll message */
- noentry, /* not used (old wwvb_control) */
+ WWVB_CONTROL, /* fudge set/change notification */
noentry, /* initialize driver (not used) */
noentry, /* not used (old wwvb_buginfo) */
wwvb_timer /* called once per second */
@@ -158,37 +188,34 @@ wwvb_start(
/*
* Open serial port. Use CLK line discipline, if available.
*/
- sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
+ snprintf(device, sizeof(device), DEVICE, unit);
+ fd = refclock_open(device, SPEED232, LDISC_CLK);
+ if (fd <= 0)
return (0);
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct wwvbunit *)
- emalloc(sizeof(struct wwvbunit)))) {
- close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct wwvbunit));
+ up = emalloc_zero(sizeof(*up));
pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
pp->io.clock_recv = wwvb_receive;
- pp->io.srcclock = (caddr_t)peer;
+ pp->io.srcclock = (void *)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
close(fd);
+ pp->io.fd = -1;
free(up);
return (0);
}
+ pp->unitptr = up;
/*
* Initialize miscellaneous variables
*/
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
+ memcpy(&pp->refid, REFID, 4);
return (1);
}
@@ -206,9 +233,11 @@ wwvb_shutdown(
struct refclockproc *pp;
pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
+ up = pp->unitptr;
+ if (-1 != pp->io.fd)
+ io_closeclock(&pp->io);
+ if (NULL != up)
+ free(up);
}
@@ -237,9 +266,9 @@ wwvb_receive(
/*
* Initialize pointers and read the timecode and timestamp
*/
- peer = (struct peer *)rbufp->recv_srcclock;
+ peer = rbufp->recv_peer;
pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
+ up = pp->unitptr;
temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
/*
@@ -251,13 +280,37 @@ wwvb_receive(
* 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.
+ * Save the timestamp of each <CR> in up->laststamp. Lines with
+ * no characters occur for every <LF>, and for some <CR>s when
+ * format 0 is used. Format 0 starts and ends each cycle with a
+ * <CR><LF> pair, format 2 starts each cycle with its only pair.
+ * The preceding <CR> is the on-time character for both formats.
+ * The timestamp provided with non-empty lines corresponds to
+ * the <CR> following the timecode, which is ultimately not used
+ * with format 0 and is used for the following timecode for
+ * format 2.
*/
if (temp == 0) {
- up->laststamp = trtmp;
+ if (up->prev_eol_cr) {
+ DPRINTF(2, ("wwvb: <LF> @ %s\n",
+ prettydate(&trtmp)));
+ } else {
+ up->laststamp = trtmp;
+ DPRINTF(2, ("wwvb: <CR> @ %s\n",
+ prettydate(&trtmp)));
+ }
+ up->prev_eol_cr = !up->prev_eol_cr;
return;
}
pp->lencode = temp;
pp->lastrec = up->laststamp;
+ up->laststamp = trtmp;
+ up->prev_eol_cr = TRUE;
+ DPRINTF(2, ("wwvb: code @ %s\n"
+ " using %s minus one char\n",
+ prettydate(&trtmp), prettydate(&pp->lastrec)));
+ if (L_ISZERO(&pp->lastrec))
+ return;
/*
* We get down to business, check the timecode format and decode
@@ -277,9 +330,11 @@ wwvb_receive(
if (sscanf(pp->a_lastcode,
"%c %3d %2d:%2d:%2d%c%cTZ=%2d",
&syncchar, &pp->day, &pp->hour, &pp->minute,
- &pp->second, &tmpchar, &dstchar, &tz) == 8)
+ &pp->second, &tmpchar, &dstchar, &tz) == 8) {
pp->nsec = 0;
break;
+ }
+ goto bad_format;
case LENWWVB2:
@@ -289,14 +344,19 @@ wwvb_receive(
"%c%c %2d %3d %2d:%2d:%2d.%3ld %c",
&syncchar, &qualchar, &pp->year, &pp->day,
&pp->hour, &pp->minute, &pp->second, &pp->nsec,
- &leapchar) == 9)
+ &leapchar) == 9) {
pp->nsec *= 1000000;
break;
+ }
+ goto bad_format;
case LENWWVB3:
- /*
+ /*
* Timecode format 3: "0003I yyyymmdd hhmmss+0000SL#"
+ * WARNING: Undocumented, and the on-time character # is
+ * not yet handled correctly by this driver. It may be
+ * as simple as compensating for an additional 1/960 s.
*/
if (sscanf(pp->a_lastcode,
"0003%c %4d%2d%2d %2d%2d%2d+0000%c%c",
@@ -307,8 +367,10 @@ wwvb_receive(
pp->nsec = 0;
break;
}
+ goto bad_format;
default:
+ bad_format:
/*
* Unknown format: If dumping internal table, record
@@ -368,12 +430,16 @@ wwvb_receive(
/*
* Process the new sample in the median filter and determine the
- * timecode timestamp.
+ * timecode timestamp, but only if the PPS is not in control.
*/
- if (!refclock_process(pp))
+#ifdef HAVE_PPSAPI
+ up->tcount++;
+ if (peer->flags & FLAG_PPS)
+ return;
+
+#endif /* HAVE_PPSAPI */
+ if (!refclock_process_f(pp, pp->fudgetime2))
refclock_report(peer, CEVNT_BADTIME);
- if (peer->disp > MAXDISTANCE)
- refclock_receive(peer);
}
@@ -389,6 +455,7 @@ wwvb_timer(
register struct wwvbunit *up;
struct refclockproc *pp;
char pollchar; /* character sent to clock */
+ l_fp now;
/*
* Time to poll the clock. The Spectracom clock responds to a
@@ -398,13 +465,26 @@ wwvb_timer(
* the clock; all others just listen in.
*/
pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
+ up = pp->unitptr;
if (up->linect > 0)
pollchar = 'R';
else
pollchar = 'T';
if (write(pp->io.fd, &pollchar, 1) != 1)
refclock_report(peer, CEVNT_FAULT);
+#ifdef DEBUG
+ get_systime(&now);
+ if (debug)
+ printf("%c poll at %s\n", pollchar, prettydate(&now));
+#endif
+#ifdef HAVE_PPSAPI
+ if (up->ppsapi_lit &&
+ refclock_pps(peer, &up->atom, pp->sloppyclockflag) > 0) {
+ up->pcount++,
+ peer->flags |= FLAG_PPS;
+ peer->precision = PPS_PRECISION;
+ }
+#endif /* HAVE_PPSAPI */
}
@@ -425,7 +505,7 @@ wwvb_poll(
* are received, declare a timeout and keep going.
*/
pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
+ up = pp->unitptr;
pp->polls++;
/*
@@ -435,16 +515,29 @@ wwvb_poll(
if (pp->sloppyclockflag & CLK_FLAG4 && pp->hour <
(int)up->lasthour)
up->linect = MONLIN;
- up->lasthour = pp->hour;
+ up->lasthour = (u_char)pp->hour;
/*
* Process median filter samples. If none received, declare a
* timeout and keep going.
*/
+#ifdef HAVE_PPSAPI
+ if (up->pcount == 0) {
+ peer->flags &= ~FLAG_PPS;
+ peer->precision = PRECISION;
+ }
+ if (up->tcount == 0) {
+ pp->coderecv = pp->codeproc;
+ refclock_report(peer, CEVNT_TIMEOUT);
+ return;
+ }
+ up->pcount = up->tcount = 0;
+#else /* HAVE_PPSAPI */
if (pp->coderecv == pp->codeproc) {
refclock_report(peer, CEVNT_TIMEOUT);
return;
}
+#endif /* HAVE_PPSAPI */
refclock_receive(peer);
record_clock_stats(&peer->srcadr, pp->a_lastcode);
#ifdef DEBUG
@@ -454,6 +547,56 @@ wwvb_poll(
#endif
}
+
+/*
+ * wwvb_control - fudge parameters have been set or changed
+ */
+#ifdef HAVE_PPSAPI
+static void
+wwvb_control(
+ int unit,
+ const struct refclockstat *in_st,
+ struct refclockstat *out_st,
+ struct peer *peer
+ )
+{
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = pp->unitptr;
+
+ if (!(pp->sloppyclockflag & CLK_FLAG1)) {
+ if (!up->ppsapi_tried)
+ return;
+ up->ppsapi_tried = 0;
+ if (!up->ppsapi_lit)
+ return;
+ peer->flags &= ~FLAG_PPS;
+ peer->precision = PRECISION;
+ time_pps_destroy(up->atom.handle);
+ up->atom.handle = 0;
+ up->ppsapi_lit = 0;
+ return;
+ }
+
+ if (up->ppsapi_tried)
+ return;
+ /*
+ * Light up the PPSAPI interface.
+ */
+ up->ppsapi_tried = 1;
+ if (refclock_ppsapi(pp->io.fd, &up->atom)) {
+ up->ppsapi_lit = 1;
+ return;
+ }
+
+ NLOG(NLOG_CLOCKINFO)
+ msyslog(LOG_WARNING, "%s flag1 1 but PPSAPI fails",
+ refnumtoa(&peer->srcadr));
+}
+#endif /* HAVE_PPSAPI */
+
#else
int refclock_wwvb_bs;
#endif /* REFCLOCK */
diff --git a/ntpd/refclock_zyfer.c b/ntpd/refclock_zyfer.c
index 44f2c4d35394..ed83b2611fc7 100644
--- a/ntpd/refclock_zyfer.c
+++ b/ntpd/refclock_zyfer.c
@@ -97,10 +97,10 @@ struct zyferunit {
/*
* Function prototypes
*/
-static int zyfer_start P((int, struct peer *));
-static void zyfer_shutdown P((int, struct peer *));
-static void zyfer_receive P((struct recvbuf *));
-static void zyfer_poll P((int, struct peer *));
+static int zyfer_start (int, struct peer *);
+static void zyfer_shutdown (int, struct peer *);
+static void zyfer_receive (struct recvbuf *);
+static void zyfer_poll (int, struct peer *);
/*
* Transfer vector