diff options
Diffstat (limited to 'contrib/ntp/libntp')
73 files changed, 20705 insertions, 0 deletions
diff --git a/contrib/ntp/libntp/Makefile.am b/contrib/ntp/libntp/Makefile.am new file mode 100644 index 000000000000..874739a18846 --- /dev/null +++ b/contrib/ntp/libntp/Makefile.am @@ -0,0 +1,130 @@ +NULL= +BUILT_SOURCES = +CLEANFILES = +noinst_LIBRARIES = libntp.a @MAKE_LIBNTPSIM@ +EXTRA_LIBRARIES = libntpsim.a + +libisc_SRCS = \ + $(srcdir)/../lib/isc/assertions.c \ + $(srcdir)/../lib/isc/buffer.c \ + $(srcdir)/../lib/isc/backtrace-emptytbl.c \ + $(srcdir)/../lib/isc/backtrace.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \ + $(srcdir)/../lib/isc/unix/dir.c \ + $(srcdir)/../lib/isc/error.c \ + $(srcdir)/../lib/isc/unix/errno2result.c \ + $(srcdir)/../lib/isc/event.c \ + $(srcdir)/../lib/isc/unix/file.c \ + $(srcdir)/../lib/isc/inet_ntop.c \ + $(srcdir)/../lib/isc/inet_pton.c \ + $(srcdir)/../lib/isc/unix/interfaceiter.c \ + $(srcdir)/../lib/isc/lib.c \ + $(srcdir)/../lib/isc/log.c \ + $(srcdir)/../lib/isc/md5.c \ + $(srcdir)/../lib/isc/nls/msgcat.c \ + $(srcdir)/../lib/isc/unix/net.c \ + $(srcdir)/../lib/isc/netaddr.c \ + $(srcdir)/../lib/isc/netscope.c \ + $(srcdir)/../lib/isc/ondestroy.c \ + $(srcdir)/../lib/isc/random.c \ + $(srcdir)/../lib/isc/result.c \ + $(srcdir)/../lib/isc/unix/stdio.c \ + $(srcdir)/../lib/isc/unix/stdtime.c \ + $(srcdir)/../lib/isc/unix/strerror.c \ + $(srcdir)/../lib/isc/task.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ + $(srcdir)/../lib/isc/unix/time.c \ + $(srcdir)/../lib/isc/sha1.c \ + $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c \ + $(NULL) + +if PTHREADS +libisc_SRCS += $(srcdir)/../lib/isc/pthreads/mutex.c +endif + +libntp_a_SRCS = \ + a_md5encrypt.c \ + adjtime.c \ + atoint.c \ + atolfp.c \ + atouint.c \ + audio.c \ + authkeys.c \ + authreadkeys.c \ + authusekey.c \ + bsd_strerror.c \ + buftvtots.c \ + caljulian.c \ + caltontp.c \ + calyearstart.c \ + clocktime.c \ + clocktypes.c \ + decodenetnum.c \ + dofptoa.c \ + dolfptoa.c \ + emalloc.c \ + findconfig.c \ + getopt.c \ + hextoint.c \ + hextolfp.c \ + humandate.c \ + icom.c \ + iosignal.c \ + is_ip_address.c \ + lib_strbuf.c \ + libssl_compat.c \ + machines.c \ + mktime.c \ + modetoa.c \ + mstolfp.c \ + msyslog.c \ + netof.c \ + ntp_calendar.c \ + ntp_crypto_rnd.c \ + ntp_intres.c \ + ntp_libopts.c \ + ntp_lineedit.c \ + ntp_random.c \ + ntp_rfc2553.c \ + ntp_worker.c \ + numtoa.c \ + numtohost.c \ + octtoint.c \ + prettydate.c \ + refidsmear.c \ + recvbuff.c \ + refnumtoa.c \ + snprintf.c \ + socket.c \ + socktoa.c \ + socktohost.c \ + ssl_init.c \ + statestr.c \ + strdup.c \ + strl_obsd.c \ + syssignal.c \ + timetoa.c \ + timevalops.c \ + uglydate.c \ + vint64ops.c \ + work_fork.c \ + work_thread.c \ + ymd2yd.c \ + $(libisc_SRCS) \ + $(NULL) + +libntp_a_SOURCES = systime.c $(libntp_a_SRCS) +libntpsim_a_SOURCES = systime_s.c $(libntp_a_SRCS) +EXTRA_libntp_a_SOURCES = adjtimex.c + +AM_CFLAGS = $(CFLAGS_NTP) + +AM_CPPFLAGS = $(NTP_INCS) +AM_CPPFLAGS += $(LIBOPTS_CFLAGS) +AM_CPPFLAGS += $(CPPFLAGS_NTP) + +EXTRA_DIST = README + +include $(top_srcdir)/depsver.mf +include $(top_srcdir)/includes.mf diff --git a/contrib/ntp/libntp/Makefile.in b/contrib/ntp/libntp/Makefile.in new file mode 100644 index 000000000000..46b7926ab3fd --- /dev/null +++ b/contrib/ntp/libntp/Makefile.in @@ -0,0 +1,1636 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@PTHREADS_TRUE@am__append_1 = $(srcdir)/../lib/isc/pthreads/mutex.c +subdir = libntp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/sntp/libopts/m4/libopts.m4 \ + $(top_srcdir)/sntp/libopts/m4/stdnoreturn.m4 \ + $(top_srcdir)/sntp/m4/ax_c99_struct_init.m4 \ + $(top_srcdir)/sntp/m4/define_dir.m4 \ + $(top_srcdir)/sntp/m4/hms_search_lib.m4 \ + $(top_srcdir)/sntp/m4/libtool.m4 \ + $(top_srcdir)/sntp/m4/ltoptions.m4 \ + $(top_srcdir)/sntp/m4/ltsugar.m4 \ + $(top_srcdir)/sntp/m4/ltversion.m4 \ + $(top_srcdir)/sntp/m4/lt~obsolete.m4 \ + $(top_srcdir)/sntp/m4/ntp_cacheversion.m4 \ + $(top_srcdir)/sntp/m4/ntp_compiler.m4 \ + $(top_srcdir)/sntp/m4/ntp_crosscompile.m4 \ + $(top_srcdir)/sntp/m4/ntp_crypto_rand.m4 \ + $(top_srcdir)/sntp/m4/ntp_debug.m4 \ + $(top_srcdir)/sntp/m4/ntp_dir_sep.m4 \ + $(top_srcdir)/sntp/m4/ntp_facilitynames.m4 \ + $(top_srcdir)/sntp/m4/ntp_googletest.m4 \ + $(top_srcdir)/sntp/m4/ntp_ipv6.m4 \ + $(top_srcdir)/sntp/m4/ntp_lib_m.m4 \ + $(top_srcdir)/sntp/m4/ntp_libevent.m4 \ + $(top_srcdir)/sntp/m4/ntp_libntp.m4 \ + $(top_srcdir)/sntp/m4/ntp_lineeditlibs.m4 \ + $(top_srcdir)/sntp/m4/ntp_locinfo.m4 \ + $(top_srcdir)/sntp/m4/ntp_openssl.m4 \ + $(top_srcdir)/sntp/m4/ntp_pkg_config.m4 \ + $(top_srcdir)/sntp/m4/ntp_problemtests.m4 \ + $(top_srcdir)/sntp/m4/ntp_prog_cc.m4 \ + $(top_srcdir)/sntp/m4/ntp_rlimit.m4 \ + $(top_srcdir)/sntp/m4/ntp_sntp.m4 \ + $(top_srcdir)/sntp/m4/ntp_unitytest.m4 \ + $(top_srcdir)/sntp/m4/ntp_ver_suffix.m4 \ + $(top_srcdir)/sntp/m4/ntp_vpathhack.m4 \ + $(top_srcdir)/sntp/m4/openldap-thread-check.m4 \ + $(top_srcdir)/sntp/m4/openldap.m4 \ + $(top_srcdir)/sntp/m4/os_cflags.m4 \ + $(top_srcdir)/sntp/m4/snprintf.m4 \ + $(top_srcdir)/sntp/m4/version.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = @ARFLAGS@ +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libntp_a_AR = $(AR) $(ARFLAGS) +libntp_a_LIBADD = +am__libntp_a_SOURCES_DIST = systime.c a_md5encrypt.c adjtime.c \ + atoint.c atolfp.c atouint.c audio.c authkeys.c authreadkeys.c \ + authusekey.c bsd_strerror.c buftvtots.c caljulian.c caltontp.c \ + calyearstart.c clocktime.c clocktypes.c decodenetnum.c \ + dofptoa.c dolfptoa.c emalloc.c findconfig.c getopt.c \ + hextoint.c hextolfp.c humandate.c icom.c iosignal.c \ + is_ip_address.c lib_strbuf.c libssl_compat.c machines.c \ + mktime.c modetoa.c mstolfp.c msyslog.c netof.c ntp_calendar.c \ + ntp_crypto_rnd.c ntp_intres.c ntp_libopts.c ntp_lineedit.c \ + ntp_random.c ntp_rfc2553.c ntp_worker.c numtoa.c numtohost.c \ + octtoint.c prettydate.c refidsmear.c recvbuff.c refnumtoa.c \ + snprintf.c socket.c socktoa.c socktohost.c ssl_init.c \ + statestr.c strdup.c strl_obsd.c syssignal.c timetoa.c \ + timevalops.c uglydate.c vint64ops.c work_fork.c work_thread.c \ + ymd2yd.c $(srcdir)/../lib/isc/assertions.c \ + $(srcdir)/../lib/isc/buffer.c \ + $(srcdir)/../lib/isc/backtrace-emptytbl.c \ + $(srcdir)/../lib/isc/backtrace.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \ + $(srcdir)/../lib/isc/unix/dir.c $(srcdir)/../lib/isc/error.c \ + $(srcdir)/../lib/isc/unix/errno2result.c \ + $(srcdir)/../lib/isc/event.c $(srcdir)/../lib/isc/unix/file.c \ + $(srcdir)/../lib/isc/inet_ntop.c \ + $(srcdir)/../lib/isc/inet_pton.c \ + $(srcdir)/../lib/isc/unix/interfaceiter.c \ + $(srcdir)/../lib/isc/lib.c $(srcdir)/../lib/isc/log.c \ + $(srcdir)/../lib/isc/md5.c $(srcdir)/../lib/isc/nls/msgcat.c \ + $(srcdir)/../lib/isc/unix/net.c $(srcdir)/../lib/isc/netaddr.c \ + $(srcdir)/../lib/isc/netscope.c \ + $(srcdir)/../lib/isc/ondestroy.c $(srcdir)/../lib/isc/random.c \ + $(srcdir)/../lib/isc/result.c \ + $(srcdir)/../lib/isc/unix/stdio.c \ + $(srcdir)/../lib/isc/unix/stdtime.c \ + $(srcdir)/../lib/isc/unix/strerror.c \ + $(srcdir)/../lib/isc/task.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ + $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \ + $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c \ + $(srcdir)/../lib/isc/pthreads/mutex.c +am__objects_1 = +@PTHREADS_TRUE@am__objects_2 = mutex.$(OBJEXT) +am__objects_3 = assertions.$(OBJEXT) buffer.$(OBJEXT) \ + backtrace-emptytbl.$(OBJEXT) backtrace.$(OBJEXT) \ + condition.$(OBJEXT) dir.$(OBJEXT) error.$(OBJEXT) \ + errno2result.$(OBJEXT) event.$(OBJEXT) file.$(OBJEXT) \ + inet_ntop.$(OBJEXT) inet_pton.$(OBJEXT) \ + interfaceiter.$(OBJEXT) lib.$(OBJEXT) log.$(OBJEXT) \ + md5.$(OBJEXT) msgcat.$(OBJEXT) net.$(OBJEXT) netaddr.$(OBJEXT) \ + netscope.$(OBJEXT) ondestroy.$(OBJEXT) random.$(OBJEXT) \ + result.$(OBJEXT) stdio.$(OBJEXT) stdtime.$(OBJEXT) \ + strerror.$(OBJEXT) task.$(OBJEXT) thread.$(OBJEXT) \ + time.$(OBJEXT) sha1.$(OBJEXT) sockaddr.$(OBJEXT) \ + tsmemcmp.$(OBJEXT) $(am__objects_1) $(am__objects_2) +am__objects_4 = a_md5encrypt.$(OBJEXT) adjtime.$(OBJEXT) \ + atoint.$(OBJEXT) atolfp.$(OBJEXT) atouint.$(OBJEXT) \ + audio.$(OBJEXT) authkeys.$(OBJEXT) authreadkeys.$(OBJEXT) \ + authusekey.$(OBJEXT) bsd_strerror.$(OBJEXT) \ + buftvtots.$(OBJEXT) caljulian.$(OBJEXT) caltontp.$(OBJEXT) \ + calyearstart.$(OBJEXT) clocktime.$(OBJEXT) \ + clocktypes.$(OBJEXT) decodenetnum.$(OBJEXT) dofptoa.$(OBJEXT) \ + dolfptoa.$(OBJEXT) emalloc.$(OBJEXT) findconfig.$(OBJEXT) \ + getopt.$(OBJEXT) hextoint.$(OBJEXT) hextolfp.$(OBJEXT) \ + humandate.$(OBJEXT) icom.$(OBJEXT) iosignal.$(OBJEXT) \ + is_ip_address.$(OBJEXT) lib_strbuf.$(OBJEXT) \ + libssl_compat.$(OBJEXT) machines.$(OBJEXT) mktime.$(OBJEXT) \ + modetoa.$(OBJEXT) mstolfp.$(OBJEXT) msyslog.$(OBJEXT) \ + netof.$(OBJEXT) ntp_calendar.$(OBJEXT) \ + ntp_crypto_rnd.$(OBJEXT) ntp_intres.$(OBJEXT) \ + ntp_libopts.$(OBJEXT) ntp_lineedit.$(OBJEXT) \ + ntp_random.$(OBJEXT) ntp_rfc2553.$(OBJEXT) \ + ntp_worker.$(OBJEXT) numtoa.$(OBJEXT) numtohost.$(OBJEXT) \ + octtoint.$(OBJEXT) prettydate.$(OBJEXT) refidsmear.$(OBJEXT) \ + recvbuff.$(OBJEXT) refnumtoa.$(OBJEXT) snprintf.$(OBJEXT) \ + socket.$(OBJEXT) socktoa.$(OBJEXT) socktohost.$(OBJEXT) \ + ssl_init.$(OBJEXT) statestr.$(OBJEXT) strdup.$(OBJEXT) \ + strl_obsd.$(OBJEXT) syssignal.$(OBJEXT) timetoa.$(OBJEXT) \ + timevalops.$(OBJEXT) uglydate.$(OBJEXT) vint64ops.$(OBJEXT) \ + work_fork.$(OBJEXT) work_thread.$(OBJEXT) ymd2yd.$(OBJEXT) \ + $(am__objects_3) $(am__objects_1) +am_libntp_a_OBJECTS = systime.$(OBJEXT) $(am__objects_4) +libntp_a_OBJECTS = $(am_libntp_a_OBJECTS) +libntpsim_a_AR = $(AR) $(ARFLAGS) +libntpsim_a_LIBADD = +am__libntpsim_a_SOURCES_DIST = systime_s.c a_md5encrypt.c adjtime.c \ + atoint.c atolfp.c atouint.c audio.c authkeys.c authreadkeys.c \ + authusekey.c bsd_strerror.c buftvtots.c caljulian.c caltontp.c \ + calyearstart.c clocktime.c clocktypes.c decodenetnum.c \ + dofptoa.c dolfptoa.c emalloc.c findconfig.c getopt.c \ + hextoint.c hextolfp.c humandate.c icom.c iosignal.c \ + is_ip_address.c lib_strbuf.c libssl_compat.c machines.c \ + mktime.c modetoa.c mstolfp.c msyslog.c netof.c ntp_calendar.c \ + ntp_crypto_rnd.c ntp_intres.c ntp_libopts.c ntp_lineedit.c \ + ntp_random.c ntp_rfc2553.c ntp_worker.c numtoa.c numtohost.c \ + octtoint.c prettydate.c refidsmear.c recvbuff.c refnumtoa.c \ + snprintf.c socket.c socktoa.c socktohost.c ssl_init.c \ + statestr.c strdup.c strl_obsd.c syssignal.c timetoa.c \ + timevalops.c uglydate.c vint64ops.c work_fork.c work_thread.c \ + ymd2yd.c $(srcdir)/../lib/isc/assertions.c \ + $(srcdir)/../lib/isc/buffer.c \ + $(srcdir)/../lib/isc/backtrace-emptytbl.c \ + $(srcdir)/../lib/isc/backtrace.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \ + $(srcdir)/../lib/isc/unix/dir.c $(srcdir)/../lib/isc/error.c \ + $(srcdir)/../lib/isc/unix/errno2result.c \ + $(srcdir)/../lib/isc/event.c $(srcdir)/../lib/isc/unix/file.c \ + $(srcdir)/../lib/isc/inet_ntop.c \ + $(srcdir)/../lib/isc/inet_pton.c \ + $(srcdir)/../lib/isc/unix/interfaceiter.c \ + $(srcdir)/../lib/isc/lib.c $(srcdir)/../lib/isc/log.c \ + $(srcdir)/../lib/isc/md5.c $(srcdir)/../lib/isc/nls/msgcat.c \ + $(srcdir)/../lib/isc/unix/net.c $(srcdir)/../lib/isc/netaddr.c \ + $(srcdir)/../lib/isc/netscope.c \ + $(srcdir)/../lib/isc/ondestroy.c $(srcdir)/../lib/isc/random.c \ + $(srcdir)/../lib/isc/result.c \ + $(srcdir)/../lib/isc/unix/stdio.c \ + $(srcdir)/../lib/isc/unix/stdtime.c \ + $(srcdir)/../lib/isc/unix/strerror.c \ + $(srcdir)/../lib/isc/task.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ + $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \ + $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c \ + $(srcdir)/../lib/isc/pthreads/mutex.c +am_libntpsim_a_OBJECTS = systime_s.$(OBJEXT) $(am__objects_4) +libntpsim_a_OBJECTS = $(am_libntpsim_a_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/sntp/libevent/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libntp_a_SOURCES) $(EXTRA_libntp_a_SOURCES) \ + $(libntpsim_a_SOURCES) +DIST_SOURCES = $(am__libntp_a_SOURCES_DIST) $(EXTRA_libntp_a_SOURCES) \ + $(am__libntpsim_a_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depsver.mf \ + $(top_srcdir)/includes.mf \ + $(top_srcdir)/sntp/libevent/build-aux/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_THREAD = @BUILD_THREAD@ +CALC_TICKADJ_DB = @CALC_TICKADJ_DB@ +CALC_TICKADJ_DL = @CALC_TICKADJ_DL@ +CALC_TICKADJ_DS = @CALC_TICKADJ_DS@ +CALC_TICKADJ_MS = @CALC_TICKADJ_MS@ +CALC_TICKADJ_NI = @CALC_TICKADJ_NI@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAGS_LIBEVENT = @CFLAGS_LIBEVENT@ +CFLAGS_NTP = @CFLAGS_NTP@ +CHUTEST = @CHUTEST@ +CONFIG_SHELL = @CONFIG_SHELL@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_LIBEVENT = @CPPFLAGS_LIBEVENT@ +CPPFLAGS_NTP = @CPPFLAGS_NTP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DCFD = @DCFD@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EDITLINE_LIBS = @EDITLINE_LIBS@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_CPPFLAGS = @GTEST_CPPFLAGS@ +GTEST_CXXFLAGS = @GTEST_CXXFLAGS@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_LIBS = @GTEST_LIBS@ +HAVE_INLINE = @HAVE_INLINE@ +HAVE_LEAPSMEARINTERVAL = @HAVE_LEAPSMEARINTERVAL@ +HAVE_RLIMIT_MEMLOCK = @HAVE_RLIMIT_MEMLOCK@ +HAVE_RLIMIT_STACK = @HAVE_RLIMIT_STACK@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDADD_LIBEVENT = @LDADD_LIBEVENT@ +LDADD_LIBNTP = @LDADD_LIBNTP@ +LDADD_LIBUTIL = @LDADD_LIBUTIL@ +LDADD_NLIST = @LDADD_NLIST@ +LDADD_NTP = @LDADD_NTP@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_NTP = @LDFLAGS_NTP@ +LIBISC_PTHREADS_NOTHREADS = @LIBISC_PTHREADS_NOTHREADS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBOPTS_CFLAGS = @LIBOPTS_CFLAGS@ +LIBOPTS_DIR = @LIBOPTS_DIR@ +LIBOPTS_LDADD = @LIBOPTS_LDADD@ +LIBPARSE = @LIBPARSE@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LSCF = @LSCF@ +LTHREAD_LIBS = @LTHREAD_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MAKE_ADJTIMED = @MAKE_ADJTIMED@ +MAKE_CHECK_LAYOUT = @MAKE_CHECK_LAYOUT@ +MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@ +MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@ +MAKE_LIBPARSE = @MAKE_LIBPARSE@ +MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@ +MAKE_NTPDSIM = @MAKE_NTPDSIM@ +MAKE_NTPSNMPD = @MAKE_NTPSNMPD@ +MAKE_NTPTIME = @MAKE_NTPTIME@ +MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@ +MAKE_TICKADJ = @MAKE_TICKADJ@ +MAKE_TIMETRIM = @MAKE_TIMETRIM@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANTAGFMT = @MANTAGFMT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NTPDATE_DB = @NTPDATE_DB@ +NTPDATE_DL = @NTPDATE_DL@ +NTPDATE_DS = @NTPDATE_DS@ +NTPDATE_MS = @NTPDATE_MS@ +NTPDATE_NI = @NTPDATE_NI@ +NTPDC_DB = @NTPDC_DB@ +NTPDC_DL = @NTPDC_DL@ +NTPDC_DS = @NTPDC_DS@ +NTPDC_MS = @NTPDC_MS@ +NTPDC_NI = @NTPDC_NI@ +NTPDSIM_DB = @NTPDSIM_DB@ +NTPDSIM_DL = @NTPDSIM_DL@ +NTPDSIM_DS = @NTPDSIM_DS@ +NTPDSIM_MS = @NTPDSIM_MS@ +NTPDSIM_NI = @NTPDSIM_NI@ +NTPD_DB = @NTPD_DB@ +NTPD_DL = @NTPD_DL@ +NTPD_DS = @NTPD_DS@ +NTPD_MS = @NTPD_MS@ +NTPD_NI = @NTPD_NI@ +NTPQ_DB = @NTPQ_DB@ +NTPQ_DL = @NTPQ_DL@ +NTPQ_DS = @NTPQ_DS@ +NTPQ_MS = @NTPQ_MS@ +NTPQ_NI = @NTPQ_NI@ +NTPSNMPD_DB = @NTPSNMPD_DB@ +NTPSNMPD_DL = @NTPSNMPD_DL@ +NTPSNMPD_DS = @NTPSNMPD_DS@ +NTPSNMPD_MS = @NTPSNMPD_MS@ +NTPSNMPD_NI = @NTPSNMPD_NI@ +NTPSWEEP_DB = @NTPSWEEP_DB@ +NTPSWEEP_DL = @NTPSWEEP_DL@ +NTPSWEEP_DS = @NTPSWEEP_DS@ +NTPSWEEP_MS = @NTPSWEEP_MS@ +NTPSWEEP_NI = @NTPSWEEP_NI@ +NTPTIME_DB = @NTPTIME_DB@ +NTPTIME_DL = @NTPTIME_DL@ +NTPTIME_DS = @NTPTIME_DS@ +NTPTIME_MS = @NTPTIME_MS@ +NTPTIME_NI = @NTPTIME_NI@ +NTPTRACE_DB = @NTPTRACE_DB@ +NTPTRACE_DL = @NTPTRACE_DL@ +NTPTRACE_DS = @NTPTRACE_DS@ +NTPTRACE_MS = @NTPTRACE_MS@ +NTPTRACE_NI = @NTPTRACE_NI@ +NTP_KEYGEN_DB = @NTP_KEYGEN_DB@ +NTP_KEYGEN_DL = @NTP_KEYGEN_DL@ +NTP_KEYGEN_DS = @NTP_KEYGEN_DS@ +NTP_KEYGEN_MS = @NTP_KEYGEN_MS@ +NTP_KEYGEN_NI = @NTP_KEYGEN_NI@ +NTP_KEYSDIR = @NTP_KEYSDIR@ +NTP_WAIT_DB = @NTP_WAIT_DB@ +NTP_WAIT_DL = @NTP_WAIT_DL@ +NTP_WAIT_DS = @NTP_WAIT_DS@ +NTP_WAIT_MS = @NTP_WAIT_MS@ +NTP_WAIT_NI = @NTP_WAIT_NI@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +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_RUBY = @PATH_RUBY@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PATH_TEST = @PATH_TEST@ +PERLLIBDIR = @PERLLIBDIR@ +PKG_CONFIG = @PKG_CONFIG@ +POSIX_SHELL = @POSIX_SHELL@ +PROPDELAY = @PROPDELAY@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNMP_CFLAGS = @SNMP_CFLAGS@ +SNMP_CPPFLAGS = @SNMP_CPPFLAGS@ +SNMP_LIBS = @SNMP_LIBS@ +SNTP = @SNTP@ +SNTP_DB = @SNTP_DB@ +SNTP_DL = @SNTP_DL@ +SNTP_DS = @SNTP_DS@ +SNTP_MS = @SNTP_MS@ +SNTP_NI = @SNTP_NI@ +STDNORETURN_H = @STDNORETURN_H@ +STRIP = @STRIP@ +TESTDCF = @TESTDCF@ +TICKADJ_DB = @TICKADJ_DB@ +TICKADJ_DL = @TICKADJ_DL@ +TICKADJ_DS = @TICKADJ_DS@ +TICKADJ_MS = @TICKADJ_MS@ +TICKADJ_NI = @TICKADJ_NI@ +TIMETRIM_DB = @TIMETRIM_DB@ +TIMETRIM_DL = @TIMETRIM_DL@ +TIMETRIM_DS = @TIMETRIM_DS@ +TIMETRIM_MS = @TIMETRIM_MS@ +TIMETRIM_NI = @TIMETRIM_NI@ +UPDATE_LEAP_DB = @UPDATE_LEAP_DB@ +UPDATE_LEAP_DL = @UPDATE_LEAP_DL@ +UPDATE_LEAP_DS = @UPDATE_LEAP_DS@ +UPDATE_LEAP_MS = @UPDATE_LEAP_MS@ +UPDATE_LEAP_NI = @UPDATE_LEAP_NI@ +VERSION = @VERSION@ +VER_SUFFIX = @VER_SUFFIX@ +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_CXX = @ac_ct_CXX@ +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 = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +BUILT_SOURCES = .deps-ver +CLEANFILES = .deps-ver +noinst_LIBRARIES = libntp.a @MAKE_LIBNTPSIM@ +EXTRA_LIBRARIES = libntpsim.a +libisc_SRCS = $(srcdir)/../lib/isc/assertions.c \ + $(srcdir)/../lib/isc/buffer.c \ + $(srcdir)/../lib/isc/backtrace-emptytbl.c \ + $(srcdir)/../lib/isc/backtrace.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \ + $(srcdir)/../lib/isc/unix/dir.c $(srcdir)/../lib/isc/error.c \ + $(srcdir)/../lib/isc/unix/errno2result.c \ + $(srcdir)/../lib/isc/event.c $(srcdir)/../lib/isc/unix/file.c \ + $(srcdir)/../lib/isc/inet_ntop.c \ + $(srcdir)/../lib/isc/inet_pton.c \ + $(srcdir)/../lib/isc/unix/interfaceiter.c \ + $(srcdir)/../lib/isc/lib.c $(srcdir)/../lib/isc/log.c \ + $(srcdir)/../lib/isc/md5.c $(srcdir)/../lib/isc/nls/msgcat.c \ + $(srcdir)/../lib/isc/unix/net.c $(srcdir)/../lib/isc/netaddr.c \ + $(srcdir)/../lib/isc/netscope.c \ + $(srcdir)/../lib/isc/ondestroy.c $(srcdir)/../lib/isc/random.c \ + $(srcdir)/../lib/isc/result.c \ + $(srcdir)/../lib/isc/unix/stdio.c \ + $(srcdir)/../lib/isc/unix/stdtime.c \ + $(srcdir)/../lib/isc/unix/strerror.c \ + $(srcdir)/../lib/isc/task.c \ + $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ + $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \ + $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c $(NULL) $(am__append_1) +libntp_a_SRCS = \ + a_md5encrypt.c \ + adjtime.c \ + atoint.c \ + atolfp.c \ + atouint.c \ + audio.c \ + authkeys.c \ + authreadkeys.c \ + authusekey.c \ + bsd_strerror.c \ + buftvtots.c \ + caljulian.c \ + caltontp.c \ + calyearstart.c \ + clocktime.c \ + clocktypes.c \ + decodenetnum.c \ + dofptoa.c \ + dolfptoa.c \ + emalloc.c \ + findconfig.c \ + getopt.c \ + hextoint.c \ + hextolfp.c \ + humandate.c \ + icom.c \ + iosignal.c \ + is_ip_address.c \ + lib_strbuf.c \ + libssl_compat.c \ + machines.c \ + mktime.c \ + modetoa.c \ + mstolfp.c \ + msyslog.c \ + netof.c \ + ntp_calendar.c \ + ntp_crypto_rnd.c \ + ntp_intres.c \ + ntp_libopts.c \ + ntp_lineedit.c \ + ntp_random.c \ + ntp_rfc2553.c \ + ntp_worker.c \ + numtoa.c \ + numtohost.c \ + octtoint.c \ + prettydate.c \ + refidsmear.c \ + recvbuff.c \ + refnumtoa.c \ + snprintf.c \ + socket.c \ + socktoa.c \ + socktohost.c \ + ssl_init.c \ + statestr.c \ + strdup.c \ + strl_obsd.c \ + syssignal.c \ + timetoa.c \ + timevalops.c \ + uglydate.c \ + vint64ops.c \ + work_fork.c \ + work_thread.c \ + ymd2yd.c \ + $(libisc_SRCS) \ + $(NULL) + +libntp_a_SOURCES = systime.c $(libntp_a_SRCS) +libntpsim_a_SOURCES = systime_s.c $(libntp_a_SRCS) +EXTRA_libntp_a_SOURCES = adjtimex.c +AM_CFLAGS = $(CFLAGS_NTP) +AM_CPPFLAGS = $(NTP_INCS) $(LIBOPTS_CFLAGS) $(CPPFLAGS_NTP) +EXTRA_DIST = README +NTP_INCS = -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \ + -I$(top_srcdir)/lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/include \ + -I$(top_srcdir)/lib/isc/unix/include +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/depsver.mf $(top_srcdir)/includes.mf $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libntp/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libntp/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/depsver.mf $(top_srcdir)/includes.mf $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libntp.a: $(libntp_a_OBJECTS) $(libntp_a_DEPENDENCIES) $(EXTRA_libntp_a_DEPENDENCIES) + $(AM_V_at)-rm -f libntp.a + $(AM_V_AR)$(libntp_a_AR) libntp.a $(libntp_a_OBJECTS) $(libntp_a_LIBADD) + $(AM_V_at)$(RANLIB) libntp.a + +libntpsim.a: $(libntpsim_a_OBJECTS) $(libntpsim_a_DEPENDENCIES) $(EXTRA_libntpsim_a_DEPENDENCIES) + $(AM_V_at)-rm -f libntpsim.a + $(AM_V_AR)$(libntpsim_a_AR) libntpsim.a $(libntpsim_a_OBJECTS) $(libntpsim_a_LIBADD) + $(AM_V_at)$(RANLIB) libntpsim.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a_md5encrypt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adjtime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adjtimex.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assertions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atolfp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atouint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authkeys.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authreadkeys.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authusekey.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace-emptytbl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsd_strerror.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buftvtots.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caljulian.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caltontp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calyearstart.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clocktime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clocktypes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/condition.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decodenetnum.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dofptoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dolfptoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emalloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errno2result.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findconfig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hextoint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hextolfp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/humandate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icom.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_pton.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interfaceiter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iosignal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/is_ip_address.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_strbuf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libssl_compat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/machines.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modetoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msgcat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mstolfp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msyslog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mutex.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netaddr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netof.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netscope.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_calendar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_crypto_rnd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_intres.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_libopts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_lineedit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_random.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_rfc2553.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_worker.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numtoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numtohost.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/octtoint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ondestroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prettydate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recvbuff.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refidsmear.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refnumtoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/result.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockaddr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socktoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socktohost.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl_init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statestr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdtime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strdup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strl_obsd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syssignal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/systime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/systime_s.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timetoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timevalops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsmemcmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uglydate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vint64ops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work_fork.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work_thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ymd2yd.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +assertions.o: $(srcdir)/../lib/isc/assertions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT assertions.o -MD -MP -MF $(DEPDIR)/assertions.Tpo -c -o assertions.o `test -f '$(srcdir)/../lib/isc/assertions.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/assertions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/assertions.Tpo $(DEPDIR)/assertions.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/assertions.c' object='assertions.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o assertions.o `test -f '$(srcdir)/../lib/isc/assertions.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/assertions.c + +assertions.obj: $(srcdir)/../lib/isc/assertions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT assertions.obj -MD -MP -MF $(DEPDIR)/assertions.Tpo -c -o assertions.obj `if test -f '$(srcdir)/../lib/isc/assertions.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/assertions.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/assertions.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/assertions.Tpo $(DEPDIR)/assertions.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/assertions.c' object='assertions.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o assertions.obj `if test -f '$(srcdir)/../lib/isc/assertions.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/assertions.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/assertions.c'; fi` + +buffer.o: $(srcdir)/../lib/isc/buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT buffer.o -MD -MP -MF $(DEPDIR)/buffer.Tpo -c -o buffer.o `test -f '$(srcdir)/../lib/isc/buffer.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/buffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer.Tpo $(DEPDIR)/buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/buffer.c' object='buffer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.o `test -f '$(srcdir)/../lib/isc/buffer.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/buffer.c + +buffer.obj: $(srcdir)/../lib/isc/buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT buffer.obj -MD -MP -MF $(DEPDIR)/buffer.Tpo -c -o buffer.obj `if test -f '$(srcdir)/../lib/isc/buffer.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/buffer.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/buffer.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer.Tpo $(DEPDIR)/buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/buffer.c' object='buffer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.obj `if test -f '$(srcdir)/../lib/isc/buffer.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/buffer.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/buffer.c'; fi` + +backtrace-emptytbl.o: $(srcdir)/../lib/isc/backtrace-emptytbl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace-emptytbl.o -MD -MP -MF $(DEPDIR)/backtrace-emptytbl.Tpo -c -o backtrace-emptytbl.o `test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace-emptytbl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace-emptytbl.Tpo $(DEPDIR)/backtrace-emptytbl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/backtrace-emptytbl.c' object='backtrace-emptytbl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace-emptytbl.o `test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace-emptytbl.c + +backtrace-emptytbl.obj: $(srcdir)/../lib/isc/backtrace-emptytbl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace-emptytbl.obj -MD -MP -MF $(DEPDIR)/backtrace-emptytbl.Tpo -c -o backtrace-emptytbl.obj `if test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace-emptytbl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace-emptytbl.Tpo $(DEPDIR)/backtrace-emptytbl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/backtrace-emptytbl.c' object='backtrace-emptytbl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace-emptytbl.obj `if test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace-emptytbl.c'; fi` + +backtrace.o: $(srcdir)/../lib/isc/backtrace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.o -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.o `test -f '$(srcdir)/../lib/isc/backtrace.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/backtrace.c' object='backtrace.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.o `test -f '$(srcdir)/../lib/isc/backtrace.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace.c + +backtrace.obj: $(srcdir)/../lib/isc/backtrace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.obj -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.obj `if test -f '$(srcdir)/../lib/isc/backtrace.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/backtrace.c' object='backtrace.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.obj `if test -f '$(srcdir)/../lib/isc/backtrace.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace.c'; fi` + +condition.o: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT condition.o -MD -MP -MF $(DEPDIR)/condition.Tpo -c -o condition.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/condition.Tpo $(DEPDIR)/condition.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' object='condition.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o condition.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c + +condition.obj: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT condition.obj -MD -MP -MF $(DEPDIR)/condition.Tpo -c -o condition.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/condition.Tpo $(DEPDIR)/condition.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' object='condition.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o condition.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; fi` + +dir.o: $(srcdir)/../lib/isc/unix/dir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dir.o -MD -MP -MF $(DEPDIR)/dir.Tpo -c -o dir.o `test -f '$(srcdir)/../lib/isc/unix/dir.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/dir.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dir.Tpo $(DEPDIR)/dir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/dir.c' object='dir.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dir.o `test -f '$(srcdir)/../lib/isc/unix/dir.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/dir.c + +dir.obj: $(srcdir)/../lib/isc/unix/dir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dir.obj -MD -MP -MF $(DEPDIR)/dir.Tpo -c -o dir.obj `if test -f '$(srcdir)/../lib/isc/unix/dir.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/dir.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/dir.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dir.Tpo $(DEPDIR)/dir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/dir.c' object='dir.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dir.obj `if test -f '$(srcdir)/../lib/isc/unix/dir.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/dir.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/dir.c'; fi` + +error.o: $(srcdir)/../lib/isc/error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT error.o -MD -MP -MF $(DEPDIR)/error.Tpo -c -o error.o `test -f '$(srcdir)/../lib/isc/error.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/error.Tpo $(DEPDIR)/error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/error.c' object='error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o error.o `test -f '$(srcdir)/../lib/isc/error.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/error.c + +error.obj: $(srcdir)/../lib/isc/error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT error.obj -MD -MP -MF $(DEPDIR)/error.Tpo -c -o error.obj `if test -f '$(srcdir)/../lib/isc/error.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/error.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/error.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/error.Tpo $(DEPDIR)/error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/error.c' object='error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o error.obj `if test -f '$(srcdir)/../lib/isc/error.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/error.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/error.c'; fi` + +errno2result.o: $(srcdir)/../lib/isc/unix/errno2result.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errno2result.o -MD -MP -MF $(DEPDIR)/errno2result.Tpo -c -o errno2result.o `test -f '$(srcdir)/../lib/isc/unix/errno2result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/errno2result.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/errno2result.Tpo $(DEPDIR)/errno2result.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/errno2result.c' object='errno2result.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errno2result.o `test -f '$(srcdir)/../lib/isc/unix/errno2result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/errno2result.c + +errno2result.obj: $(srcdir)/../lib/isc/unix/errno2result.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errno2result.obj -MD -MP -MF $(DEPDIR)/errno2result.Tpo -c -o errno2result.obj `if test -f '$(srcdir)/../lib/isc/unix/errno2result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/errno2result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/errno2result.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/errno2result.Tpo $(DEPDIR)/errno2result.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/errno2result.c' object='errno2result.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errno2result.obj `if test -f '$(srcdir)/../lib/isc/unix/errno2result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/errno2result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/errno2result.c'; fi` + +event.o: $(srcdir)/../lib/isc/event.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT event.o -MD -MP -MF $(DEPDIR)/event.Tpo -c -o event.o `test -f '$(srcdir)/../lib/isc/event.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/event.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/event.Tpo $(DEPDIR)/event.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/event.c' object='event.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o event.o `test -f '$(srcdir)/../lib/isc/event.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/event.c + +event.obj: $(srcdir)/../lib/isc/event.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT event.obj -MD -MP -MF $(DEPDIR)/event.Tpo -c -o event.obj `if test -f '$(srcdir)/../lib/isc/event.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/event.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/event.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/event.Tpo $(DEPDIR)/event.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/event.c' object='event.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o event.obj `if test -f '$(srcdir)/../lib/isc/event.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/event.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/event.c'; fi` + +file.o: $(srcdir)/../lib/isc/unix/file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.o -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.o `test -f '$(srcdir)/../lib/isc/unix/file.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/file.c' object='file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.o `test -f '$(srcdir)/../lib/isc/unix/file.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/file.c + +file.obj: $(srcdir)/../lib/isc/unix/file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.obj -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.obj `if test -f '$(srcdir)/../lib/isc/unix/file.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/file.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/file.c' object='file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.obj `if test -f '$(srcdir)/../lib/isc/unix/file.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/file.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/file.c'; fi` + +inet_ntop.o: $(srcdir)/../lib/isc/inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_ntop.o -MD -MP -MF $(DEPDIR)/inet_ntop.Tpo -c -o inet_ntop.o `test -f '$(srcdir)/../lib/isc/inet_ntop.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_ntop.Tpo $(DEPDIR)/inet_ntop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/inet_ntop.c' object='inet_ntop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_ntop.o `test -f '$(srcdir)/../lib/isc/inet_ntop.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_ntop.c + +inet_ntop.obj: $(srcdir)/../lib/isc/inet_ntop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_ntop.obj -MD -MP -MF $(DEPDIR)/inet_ntop.Tpo -c -o inet_ntop.obj `if test -f '$(srcdir)/../lib/isc/inet_ntop.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_ntop.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_ntop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_ntop.Tpo $(DEPDIR)/inet_ntop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/inet_ntop.c' object='inet_ntop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_ntop.obj `if test -f '$(srcdir)/../lib/isc/inet_ntop.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_ntop.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_ntop.c'; fi` + +inet_pton.o: $(srcdir)/../lib/isc/inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_pton.o -MD -MP -MF $(DEPDIR)/inet_pton.Tpo -c -o inet_pton.o `test -f '$(srcdir)/../lib/isc/inet_pton.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_pton.Tpo $(DEPDIR)/inet_pton.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/inet_pton.c' object='inet_pton.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_pton.o `test -f '$(srcdir)/../lib/isc/inet_pton.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_pton.c + +inet_pton.obj: $(srcdir)/../lib/isc/inet_pton.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_pton.obj -MD -MP -MF $(DEPDIR)/inet_pton.Tpo -c -o inet_pton.obj `if test -f '$(srcdir)/../lib/isc/inet_pton.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_pton.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_pton.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_pton.Tpo $(DEPDIR)/inet_pton.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/inet_pton.c' object='inet_pton.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_pton.obj `if test -f '$(srcdir)/../lib/isc/inet_pton.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_pton.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_pton.c'; fi` + +interfaceiter.o: $(srcdir)/../lib/isc/unix/interfaceiter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT interfaceiter.o -MD -MP -MF $(DEPDIR)/interfaceiter.Tpo -c -o interfaceiter.o `test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/interfaceiter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/interfaceiter.Tpo $(DEPDIR)/interfaceiter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/interfaceiter.c' object='interfaceiter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o interfaceiter.o `test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/interfaceiter.c + +interfaceiter.obj: $(srcdir)/../lib/isc/unix/interfaceiter.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT interfaceiter.obj -MD -MP -MF $(DEPDIR)/interfaceiter.Tpo -c -o interfaceiter.obj `if test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/interfaceiter.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/interfaceiter.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/interfaceiter.Tpo $(DEPDIR)/interfaceiter.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/interfaceiter.c' object='interfaceiter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o interfaceiter.obj `if test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/interfaceiter.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/interfaceiter.c'; fi` + +lib.o: $(srcdir)/../lib/isc/lib.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib.o -MD -MP -MF $(DEPDIR)/lib.Tpo -c -o lib.o `test -f '$(srcdir)/../lib/isc/lib.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/lib.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib.Tpo $(DEPDIR)/lib.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/lib.c' object='lib.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib.o `test -f '$(srcdir)/../lib/isc/lib.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/lib.c + +lib.obj: $(srcdir)/../lib/isc/lib.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib.obj -MD -MP -MF $(DEPDIR)/lib.Tpo -c -o lib.obj `if test -f '$(srcdir)/../lib/isc/lib.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/lib.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/lib.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib.Tpo $(DEPDIR)/lib.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/lib.c' object='lib.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib.obj `if test -f '$(srcdir)/../lib/isc/lib.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/lib.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/lib.c'; fi` + +log.o: $(srcdir)/../lib/isc/log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log.o -MD -MP -MF $(DEPDIR)/log.Tpo -c -o log.o `test -f '$(srcdir)/../lib/isc/log.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/log.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/log.Tpo $(DEPDIR)/log.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/log.c' object='log.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log.o `test -f '$(srcdir)/../lib/isc/log.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/log.c + +log.obj: $(srcdir)/../lib/isc/log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log.obj -MD -MP -MF $(DEPDIR)/log.Tpo -c -o log.obj `if test -f '$(srcdir)/../lib/isc/log.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/log.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/log.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/log.Tpo $(DEPDIR)/log.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/log.c' object='log.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log.obj `if test -f '$(srcdir)/../lib/isc/log.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/log.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/log.c'; fi` + +md5.o: $(srcdir)/../lib/isc/md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.o -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.o `test -f '$(srcdir)/../lib/isc/md5.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/md5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/md5.c' object='md5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.o `test -f '$(srcdir)/../lib/isc/md5.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/md5.c + +md5.obj: $(srcdir)/../lib/isc/md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.obj -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.obj `if test -f '$(srcdir)/../lib/isc/md5.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/md5.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/md5.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/md5.c' object='md5.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.obj `if test -f '$(srcdir)/../lib/isc/md5.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/md5.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/md5.c'; fi` + +msgcat.o: $(srcdir)/../lib/isc/nls/msgcat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msgcat.o -MD -MP -MF $(DEPDIR)/msgcat.Tpo -c -o msgcat.o `test -f '$(srcdir)/../lib/isc/nls/msgcat.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/nls/msgcat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/msgcat.Tpo $(DEPDIR)/msgcat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/nls/msgcat.c' object='msgcat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgcat.o `test -f '$(srcdir)/../lib/isc/nls/msgcat.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/nls/msgcat.c + +msgcat.obj: $(srcdir)/../lib/isc/nls/msgcat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msgcat.obj -MD -MP -MF $(DEPDIR)/msgcat.Tpo -c -o msgcat.obj `if test -f '$(srcdir)/../lib/isc/nls/msgcat.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/nls/msgcat.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/nls/msgcat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/msgcat.Tpo $(DEPDIR)/msgcat.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/nls/msgcat.c' object='msgcat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgcat.obj `if test -f '$(srcdir)/../lib/isc/nls/msgcat.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/nls/msgcat.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/nls/msgcat.c'; fi` + +net.o: $(srcdir)/../lib/isc/unix/net.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT net.o -MD -MP -MF $(DEPDIR)/net.Tpo -c -o net.o `test -f '$(srcdir)/../lib/isc/unix/net.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/net.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/net.Tpo $(DEPDIR)/net.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/net.c' object='net.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o net.o `test -f '$(srcdir)/../lib/isc/unix/net.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/net.c + +net.obj: $(srcdir)/../lib/isc/unix/net.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT net.obj -MD -MP -MF $(DEPDIR)/net.Tpo -c -o net.obj `if test -f '$(srcdir)/../lib/isc/unix/net.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/net.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/net.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/net.Tpo $(DEPDIR)/net.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/net.c' object='net.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o net.obj `if test -f '$(srcdir)/../lib/isc/unix/net.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/net.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/net.c'; fi` + +netaddr.o: $(srcdir)/../lib/isc/netaddr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netaddr.o -MD -MP -MF $(DEPDIR)/netaddr.Tpo -c -o netaddr.o `test -f '$(srcdir)/../lib/isc/netaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netaddr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netaddr.Tpo $(DEPDIR)/netaddr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/netaddr.c' object='netaddr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netaddr.o `test -f '$(srcdir)/../lib/isc/netaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netaddr.c + +netaddr.obj: $(srcdir)/../lib/isc/netaddr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netaddr.obj -MD -MP -MF $(DEPDIR)/netaddr.Tpo -c -o netaddr.obj `if test -f '$(srcdir)/../lib/isc/netaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netaddr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netaddr.Tpo $(DEPDIR)/netaddr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/netaddr.c' object='netaddr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netaddr.obj `if test -f '$(srcdir)/../lib/isc/netaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netaddr.c'; fi` + +netscope.o: $(srcdir)/../lib/isc/netscope.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netscope.o -MD -MP -MF $(DEPDIR)/netscope.Tpo -c -o netscope.o `test -f '$(srcdir)/../lib/isc/netscope.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netscope.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netscope.Tpo $(DEPDIR)/netscope.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/netscope.c' object='netscope.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netscope.o `test -f '$(srcdir)/../lib/isc/netscope.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netscope.c + +netscope.obj: $(srcdir)/../lib/isc/netscope.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netscope.obj -MD -MP -MF $(DEPDIR)/netscope.Tpo -c -o netscope.obj `if test -f '$(srcdir)/../lib/isc/netscope.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netscope.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netscope.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netscope.Tpo $(DEPDIR)/netscope.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/netscope.c' object='netscope.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netscope.obj `if test -f '$(srcdir)/../lib/isc/netscope.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netscope.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netscope.c'; fi` + +ondestroy.o: $(srcdir)/../lib/isc/ondestroy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ondestroy.o -MD -MP -MF $(DEPDIR)/ondestroy.Tpo -c -o ondestroy.o `test -f '$(srcdir)/../lib/isc/ondestroy.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/ondestroy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ondestroy.Tpo $(DEPDIR)/ondestroy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/ondestroy.c' object='ondestroy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ondestroy.o `test -f '$(srcdir)/../lib/isc/ondestroy.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/ondestroy.c + +ondestroy.obj: $(srcdir)/../lib/isc/ondestroy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ondestroy.obj -MD -MP -MF $(DEPDIR)/ondestroy.Tpo -c -o ondestroy.obj `if test -f '$(srcdir)/../lib/isc/ondestroy.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/ondestroy.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/ondestroy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ondestroy.Tpo $(DEPDIR)/ondestroy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/ondestroy.c' object='ondestroy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ondestroy.obj `if test -f '$(srcdir)/../lib/isc/ondestroy.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/ondestroy.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/ondestroy.c'; fi` + +random.o: $(srcdir)/../lib/isc/random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.o -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.o `test -f '$(srcdir)/../lib/isc/random.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/random.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/random.c' object='random.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.o `test -f '$(srcdir)/../lib/isc/random.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/random.c + +random.obj: $(srcdir)/../lib/isc/random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.obj -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.obj `if test -f '$(srcdir)/../lib/isc/random.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/random.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/random.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/random.c' object='random.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.obj `if test -f '$(srcdir)/../lib/isc/random.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/random.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/random.c'; fi` + +result.o: $(srcdir)/../lib/isc/result.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT result.o -MD -MP -MF $(DEPDIR)/result.Tpo -c -o result.o `test -f '$(srcdir)/../lib/isc/result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/result.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/result.Tpo $(DEPDIR)/result.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/result.c' object='result.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o result.o `test -f '$(srcdir)/../lib/isc/result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/result.c + +result.obj: $(srcdir)/../lib/isc/result.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT result.obj -MD -MP -MF $(DEPDIR)/result.Tpo -c -o result.obj `if test -f '$(srcdir)/../lib/isc/result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/result.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/result.Tpo $(DEPDIR)/result.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/result.c' object='result.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o result.obj `if test -f '$(srcdir)/../lib/isc/result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/result.c'; fi` + +stdio.o: $(srcdir)/../lib/isc/unix/stdio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdio.o -MD -MP -MF $(DEPDIR)/stdio.Tpo -c -o stdio.o `test -f '$(srcdir)/../lib/isc/unix/stdio.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdio.Tpo $(DEPDIR)/stdio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/stdio.c' object='stdio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdio.o `test -f '$(srcdir)/../lib/isc/unix/stdio.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdio.c + +stdio.obj: $(srcdir)/../lib/isc/unix/stdio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdio.obj -MD -MP -MF $(DEPDIR)/stdio.Tpo -c -o stdio.obj `if test -f '$(srcdir)/../lib/isc/unix/stdio.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdio.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdio.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdio.Tpo $(DEPDIR)/stdio.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/stdio.c' object='stdio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdio.obj `if test -f '$(srcdir)/../lib/isc/unix/stdio.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdio.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdio.c'; fi` + +stdtime.o: $(srcdir)/../lib/isc/unix/stdtime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdtime.o -MD -MP -MF $(DEPDIR)/stdtime.Tpo -c -o stdtime.o `test -f '$(srcdir)/../lib/isc/unix/stdtime.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdtime.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdtime.Tpo $(DEPDIR)/stdtime.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/stdtime.c' object='stdtime.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdtime.o `test -f '$(srcdir)/../lib/isc/unix/stdtime.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdtime.c + +stdtime.obj: $(srcdir)/../lib/isc/unix/stdtime.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdtime.obj -MD -MP -MF $(DEPDIR)/stdtime.Tpo -c -o stdtime.obj `if test -f '$(srcdir)/../lib/isc/unix/stdtime.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdtime.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdtime.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdtime.Tpo $(DEPDIR)/stdtime.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/stdtime.c' object='stdtime.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdtime.obj `if test -f '$(srcdir)/../lib/isc/unix/stdtime.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdtime.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdtime.c'; fi` + +strerror.o: $(srcdir)/../lib/isc/unix/strerror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strerror.o -MD -MP -MF $(DEPDIR)/strerror.Tpo -c -o strerror.o `test -f '$(srcdir)/../lib/isc/unix/strerror.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/strerror.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/strerror.Tpo $(DEPDIR)/strerror.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/strerror.c' object='strerror.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strerror.o `test -f '$(srcdir)/../lib/isc/unix/strerror.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/strerror.c + +strerror.obj: $(srcdir)/../lib/isc/unix/strerror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strerror.obj -MD -MP -MF $(DEPDIR)/strerror.Tpo -c -o strerror.obj `if test -f '$(srcdir)/../lib/isc/unix/strerror.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/strerror.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/strerror.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/strerror.Tpo $(DEPDIR)/strerror.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/strerror.c' object='strerror.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strerror.obj `if test -f '$(srcdir)/../lib/isc/unix/strerror.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/strerror.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/strerror.c'; fi` + +task.o: $(srcdir)/../lib/isc/task.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.o -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.o `test -f '$(srcdir)/../lib/isc/task.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/task.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/task.c' object='task.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.o `test -f '$(srcdir)/../lib/isc/task.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/task.c + +task.obj: $(srcdir)/../lib/isc/task.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.obj -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.obj `if test -f '$(srcdir)/../lib/isc/task.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/task.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/task.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/task.c' object='task.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.obj `if test -f '$(srcdir)/../lib/isc/task.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/task.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/task.c'; fi` + +thread.o: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.o -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' object='thread.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c + +thread.obj: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.obj -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' object='thread.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; fi` + +time.o: $(srcdir)/../lib/isc/unix/time.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT time.o -MD -MP -MF $(DEPDIR)/time.Tpo -c -o time.o `test -f '$(srcdir)/../lib/isc/unix/time.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/time.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/time.Tpo $(DEPDIR)/time.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/time.c' object='time.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o time.o `test -f '$(srcdir)/../lib/isc/unix/time.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/time.c + +time.obj: $(srcdir)/../lib/isc/unix/time.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT time.obj -MD -MP -MF $(DEPDIR)/time.Tpo -c -o time.obj `if test -f '$(srcdir)/../lib/isc/unix/time.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/time.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/time.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/time.Tpo $(DEPDIR)/time.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/unix/time.c' object='time.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o time.obj `if test -f '$(srcdir)/../lib/isc/unix/time.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/time.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/time.c'; fi` + +sha1.o: $(srcdir)/../lib/isc/sha1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha1.o -MD -MP -MF $(DEPDIR)/sha1.Tpo -c -o sha1.o `test -f '$(srcdir)/../lib/isc/sha1.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sha1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sha1.Tpo $(DEPDIR)/sha1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/sha1.c' object='sha1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha1.o `test -f '$(srcdir)/../lib/isc/sha1.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sha1.c + +sha1.obj: $(srcdir)/../lib/isc/sha1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha1.obj -MD -MP -MF $(DEPDIR)/sha1.Tpo -c -o sha1.obj `if test -f '$(srcdir)/../lib/isc/sha1.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sha1.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sha1.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sha1.Tpo $(DEPDIR)/sha1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/sha1.c' object='sha1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha1.obj `if test -f '$(srcdir)/../lib/isc/sha1.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sha1.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sha1.c'; fi` + +sockaddr.o: $(srcdir)/../lib/isc/sockaddr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sockaddr.o -MD -MP -MF $(DEPDIR)/sockaddr.Tpo -c -o sockaddr.o `test -f '$(srcdir)/../lib/isc/sockaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sockaddr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sockaddr.Tpo $(DEPDIR)/sockaddr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/sockaddr.c' object='sockaddr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.o `test -f '$(srcdir)/../lib/isc/sockaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sockaddr.c + +sockaddr.obj: $(srcdir)/../lib/isc/sockaddr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sockaddr.obj -MD -MP -MF $(DEPDIR)/sockaddr.Tpo -c -o sockaddr.obj `if test -f '$(srcdir)/../lib/isc/sockaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sockaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sockaddr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sockaddr.Tpo $(DEPDIR)/sockaddr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/sockaddr.c' object='sockaddr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.obj `if test -f '$(srcdir)/../lib/isc/sockaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sockaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sockaddr.c'; fi` + +tsmemcmp.o: $(srcdir)/../lib/isc/tsmemcmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsmemcmp.o -MD -MP -MF $(DEPDIR)/tsmemcmp.Tpo -c -o tsmemcmp.o `test -f '$(srcdir)/../lib/isc/tsmemcmp.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/tsmemcmp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tsmemcmp.Tpo $(DEPDIR)/tsmemcmp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/tsmemcmp.c' object='tsmemcmp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsmemcmp.o `test -f '$(srcdir)/../lib/isc/tsmemcmp.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/tsmemcmp.c + +tsmemcmp.obj: $(srcdir)/../lib/isc/tsmemcmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsmemcmp.obj -MD -MP -MF $(DEPDIR)/tsmemcmp.Tpo -c -o tsmemcmp.obj `if test -f '$(srcdir)/../lib/isc/tsmemcmp.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/tsmemcmp.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/tsmemcmp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tsmemcmp.Tpo $(DEPDIR)/tsmemcmp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/tsmemcmp.c' object='tsmemcmp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsmemcmp.obj `if test -f '$(srcdir)/../lib/isc/tsmemcmp.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/tsmemcmp.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/tsmemcmp.c'; fi` + +mutex.o: $(srcdir)/../lib/isc/pthreads/mutex.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mutex.o -MD -MP -MF $(DEPDIR)/mutex.Tpo -c -o mutex.o `test -f '$(srcdir)/../lib/isc/pthreads/mutex.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/pthreads/mutex.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mutex.Tpo $(DEPDIR)/mutex.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/pthreads/mutex.c' object='mutex.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.o `test -f '$(srcdir)/../lib/isc/pthreads/mutex.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/pthreads/mutex.c + +mutex.obj: $(srcdir)/../lib/isc/pthreads/mutex.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mutex.obj -MD -MP -MF $(DEPDIR)/mutex.Tpo -c -o mutex.obj `if test -f '$(srcdir)/../lib/isc/pthreads/mutex.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/pthreads/mutex.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/pthreads/mutex.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mutex.Tpo $(DEPDIR)/mutex.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/pthreads/mutex.c' object='mutex.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.obj `if test -f '$(srcdir)/../lib/isc/pthreads/mutex.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/pthreads/mutex.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/pthreads/mutex.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man 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-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + +$(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) $(AM_MAKEFLAGS) clean && \ + echo -n "Prior $(subdir)/$(DEPDIR) version " && \ + cat $@ && \ + rm -rf $(DEPDIR) && \ + mkdir $(DEPDIR) && \ + case "$(top_builddir)" in \ + .) \ + ./config.status Makefile depfiles \ + ;; \ + *) \ + cd "$(top_builddir)" && \ + ./config.status $(subdir)/Makefile depfiles && \ + cd $(subdir) \ + ;; \ + 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) $(AM_MAKEFLAGS) $(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. +.NOEXPORT: diff --git a/contrib/ntp/libntp/README b/contrib/ntp/libntp/README new file mode 100644 index 000000000000..fac718548990 --- /dev/null +++ b/contrib/ntp/libntp/README @@ -0,0 +1,5 @@ +README file for directory ./libntp of the NTP Version 4 distribution + +This directory contains the sources for the NTP library used by most +programs in this distribution. See the README and RELNOTES files in the +parent directory for directions on how to make this library. diff --git a/contrib/ntp/libntp/a_md5encrypt.c b/contrib/ntp/libntp/a_md5encrypt.c new file mode 100644 index 000000000000..7edcd2e30583 --- /dev/null +++ b/contrib/ntp/libntp/a_md5encrypt.c @@ -0,0 +1,141 @@ +/* + * digest support for NTP, MD5 and with OpenSSL more + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "ntp_fp.h" +#include "ntp_string.h" +#include "ntp_stdlib.h" +#include "ntp.h" +#include "ntp_md5.h" /* provides OpenSSL digest API */ +#include "isc/string.h" +#include "libssl_compat.h" +/* + * MD5authencrypt - generate message digest + * + * Returns length of MAC including key ID and digest. + */ +size_t +MD5authencrypt( + int type, /* hash algorithm */ + const u_char * key, /* key pointer */ + u_int32 * pkt, /* packet pointer */ + size_t length /* packet length */ + ) +{ + u_char digest[EVP_MAX_MD_SIZE]; + u_int len; + EVP_MD_CTX *ctx; + + /* + * Compute digest of key concatenated with packet. Note: the + * key type and digest type have been verified when the key + * was creaded. + */ + INIT_SSL(); + ctx = EVP_MD_CTX_new(); + if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { + msyslog(LOG_ERR, + "MAC encrypt: digest init failed"); + EVP_MD_CTX_free(ctx); + return (0); + } + EVP_DigestUpdate(ctx, key, cache_secretsize); + EVP_DigestUpdate(ctx, (u_char *)pkt, length); + EVP_DigestFinal(ctx, digest, &len); + EVP_MD_CTX_free(ctx); + /* If the MAC is longer than the MAX then truncate it. */ + if (len > MAX_MAC_LEN - 4) + len = MAX_MAC_LEN - 4; + memmove((u_char *)pkt + length + 4, digest, len); + return (len + 4); +} + + +/* + * MD5authdecrypt - verify MD5 message authenticator + * + * Returns one if digest valid, zero if invalid. + */ +int +MD5authdecrypt( + int type, /* hash algorithm */ + const u_char * key, /* key pointer */ + u_int32 * pkt, /* packet pointer */ + size_t length, /* packet length */ + size_t size /* MAC size */ + ) +{ + u_char digest[EVP_MAX_MD_SIZE]; + u_int len; + EVP_MD_CTX *ctx; + + /* + * Compute digest of key concatenated with packet. Note: the + * key type and digest type have been verified when the key + * was created. + */ + INIT_SSL(); + ctx = EVP_MD_CTX_new(); + if (!(ctx && EVP_DigestInit(ctx, EVP_get_digestbynid(type)))) { + msyslog(LOG_ERR, + "MAC decrypt: digest init failed"); + EVP_MD_CTX_free(ctx); + return (0); + } + EVP_DigestUpdate(ctx, key, cache_secretsize); + EVP_DigestUpdate(ctx, (u_char *)pkt, length); + EVP_DigestFinal(ctx, digest, &len); + EVP_MD_CTX_free(ctx); + /* If the MAC is longer than the MAX then truncate it. */ + if (len > MAX_MAC_LEN - 4) + len = MAX_MAC_LEN - 4; + if (size != (size_t)len + 4) { + msyslog(LOG_ERR, + "MAC decrypt: MAC length error"); + return (0); + } + return !isc_tsmemcmp(digest, (u_char *)pkt + length + 4, len); +} + +/* + * Calculate the reference id from the address. If it is an IPv4 + * address, use it as is. If it is an IPv6 address, do a md5 on + * it and use the bottom 4 bytes. + * The result is in network byte order. + */ +u_int32 +addr2refid(sockaddr_u *addr) +{ + u_char digest[20]; + u_int32 addr_refid; + EVP_MD_CTX *ctx; + u_int len; + + if (IS_IPV4(addr)) + return (NSRCADR(addr)); + + INIT_SSL(); + + ctx = EVP_MD_CTX_new(); + EVP_MD_CTX_init(ctx); +#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW + /* MD5 is not used as a crypto hash here. */ + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); +#endif + if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) { + msyslog(LOG_ERR, + "MD5 init failed"); + EVP_MD_CTX_free(ctx); /* pedantic... but safe */ + exit(1); + } + + EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr), + sizeof(struct in6_addr)); + EVP_DigestFinal(ctx, digest, &len); + EVP_MD_CTX_free(ctx); + memcpy(&addr_refid, digest, sizeof(addr_refid)); + return (addr_refid); +} diff --git a/contrib/ntp/libntp/adjtime.c b/contrib/ntp/libntp/adjtime.c new file mode 100644 index 000000000000..a8e65808bf29 --- /dev/null +++ b/contrib/ntp/libntp/adjtime.c @@ -0,0 +1,386 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef MPE +/* + * MPE lacks adjtime(), so we define our own. But note that time slewing has + * a sub-second accuracy bug documented in SR 5003462838 which prevents ntpd + * from being able to maintain clock synch. Because of the bug, this adjtime() + * implementation as used by ntpd has a side-effect of screwing up the hardware + * PDC clock, which will need to be reset with a reboot. + * + * This problem affects all versions of MPE at the time of this writing (when + * MPE/iX 7.0 is the most current). It only causes bad things to happen when + * doing continuous clock synchronization with ntpd; note that you CAN run ntpd + * with "disable ntp" in ntp.conf if you wish to provide a time server. + * + * The one-time clock adjustment functionality of ntpdate and ntp_timeset can + * be used without screwing up the PDC clock. + * + */ +#include <time.h> + +int adjtime(struct timeval *delta, struct timeval *olddelta); + +int adjtime(struct timeval *delta, struct timeval *olddelta) + +{ +/* Documented, supported MPE system intrinsics. */ + +extern void GETPRIVMODE(void); +extern void GETUSERMODE(void); + +/* Undocumented, unsupported MPE internal functions. */ + +extern long long current_correction_usecs(void); +extern long long get_time(void); +extern void get_time_change_info(long long *, char *, char *); +extern long long pdc_time(int *); +extern void set_time_correction(long long, int, int); +extern long long ticks_to_micro(long long); + +long long big_sec, big_usec, new_correction = 0LL; +long long prev_correction; + +if (delta != NULL) { + /* Adjustment required. Convert delta to 64-bit microseconds. */ + big_sec = (long)delta->tv_sec; + big_usec = delta->tv_usec; + new_correction = (big_sec * 1000000LL) + big_usec; +} + +GETPRIVMODE(); + +/* Determine how much of a previous correction (if any) we're interrupting. */ +prev_correction = current_correction_usecs(); + +if (delta != NULL) { + /* Adjustment required. */ + +#if 0 + /* Speculative code disabled until bug SR 5003462838 is fixed. This bug + prevents accurate time slewing, and indeed renders ntpd inoperable. */ + + if (prev_correction != 0LL) { + /* A previous adjustment did not complete. Since the PDC UTC clock was + immediately jumped at the start of the previous adjustment, we must + explicitly reset it to the value of the MPE local time clock minus the + time zone offset. */ + + char pwf_since_boot, recover_pwf_time; + long long offset_ticks, offset_usecs, pdc_usecs_current, pdc_usecs_wanted; + int hpe_status; + + get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); + offset_usecs = ticks_to_micro(offset_ticks); + pdc_usecs_wanted = get_time() - offset_usecs; + pdc_usecs_current = pdc_time(&hpe_status); + if (hpe_status == 0) + /* Force new PDC time by starting an extra correction. */ + set_time_correction(pdc_usecs_wanted - pdc_usecs_current,0,1); + } +#endif /* 0 */ + + /* Immediately jump the PDC time to the new value, and then initiate a + gradual MPE time correction slew. */ + set_time_correction(new_correction,0,1); +} + +GETUSERMODE(); + +if (olddelta != NULL) { + /* Caller wants to know remaining amount of previous correction. */ + (long)olddelta->tv_sec = prev_correction / 1000000LL; + olddelta->tv_usec = prev_correction % 1000000LL; +} + +return 0; +} +#endif /* MPE */ + +#ifdef NEED_HPUX_ADJTIME +/*************************************************************************/ +/* (c) Copyright Tai Jin, 1988. All Rights Reserved. */ +/* Hewlett-Packard Laboratories. */ +/* */ +/* Permission is hereby granted for unlimited modification, use, and */ +/* distribution. This software is made available with no warranty of */ +/* any kind, express or implied. This copyright notice must remain */ +/* intact in all versions of this software. */ +/* */ +/* The author would appreciate it if any bug fixes and enhancements were */ +/* to be sent back to him for incorporation into future versions of this */ +/* software. Please send changes to tai@iag.hp.com or ken@sdd.hp.com. */ +/*************************************************************************/ + +/* + * Revision history + * + * 9 Jul 94 David L. Mills, Unibergity of Delabunch + * Implemented variable threshold to limit age of + * corrections; reformatted code for readability. + */ + +#ifndef lint +static char RCSid[] = "adjtime.c,v 3.1 1993/07/06 01:04:42 jbj Exp"; +#endif + +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <time.h> +#include <signal.h> +#include "adjtime.h" + +#define abs(x) ((x) < 0 ? -(x) : (x)) + +/* + * The following paramters are appropriate for an NTP adjustment + * interval of one second. + */ +#define ADJ_THRESH 200 /* initial threshold */ +#define ADJ_DELTA 4 /* threshold decrement */ + +static long adjthresh; /* adjustment threshold */ +static long saveup; /* corrections accumulator */ + +/* + * clear_adjtime - reset accumulator and threshold variables + */ +void +_clear_adjtime(void) +{ + saveup = 0; + adjthresh = ADJ_THRESH; +} + +/* + * adjtime - hp-ux copout of the standard Unix adjtime() system call + */ +int +adjtime( + register struct timeval *delta, + register struct timeval *olddelta + ) +{ + struct timeval newdelta; + + /* + * Corrections greater than one second are done immediately. + */ + if (delta->tv_sec) { + adjthresh = ADJ_THRESH; + saveup = 0; + return(_adjtime(delta, olddelta)); + } + + /* + * Corrections less than one second are accumulated until + * tripping a threshold, which is initially set at ADJ_THESH and + * reduced in ADJ_DELTA steps to zero. The idea here is to + * introduce large corrections quickly, while making sure that + * small corrections are introduced without excessive delay. The + * idea comes from the ARPAnet routing update algorithm. + */ + saveup += delta->tv_usec; + if (abs(saveup) >= adjthresh) { + adjthresh = ADJ_THRESH; + newdelta.tv_sec = 0; + newdelta.tv_usec = saveup; + saveup = 0; + return(_adjtime(&newdelta, olddelta)); + } else { + adjthresh -= ADJ_DELTA; + } + + /* + * While nobody uses it, return the residual before correction, + * as per Unix convention. + */ + if (olddelta) + olddelta->tv_sec = olddelta->tv_usec = 0; + return(0); +} + +/* + * _adjtime - does the actual work + */ +int +_adjtime( + register struct timeval *delta, + register struct timeval *olddelta + ) +{ + register int mqid; + MsgBuf msg; + register MsgBuf *msgp = &msg; + + /* + * Get the key to the adjtime message queue (note that we must + * get it every time because the queue might have been removed + * and recreated) + */ + if ((mqid = msgget(KEY, 0)) == -1) + return (-1); + msgp->msgb.mtype = CLIENT; + msgp->msgb.tv = *delta; + if (olddelta) + msgp->msgb.code = DELTA2; + else + msgp->msgb.code = DELTA1; + + /* + * Tickle adjtimed and snatch residual, if indicated. Lots of + * fanatic error checking here. + */ + if (msgsnd(mqid, &msgp->msgp, MSGSIZE, 0) == -1) + return (-1); + if (olddelta) { + if (msgrcv(mqid, &msgp->msgp, MSGSIZE, SERVER, 0) == -1) + return (-1); + *olddelta = msgp->msgb.tv; + } + return (0); +} + +#else +# if NEED_QNX_ADJTIME +/* + * Emulate adjtime() using QNX ClockAdjust(). + * Chris Burghart <burghart@atd.ucar.edu>, 11/2001 + * Miroslaw Pabich <miroslaw_pabich@o2.pl>, 09/2005 + * + * This is an implementation of adjtime() for QNX. + * ClockAdjust() is used to tweak the system clock for about + * 1 second period until the desired delta is achieved. + * Time correction slew is limited to reasonable value. + * Internal rounding and relative errors are reduced. + */ +# include <sys/neutrino.h> +# include <sys/time.h> + +# include <ntp_stdlib.h> + +/* + * Time correction slew limit. QNX is a hard real-time system, + * so don't adjust system clock too fast. + */ +#define CORR_SLEW_LIMIT 0.02 /* [s/s] */ + +/* + * Period of system clock adjustment. It should be equal to adjtime + * execution period (1s). If slightly less than 1s (0.95-0.99), then olddelta + * residual error (introduced by execution period jitter) will be reduced. + */ +#define ADJUST_PERIOD 0.97 /* [s] */ + +int +adjtime (struct timeval *delta, struct timeval *olddelta) +{ + double delta_nsec; + double delta_nsec_old; + struct _clockadjust adj; + struct _clockadjust oldadj; + + /* + * How many nanoseconds are we adjusting? + */ + if (delta != NULL) + delta_nsec = 1e9 * (long)delta->tv_sec + 1e3 * delta->tv_usec; + else + delta_nsec = 0; + + /* + * Build the adjust structure and call ClockAdjust() + */ + if (delta_nsec != 0) + { + struct _clockperiod period; + long count; + long increment; + long increment_limit; + int isneg = 0; + + /* + * Convert to absolute value for future processing + */ + if (delta_nsec < 0) + { + isneg = 1; + delta_nsec = -delta_nsec; + } + + /* + * Get the current clock period (nanoseconds) + */ + if (ClockPeriod (CLOCK_REALTIME, 0, &period, 0) < 0) + return -1; + + /* + * Compute count and nanoseconds increment + */ + count = 1e9 * ADJUST_PERIOD / period.nsec; + increment = delta_nsec / count + .5; + /* Reduce relative error */ + if (count > increment + 1) + { + increment = 1 + (long)((delta_nsec - 1) / count); + count = delta_nsec / increment + .5; + } + + /* + * Limit the adjust increment to appropriate value + */ + increment_limit = CORR_SLEW_LIMIT * period.nsec; + if (increment > increment_limit) + { + increment = increment_limit; + count = delta_nsec / increment + .5; + /* Reduce relative error */ + if (increment > count + 1) + { + count = 1 + (long)((delta_nsec - 1) / increment); + increment = delta_nsec / count + .5; + } + } + + adj.tick_nsec_inc = isneg ? -increment : increment; + adj.tick_count = count; + } + else + { + adj.tick_nsec_inc = 0; + adj.tick_count = 0; + } + + if (ClockAdjust (CLOCK_REALTIME, &adj, &oldadj) < 0) + return -1; + + /* + * Build olddelta + */ + delta_nsec_old = (double)oldadj.tick_count * oldadj.tick_nsec_inc; + if (olddelta != NULL) + { + if (delta_nsec_old != 0) + { + /* Reduce rounding error */ + delta_nsec_old += (delta_nsec_old < 0) ? -500 : 500; + olddelta->tv_sec = delta_nsec_old / 1e9; + olddelta->tv_usec = (long)(delta_nsec_old - 1e9 + * (long)olddelta->tv_sec) / 1000; + } + else + { + olddelta->tv_sec = 0; + olddelta->tv_usec = 0; + } + } + + return 0; +} +# else /* no special adjtime() needed */ +int adjtime_bs; +# endif +#endif diff --git a/contrib/ntp/libntp/adjtimex.c b/contrib/ntp/libntp/adjtimex.c new file mode 100644 index 000000000000..03e9d79e359e --- /dev/null +++ b/contrib/ntp/libntp/adjtimex.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#ifndef lint +_sccsid:.asciz "11/19/91 ULTRIX @(#)adjtime.c 6.1" +#endif not lint + +#include "SYS.h" + +SYSCALL(adjtimex) + ret + diff --git a/contrib/ntp/libntp/atoint.c b/contrib/ntp/libntp/atoint.c new file mode 100644 index 000000000000..9da8c13c32d6 --- /dev/null +++ b/contrib/ntp/libntp/atoint.c @@ -0,0 +1,51 @@ +/* + * atoint - convert an ascii string to a signed long, with error checking + */ +#include <config.h> +#include <sys/types.h> +#include <ctype.h> + +#include "ntp_types.h" +#include "ntp_stdlib.h" + +int +atoint( + const char *str, + long *ival + ) +{ + register long u; + register const char *cp; + register int isneg; + register int oflow_digit; + + cp = str; + + if (*cp == '-') { + cp++; + isneg = 1; + oflow_digit = '8'; + } else { + isneg = 0; + oflow_digit = '7'; + } + + if (*cp == '\0') + return 0; + + u = 0; + while (*cp != '\0') { + if (!isdigit((unsigned char)*cp)) + return 0; + if (u > 214748364 || (u == 214748364 && *cp > oflow_digit)) + return 0; /* overflow */ + u = (u << 3) + (u << 1); + u += *cp++ - '0'; /* ascii dependent */ + } + + if (isneg) + *ival = -u; + else + *ival = u; + return 1; +} diff --git a/contrib/ntp/libntp/atolfp.c b/contrib/ntp/libntp/atolfp.c new file mode 100644 index 000000000000..439194eda9bb --- /dev/null +++ b/contrib/ntp/libntp/atolfp.c @@ -0,0 +1,122 @@ +/* + * atolfp - convert an ascii string to an l_fp number + */ +#include <config.h> +#include <stdio.h> +#include <ctype.h> + +#include "ntp_fp.h" +#include "ntp_string.h" +#include "ntp_assert.h" + +/* + * Powers of 10 + */ +static u_long ten_to_the_n[10] = { + 0, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, +}; + + +int +atolfp( + const char *str, + l_fp *lfp + ) +{ + register const char *cp; + register u_long dec_i; + register u_long dec_f; + char *ind; + int ndec; + int isneg; + static const char *digits = "0123456789"; + + REQUIRE(str != NULL); + + isneg = 0; + dec_i = dec_f = 0; + ndec = 0; + cp = str; + + /* + * We understand numbers of the form: + * + * [spaces][-|+][digits][.][digits][spaces|\n|\0] + */ + while (isspace((unsigned char)*cp)) + cp++; + + if (*cp == '-') { + cp++; + isneg = 1; + } + + if (*cp == '+') + cp++; + + if (*cp != '.' && !isdigit((unsigned char)*cp)) + return 0; + + while (*cp != '\0' && (ind = strchr(digits, *cp)) != NULL) { + dec_i = (dec_i << 3) + (dec_i << 1); /* multiply by 10 */ + dec_i += (u_long)(ind - digits); + cp++; + } + + if (*cp != '\0' && !isspace((unsigned char)*cp)) { + if (*cp++ != '.') + return 0; + + while (ndec < 9 && *cp != '\0' + && (ind = strchr(digits, *cp)) != NULL) { + ndec++; + dec_f = (dec_f << 3) + (dec_f << 1); /* *10 */ + dec_f += (u_long)(ind - digits); + cp++; + } + + while (isdigit((unsigned char)*cp)) + cp++; + + if (*cp != '\0' && !isspace((unsigned char)*cp)) + return 0; + } + + if (ndec > 0) { + register u_long tmp; + register u_long bit; + register u_long ten_fact; + + ten_fact = ten_to_the_n[ndec]; + + tmp = 0; + bit = 0x80000000; + while (bit != 0) { + dec_f <<= 1; + if (dec_f >= ten_fact) { + tmp |= bit; + dec_f -= ten_fact; + } + bit >>= 1; + } + if ((dec_f << 1) > ten_fact) + tmp++; + dec_f = tmp; + } + + if (isneg) + M_NEG(dec_i, dec_f); + + lfp->l_ui = dec_i; + lfp->l_uf = dec_f; + return 1; +} diff --git a/contrib/ntp/libntp/atouint.c b/contrib/ntp/libntp/atouint.c new file mode 100644 index 000000000000..0a6163907a51 --- /dev/null +++ b/contrib/ntp/libntp/atouint.c @@ -0,0 +1,42 @@ +#include <config.h> +#include <sys/types.h> +#include <ctype.h> + +#include "ntp_types.h" +#include "ntp_stdlib.h" + +/* + * atouint() - convert an ascii string representing a whole base 10 + * number to u_long *uval, returning TRUE if successful. + * Does not modify *uval and returns FALSE if str is not + * a positive base10 integer or is too large for a u_int32. + * this function uses u_long but should use u_int32, and + * probably be renamed. + */ +int +atouint( + const char *str, + u_long *uval + ) +{ + u_long u; + const char *cp; + + cp = str; + if ('\0' == *cp) + return 0; + + u = 0; + while ('\0' != *cp) { + if (!isdigit((unsigned char)*cp)) + return 0; + if (u > 429496729 || (u == 429496729 && *cp >= '6')) + return 0; /* overflow */ + /* hand-optimized u *= 10; */ + u = (u << 3) + (u << 1); + u += *cp++ - '0'; /* not '\0' */ + } + + *uval = u; + return 1; +} diff --git a/contrib/ntp/libntp/audio.c b/contrib/ntp/libntp/audio.c new file mode 100644 index 000000000000..3b0a0b364c11 --- /dev/null +++ b/contrib/ntp/libntp/audio.c @@ -0,0 +1,507 @@ +/* + * audio.c - audio interface for reference clock audio drivers + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(HAVE_SYS_AUDIOIO_H) || defined(HAVE_SUN_AUDIOIO_H) || \ + defined(HAVE_SYS_SOUNDCARD_H) || defined(HAVE_MACHINE_SOUNDCARD_H) + +#include "audio.h" +#include "ntp_stdlib.h" +#include "ntp_syslog.h" +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdio.h> +#include "ntp_string.h" + +#ifdef HAVE_SYS_AUDIOIO_H +# include <sys/audioio.h> +#endif /* HAVE_SYS_AUDIOIO_H */ + +#ifdef HAVE_SUN_AUDIOIO_H +# include <sys/ioccom.h> +# include <sun/audioio.h> +#endif /* HAVE_SUN_AUDIOIO_H */ + +#ifdef HAVE_SYS_IOCTL_H +# include <sys/ioctl.h> +#endif /* HAVE_SYS_IOCTL_H */ + +#include <fcntl.h> + +#ifdef HAVE_MACHINE_SOUNDCARD_H +# include <machine/soundcard.h> +# define PCM_STYLE_SOUND +#else +# ifdef HAVE_SYS_SOUNDCARD_H +# include <sys/soundcard.h> +# define PCM_STYLE_SOUND +# endif +#endif + +#ifdef PCM_STYLE_SOUND +# include <ctype.h> +#endif + +/* + * Global variables + */ +#ifdef HAVE_SYS_AUDIOIO_H +static struct audio_device device; /* audio device ident */ +#endif /* HAVE_SYS_AUDIOIO_H */ +#ifdef PCM_STYLE_SOUND +# define INIT_FILE "/etc/ntp.audio" +int agc = SOUND_MIXER_WRITE_RECLEV; /* or IGAIN or LINE */ +int audiomonitor = SOUND_MIXER_WRITE_VOLUME; /* or OGAIN */ +int devmask = 0; +int recmask = 0; +char cf_c_dev[100], cf_i_dev[100], cf_agc[100], cf_monitor[100]; + +const char *m_names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; +#else /* not PCM_STYLE_SOUND */ +static struct audio_info info; /* audio device info */ +#endif /* not PCM_STYLE_SOUND */ +static int ctl_fd; /* audio control file descriptor */ + +#ifdef PCM_STYLE_SOUND +static void audio_config_read (int, const char **, const char **); +static int mixer_name (const char *, int); + + +int +mixer_name( + const char *m_name, + int m_mask + ) +{ + int i; + + for (i = 0; i < SOUND_MIXER_NRDEVICES; ++i) + if (((1 << i) & m_mask) + && !strcmp(m_names[i], m_name)) + break; + + return (SOUND_MIXER_NRDEVICES == i) + ? -1 + : i + ; +} + + +/* + * Check: + * + * /etc/ntp.audio# where # is the unit number + * /etc/ntp.audio.# where # is the unit number + * /etc/ntp.audio + * + * for contents of the form: + * + * idev /dev/input_device + * cdev /dev/control_device + * agc pcm_input_device {igain,line,line1,...} + * monitor pcm_monitor_device {ogain,...} + * + * The device names for the "agc" and "monitor" keywords + * can be found by running either the "mixer" program or the + * util/audio-pcm program. + * + * Great hunks of this subroutine were swiped from refclock_oncore.c + */ +static void +audio_config_read( + int unit, + const char **c_dev, /* Control device */ + const char **i_dev /* input device */ + ) +{ + FILE *fd; + char device[20], line[100], ab[100]; + + snprintf(device, sizeof(device), "%s%d", INIT_FILE, unit); + if ((fd = fopen(device, "r")) == NULL) { + printf("audio_config_read: <%s> NO\n", device); + snprintf(device, sizeof(device), "%s.%d", INIT_FILE, + unit); + if ((fd = fopen(device, "r")) == NULL) { + printf("audio_config_read: <%s> NO\n", device); + snprintf(device, sizeof(device), "%s", + INIT_FILE); + if ((fd = fopen(device, "r")) == NULL) { + printf("audio_config_read: <%s> NO\n", + device); + return; + } + } + } + printf("audio_config_read: reading <%s>\n", device); + while (fgets(line, sizeof line, fd)) { + char *cp, *cc, *ca; + int i; + + /* Remove comments */ + if ((cp = strchr(line, '#'))) + *cp = '\0'; + + /* Remove any trailing spaces */ + for (i = strlen(line); + i > 0 && isascii((unsigned char)line[i - 1]) && isspace((unsigned char)line[i - 1]); + ) + line[--i] = '\0'; + + /* Remove leading space */ + for (cc = line; *cc && isascii((unsigned char)*cc) && isspace((unsigned char)*cc); cc++) + continue; + + /* Stop if nothing left */ + if (!*cc) + continue; + + /* Uppercase the command and find the arg */ + for (ca = cc; *ca; ca++) { + if (isascii((unsigned char)*ca)) { + if (islower((unsigned char)*ca)) { + *ca = toupper((unsigned char)*ca); + } else if (isspace((unsigned char)*ca) || (*ca == '=')) + break; + } + } + + /* Remove space (and possible =) leading the arg */ + for (; *ca && isascii((unsigned char)*ca) && (isspace((unsigned char)*ca) || (*ca == '=')); ca++) + continue; + + if (!strncmp(cc, "IDEV", 4) && + 1 == sscanf(ca, "%99s", ab)) { + strlcpy(cf_i_dev, ab, sizeof(cf_i_dev)); + printf("idev <%s>\n", ab); + } else if (!strncmp(cc, "CDEV", 4) && + 1 == sscanf(ca, "%99s", ab)) { + strlcpy(cf_c_dev, ab, sizeof(cf_c_dev)); + printf("cdev <%s>\n", ab); + } else if (!strncmp(cc, "AGC", 3) && + 1 == sscanf(ca, "%99s", ab)) { + strlcpy(cf_agc, ab, sizeof(cf_agc)); + printf("agc <%s> %d\n", ab, i); + } else if (!strncmp(cc, "MONITOR", 7) && + 1 == sscanf(ca, "%99s", ab)) { + strlcpy(cf_monitor, ab, sizeof(cf_monitor)); + printf("monitor <%s> %d\n", ab, mixer_name(ab, -1)); + } + } + fclose(fd); + return; +} +#endif /* PCM_STYLE_SOUND */ + +/* + * audio_init - open and initialize audio device + * + * This code works with SunOS 4.x, Solaris 2.x, and PCM; however, it is + * believed generic and applicable to other systems with a minor twid + * or two. All it does is open the device, set the buffer size (Solaris + * only), preset the gain and set the input port. It assumes that the + * codec sample rate (8000 Hz), precision (8 bits), number of channels + * (1) and encoding (ITU-T G.711 mu-law companded) have been set by + * default. + */ +int +audio_init( + const char *dname, /* device name */ + int bufsiz, /* buffer size */ + int unit /* device unit (0-3) */ + ) +{ +#ifdef PCM_STYLE_SOUND +# define ACTL_DEV "/dev/mixer%d" + char actl_dev[30]; +# ifdef HAVE_STRUCT_SND_SIZE + struct snd_size s_size; +# endif +# ifdef AIOGFMT + snd_chan_param s_c_p; +# endif +#endif + int fd; + int rval; + const char *actl = +#ifdef PCM_STYLE_SOUND + actl_dev +#else + "/dev/audioctl" +#endif + ; + +#ifdef PCM_STYLE_SOUND + snprintf(actl_dev, sizeof(actl_dev), ACTL_DEV, unit); + + audio_config_read(unit, &actl, &dname); + /* If we have values for cf_c_dev or cf_i_dev, use them. */ + if (*cf_c_dev) + actl = cf_c_dev; + if (*cf_i_dev) + dname = cf_i_dev; +#endif + + /* + * Open audio device + */ + fd = open(dname, O_RDWR | O_NONBLOCK, 0777); + if (fd < 0) { + msyslog(LOG_ERR, "audio_init: %s %m", dname); + return (fd); + } + + /* + * Open audio control device. + */ + ctl_fd = open(actl, O_RDWR); + if (ctl_fd < 0) { + msyslog(LOG_ERR, "audio_init: invalid control device <%s>", + actl); + close(fd); + return(ctl_fd); + } + + /* + * Set audio device parameters. + */ +#ifdef PCM_STYLE_SOUND + printf("audio_init: <%s> bufsiz %d\n", dname, bufsiz); + rval = fd; + +# ifdef HAVE_STRUCT_SND_SIZE + if (ioctl(fd, AIOGSIZE, &s_size) == -1) + printf("audio_init: AIOGSIZE: %s\n", strerror(errno)); + else + printf("audio_init: orig: play_size %d, rec_size %d\n", + s_size.play_size, s_size.rec_size); + + s_size.play_size = s_size.rec_size = bufsiz; + printf("audio_init: want: play_size %d, rec_size %d\n", + s_size.play_size, s_size.rec_size); + + if (ioctl(fd, AIOSSIZE, &s_size) == -1) + printf("audio_init: AIOSSIZE: %s\n", strerror(errno)); + else + printf("audio_init: set: play_size %d, rec_size %d\n", + s_size.play_size, s_size.rec_size); +# endif /* HAVE_STRUCT_SND_SIZE */ + +# ifdef SNDCTL_DSP_SETFRAGMENT + { + int tmp = (16 << 16) + 6; /* 16 fragments, each 2^6 bytes */ + if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) + printf("audio_init: SNDCTL_DSP_SETFRAGMENT: %s\n", + strerror(errno)); + } +# endif /* SNDCTL_DSP_SETFRAGMENT */ + +# ifdef AIOGFMT + if (ioctl(fd, AIOGFMT, &s_c_p) == -1) + printf("audio_init: AIOGFMT: %s\n", strerror(errno)); + else + printf("audio_init: play_rate %lu, rec_rate %lu, play_format %#lx, rec_format %#lx\n", + s_c_p.play_rate, s_c_p.rec_rate, s_c_p.play_format, s_c_p.rec_format); +# endif + + /* Grab the device and record masks */ + + if (ioctl(ctl_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) + printf("SOUND_MIXER_READ_DEVMASK: %s\n", strerror(errno)); + if (ioctl(ctl_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) + printf("SOUND_MIXER_READ_RECMASK: %s\n", strerror(errno)); + + /* validate and set any specified config file stuff */ + if (cf_agc[0] != '\0') { + int i; + + /* recmask */ + i = mixer_name(cf_agc, recmask); + if (i >= 0) + agc = MIXER_WRITE(i); + else + printf("input %s not in recmask %#x\n", + cf_agc, recmask); + } + + if (cf_monitor[0] != '\0') { + int i; + + /* devmask */ + i = mixer_name(cf_monitor, devmask); + if (i >= 0) + audiomonitor = MIXER_WRITE(i); + else + printf("monitor %s not in devmask %#x\n", + cf_monitor, devmask); + } + +#else /* not PCM_STYLE_SOUND */ + AUDIO_INITINFO(&info); + info.play.gain = AUDIO_MAX_GAIN; + info.play.port = AUDIO_SPEAKER; +# ifdef HAVE_SYS_AUDIOIO_H + info.record.buffer_size = bufsiz; +# endif /* HAVE_SYS_AUDIOIO_H */ + rval = ioctl(ctl_fd, (int)AUDIO_SETINFO, (char *)&info); + if (rval < 0) { + msyslog(LOG_ERR, "audio: invalid control device parameters"); + close(ctl_fd); + close(fd); + return(rval); + } + rval = fd; +#endif /* not PCM_STYLE_SOUND */ + return (rval); +} + + +/* + * audio_gain - adjust codec gains and port + */ +int +audio_gain( + int gain, /* volume level (gain) 0-255 */ + int mongain, /* input to output mix (monitor gain) 0-255 */ + int port /* selected I/O port: 1 mic/2 line in */ + ) +{ + int rval; + static int o_mongain = -1; + static int o_port = -1; + +#ifdef PCM_STYLE_SOUND + int l, r; + +# ifdef GCC + rval = 0; /* GCC thinks rval is used uninitialized */ +# endif + + r = l = 100 * gain / 255; /* Normalize to 0-100 */ +# ifdef DEBUG + if (debug > 1) + printf("audio_gain: gain %d/%d\n", gain, l); +# endif +#if 0 /* not a good idea to do this; connector wiring dependency */ + /* figure out what channel(s) to use. just nuke right for now. */ + r = 0 ; /* setting to zero nicely mutes the channel */ +#endif + l |= r << 8; + if (cf_agc[0] != '\0') + rval = ioctl(ctl_fd, agc, &l); + else + rval = ioctl(ctl_fd + , (2 == port) + ? SOUND_MIXER_WRITE_LINE + : SOUND_MIXER_WRITE_MIC + , &l); + if (-1 == rval) { + printf("audio_gain: agc write: %s\n", strerror(errno)); + return rval; + } + + if (o_mongain != mongain) { + r = l = 100 * mongain / 255; /* Normalize to 0-100 */ +# ifdef DEBUG + if (debug > 1) + printf("audio_gain: mongain %d/%d\n", mongain, l); +# endif + l |= r << 8; + if (cf_monitor[0] != '\0') + rval = ioctl(ctl_fd, audiomonitor, &l ); + else + rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_VOLUME, + &l); + if (-1 == rval) { + printf("audio_gain: mongain write: %s\n", + strerror(errno)); + return (rval); + } + o_mongain = mongain; + } + + if (o_port != port) { +# ifdef DEBUG + if (debug > 1) + printf("audio_gain: port %d\n", port); +# endif + l = (1 << ((port == 2) ? SOUND_MIXER_LINE : SOUND_MIXER_MIC)); + rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_RECSRC, &l); + if (rval == -1) { + printf("SOUND_MIXER_WRITE_RECSRC: %s\n", + strerror(errno)); + return (rval); + } +# ifdef DEBUG + if (debug > 1) { + if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &l) == -1) + printf("SOUND_MIXER_WRITE_RECSRC: %s\n", + strerror(errno)); + else + printf("audio_gain: recsrc is %d\n", l); + } +# endif + o_port = port; + } +#else /* not PCM_STYLE_SOUND */ + ioctl(ctl_fd, (int)AUDIO_GETINFO, (char *)&info); + info.record.encoding = AUDIO_ENCODING_ULAW; + info.record.error = 0; + info.record.gain = gain; + if (o_mongain != mongain) + o_mongain = info.monitor_gain = mongain; + if (o_port != port) + o_port = info.record.port = port; + rval = ioctl(ctl_fd, (int)AUDIO_SETINFO, (char *)&info); + if (rval < 0) { + msyslog(LOG_ERR, "audio_gain: %m"); + return (rval); + } + rval = info.record.error; +#endif /* not PCM_STYLE_SOUND */ + return (rval); +} + + +/* + * audio_show - display audio parameters + * + * This code doesn't really do anything, except satisfy curiousity and + * verify the ioctl's work. + */ +void +audio_show(void) +{ +#ifdef PCM_STYLE_SOUND + int recsrc = 0; + + printf("audio_show: ctl_fd %d\n", ctl_fd); + if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) + printf("SOUND_MIXER_READ_RECSRC: %s\n", strerror(errno)); + +#else /* not PCM_STYLE_SOUND */ +# ifdef HAVE_SYS_AUDIOIO_H + ioctl(ctl_fd, (int)AUDIO_GETDEV, &device); + printf("audio: name %s, version %s, config %s\n", + device.name, device.version, device.config); +# endif /* HAVE_SYS_AUDIOIO_H */ + ioctl(ctl_fd, (int)AUDIO_GETINFO, (char *)&info); + printf( + "audio: rate %d, chan %d, prec %d, code %d, gain %d, mon %d, port %d\n", + info.record.sample_rate, info.record.channels, + info.record.precision, info.record.encoding, + info.record.gain, info.monitor_gain, info.record.port); + printf( + "audio: samples %d, eof %d, pause %d, error %d, waiting %d, balance %d\n", + info.record.samples, info.record.eof, + info.record.pause, info.record.error, + info.record.waiting, info.record.balance); +#endif /* not PCM_STYLE_SOUND */ +} +#else +int audio_bs; +#endif /* HAVE_{SYS_AUDIOIO,SUN_AUDIOIO,MACHINE_SOUNDCARD,SYS_SOUNDCARD}_H */ diff --git a/contrib/ntp/libntp/authkeys.c b/contrib/ntp/libntp/authkeys.c new file mode 100644 index 000000000000..51337d5c4f6f --- /dev/null +++ b/contrib/ntp/libntp/authkeys.c @@ -0,0 +1,827 @@ +/* + * authkeys.c - routines to manage the storage of authentication keys + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <math.h> +#include <stdio.h> + +#include "ntp.h" +#include "ntp_fp.h" +#include "ntpd.h" +#include "ntp_lists.h" +#include "ntp_string.h" +#include "ntp_malloc.h" +#include "ntp_stdlib.h" +#include "ntp_keyacc.h" + +/* + * Structure to store keys in in the hash table. + */ +typedef struct savekey symkey; + +struct savekey { + symkey * hlink; /* next in hash bucket */ + DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */ + u_char * secret; /* shared secret */ + KeyAccT * keyacclist; /* Private key access list */ + u_long lifetime; /* remaining lifetime */ + keyid_t keyid; /* key identifier */ + u_short type; /* OpenSSL digest NID */ + size_t secretsize; /* secret octets */ + u_short flags; /* KEY_ flags that wave */ +}; + +/* define the payload region of symkey beyond the list pointers */ +#define symkey_payload secret + +#define KEY_TRUSTED 0x001 /* this key is trusted */ + +#ifdef DEBUG +typedef struct symkey_alloc_tag symkey_alloc; + +struct symkey_alloc_tag { + symkey_alloc * link; + void * mem; /* enable free() atexit */ +}; + +symkey_alloc * authallocs; +#endif /* DEBUG */ + +static u_short auth_log2(size_t); +static void auth_resize_hashtable(void); +static void allocsymkey(keyid_t, u_short, + u_short, u_long, size_t, u_char *, KeyAccT *); +static void freesymkey(symkey *); +#ifdef DEBUG +static void free_auth_mem(void); +#endif + +symkey key_listhead; /* list of all in-use keys */; +/* + * The hash table. This is indexed by the low order bits of the + * keyid. We make this fairly big for potentially busy servers. + */ +#define DEF_AUTHHASHSIZE 64 +/*#define HASHMASK ((HASHSIZE)-1)*/ +#define KEYHASH(keyid) ((keyid) & authhashmask) + +int authhashdisabled; +u_short authhashbuckets = DEF_AUTHHASHSIZE; +u_short authhashmask = DEF_AUTHHASHSIZE - 1; +symkey **key_hash; + +u_long authkeynotfound; /* keys not found */ +u_long authkeylookups; /* calls to lookup keys */ +u_long authnumkeys; /* number of active keys */ +u_long authkeyexpired; /* key lifetime expirations */ +u_long authkeyuncached; /* cache misses */ +u_long authnokey; /* calls to encrypt with no key */ +u_long authencryptions; /* calls to encrypt */ +u_long authdecryptions; /* calls to decrypt */ + +/* + * Storage for free symkey structures. We malloc() such things but + * never free them. + */ +symkey *authfreekeys; +int authnumfreekeys; + +#define MEMINC 16 /* number of new free ones to get */ + +/* + * The key cache. We cache the last key we looked at here. + * Note: this should hold the last *trusted* key. Also the + * cache is only loaded when the digest type / MAC algorithm + * is valid. + */ +keyid_t cache_keyid; /* key identifier */ +u_char *cache_secret; /* secret */ +size_t cache_secretsize; /* secret length */ +int cache_type; /* OpenSSL digest NID */ +u_short cache_flags; /* flags that wave */ +KeyAccT *cache_keyacclist; /* key access list */ + +/* -------------------------------------------------------------------- + * manage key access lists + * -------------------------------------------------------------------- + */ +/* allocate and populate new access node and pushes it on the list. + * Returns the new head. + */ +KeyAccT* +keyacc_new_push( + KeyAccT * head, + const sockaddr_u * addr + ) +{ + KeyAccT * node = emalloc(sizeof(KeyAccT)); + + memcpy(&node->addr, addr, sizeof(sockaddr_u)); + node->next = head; + return node; +} + +/* ----------------------------------------------------------------- */ +/* pop and deallocate the first node of a list of access nodes, if + * the list is not empty. Returns the tail of the list. + */ +KeyAccT* +keyacc_pop_free( + KeyAccT *head + ) +{ + KeyAccT * next = NULL; + if (head) { + next = head->next; + free(head); + } + return next; +} + +/* ----------------------------------------------------------------- */ +/* deallocate the list; returns an empty list. */ +KeyAccT* +keyacc_all_free( + KeyAccT * head + ) +{ + while (head) + head = keyacc_pop_free(head); + return head; +} + +/* ----------------------------------------------------------------- */ +/* scan a list to see if it contains a given address. Return the + * default result value in case of an empty list. + */ +int /*BOOL*/ +keyacc_contains( + const KeyAccT *head, + const sockaddr_u *addr, + int defv) +{ + if (head) { + do { + if (SOCK_EQ(&head->addr, addr)) + return TRUE; + } while (NULL != (head = head->next)); + return FALSE; + } else { + return !!defv; + } +} + + +/* + * init_auth - initialize internal data + */ +void +init_auth(void) +{ + size_t newalloc; + + /* + * Initialize hash table and free list + */ + newalloc = authhashbuckets * sizeof(key_hash[0]); + + key_hash = erealloc(key_hash, newalloc); + memset(key_hash, '\0', newalloc); + + INIT_DLIST(key_listhead, llink); + +#ifdef DEBUG + atexit(&free_auth_mem); +#endif +} + + +/* + * free_auth_mem - assist in leak detection by freeing all dynamic + * allocations from this module. + */ +#ifdef DEBUG +static void +free_auth_mem(void) +{ + symkey * sk; + symkey_alloc * alloc; + symkey_alloc * next_alloc; + + while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { + freesymkey(sk); + } + free(key_hash); + key_hash = NULL; + cache_keyid = 0; + cache_flags = 0; + cache_keyacclist = NULL; + for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { + next_alloc = alloc->link; + free(alloc->mem); + } + authfreekeys = NULL; + authnumfreekeys = 0; +} +#endif /* DEBUG */ + + +/* + * auth_moremem - get some more free key structures + */ +void +auth_moremem( + int keycount + ) +{ + symkey * sk; + int i; +#ifdef DEBUG + void * base; + symkey_alloc * allocrec; +# define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec)) +#else +# define MOREMEM_EXTRA_ALLOC (0) +#endif + + i = (keycount > 0) + ? keycount + : MEMINC; + sk = emalloc_zero(i * sizeof(*sk) + MOREMEM_EXTRA_ALLOC); +#ifdef DEBUG + base = sk; +#endif + authnumfreekeys += i; + + for (; i > 0; i--, sk++) { + LINK_SLIST(authfreekeys, sk, llink.f); + } + +#ifdef DEBUG + allocrec = (void *)sk; + allocrec->mem = base; + LINK_SLIST(authallocs, allocrec, link); +#endif +} + + +/* + * auth_prealloc_symkeys + */ +void +auth_prealloc_symkeys( + int keycount + ) +{ + int allocated; + int additional; + + allocated = authnumkeys + authnumfreekeys; + additional = keycount - allocated; + if (additional > 0) + auth_moremem(additional); + auth_resize_hashtable(); +} + + +static u_short +auth_log2(size_t x) +{ + /* + ** bithack to calculate floor(log2(x)) + ** + ** This assumes + ** - (sizeof(size_t) is a power of two + ** - CHAR_BITS is a power of two + ** - returning zero for arguments <= 0 is OK. + ** + ** Does only shifts, masks and sums in integer arithmetic in + ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for + ** 32bit/64bit size_t) + */ + int s; + int r = 0; + size_t m = ~(size_t)0; + + for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) { + m <<= s; + if (x & m) + r += s; + else + x <<= s; + } + return (u_short)r; +} + +static void +authcache_flush_id( + keyid_t id + ) +{ + if (cache_keyid == id) { + cache_keyid = 0; + cache_type = 0; + cache_flags = 0; + cache_secret = NULL; + cache_secretsize = 0; + cache_keyacclist = NULL; + } +} + + +/* + * auth_resize_hashtable + * + * Size hash table to average 4 or fewer entries per bucket initially, + * within the bounds of at least 4 and no more than 15 bits for the hash + * table index. Populate the hash table. + */ +static void +auth_resize_hashtable(void) +{ + u_long totalkeys; + u_short hashbits; + u_short hash; + size_t newalloc; + symkey * sk; + + totalkeys = authnumkeys + authnumfreekeys; + hashbits = auth_log2(totalkeys / 4) + 1; + hashbits = max(4, hashbits); + hashbits = min(15, hashbits); + + authhashbuckets = 1 << hashbits; + authhashmask = authhashbuckets - 1; + newalloc = authhashbuckets * sizeof(key_hash[0]); + + key_hash = erealloc(key_hash, newalloc); + memset(key_hash, '\0', newalloc); + + ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) + hash = KEYHASH(sk->keyid); + LINK_SLIST(key_hash[hash], sk, hlink); + ITER_DLIST_END() +} + + +/* + * allocsymkey - common code to allocate and link in symkey + * + * secret must be allocated with a free-compatible allocator. It is + * owned by the referring symkey structure, and will be free()d by + * freesymkey(). + */ +static void +allocsymkey( + keyid_t id, + u_short flags, + u_short type, + u_long lifetime, + size_t secretsize, + u_char * secret, + KeyAccT * ka + ) +{ + symkey * sk; + symkey ** bucket; + + bucket = &key_hash[KEYHASH(id)]; + + + if (authnumfreekeys < 1) + auth_moremem(-1); + UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); + DEBUG_ENSURE(sk != NULL); + sk->keyid = id; + sk->flags = flags; + sk->type = type; + sk->secretsize = secretsize; + sk->secret = secret; + sk->keyacclist = ka; + sk->lifetime = lifetime; + LINK_SLIST(*bucket, sk, hlink); + LINK_TAIL_DLIST(key_listhead, sk, llink); + authnumfreekeys--; + authnumkeys++; +} + + +/* + * freesymkey - common code to remove a symkey and recycle its entry. + */ +static void +freesymkey( + symkey * sk + ) +{ + symkey ** bucket; + symkey * unlinked; + + if (NULL == sk) + return; + + authcache_flush_id(sk->keyid); + keyacc_all_free(sk->keyacclist); + + bucket = &key_hash[KEYHASH(sk->keyid)]; + if (sk->secret != NULL) { + memset(sk->secret, '\0', sk->secretsize); + free(sk->secret); + } + UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); + DEBUG_ENSURE(sk == unlinked); + UNLINK_DLIST(sk, llink); + memset((char *)sk + offsetof(symkey, symkey_payload), '\0', + sizeof(*sk) - offsetof(symkey, symkey_payload)); + LINK_SLIST(authfreekeys, sk, llink.f); + authnumkeys--; + authnumfreekeys++; +} + + +/* + * auth_findkey - find a key in the hash table + */ +struct savekey * +auth_findkey( + keyid_t id + ) +{ + symkey * sk; + + for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) + if (id == sk->keyid) + return sk; + return NULL; +} + + +/* + * auth_havekey - return TRUE if the key id is zero or known. The + * key needs not to be trusted. + */ +int +auth_havekey( + keyid_t id + ) +{ + return + (0 == id) || + (cache_keyid == id) || + (NULL != auth_findkey(id)); +} + + +/* + * authhavekey - return TRUE and cache the key, if zero or both known + * and trusted. + */ +int +authhavekey( + keyid_t id + ) +{ + symkey * sk; + + authkeylookups++; + if (0 == id || cache_keyid == id) + return !!(KEY_TRUSTED & cache_flags); + + /* + * Search the bin for the key. If not found, or found but the key + * type is zero, somebody marked it trusted without specifying a + * key or key type. In this case consider the key missing. + */ + authkeyuncached++; + sk = auth_findkey(id); + if ((sk == NULL) || (sk->type == 0)) { + authkeynotfound++; + return FALSE; + } + + /* + * If the key is not trusted, the key is not considered found. + */ + if ( ! (KEY_TRUSTED & sk->flags)) { + authnokey++; + return FALSE; + } + + /* + * The key is found and trusted. Initialize the key cache. + */ + cache_keyid = sk->keyid; + cache_type = sk->type; + cache_flags = sk->flags; + cache_secret = sk->secret; + cache_secretsize = sk->secretsize; + cache_keyacclist = sk->keyacclist; + + return TRUE; +} + + +/* + * authtrust - declare a key to be trusted/untrusted + */ +void +authtrust( + keyid_t id, + u_long trust + ) +{ + symkey * sk; + u_long lifetime; + + /* + * Search bin for key; if it does not exist and is untrusted, + * forget it. + */ + + sk = auth_findkey(id); + if (!trust && sk == NULL) + return; + + /* + * There are two conditions remaining. Either it does not + * exist and is to be trusted or it does exist and is or is + * not to be trusted. + */ + if (sk != NULL) { + /* + * Key exists. If it is to be trusted, say so and update + * its lifetime. If no longer trusted, return it to the + * free list. Flush the cache first to be sure there are + * no discrepancies. + */ + authcache_flush_id(id); + if (trust > 0) { + sk->flags |= KEY_TRUSTED; + if (trust > 1) + sk->lifetime = current_time + trust; + else + sk->lifetime = 0; + } else { + freesymkey(sk); + } + return; + } + + /* + * keyid is not present, but the is to be trusted. We allocate + * a new key, but do not specify a key type or secret. + */ + if (trust > 1) { + lifetime = current_time + trust; + } else { + lifetime = 0; + } + allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); +} + + +/* + * authistrusted - determine whether a key is trusted + */ +int +authistrusted( + keyid_t id + ) +{ + symkey * sk; + + if (id == cache_keyid) + return !!(KEY_TRUSTED & cache_flags); + + authkeyuncached++; + sk = auth_findkey(id); + if (sk == NULL || !(KEY_TRUSTED & sk->flags)) { + authkeynotfound++; + return FALSE; + } + return TRUE; +} + + +/* + * authistrustedip - determine if the IP is OK for the keyid + */ + int + authistrustedip( + keyid_t keyno, + sockaddr_u * sau + ) +{ + symkey * sk; + + /* That specific key was already used to authenticate the + * packet. Therefore, the key *must* exist... There's a chance + * that is not trusted, though. + */ + if (keyno == cache_keyid) { + return (KEY_TRUSTED & cache_flags) && + keyacc_contains(cache_keyacclist, sau, TRUE); + } else { + authkeyuncached++; + sk = auth_findkey(keyno); + INSIST(NULL != sk); + return (KEY_TRUSTED & sk->flags) && + keyacc_contains(sk->keyacclist, sau, TRUE); + } +} + +/* Note: There are two locations below where 'strncpy()' is used. While + * this function is a hazard by itself, it's essential that it is used + * here. Bug 1243 involved that the secret was filled with NUL bytes + * after the first NUL encountered, and 'strlcpy()' simply does NOT have + * this behaviour. So disabling the fix and reverting to the buggy + * behaviour due to compatibility issues MUST also fill with NUL and + * this needs 'strncpy'. Also, the secret is managed as a byte blob of a + * given size, and eventually truncating it and replacing the last byte + * with a NUL would be a bug. + * perlinger@ntp.org 2015-10-10 + */ +void +MD5auth_setkey( + keyid_t keyno, + int keytype, + const u_char *key, + size_t secretsize, + KeyAccT *ka + ) +{ + symkey * sk; + u_char * secret; + + DEBUG_ENSURE(keytype <= USHRT_MAX); + DEBUG_ENSURE(secretsize < 4 * 1024); + /* + * See if we already have the key. If so just stick in the + * new value. + */ + sk = auth_findkey(keyno); + if (sk != NULL && keyno == sk->keyid) { + /* TALOS-CAN-0054: make sure we have a new buffer! */ + if (NULL != sk->secret) { + memset(sk->secret, 0, sk->secretsize); + free(sk->secret); + } + sk->secret = emalloc(secretsize + 1); + sk->type = (u_short)keytype; + sk->secretsize = secretsize; + /* make sure access lists don't leak here! */ + if (ka != sk->keyacclist) { + keyacc_all_free(sk->keyacclist); + sk->keyacclist = ka; + } +#ifndef DISABLE_BUG1243_FIX + memcpy(sk->secret, key, secretsize); +#else + /* >MUST< use 'strncpy()' here! See above! */ + strncpy((char *)sk->secret, (const char *)key, + secretsize); +#endif + authcache_flush_id(keyno); + return; + } + + /* + * Need to allocate new structure. Do it. + */ + secret = emalloc(secretsize + 1); +#ifndef DISABLE_BUG1243_FIX + memcpy(secret, key, secretsize); +#else + /* >MUST< use 'strncpy()' here! See above! */ + strncpy((char *)secret, (const char *)key, secretsize); +#endif + allocsymkey(keyno, 0, (u_short)keytype, 0, + secretsize, secret, ka); +#ifdef DEBUG + if (debug >= 4) { + size_t j; + + printf("auth_setkey: key %d type %d len %d ", (int)keyno, + keytype, (int)secretsize); + for (j = 0; j < secretsize; j++) { + printf("%02x", secret[j]); + } + printf("\n"); + } +#endif +} + + +/* + * auth_delkeys - delete non-autokey untrusted keys, and clear all info + * except the trusted bit of non-autokey trusted keys, in + * preparation for rereading the keys file. + */ +void +auth_delkeys(void) +{ + symkey * sk; + + ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) + if (sk->keyid > NTP_MAXKEY) { /* autokey */ + continue; + } + + /* + * Don't lose info as to which keys are trusted. Make + * sure there are no dangling pointers! + */ + if (KEY_TRUSTED & sk->flags) { + if (sk->secret != NULL) { + memset(sk->secret, 0, sk->secretsize); + free(sk->secret); + sk->secret = NULL; /* TALOS-CAN-0054 */ + } + sk->keyacclist = keyacc_all_free(sk->keyacclist); + sk->secretsize = 0; + sk->lifetime = 0; + } else { + freesymkey(sk); + } + ITER_DLIST_END() +} + + +/* + * auth_agekeys - delete keys whose lifetimes have expired + */ +void +auth_agekeys(void) +{ + symkey * sk; + + ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) + if (sk->lifetime > 0 && current_time > sk->lifetime) { + freesymkey(sk); + authkeyexpired++; + } + ITER_DLIST_END() + DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", + current_time, authnumkeys, authkeyexpired)); +} + + +/* + * authencrypt - generate message authenticator + * + * Returns length of authenticator field, zero if key not found. + */ +size_t +authencrypt( + keyid_t keyno, + u_int32 * pkt, + size_t length + ) +{ + /* + * A zero key identifier means the sender has not verified + * the last message was correctly authenticated. The MAC + * consists of a single word with value zero. + */ + authencryptions++; + pkt[length / 4] = htonl(keyno); + if (0 == keyno) { + return 4; + } + if (!authhavekey(keyno)) { + return 0; + } + + return MD5authencrypt(cache_type, cache_secret, pkt, length); +} + + +/* + * authdecrypt - verify message authenticator + * + * Returns TRUE if authenticator valid, FALSE if invalid or not found. + */ +int +authdecrypt( + keyid_t keyno, + u_int32 * pkt, + size_t length, + size_t size + ) +{ + /* + * A zero key identifier means the sender has not verified + * the last message was correctly authenticated. For our + * purpose this is an invalid authenticator. + */ + authdecryptions++; + if (0 == keyno || !authhavekey(keyno) || size < 4) { + return FALSE; + } + + return MD5authdecrypt(cache_type, cache_secret, pkt, length, + size); +} diff --git a/contrib/ntp/libntp/authreadkeys.c b/contrib/ntp/libntp/authreadkeys.c new file mode 100644 index 000000000000..e9273ad61dbe --- /dev/null +++ b/contrib/ntp/libntp/authreadkeys.c @@ -0,0 +1,369 @@ +/* + * authreadkeys.c - routines to support the reading of the key file + */ +#include <config.h> +#include <stdio.h> +#include <ctype.h> + +#include "ntpd.h" /* Only for DPRINTF */ +#include "ntp_fp.h" +#include "ntp.h" +#include "ntp_syslog.h" +#include "ntp_stdlib.h" +#include "ntp_keyacc.h" + +#ifdef OPENSSL +#include "openssl/objects.h" +#include "openssl/evp.h" +#endif /* OPENSSL */ + +/* Forwards */ +static char *nexttok (char **); + +/* + * nexttok - basic internal tokenizing routine + */ +static char * +nexttok( + char **str + ) +{ + register char *cp; + char *starttok; + + cp = *str; + + /* + * Space past white space + */ + while (*cp == ' ' || *cp == '\t') + cp++; + + /* + * Save this and space to end of token + */ + starttok = cp; + while (*cp != '\0' && *cp != '\n' && *cp != ' ' + && *cp != '\t' && *cp != '#') + cp++; + + /* + * If token length is zero return an error, else set end of + * token to zero and return start. + */ + if (starttok == cp) + return NULL; + + if (*cp == ' ' || *cp == '\t') + *cp++ = '\0'; + else + *cp = '\0'; + + *str = cp; + return starttok; +} + + +/* TALOS-CAN-0055: possibly DoS attack by setting the key file to the + * log file. This is hard to prevent (it would need to check two files + * to be the same on the inode level, which will not work so easily with + * Windows or VMS) but we can avoid the self-amplification loop: We only + * log the first 5 errors, silently ignore the next 10 errors, and give + * up when when we have found more than 15 errors. + * + * This avoids the endless file iteration we will end up with otherwise, + * and also avoids overflowing the log file. + * + * Nevertheless, once this happens, the keys are gone since this would + * require a save/swap strategy that is not easy to apply due to the + * data on global/static level. + */ + +static const u_int nerr_loglimit = 5u; +static const u_int nerr_maxlimit = 15; + +static void log_maybe(u_int*, const char*, ...) NTP_PRINTF(2, 3); + +typedef struct keydata KeyDataT; +struct keydata { + KeyDataT *next; /* queue/stack link */ + KeyAccT *keyacclist; /* key access list */ + keyid_t keyid; /* stored key ID */ + u_short keytype; /* stored key type */ + u_short seclen; /* length of secret */ + u_char secbuf[1]; /* begin of secret (formal only)*/ +}; + +static void +log_maybe( + u_int *pnerr, + const char *fmt , + ...) +{ + va_list ap; + if ((NULL == pnerr) || (++(*pnerr) <= nerr_loglimit)) { + va_start(ap, fmt); + mvsyslog(LOG_ERR, fmt, ap); + va_end(ap); + } +} + +static void +free_keydata( + KeyDataT *node + ) +{ + KeyAccT *kap; + + if (node) { + while (node->keyacclist) { + kap = node->keyacclist; + node->keyacclist = kap->next; + free(kap); + } + + /* purge secrets from memory before free()ing it */ + memset(node, 0, sizeof(*node) + node->seclen); + free(node); + } +} + +/* + * authreadkeys - (re)read keys from a file. + */ +int +authreadkeys( + const char *file + ) +{ + FILE *fp; + char *line; + char *token; + keyid_t keyno; + int keytype; + char buf[512]; /* lots of room for line */ + u_char keystr[32]; /* Bug 2537 */ + size_t len; + size_t j; + u_int nerr; + KeyDataT *list = NULL; + KeyDataT *next = NULL; + /* + * Open file. Complain and return if it can't be opened. + */ + fp = fopen(file, "r"); + if (fp == NULL) { + msyslog(LOG_ERR, "authreadkeys: file '%s': %m", + file); + goto onerror; + } + INIT_SSL(); + + /* + * Now read lines from the file, looking for key entries. Put + * the data into temporary store for later propagation to avoid + * two-pass processing. + */ + nerr = 0; + while ((line = fgets(buf, sizeof buf, fp)) != NULL) { + if (nerr > nerr_maxlimit) + break; + token = nexttok(&line); + if (token == NULL) + continue; + + /* + * First is key number. See if it is okay. + */ + keyno = atoi(token); + if (keyno < 1) { + log_maybe(&nerr, + "authreadkeys: cannot change key %s", + token); + continue; + } + + if (keyno > NTP_MAXKEY) { + log_maybe(&nerr, + "authreadkeys: key %s > %d reserved for Autokey", + token, NTP_MAXKEY); + continue; + } + + /* + * Next is keytype. See if that is all right. + */ + token = nexttok(&line); + if (token == NULL) { + log_maybe(&nerr, + "authreadkeys: no key type for key %d", + keyno); + continue; + } + + /* We want to silently ignore keys where we do not + * support the requested digest type. OTOH, we want to + * make sure the file is well-formed. That means we + * have to process the line completely and have to + * finally throw away the result... This is a bit more + * work, but it also results in better error detection. + */ +#ifdef OPENSSL + /* + * The key type is the NID used by the message digest + * algorithm. There are a number of inconsistencies in + * the OpenSSL database. We attempt to discover them + * here and prevent use of inconsistent data later. + */ + keytype = keytype_from_text(token, NULL); + if (keytype == 0) { + log_maybe(NULL, + "authreadkeys: invalid type for key %d", + keyno); + } else if (EVP_get_digestbynid(keytype) == NULL) { + log_maybe(NULL, + "authreadkeys: no algorithm for key %d", + keyno); + keytype = 0; + } +#else /* !OPENSSL follows */ + /* + * The key type is unused, but is required to be 'M' or + * 'm' for compatibility. + */ + if (!(*token == 'M' || *token == 'm')) { + log_maybe(NULL, + "authreadkeys: invalid type for key %d", + keyno); + keytype = 0; + } else { + keytype = KEY_TYPE_MD5; + } +#endif /* !OPENSSL */ + + /* + * Finally, get key and insert it. If it is longer than 20 + * characters, it is a binary string encoded in hex; + * otherwise, it is a text string of printable ASCII + * characters. + */ + token = nexttok(&line); + if (token == NULL) { + log_maybe(&nerr, + "authreadkeys: no key for key %d", keyno); + continue; + } + next = NULL; + len = strlen(token); + if (len <= 20) { /* Bug 2537 */ + next = emalloc(sizeof(KeyDataT) + len); + next->keyacclist = NULL; + next->keyid = keyno; + next->keytype = keytype; + next->seclen = len; + memcpy(next->secbuf, token, len); + } else { + static const char hex[] = "0123456789abcdef"; + u_char temp; + char *ptr; + size_t jlim; + + jlim = min(len, 2 * sizeof(keystr)); + for (j = 0; j < jlim; j++) { + ptr = strchr(hex, tolower((unsigned char)token[j])); + if (ptr == NULL) + break; /* abort decoding */ + temp = (u_char)(ptr - hex); + if (j & 1) + keystr[j / 2] |= temp; + else + keystr[j / 2] = temp << 4; + } + if (j < jlim) { + log_maybe(&nerr, + "authreadkeys: invalid hex digit for key %d", + keyno); + continue; + } + len = jlim/2; /* hmmmm.... what about odd length?!? */ + next = emalloc(sizeof(KeyDataT) + len); + next->keyacclist = NULL; + next->keyid = keyno; + next->keytype = keytype; + next->seclen = len; + memcpy(next->secbuf, keystr, len); + } + + token = nexttok(&line); + DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL")); + if (token != NULL) { /* A comma-separated IP access list */ + char *tp = token; + + while (tp) { + char *i; + sockaddr_u addr; + + i = strchr(tp, (int)','); + if (i) + *i = '\0'; + DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); + + if (is_ip_address(tp, AF_UNSPEC, &addr)) { + next->keyacclist = keyacc_new_push( + next->keyacclist, &addr); + } else { + log_maybe(&nerr, + "authreadkeys: invalid IP address <%s> for key %d", + tp, keyno); + } + + if (i) { + tp = i + 1; + } else { + tp = 0; + } + } + } + + /* check if this has to be weeded out... */ + if (0 == keytype) { + free_keydata(next); + next = NULL; + continue; + } + + INSIST(NULL != next); + next->next = list; + list = next; + } + fclose(fp); + if (nerr > 0) { + const char * why = ""; + if (nerr > nerr_maxlimit) + why = " (emergency break)"; + msyslog(LOG_ERR, + "authreadkeys: rejecting file '%s' after %u error(s)%s", + file, nerr, why); + goto onerror; + } + + /* first remove old file-based keys */ + auth_delkeys(); + /* insert the new key material */ + while (NULL != (next = list)) { + list = next->next; + MD5auth_setkey(next->keyid, next->keytype, + next->secbuf, next->seclen, next->keyacclist); + next->keyacclist = NULL; /* consumed by MD5auth_setkey */ + free_keydata(next); + } + return (1); + + onerror: + /* Mop up temporary storage before bailing out. */ + while (NULL != (next = list)) { + list = next->next; + free_keydata(next); + } + return (0); +} diff --git a/contrib/ntp/libntp/authusekey.c b/contrib/ntp/libntp/authusekey.c new file mode 100644 index 000000000000..ff449d3df6fc --- /dev/null +++ b/contrib/ntp/libntp/authusekey.c @@ -0,0 +1,34 @@ +/* + * authusekey - decode a key from ascii and use it + */ +#include <config.h> +#include <stdio.h> +#include <ctype.h> + +#include "ntp_types.h" +#include "ntp_string.h" +#include "ntp_stdlib.h" + +/* + * Types of ascii representations for keys. "Standard" means a 64 bit + * hex number in NBS format, i.e. with the low order bit of each byte + * a parity bit. "NTP" means a 64 bit key in NTP format, with the + * high order bit of each byte a parity bit. "Ascii" means a 1-to-8 + * character string whose ascii representation is used as the key. + */ +int +authusekey( + keyid_t keyno, + int keytype, + const u_char *str + ) +{ + size_t len; + + len = strlen((const char *)str); + if (0 == len) + return 0; + + MD5auth_setkey(keyno, keytype, str, len, NULL); + return 1; +} diff --git a/contrib/ntp/libntp/bsd_strerror.c b/contrib/ntp/libntp/bsd_strerror.c new file mode 100644 index 000000000000..5ace9aa48542 --- /dev/null +++ b/contrib/ntp/libntp/bsd_strerror.c @@ -0,0 +1,49 @@ +#include <config.h> + +#if !HAVE_STRERROR +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strerror.c 5.1 (Berkeley) 4/9/89"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> + +#include <stdio.h> +#include <string.h> + +#include "l_stdlib.h" + +char * +strerror( + int errnum + ) +{ + extern int sys_nerr; + extern char *sys_errlist[]; + static char ebuf[20]; + + if ((unsigned int)errnum < sys_nerr) + return sys_errlist[errnum]; + snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", errnum); + + return ebuf; +} +#else +int strerror_bs; +#endif diff --git a/contrib/ntp/libntp/buftvtots.c b/contrib/ntp/libntp/buftvtots.c new file mode 100644 index 000000000000..a77e9f7c9ba2 --- /dev/null +++ b/contrib/ntp/libntp/buftvtots.c @@ -0,0 +1,38 @@ +/* + * buftvtots - pull a Unix-format (struct timeval) time stamp out of + * an octet stream and convert it to a l_fp time stamp. + * This is useful when using the clock line discipline. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "ntp_fp.h" +#include "ntp_string.h" +#include "timevalops.h" + +#ifndef SYS_WINNT +int +buftvtots( + const char *bufp, + l_fp *ts + ) +{ + struct timeval tv; + + /* + * copy to adhere to alignment restrictions + */ + memcpy(&tv, bufp, sizeof(tv)); + + /* + * and use it + */ + if (tv.tv_usec > MICROSECONDS - 1) + return FALSE; + + *ts = tval_stamp_to_lfp(tv); + + return TRUE; +} +#endif /* !SYS_WINNT */ diff --git a/contrib/ntp/libntp/caljulian.c b/contrib/ntp/libntp/caljulian.c new file mode 100644 index 000000000000..4a306033ad70 --- /dev/null +++ b/contrib/ntp/libntp/caljulian.c @@ -0,0 +1,41 @@ +/* + * caljulian - determine the Julian date from an NTP time. + * + * (Note: since we use the GREGORIAN calendar, this should be renamed to + * 'calgregorian' eventually...) + */ +#include <config.h> +#include <sys/types.h> + +#include "ntp_types.h" +#include "ntp_calendar.h" + +#if !(defined(ISC_CHECK_ALL) || defined(ISC_CHECK_NONE) || \ + defined(ISC_CHECK_ENSURE) || defined(ISC_CHECK_INSIST) || \ + defined(ISC_CHECK_INVARIANT)) +# define ISC_CHECK_ALL +#endif + +#include "ntp_assert.h" + +void +caljulian( + uint32_t ntp, + struct calendar * jt + ) +{ + vint64 vlong; + ntpcal_split split; + + + INSIST(NULL != jt); + + /* + * Unfold ntp time around current time into NTP domain. Split + * into days and seconds, shift days into CE domain and + * process the parts. + */ + vlong = ntpcal_ntp_to_ntp(ntp, NULL); + split = ntpcal_daysplit(&vlong); + ntpcal_daysplit_to_date(jt, &split, DAY_NTP_STARTS); +} diff --git a/contrib/ntp/libntp/caltontp.c b/contrib/ntp/libntp/caltontp.c new file mode 100644 index 000000000000..808c94c64afd --- /dev/null +++ b/contrib/ntp/libntp/caltontp.c @@ -0,0 +1,68 @@ +/* + * caltontp - convert a date to an NTP time + */ +#include <config.h> +#include <sys/types.h> + +#include "ntp_types.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" +#include "ntp_assert.h" +#include "ntp_unixtime.h" + +/* + * Juergen Perlinger, 2008-11-12 + * Add support for full calendar calculatios. If the day-of-year is provided + * (that is, not zero) it will be used instead of month and day-of-month; + * otherwise a full turn through the calendar calculations will be taken. + * + * I know that Harlan Stenn likes to see assertions in production code, and I + * agree there, but it would be a tricky thing here. The algorithm is quite + * capable of producing sensible answers even to seemingly weird inputs: the + * date <any year here>-03-00, the 0.th March of the year, will be automtically + * treated as the last day of February, no matter whether the year is a leap + * year or not. So adding constraints is merely for the benefit of the callers, + * because the only thing we can check for consistency is our input, produced + * by somebody else. + * + * BTW: A total roundtrip using 'caljulian' would be a quite shaky thing: + * Because of the truncation of the NTP time stamp to 32 bits and the epoch + * unfolding around the current time done by 'caljulian' the roundtrip does + * *not* necessarily reproduce the input, especially if the time spec is more + * than 68 years off from the current time... + */ + +uint32_t +caltontp( + const struct calendar *jt + ) +{ + int32_t eraday; /* CE Rata Die number */ + vint64 ntptime;/* resulting NTP time */ + + REQUIRE(jt != NULL); + + REQUIRE(jt->month <= 13); /* permit month 0..13! */ + REQUIRE(jt->monthday <= 32); + REQUIRE(jt->yearday <= 366); + REQUIRE(jt->hour <= 24); + REQUIRE(jt->minute <= MINSPERHR); + REQUIRE(jt->second <= SECSPERMIN); + + /* + * First convert the date to he corresponding RataDie + * number. If yearday is not zero, assume that it contains a + * useable value and avoid all calculations involving month + * and day-of-month. Do a full evaluation otherwise. + */ + if (jt->yearday) + eraday = ntpcal_year_to_ystart(jt->year) + + jt->yearday - 1; + else + eraday = ntpcal_date_to_rd(jt); + + ntptime = ntpcal_dayjoin(eraday - DAY_NTP_STARTS, + ntpcal_etime_to_seconds(jt->hour, jt->minute, + jt->second)); + return ntptime.d_s.lo; +} diff --git a/contrib/ntp/libntp/calyearstart.c b/contrib/ntp/libntp/calyearstart.c new file mode 100644 index 000000000000..9e3f58fb393d --- /dev/null +++ b/contrib/ntp/libntp/calyearstart.c @@ -0,0 +1,88 @@ +/* + * calyearstart - determine the NTP time at midnight of January 1 in + * the year of the given date. + */ +#include <config.h> +#include <sys/types.h> + +#include "ntp_types.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" +#include "ntp_assert.h" + +/* + * Juergen Perlinger, 2010-05-02 + * + * Redone in terms of the calendar functions. It's rather simple: + * - expand the NTP time stamp + * - split into days and seconds since midnight, dropping the partial day + * - get full number of days before year start in NTP epoch + * - convert to seconds, truncated to 32 bits. + */ +u_int32 +calyearstart(u_int32 ntptime, const time_t *pivot) +{ + u_int32 ndays; /* elapsed days since NTP starts */ + vint64 vlong; + ntpcal_split split; + + vlong = ntpcal_ntp_to_ntp(ntptime, pivot); + split = ntpcal_daysplit(&vlong); + ndays = ntpcal_rd_to_ystart(split.hi + DAY_NTP_STARTS) + - DAY_NTP_STARTS; + + return (u_int32)(ndays * SECSPERDAY); +} + +/* + * calmonthstart - get NTP time at midnight of the first day of the + * current month. + */ +u_int32 +calmonthstart(u_int32 ntptime, const time_t *pivot) +{ + u_int32 ndays; /* elapsed days since NTP starts */ + vint64 vlong; + ntpcal_split split; + + vlong = ntpcal_ntp_to_ntp(ntptime, pivot); + split = ntpcal_daysplit(&vlong); + ndays = ntpcal_rd_to_mstart(split.hi + DAY_NTP_STARTS) + - DAY_NTP_STARTS; + + return (u_int32)(ndays * SECSPERDAY); +} + +/* + * calweekstart - get NTP time at midnight of the last monday on or + * before the current date. + */ +u_int32 +calweekstart(u_int32 ntptime, const time_t *pivot) +{ + u_int32 ndays; /* elapsed days since NTP starts */ + vint64 vlong; + ntpcal_split split; + + vlong = ntpcal_ntp_to_ntp(ntptime, pivot); + split = ntpcal_daysplit(&vlong); + ndays = ntpcal_weekday_le(split.hi + DAY_NTP_STARTS, CAL_MONDAY) + - DAY_NTP_STARTS; + + return (u_int32)(ndays * SECSPERDAY); +} + +/* + * caldaystart - get NTP time at midnight of the current day. + */ +u_int32 +caldaystart(u_int32 ntptime, const time_t *pivot) +{ + vint64 vlong; + ntpcal_split split; + + vlong = ntpcal_ntp_to_ntp(ntptime, pivot); + split = ntpcal_daysplit(&vlong); + + return ntptime - split.lo; +} diff --git a/contrib/ntp/libntp/clocktime.c b/contrib/ntp/libntp/clocktime.c new file mode 100644 index 000000000000..c1a3ba09c0af --- /dev/null +++ b/contrib/ntp/libntp/clocktime.c @@ -0,0 +1,149 @@ +/* + * clocktime - compute the NTP date from a day of year, hour, minute + * and second. + */ +#include <config.h> +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_stdlib.h" +#include "ntp_calendar.h" + +/* + * We check that the time be within CLOSETIME seconds of the receive + * time stamp. This is about 4 hours, which hopefully should be wide + * enough to collect most data, while close enough to keep things from + * getting confused. + */ +#define CLOSETIME (4u*60u*60u) + +/* + * Since we try to match years, the result of a full search will not + * change when we are already less than a half year from the receive + * time stamp. Since the length of a year is variable we use a + * slightly narrower limit; this might require a full evaluation near + * the edge, but will make sure we always get the correct result. + */ +#define NEARTIME (182u * SECSPERDAY) + +/* + * local calendar helpers + */ +static int32 ntp_to_year(u_int32); +static u_int32 year_to_ntp(int32); + +/* + * Take a time spec given as day-of-year, hour, minute and second as + * well as a GMT offset in hours and convert it to a NTP time stamp in + * '*ts_ui'. The value will be in the range (rec_ui-0.5yrs) to + * (rec_ui+0.5yrs). A hint for the current start-of-year will be + * read from '*yearstart'. + * + * On return '*ts_ui' will always the best matching solution, and + * '*yearstart' will receive the associated start-of-year. + * + * The function will tell if the result in 'ts_ui' is in CLOSETIME + * (+/-4hrs) around the receive time by returning a non-zero value. + * + * Note: The function puts no constraints on the value ranges for the + * time specification, but evaluates the effective seconds in + * 32-bit arithmetic. + */ +int +clocktime( + int yday , /* day-of-year */ + int hour , /* hour of day */ + int minute , /* minute of hour */ + int second , /* second of minute */ + int tzoff , /* hours west of GMT */ + u_int32 rec_ui , /* pivot value */ + u_long *yearstart, /* cached start-of-year, should be fixed to u_int32 */ + u_int32 *ts_ui ) /* effective time stamp */ +{ + u_int32 ystt[3]; /* year start */ + u_int32 test[3]; /* result time stamp */ + u_int32 diff[3]; /* abs difference to receive */ + int32 y, tmp, idx, min; + + /* + * Compute the offset into the year in seconds. Note that + * this could come out to be a negative number. + */ + tmp = ((int32)second + + SECSPERMIN * ((int32)minute + + MINSPERHR * ((int32)hour + (int32)tzoff + + HRSPERDAY * ((int32)yday - 1)))); + /* + * Based on the cached year start, do a first attempt. Be + * happy and return if this gets us better than NEARTIME to + * the receive time stamp. Do this only if the cached year + * start is not zero, which will not happen after 1900 for the + * next few thousand years. + */ + if (*yearstart) { + /* -- get time stamp of potential solution */ + test[0] = (u_int32)(*yearstart) + tmp; + /* -- calc absolute difference to receive time */ + diff[0] = test[0] - rec_ui; + if (diff[0] >= 0x80000000u) + diff[0] = ~diff[0] + 1; + /* -- can't get closer if diff < NEARTIME */ + if (diff[0] < NEARTIME) { + *ts_ui = test[0]; + return diff[0] < CLOSETIME; + } + } + + /* + * Now the dance begins. Based on the receive time stamp and + * the seconds offset in 'tmp', we make an educated guess + * about the year to start with. This takes us on the spot + * with a fuzz of +/-1 year. + * + * We calculate the effective timestamps for the three years + * around the guess and select the entry with the minimum + * absolute difference to the receive time stamp. + */ + y = ntp_to_year(rec_ui - tmp); + for (idx = 0; idx < 3; idx++) { + /* -- get year start of potential solution */ + ystt[idx] = year_to_ntp(y + idx - 1); + /* -- get time stamp of potential solution */ + test[idx] = ystt[idx] + tmp; + /* -- calc absolute difference to receive time */ + diff[idx] = test[idx] - rec_ui; + if (diff[idx] >= 0x80000000u) + diff[idx] = ~diff[idx] + 1; + } + /* -*- assume current year fits best, then search best fit */ + for (min = 1, idx = 0; idx < 3; idx++) + if (diff[idx] < diff[min]) + min = idx; + /* -*- store results and update year start */ + *ts_ui = test[min]; + *yearstart = ystt[min]; + + /* -*- tell if we could get into CLOSETIME*/ + return diff[min] < CLOSETIME; +} + +static int32 +ntp_to_year( + u_int32 ntp) +{ + vint64 t; + ntpcal_split s; + + t = ntpcal_ntp_to_ntp(ntp, NULL); + s = ntpcal_daysplit(&t); + s = ntpcal_split_eradays(s.hi + DAY_NTP_STARTS - 1, NULL); + return s.hi + 1; +} + +static u_int32 +year_to_ntp( + int32 year) +{ + u_int32 days; + days = ntpcal_days_in_years(year-1) - DAY_NTP_STARTS + 1; + return days * SECSPERDAY; +} diff --git a/contrib/ntp/libntp/clocktypes.c b/contrib/ntp/libntp/clocktypes.c new file mode 100644 index 000000000000..de7f6b4f3854 --- /dev/null +++ b/contrib/ntp/libntp/clocktypes.c @@ -0,0 +1,123 @@ +/* + * Data for pretty printing clock types + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "ntp.h" +#include "lib_strbuf.h" +#include "ntp_refclock.h" +#include "ntp_stdlib.h" + +struct clktype clktypes[] = { + { REFCLK_NONE, "unspecified type (0)", + "UNKNOWN" }, + { REFCLK_LOCALCLOCK, "Undisciplined local clock (1)", + "LOCAL" }, + { REFCLK_GPS_TRAK, "TRAK 8810 GPS Receiver (2)", + "GPS_TRAK" }, + { REFCLK_WWV_PST, "PSTI/Traconex WWV/WWVH Receiver (3)", + "WWV_PST" }, + { REFCLK_SPECTRACOM, "Spectracom (generic) Receivers (4)", + "SPECTRACOM" }, + { REFCLK_TRUETIME, "TrueTime (generic) Receivers (5)", + "TRUETIME" }, + { REFCLK_IRIG_AUDIO, "IRIG Audio Decoder (6)", + "IRIG_AUDIO" }, + { REFCLK_CHU_AUDIO, "CHU Audio Demodulator/Decoder (7)", + "CHU_AUDIO" }, + { REFCLK_PARSE, "Generic reference clock driver (8)", + "GENERIC" }, + { REFCLK_GPS_MX4200, "Magnavox MX4200 GPS Receiver (9)", + "GPS_MX4200" }, + { REFCLK_GPS_AS2201, "Austron 2201A GPS Receiver (10)", + "GPS_AS2201" }, + { REFCLK_GPS_ARBITER, "Arbiter 1088A/B GPS Receiver (11)", + "GPS_ARBITER" }, + { REFCLK_IRIG_TPRO, "KSI/Odetics TPRO/S IRIG Interface (12)", + "IRIG_TPRO" }, + { REFCLK_ATOM_LEITCH, "Leitch CSD 5300 Master Clock Controller (13)", + "ATOM_LEITCH" }, + { REFCLK_MSF_EES, "EES M201 MSF Receiver (14)", + "MSF_EES" }, + { REFCLK_NONE, "not used (15)", + "NOT_USED" }, + { REFCLK_IRIG_BANCOMM, "Bancomm GPS/IRIG Receiver (16)", + "GPS_BANC" }, + { REFCLK_GPS_DATUM, "Datum Precision Time System (17)", + "GPS_DATUM" }, + { REFCLK_ACTS, "Automated Computer Time Service (18)", + "ACTS_MODEM" }, + { REFCLK_WWV_HEATH, "Heath WWV/WWVH Receiver (19)", + "WWV_HEATH" }, + { REFCLK_GPS_NMEA, "Generic NMEA GPS Receiver (20)", + "GPS_NMEA" }, + { REFCLK_GPS_VME, "TrueTime GPS-VME Interface (21)", + "GPS_VME" }, + { REFCLK_ATOM_PPS, "PPS Clock Discipline (22)", + "PPS" }, + { REFCLK_NONE, "not used (23)", + "NOT_USED" }, + { REFCLK_NONE, "not used (24)", + "NOT_USED" }, + { REFCLK_NONE, "not used (25)", + "NOT_USED" }, + { REFCLK_GPS_HP, "HP 58503A GPS Time & Frequency Receiver (26)", + "GPS_HP" }, + { REFCLK_ARCRON_MSF, "ARCRON MSF (and DCF77) Receiver (27)", + "MSF_ARCRON" }, + { REFCLK_SHM, "Clock attached thru shared Memory (28)", + "SHM" }, + { REFCLK_PALISADE, "Trimble Navigation Palisade GPS (29)", + "GPS_PALISADE" }, + { REFCLK_ONCORE, "Motorola UT Oncore GPS (30)", + "GPS_ONCORE" }, + { REFCLK_GPS_JUPITER, "Rockwell Jupiter GPS (31)", + "GPS_JUPITER" }, + { REFCLK_CHRONOLOG, "Chrono-log K (32)", + "CHRONOLOG" }, + { REFCLK_DUMBCLOCK, "Dumb generic hh:mm:ss local clock (33)", + "DUMBCLOCK" }, + { REFCLK_ULINK, "Ultralink M320 WWVB receiver (34)", + "ULINK_M320"}, + { REFCLK_PCF, "Conrad parallel port radio clock (35)", + "PCF"}, + { REFCLK_WWV_AUDIO, "WWV/H Audio Demodulator/Decoder (36)", + "WWV_AUDIO"}, + { REFCLK_FG, "Forum Graphic GPS Dating Station (37)", + "GPS_FG"}, + { REFCLK_HOPF_SERIAL, "hopf Elektronic serial line receiver (38)", + "HOPF_S"}, + { REFCLK_HOPF_PCI, "hopf Elektronic PCI receiver (39)", + "HOPF_P"}, + { REFCLK_JJY, "JJY receiver (40)", + "JJY"}, + { REFCLK_TT560, "TrueTime 560 IRIG-B decoder (41)", + "TT_IRIG"}, + { REFCLK_ZYFER, "Zyfer GPStarplus receiver (42)", + "GPS_ZYFER" }, + { REFCLK_RIPENCC, "RIPE NCC Trimble driver (43)", + "GPS_RIPENCC" }, + { REFCLK_NEOCLOCK4X, "NeoClock4X DCF77 / TDF receiver (44)", + "NEOCLK4X"}, + { REFCLK_TSYNCPCI, "Spectracom TSYNC PCI timing board (45)", + "PCI_TSYNC"}, + { REFCLK_GPSDJSON, "GPSD JSON socket (46)", + "GPSD_JSON"}, + { -1, "", "" } +}; + +const char * +clockname( + int num + ) +{ + register struct clktype *clk; + + for (clk = clktypes; clk->code != -1; clk++) { + if (num == clk->code) + return (clk->abbrev); + } + return (NULL); +} diff --git a/contrib/ntp/libntp/decodenetnum.c b/contrib/ntp/libntp/decodenetnum.c new file mode 100644 index 000000000000..35b908f39478 --- /dev/null +++ b/contrib/ntp/libntp/decodenetnum.c @@ -0,0 +1,86 @@ +/* + * decodenetnum - return a net number (this is crude, but careful) + */ +#include <config.h> +#include <sys/types.h> +#include <ctype.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include "ntp.h" +#include "ntp_stdlib.h" +#include "ntp_assert.h" + +/* + * decodenetnum convert text IP address and port to sockaddr_u + * + * Returns 0 for failure, 1 for success. + */ +int +decodenetnum( + const char *num, + sockaddr_u *netnum + ) +{ + struct addrinfo hints, *ai = NULL; + int err; + u_short port; + const char *cp; + const char *port_str; + char *pp; + char *np; + char name[80]; + + REQUIRE(num != NULL); + + if (strlen(num) >= sizeof(name)) { + return 0; + } + + port_str = NULL; + if ('[' != num[0]) { + /* + * to distinguish IPv6 embedded colons from a port + * specification on an IPv4 address, assume all + * legal IPv6 addresses have at least two colons. + */ + pp = strchr(num, ':'); + if (NULL == pp) + cp = num; /* no colons */ + else if (NULL != strchr(pp + 1, ':')) + cp = num; /* two or more colons */ + else { /* one colon */ + strlcpy(name, num, sizeof(name)); + cp = name; + pp = strchr(cp, ':'); + *pp = '\0'; + port_str = pp + 1; + } + } else { + cp = num + 1; + np = name; + while (*cp && ']' != *cp) + *np++ = *cp++; + *np = 0; + if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) + port_str = &cp[2]; + cp = name; + } + ZERO(hints); + hints.ai_flags = Z_AI_NUMERICHOST; + err = getaddrinfo(cp, "ntp", &hints, &ai); + if (err != 0) + return 0; + INSIST(ai->ai_addrlen <= sizeof(*netnum)); + ZERO(*netnum); + memcpy(netnum, ai->ai_addr, ai->ai_addrlen); + freeaddrinfo(ai); + if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port)) + port = NTP_PORT; + SET_PORT(netnum, port); + return 1; +} diff --git a/contrib/ntp/libntp/dofptoa.c b/contrib/ntp/libntp/dofptoa.c new file mode 100644 index 000000000000..758af2fd7f9f --- /dev/null +++ b/contrib/ntp/libntp/dofptoa.c @@ -0,0 +1,159 @@ +/* + * dofptoa - do the grunge work to convert an fp number to ascii + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "lib_strbuf.h" +#include "ntp_string.h" +#include "ntp_stdlib.h" + +char * +dofptoa( + u_fp fpv, + int neg, + short ndec, + int msec + ) +{ + register u_char *cp, *cpend; + register u_long val; + register short dec; + u_char cbuf[12]; + u_char *cpdec; + char *buf; + char *bp; + + /* + * Get a string buffer before starting + */ + LIB_GETBUF(buf); + + /* + * Zero out the buffer + */ + ZERO(cbuf); + + /* + * Set the pointers to point at the first + * decimal place. Get a local copy of the value. + */ + cp = cpend = &cbuf[5]; + val = fpv; + + /* + * If we have to, decode the integral part + */ + if (!(val & 0xffff0000)) + cp--; + else { + register u_short sv = (u_short)(val >> 16); + register u_short tmp; + register u_short ten = 10; + + do { + tmp = sv; + sv = (u_short) (sv/ten); + *(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1))); + } while (sv != 0); + } + + /* + * Figure out how much of the fraction to do + */ + if (msec) { + dec = (short)(ndec + 3); + if (dec < 3) + dec = 3; + cpdec = &cbuf[8]; + } else { + dec = ndec; + cpdec = cpend; + } + + if (dec > 6) + dec = 6; + + if (dec > 0) { + do { + val &= 0xffff; + val = (val << 3) + (val << 1); + *cpend++ = (u_char)(val >> 16); + } while (--dec > 0); + } + + if (val & 0x8000) { + register u_char *tp; + /* + * Round it. Ick. + */ + tp = cpend; + *(--tp) += 1; + while (*tp >= 10) { + *tp = 0; + *(--tp) += 1; + } + } + + /* + * Remove leading zeroes if necessary + */ + while (cp < (cpdec -1) && *cp == 0) + cp++; + + /* + * Copy it into the buffer, asciizing as we go. + */ + bp = buf; + if (neg) + *bp++ = '-'; + + while (cp < cpend) { + if (cp == cpdec) + *bp++ = '.'; + *bp++ = (char)(*cp++ + '0'); + } + *bp = '\0'; + return buf; +} + + +char * +fptoa( + s_fp fpv, + short ndec + ) +{ + u_fp plusfp; + int neg; + + neg = (fpv < 0); + if (neg) { + plusfp = (u_fp)(-fpv); + } else { + plusfp = (u_fp)fpv; + } + + return dofptoa(plusfp, neg, ndec, FALSE); +} + + +char * +fptoms( + s_fp fpv, + short ndec + ) +{ + u_fp plusfp; + int neg; + + neg = (fpv < 0); + if (neg) { + plusfp = (u_fp)(-fpv); + } else { + plusfp = (u_fp)fpv; + } + + return dofptoa(plusfp, neg, ndec, TRUE); +} diff --git a/contrib/ntp/libntp/dolfptoa.c b/contrib/ntp/libntp/dolfptoa.c new file mode 100644 index 000000000000..68f56e1637e2 --- /dev/null +++ b/contrib/ntp/libntp/dolfptoa.c @@ -0,0 +1,174 @@ +/* + * dolfptoa - do the grunge work of converting an l_fp number to decimal + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "lib_strbuf.h" +#include "ntp_string.h" +#include "ntp_stdlib.h" + +char * +dolfptoa( + u_int32 fpi, + u_int32 fpv, + int neg, + short ndec, + int msec + ) +{ + u_char *cp, *cpend, *cpdec; + int dec; + u_char cbuf[24]; + char *buf, *bp; + + /* + * Get a string buffer before starting + */ + LIB_GETBUF(buf); + + /* + * Zero the character buffer + */ + ZERO(cbuf); + + /* + * Work on the integral part. This should work reasonable on + * all machines with 32 bit arithmetic. Please note that 32 bits + * can *always* be represented with at most 10 decimal digits, + * including a possible rounding from the fractional part. + */ + cp = cpend = cpdec = &cbuf[10]; + for (dec = (int)(cp - cbuf); dec > 0 && fpi != 0; dec--) { + /* can add another digit */ + u_int32 digit; + + digit = fpi; + fpi /= 10U; + digit -= (fpi << 3) + (fpi << 1); /* i*10 */ + *--cp = (u_char)digit; + } + + /* + * Done that, now deal with the problem of the fraction. First + * determine the number of decimal places. + */ + dec = ndec; + if (dec < 0) + dec = 0; + if (msec) { + dec += 3; + cpdec += 3; + } + if ((size_t)dec > sizeof(cbuf) - (cpend - cbuf)) + dec = (int)(sizeof(cbuf) - (cpend - cbuf)); + + /* + * If there's a fraction to deal with, do so. + */ + for (/*NOP*/; dec > 0 && fpv != 0; dec--) { + u_int32 digit, tmph, tmpl; + + /* + * The scheme here is to multiply the fraction + * (0.1234...) by ten. This moves a junk of BCD into + * the units part. record that and iterate. + * multiply by shift/add in two dwords. + */ + digit = 0; + M_LSHIFT(digit, fpv); + tmph = digit; + tmpl = fpv; + M_LSHIFT(digit, fpv); + M_LSHIFT(digit, fpv); + M_ADD(digit, fpv, tmph, tmpl); + *cpend++ = (u_char)digit; + } + + /* decide whether to round or simply extend by zeros */ + if (dec > 0) { + /* only '0' digits left -- just reposition end */ + cpend += dec; + } else { + /* some bits remain in 'fpv'; do round */ + u_char *tp = cpend; + int carry = ((fpv & 0x80000000) != 0); + + for (dec = (int)(tp - cbuf); carry && dec > 0; dec--) { + *--tp += 1; + if (*tp == 10) + *tp = 0; + else + carry = FALSE; + } + + if (tp < cp) /* rounding from 999 to 1000 or similiar? */ + cp = tp; + } + + /* + * We've now got the fraction in cbuf[], with cp pointing at + * the first character, cpend pointing past the last, and + * cpdec pointing at the first character past the decimal. + * Remove leading zeros, then format the number into the + * buffer. + */ + while (cp < cpdec && *cp == 0) + cp++; + if (cp >= cpdec) + cp = cpdec - 1; + + bp = buf; + if (neg) + *bp++ = '-'; + while (cp < cpend) { + if (cp == cpdec) + *bp++ = '.'; + *bp++ = (char)(*cp++) + '0'; + } + *bp = '\0'; + + /* + * Done! + */ + return buf; +} + + +char * +mfptoa( + u_int32 fpi, + u_int32 fpf, + short ndec + ) +{ + int isneg; + + isneg = M_ISNEG(fpi); + if (isneg) { + M_NEG(fpi, fpf); + } + + return dolfptoa(fpi, fpf, isneg, ndec, FALSE); +} + + +char * +mfptoms( + u_int32 fpi, + u_int32 fpf, + short ndec + ) +{ + int isneg; + + isneg = M_ISNEG(fpi); + if (isneg) { + M_NEG(fpi, fpf); + } + + return dolfptoa(fpi, fpf, isneg, ndec, TRUE); +} + + diff --git a/contrib/ntp/libntp/emalloc.c b/contrib/ntp/libntp/emalloc.c new file mode 100644 index 000000000000..8b7ef990c6b6 --- /dev/null +++ b/contrib/ntp/libntp/emalloc.c @@ -0,0 +1,149 @@ +/* + * emalloc - return new memory obtained from the system. Belch if none. + */ +#include <config.h> +#include "ntp_types.h" +#include "ntp_malloc.h" +#include "ntp_syslog.h" +#include "ntp_stdlib.h" + + +/* + * When using the debug MS CRT allocator, each allocation stores the + * callsite __FILE__ and __LINE__, which is then displayed at process + * termination, to track down leaks. We don't want all of our + * allocations to show up as coming from emalloc.c, so we preserve the + * original callsite's source file and line using macros which pass + * __FILE__ and __LINE__ as parameters to these routines. + * Other debug malloc implementations can be used by defining + * EREALLOC_IMPL() as ports/winnt/include/config.h does. + */ + +void * +ereallocz( + void * ptr, + size_t newsz, + size_t priorsz, + int zero_init +#ifdef EREALLOC_CALLSITE /* ntp_malloc.h */ + , + const char * file, + int line +#endif + ) +{ + char * mem; + size_t allocsz; + + if (0 == newsz) + allocsz = 1; + else + allocsz = newsz; + + mem = EREALLOC_IMPL(ptr, allocsz, file, line); + if (NULL == mem) { + msyslog_term = TRUE; +#ifndef EREALLOC_CALLSITE + msyslog(LOG_ERR, "fatal out of memory (%lu bytes)", + (u_long)newsz); +#else + msyslog(LOG_ERR, + "fatal out of memory %s line %d (%lu bytes)", + file, line, (u_long)newsz); +#endif + exit(1); + } + + if (zero_init && newsz > priorsz) + zero_mem(mem + priorsz, newsz - priorsz); + + return mem; +} + +/* oreallocarray.c is licensed under the following: + * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +oreallocarray( + void *optr, + size_t nmemb, + size_t size +#ifdef EREALLOC_CALLSITE /* ntp_malloc.h */ + , + const char * file, + int line +#endif + ) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { +#ifndef EREALLOC_CALLSITE + msyslog(LOG_ERR, "fatal allocation size overflow"); +#else + msyslog(LOG_ERR, + "fatal allocation size overflow %s line %d", + file, line); +#endif + exit(1); + } +#ifndef EREALLOC_CALLSITE + return ereallocz(optr, (size * nmemb), 0, FALSE); +#else + return ereallocz(optr, (size * nmemb), 0, FALSE, file, line); +#endif +} + +char * +estrdup_impl( + const char * str +#ifdef EREALLOC_CALLSITE + , + const char * file, + int line +#endif + ) +{ + char * copy; + size_t bytes; + + bytes = strlen(str) + 1; + copy = ereallocz(NULL, bytes, 0, FALSE +#ifdef EREALLOC_CALLSITE + , file, line +#endif + ); + memcpy(copy, str, bytes); + + return copy; +} + + +#if 0 +#ifndef EREALLOC_CALLSITE +void * +emalloc(size_t newsz) +{ + return ereallocz(NULL, newsz, 0, FALSE); +} +#endif +#endif + diff --git a/contrib/ntp/libntp/findconfig.c b/contrib/ntp/libntp/findconfig.c new file mode 100644 index 000000000000..1785ff700395 --- /dev/null +++ b/contrib/ntp/libntp/findconfig.c @@ -0,0 +1,74 @@ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef NEED_HPUX_FINDCONFIG +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/utsname.h> +#include <unistd.h> + +const char * +FindConfig( + const char *base + ) +{ + static char result[BUFSIZ]; + char hostname[BUFSIZ], *cp; + struct stat sbuf; + struct utsname unamebuf; + + /* All keyed by initial target being a directory */ + strlcpy(result, base, sizeof(result)); + if (stat(result, &sbuf) == 0) { + if (S_ISDIR(sbuf.st_mode)) { + + /* First choice is my hostname */ + if (gethostname(hostname, BUFSIZ) >= 0) { + snprintf(result, sizeof(result), "%s/%s", base, hostname); + if (stat(result, &sbuf) == 0) { + goto outahere; + } else { + + /* Second choice is of form default.835 */ + (void) uname(&unamebuf); + if (strncmp(unamebuf.machine, "9000/", 5) == 0) + cp = unamebuf.machine + 5; + else + cp = unamebuf.machine; + snprintf(result, sizeof(result), "%s/default.%s", base, cp); + if (stat(result, &sbuf) == 0) { + goto outahere; + } else { + + /* Last choice is just default */ + snprintf(result, sizeof(result), "%s/default", base); + if (stat(result, &sbuf) == 0) { + goto outahere; + } else { + strlcpy(result, + "/not/found", + sizeof(result)); + } + } + } + } + } + } + outahere: + return(result); +} +#else +#include "ntp_stdlib.h" + +const char * +FindConfig( + const char *base + ) +{ + return base; +} +#endif diff --git a/contrib/ntp/libntp/getopt.c b/contrib/ntp/libntp/getopt.c new file mode 100644 index 000000000000..63c82faa6f77 --- /dev/null +++ b/contrib/ntp/libntp/getopt.c @@ -0,0 +1,108 @@ +/* + * getopt - get option letter from argv + * + * This is a version of the public domain getopt() implementation by + * Henry Spencer, changed for 4.3BSD compatibility (in addition to System V). + * It allows rescanning of an option list by setting optind to 0 before + * calling, which is why we use it even if the system has its own (in fact, + * this one has a unique name so as not to conflict with the system's). + * Thanks to Dennis Ferguson for the appropriate modifications. + * + * This file is in the Public Domain. + */ + +/*LINTLIBRARY*/ + +#include <config.h> +#include <stdio.h> + +#include "ntp_stdlib.h" + +#ifdef lint +#undef putc +#define putc fputc +#endif /* lint */ + +char *ntp_optarg; /* Global argument pointer. */ +int ntp_optind = 0; /* Global argv index. */ +int ntp_opterr = 1; /* for compatibility, should error be printed? */ +int ntp_optopt; /* for compatibility, option character checked */ + +static char *scan = NULL; /* Private scan pointer. */ +static const char *prog = "amnesia"; + +/* + * Print message about a bad option. + */ +static int +badopt( + const char *mess, + int ch + ) +{ + if (ntp_opterr) { + fputs(prog, stderr); + fputs(mess, stderr); + (void) putc(ch, stderr); + (void) putc('\n', stderr); + } + return ('?'); +} + +int +ntp_getopt( + int argc, + char *argv[], + const char *optstring + ) +{ + register char c; + register const char *place; + + prog = argv[0]; + ntp_optarg = NULL; + + if (ntp_optind == 0) { + scan = NULL; + ntp_optind++; + } + + if (scan == NULL || *scan == '\0') { + if (ntp_optind >= argc + || argv[ntp_optind][0] != '-' + || argv[ntp_optind][1] == '\0') { + return (EOF); + } + if (argv[ntp_optind][1] == '-' + && argv[ntp_optind][2] == '\0') { + ntp_optind++; + return (EOF); + } + + scan = argv[ntp_optind++]+1; + } + + c = *scan++; + ntp_optopt = c & 0377; + for (place = optstring; place != NULL && *place != '\0'; ++place) + if (*place == c) + break; + + if (place == NULL || *place == '\0' || c == ':' || c == '?') { + return (badopt(": unknown option -", c)); + } + + place++; + if (*place == ':') { + if (*scan != '\0') { + ntp_optarg = scan; + scan = NULL; + } else if (ntp_optind >= argc) { + return (badopt(": option requires argument -", c)); + } else { + ntp_optarg = argv[ntp_optind++]; + } + } + + return (c & 0377); +} diff --git a/contrib/ntp/libntp/hextoint.c b/contrib/ntp/libntp/hextoint.c new file mode 100644 index 000000000000..980a43f9d899 --- /dev/null +++ b/contrib/ntp/libntp/hextoint.c @@ -0,0 +1,42 @@ +/* + * hextoint - convert an ascii string in hex to an unsigned + * long, with error checking + */ +#include <config.h> +#include <ctype.h> + +#include "ntp_stdlib.h" + +int +hextoint( + const char *str, + u_long *pu + ) +{ + register u_long u; + register const char *cp; + + cp = str; + + if (*cp == '\0') + return 0; + + u = 0; + while (*cp != '\0') { + if (!isxdigit((unsigned char)*cp)) + return 0; + if (u & 0xF0000000) + return 0; /* overflow */ + u <<= 4; + if ('0' <= *cp && *cp <= '9') + u += *cp++ - '0'; + else if ('a' <= *cp && *cp <= 'f') + u += *cp++ - 'a' + 10; + else if ('A' <= *cp && *cp <= 'F') + u += *cp++ - 'A' + 10; + else + return 0; + } + *pu = u; + return 1; +} diff --git a/contrib/ntp/libntp/hextolfp.c b/contrib/ntp/libntp/hextolfp.c new file mode 100644 index 000000000000..19a93cdd427f --- /dev/null +++ b/contrib/ntp/libntp/hextolfp.c @@ -0,0 +1,70 @@ +/* + * hextolfp - convert an ascii hex string to an l_fp number + */ +#include <config.h> +#include <stdio.h> +#include <ctype.h> + +#include "ntp_fp.h" +#include "ntp_string.h" +#include "ntp_stdlib.h" + +int +hextolfp( + const char *str, + l_fp *lfp + ) +{ + register const char *cp; + register const char *cpstart; + register u_long dec_i; + register u_long dec_f; + char *ind = NULL; + static const char *digits = "0123456789abcdefABCDEF"; + + dec_i = dec_f = 0; + cp = str; + + /* + * We understand numbers of the form: + * + * [spaces]8_hex_digits[.]8_hex_digits[spaces|\n|\0] + */ + while (isspace((unsigned char)*cp)) + cp++; + + cpstart = cp; + while (*cp != '\0' && (cp - cpstart) < 8 && + (ind = strchr(digits, *cp)) != NULL) { + dec_i = dec_i << 4; /* multiply by 16 */ + dec_i += ((ind - digits) > 15) + ? (u_long)(ind - digits - 6) + : (u_long)(ind - digits); + cp++; + } + + if ((cp - cpstart) < 8 || ind == NULL) + return 0; + if (*cp == '.') + cp++; + + cpstart = cp; + while (*cp != '\0' && (cp - cpstart) < 8 && + (ind = strchr(digits, *cp)) != NULL) { + dec_f = dec_f << 4; /* multiply by 16 */ + dec_f += ((ind - digits) > 15) + ? (u_long)(ind - digits - 6) + : (u_long)(ind - digits); + cp++; + } + + if ((cp - cpstart) < 8 || ind == NULL) + return 0; + + if (*cp != '\0' && !isspace((unsigned char)*cp)) + return 0; + + lfp->l_ui = dec_i; + lfp->l_uf = dec_f; + return 1; +} diff --git a/contrib/ntp/libntp/humandate.c b/contrib/ntp/libntp/humandate.c new file mode 100644 index 000000000000..d9d5e89df017 --- /dev/null +++ b/contrib/ntp/libntp/humandate.c @@ -0,0 +1,60 @@ +/* + * humandate.c - convert an NTP (or the current) time to something readable + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" /* includes <sys/time.h> and <time.h> */ +#include "lib_strbuf.h" +#include "ntp_stdlib.h" + + +/* This is used in msyslog.c; we don't want to clutter up the log with + the year and day of the week, etc.; just the minimal date and time. */ + +const char * +humanlogtime(void) +{ + char * bp; + time_t cursec; + struct tm * tm; + + cursec = time(NULL); + tm = localtime(&cursec); + if (!tm) + return "-- --- --:--:--"; + + LIB_GETBUF(bp); + + snprintf(bp, LIB_BUFLENGTH, "%2d %s %02d:%02d:%02d", + tm->tm_mday, months[tm->tm_mon], + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return bp; +} + + +/* + * humantime() -- like humanlogtime() but without date, and with the + * time to display given as an argument. + */ +const char * +humantime( + time_t cursec + ) +{ + char * bp; + struct tm * tm; + + tm = localtime(&cursec); + if (!tm) + return "--:--:--"; + + LIB_GETBUF(bp); + + snprintf(bp, LIB_BUFLENGTH, "%02d:%02d:%02d", + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return bp; +} diff --git a/contrib/ntp/libntp/icom.c b/contrib/ntp/libntp/icom.c new file mode 100644 index 000000000000..2e95db5eb3f4 --- /dev/null +++ b/contrib/ntp/libntp/icom.c @@ -0,0 +1,178 @@ +/* + * Program to control ICOM radios + * + * This is a ripoff of the utility routines in the ICOM software + * distribution. The only function provided is to load the radio + * frequency. All other parameters must be manually set before use. + */ +#include <config.h> +#include <ntp_stdlib.h> +#include <ntp_tty.h> +#include <l_stdlib.h> +#include <icom.h> + +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> + + +#ifdef SYS_WINNT +#undef write /* ports/winnt/include/config.h: #define write _write */ +extern int async_write(int, const void *, unsigned int); +#define write(fd, data, octets) async_write(fd, data, octets) +#endif + +/* + * Packet routines + * + * These routines send a packet and receive the response. If an error + * (collision) occurs on transmit, the packet is resent. If an error + * occurs on receive (timeout), all input to the terminating FI is + * discarded and the packet is resent. If the maximum number of retries + * is not exceeded, the program returns the number of octets in the user + * buffer; otherwise, it returns zero. + * + * ICOM frame format + * + * Frames begin with a two-octet preamble PR-PR followyd by the + * transceiver address RE, controller address TX, control code CN, zero + * or more data octets DA (depending on command), and terminator FI. + * Since the bus is bidirectional, every octet output is echoed on + * input. Every valid frame sent is answered with a frame in the same + * format, but with the RE and TX fields interchanged. The CN field is + * set to NAK if an error has occurred. Otherwise, the data are returned + * in this and following DA octets. If no data are returned, the CN + * octet is set to ACK. + * + * +------+------+------+------+------+--//--+------+ + * | PR | PR | RE | TX | CN | DA | FI | + * +------+------+------+------+------+--//--+------+ + */ +/* + * Scraps + */ +#define DICOM /dev/icom/ /* ICOM port link */ + +/* + * Local function prototypes + */ +static void doublefreq (double, u_char *, int); + + +/* + * icom_freq(fd, ident, freq) - load radio frequency + * + * returns: + * 0 (ok) + * -1 (error) + * 1 (short write to device) + */ +int +icom_freq( + int fd, /* file descriptor */ + int ident, /* ICOM radio identifier */ + double freq /* frequency (MHz) */ + ) +{ + u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI, + FI}; + int temp; + int rc; + + cmd[3] = (char)ident; + if (ident == IC735) + temp = 4; + else + temp = 5; + doublefreq(freq * 1e6, &cmd[6], temp); + rc = write(fd, cmd, temp + 7); + if (rc == -1) { + msyslog(LOG_ERR, "icom_freq: write() failed: %m"); + return -1; + } else if (rc != temp + 7) { + msyslog(LOG_ERR, "icom_freq: only wrote %d of %d bytes.", + rc, temp+7); + return 1; + } + + return 0; +} + + +/* + * doublefreq(freq, y, len) - double to ICOM frequency with padding + */ +static void +doublefreq( /* returns void */ + double freq, /* frequency */ + u_char *x, /* radio frequency */ + int len /* length (octets) */ + ) +{ + int i; + char s1[16]; + char *y; + + snprintf(s1, sizeof(s1), " %10.0f", freq); + y = s1 + 10; + i = 0; + while (*y != ' ') { + x[i] = *y-- & 0x0f; + x[i] = x[i] | ((*y-- & 0x0f) << 4); + i++; + } + for ( ; i < len; i++) + x[i] = 0; + x[i] = FI; +} + +/* + * icom_init() - open and initialize serial interface + * + * This routine opens the serial interface for raw transmission; that + * is, character-at-a-time, no stripping, checking or monkeying with the + * bits. For Unix, an input operation ends either with the receipt of a + * character or a 0.5-s timeout. + */ +int +icom_init( + const char *device, /* device name/link */ + int speed, /* line speed */ + int trace /* trace flags */ ) +{ + TTY ttyb; + int fd; + int rc; + int saved_errno; + + fd = tty_open(device, O_RDWR, 0777); + if (fd < 0) + return -1; + + rc = tcgetattr(fd, &ttyb); + if (rc < 0) { + saved_errno = errno; + close(fd); + errno = saved_errno; + return -1; + } + ttyb.c_iflag = 0; /* input modes */ + ttyb.c_oflag = 0; /* output modes */ + ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */ + ttyb.c_lflag = 0; /* local modes */ + ttyb.c_cc[VMIN] = 0; /* min chars */ + ttyb.c_cc[VTIME] = 5; /* receive timeout */ + cfsetispeed(&ttyb, (u_int)speed); + cfsetospeed(&ttyb, (u_int)speed); + rc = tcsetattr(fd, TCSANOW, &ttyb); + if (rc < 0) { + saved_errno = errno; + close(fd); + errno = saved_errno; + return -1; + } + return (fd); +} + +/* end program */ diff --git a/contrib/ntp/libntp/iosignal.c b/contrib/ntp/libntp/iosignal.c new file mode 100644 index 000000000000..8749a23b8e81 --- /dev/null +++ b/contrib/ntp/libntp/iosignal.c @@ -0,0 +1,546 @@ +/* + * iosignal.c - input/output routines for ntpd. The socket-opening code + * was shamelessly stolen from ntpd. + */ + +/* + * [Bug 158] + * Do the #includes differently, as under some versions of Linux + * sys/param.h has a #undef CONFIG_PHONE line in it. + * + * As we have ~40 CONFIG_ variables, I don't feel like renaming them + * every time somebody adds a new macro to some system header. + */ + +#ifdef HAVE_CONFIG_H +# include <config.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 + +#include <arpa/inet.h> + +#if _BSDI_VERSION >= 199510 +# include <ifaddrs.h> +#endif + +# ifdef __QNXNTO__ +# include <fcntl.h> +# include <unix.h> +# define FNDELAY O_NDELAY +# endif + +#include "ntp_machine.h" +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_if.h" +#include "ntp_stdlib.h" +#include "iosignal.h" + +#if defined(HAVE_SIGNALED_IO) +static RETSIGTYPE sigio_handler (int); + +/* consistency safegurad to catch BLOCK/UNBLOCK oversights */ +static int sigio_block_count = 0; + +/* main inputhandler to be called on SIGIO */ +static input_handler_t *input_handler_callback = NULL; + +# if defined(HAVE_SIGACTION) +/* + * If sigaction() is used for signal handling and a signal is + * pending then the kernel blocks the signal before it calls + * the signal handler. + * + * The variable below is used to take care that the SIGIO signal + * is not unintentionally unblocked inside the sigio_handler() + * if the handler executes a piece of code that is normally + * bracketed by BLOCKIO()/UNBLOCKIO() calls. + */ +static int sigio_handler_active = 0; +# endif + +/* + * SIGPOLL and SIGIO ROUTINES. + */ + + + +/* + * TTY initialization routines. + */ +int +init_clock_sig( + struct refclockio *rio + ) +{ +# ifdef USE_TTY_SIGPOLL + { + /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ + if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0) + { + msyslog(LOG_ERR, + "init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m"); + return 1; + } + return 0; + } +# else + /* + * Special cases first! + */ + /* Was: defined(SYS_HPUX) */ +# if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT) +#define CLOCK_DONE + { + int pgrp, on = 1; + + /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ + pgrp = getpid(); + if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } + + /* + * set non-blocking, async I/O on the descriptor + */ + if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } + + if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } + return 0; + } +# endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */ + /* Was: defined(SYS_AIX) && !defined(_BSD) */ +# if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN) + /* + * SYSV compatibility mode under AIX. + */ +#define CLOCK_DONE + { + int pgrp, on = 1; + + /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ + if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m"); + return 1; + } + pgrp = -getpid(); + if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m"); + return 1; + } + + if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0) + { + msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m"); + return 1; + } + return 0; + } +# endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */ +# ifndef CLOCK_DONE + { + /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */ +# if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY) + /* + * there are, however, always exceptions to the rules + * one is, that OSF accepts SETOWN on TTY fd's only, iff they are + * CTTYs. SunOS and HPUX do not semm to have this restriction. + * another question is: how can you do multiple SIGIO from several + * ttys (as they all should be CTTYs), wondering... + * + * kd 95-07-16 + */ + if (ioctl(rio->fd, TIOCSCTTY, 0) == -1) + { + msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m"); + return 1; + } +# endif /* TIOCSCTTY && USE_FSETOWNCTTY */ + + if (fcntl(rio->fd, F_SETOWN, getpid()) == -1) + { + msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m"); + return 1; + } + + if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0) + { + msyslog(LOG_ERR, + "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m"); + return 1; + } + return 0; + } +# endif /* CLOCK_DONE */ +# endif /* !USE_TTY_SIGPOLL */ +} + + + +void +init_socket_sig( + int fd + ) +{ +# ifdef USE_UDP_SIGPOLL + { + if (ioctl(fd, I_SETSIG, S_INPUT) < 0) + { + msyslog(LOG_ERR, + "init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m - EXITING"); + exit(1); + } + } +# else /* USE_UDP_SIGPOLL */ + { + int pgrp; +# ifdef FIOASYNC + int on = 1; +# endif + +# if defined(FIOASYNC) + if (ioctl(fd, FIOASYNC, (char *)&on) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } +# elif defined(FASYNC) + { + int flags; + + if ((flags = fcntl(fd, F_GETFL, 0)) == -1) + { + msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } + if (fcntl(fd, F_SETFL, flags|FASYNC) < 0) + { + msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } + } +# else +# include "Bletch: Need asynchronous I/O!" +# endif + +# ifdef UDP_BACKWARDS_SETOWN + pgrp = -getpid(); +# else + pgrp = getpid(); +# endif + +# if defined(SIOCSPGRP) + if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1) + { + msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } +# elif defined(FIOSETOWN) + if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1) + { + msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } +# elif defined(F_SETOWN) + if (fcntl(fd, F_SETOWN, pgrp) == -1) + { + msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m - EXITING"); + exit(1); + /*NOTREACHED*/ + } +# else +# include "Bletch: Need to set process(group) to receive SIG(IO|POLL)" +# endif + } +# endif /* USE_UDP_SIGPOLL */ +} + +static RETSIGTYPE +sigio_handler( + int sig + ) +{ + int saved_errno = errno; + l_fp ts; + + get_systime(&ts); + +# if defined(HAVE_SIGACTION) + sigio_handler_active++; + if (sigio_handler_active != 1) /* This should never happen! */ + msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1"); +# endif + + INSIST(input_handler_callback != NULL); + (*input_handler_callback)(&ts); + +# if defined(HAVE_SIGACTION) + sigio_handler_active--; + if (sigio_handler_active != 0) /* This should never happen! */ + msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0"); +# endif + + errno = saved_errno; +} + +/* + * Signal support routines. + */ +# ifdef HAVE_SIGACTION +void +set_signal(input_handler_t *input) +{ + INSIST(input != NULL); + + input_handler_callback = input; + + using_sigio = TRUE; +# ifdef USE_SIGIO + (void) signal_no_reset(SIGIO, sigio_handler); +# endif +# ifdef USE_SIGPOLL + (void) signal_no_reset(SIGPOLL, sigio_handler); +# endif +} + +void +block_io_and_alarm(void) +{ + sigset_t set; + + if (sigemptyset(&set)) + msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m"); +# if defined(USE_SIGIO) + if (sigaddset(&set, SIGIO)) + msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m"); +# endif +# if defined(USE_SIGPOLL) + if (sigaddset(&set, SIGPOLL)) + msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m"); +# endif + if (sigaddset(&set, SIGALRM)) + msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m"); + + if (sigprocmask(SIG_BLOCK, &set, NULL)) + msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m"); +} + +void +block_sigio(void) +{ + if ( sigio_handler_active == 0 ) /* not called from within signal handler */ + { + sigset_t set; + + ++sigio_block_count; + if (sigio_block_count > 1) + msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1"); + if (sigio_block_count < 1) + msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1"); + + if (sigemptyset(&set)) + msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m"); +# if defined(USE_SIGIO) + if (sigaddset(&set, SIGIO)) + msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m"); +# endif +# if defined(USE_SIGPOLL) + if (sigaddset(&set, SIGPOLL)) + msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m"); +# endif + + if (sigprocmask(SIG_BLOCK, &set, NULL)) + msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m"); + } +} + +void +unblock_io_and_alarm(void) +{ + sigset_t unset; + + if (sigemptyset(&unset)) + msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m"); + +# if defined(USE_SIGIO) + if (sigaddset(&unset, SIGIO)) + msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m"); +# endif +# if defined(USE_SIGPOLL) + if (sigaddset(&unset, SIGPOLL)) + msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m"); +# endif + if (sigaddset(&unset, SIGALRM)) + msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m"); + + if (sigprocmask(SIG_UNBLOCK, &unset, NULL)) + msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m"); +} + +void +unblock_sigio(void) +{ + if ( sigio_handler_active == 0 ) /* not called from within signal handler */ + { + sigset_t unset; + + --sigio_block_count; + if (sigio_block_count > 0) + msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0"); + if (sigio_block_count < 0) + msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0"); + + if (sigemptyset(&unset)) + msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m"); + +# if defined(USE_SIGIO) + if (sigaddset(&unset, SIGIO)) + msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m"); +# endif +# if defined(USE_SIGPOLL) + if (sigaddset(&unset, SIGPOLL)) + msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m"); +# endif + + if (sigprocmask(SIG_UNBLOCK, &unset, NULL)) + msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m"); + } +} + +void +wait_for_signal(void) +{ + sigset_t old; + + if (sigprocmask(SIG_UNBLOCK, NULL, &old)) + msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m"); + +# if defined(USE_SIGIO) + if (sigdelset(&old, SIGIO)) + msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m"); +# endif +# if defined(USE_SIGPOLL) + if (sigdelset(&old, SIGPOLL)) + msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m"); +# endif + if (sigdelset(&old, SIGALRM)) + msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m"); + + if (sigsuspend(&old) && (errno != EINTR)) + msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m"); +} + +# else /* !HAVE_SIGACTION */ +/* + * Must be an old bsd system. + * We assume there is no SIGPOLL. + */ + +void +block_io_and_alarm(void) +{ + int mask; + + mask = sigmask(SIGIO) | sigmask(SIGALRM); + if (sigblock(mask)) + msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m"); +} + +void +block_sigio(void) +{ + int mask; + + ++sigio_block_count; + if (sigio_block_count > 1) + msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1"); + if (sigio_block_count < 1) + msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1"); + + mask = sigmask(SIGIO); + if (sigblock(mask)) + msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m"); +} + +void +set_signal(input_handler_t *input) +{ + INSIST(input != NULL); + + input_handler_callback = input; + + using_sigio = TRUE; + (void) signal_no_reset(SIGIO, sigio_handler); +} + +void +unblock_io_and_alarm(void) +{ + int mask, omask; + + mask = sigmask(SIGIO) | sigmask(SIGALRM); + omask = sigblock(0); + omask &= ~mask; + (void) sigsetmask(omask); +} + +void +unblock_sigio(void) +{ + int mask, omask; + + --sigio_block_count; + if (sigio_block_count > 0) + msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0"); + if (sigio_block_count < 0) + msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0"); + mask = sigmask(SIGIO); + omask = sigblock(0); + omask &= ~mask; + (void) sigsetmask(omask); +} + +void +wait_for_signal(void) +{ + int mask, omask; + + mask = sigmask(SIGIO) | sigmask(SIGALRM); + omask = sigblock(0); + omask &= ~mask; + if (sigpause(omask) && (errno != EINTR)) + msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m"); +} + +# endif /* HAVE_SIGACTION */ +#else +int NotAnEmptyCompilationUnit; +#endif diff --git a/contrib/ntp/libntp/is_ip_address.c b/contrib/ntp/libntp/is_ip_address.c new file mode 100644 index 000000000000..d36984ca00b6 --- /dev/null +++ b/contrib/ntp/libntp/is_ip_address.c @@ -0,0 +1,89 @@ +/* + * is_ip_address + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "ntp_assert.h" +#include "ntp_stdlib.h" +#include "safecast.h" + +/* Don't include ISC's version of IPv6 variables and structures */ +#define ISC_IPV6_H 1 +#include <isc/netaddr.h> +#include <isc/sockaddr.h> + + +/* + * 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, + u_short af, + sockaddr_u * addr + ) +{ + struct in_addr in4; + struct addrinfo hints; + struct addrinfo *result; + struct sockaddr_in6 *resaddr6; + char tmpbuf[128]; + char *pch; + + REQUIRE(host != NULL); + REQUIRE(addr != NULL); + + ZERO_SOCK(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 (AF_UNSPEC == af || AF_INET == af) + if (inet_pton(AF_INET, host, &in4) == 1) { + AF(addr) = AF_INET; + SET_ADDR4N(addr, in4.s_addr); + + return TRUE; + } + + if (AF_UNSPEC == af || AF_INET6 == af) + if (sizeof(tmpbuf) > strlen(host)) { + if ('[' == host[0]) { + strlcpy(tmpbuf, &host[1], sizeof(tmpbuf)); + pch = strchr(tmpbuf, ']'); + if (pch != NULL) + *pch = '\0'; + } else { + strlcpy(tmpbuf, host, sizeof(tmpbuf)); + } + ZERO(hints); + hints.ai_family = AF_INET6; + hints.ai_flags |= AI_NUMERICHOST; + if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) { + AF(addr) = AF_INET6; + resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr); + SET_ADDR6N(addr, resaddr6->sin6_addr); + SET_SCOPE(addr, resaddr6->sin6_scope_id); + + freeaddrinfo(result); + return TRUE; + } + } + /* + * If we got here it was not an IP address + */ + return FALSE; +} diff --git a/contrib/ntp/libntp/lib_strbuf.c b/contrib/ntp/libntp/lib_strbuf.c new file mode 100644 index 000000000000..76f70163de98 --- /dev/null +++ b/contrib/ntp/libntp/lib_strbuf.c @@ -0,0 +1,39 @@ +/* + * lib_strbuf - library string storage + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <isc/net.h> +#include <isc/result.h> + +#include "ntp_fp.h" +#include "ntp_stdlib.h" +#include "lib_strbuf.h" + + +/* + * Storage declarations + */ +int debug; +libbufstr lib_stringbuf[LIB_NUMBUF]; +int lib_nextbuf; +int ipv4_works; +int ipv6_works; +int lib_inited; + + +/* + * initialization routine. Might be needed if the code is ROMized. + */ +void +init_lib(void) +{ + if (lib_inited) + return; + ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4()); + ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6()); + init_systime(); + lib_inited = TRUE; +} diff --git a/contrib/ntp/libntp/libssl_compat.c b/contrib/ntp/libntp/libssl_compat.c new file mode 100644 index 000000000000..ce6acb7d3c78 --- /dev/null +++ b/contrib/ntp/libntp/libssl_compat.c @@ -0,0 +1,335 @@ +/* + * libssl_compat.c -- OpenSSL v1.1 compatibility functions + * + * --------------------------------------------------------------------- + * Written by Juergen Perlinger <perlinger@ntp.org> for the NTP project + * + * Based on an idea by Kurt Roeckx <kurt@roeckx.be> + * + * --------------------------------------------------------------------- + * This is a clean room implementation of shim functions that have + * counterparts in the OpenSSL v1.1 API but not in earlier versions. So + * while OpenSSL broke binary compatibility with v1.1, this shim module + * should provide the necessary source code compatibility with older + * versions of OpenSSL. + * --------------------------------------------------------------------- + */ +#include "config.h" + +#include <string.h> +#include <openssl/bn.h> +#include <openssl/evp.h> + +#include "ntp_types.h" + +/* ----------------------------------------------------------------- */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +/* ----------------------------------------------------------------- */ + +#include "libssl_compat.h" +#include "ntp_assert.h" + +/* -------------------------------------------------------------------- + * replace a BIGNUM owned by the caller with another one if it's not + * NULL, taking over the ownership of the new value. This clears & frees + * the old value -- the clear might be overkill, but it's better to err + * on the side of paranoia here. + */ +static void +replace_bn_nn( + BIGNUM ** ps, + BIGNUM * n + ) +{ + if (n) { + REQUIRE(*ps != n); + BN_clear_free(*ps); + *ps = n; + } +} + +/* -------------------------------------------------------------------- + * allocation and deallocation of prime number callbacks + */ +BN_GENCB* +sslshimBN_GENCB_new(void) +{ + return calloc(1,sizeof(BN_GENCB)); +} + +void +sslshimBN_GENCB_free( + BN_GENCB *cb + ) +{ + free(cb); +} + +/* -------------------------------------------------------------------- + * allocation and deallocation of message digests + */ +EVP_MD_CTX* +sslshim_EVP_MD_CTX_new(void) +{ + return calloc(1, sizeof(EVP_MD_CTX)); +} + +void +sslshim_EVP_MD_CTX_free( + EVP_MD_CTX * pctx + ) +{ + free(pctx); +} + +/* -------------------------------------------------------------------- + * get EVP keys and key type + */ +int +sslshim_EVP_PKEY_id( + const EVP_PKEY *pkey + ) +{ + return (pkey) ? pkey->type : EVP_PKEY_NONE; +} + +int +sslshim_EVP_PKEY_base_id( + const EVP_PKEY *pkey + ) +{ + return (pkey) ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE; +} + +RSA* +sslshim_EVP_PKEY_get0_RSA( + EVP_PKEY * pkey + ) +{ + return (pkey) ? pkey->pkey.rsa : NULL; +} + +DSA* +sslshim_EVP_PKEY_get0_DSA( + EVP_PKEY * pkey + ) +{ + return (pkey) ? pkey->pkey.dsa : NULL; +} + +/* -------------------------------------------------------------------- + * set/get RSA params + */ +void +sslshim_RSA_get0_key( + const RSA * prsa, + const BIGNUM ** pn, + const BIGNUM ** pe, + const BIGNUM ** pd + ) +{ + REQUIRE(prsa != NULL); + + if (pn) + *pn = prsa->n; + if (pe) + *pe = prsa->e; + if (pd) + *pd = prsa->d; +} + +int +sslshim_RSA_set0_key( + RSA * prsa, + BIGNUM * n, + BIGNUM * e, + BIGNUM * d + ) +{ + REQUIRE(prsa != NULL); + if (!((prsa->n || n) && (prsa->e || e))) + return 0; + + replace_bn_nn(&prsa->n, n); + replace_bn_nn(&prsa->e, e); + replace_bn_nn(&prsa->d, d); + + return 1; +} + +void +sslshim_RSA_get0_factors( + const RSA * prsa, + const BIGNUM ** pp, + const BIGNUM ** pq + ) +{ + REQUIRE(prsa != NULL); + + if (pp) + *pp = prsa->p; + if (pq) + *pq = prsa->q; +} + +int +sslshim_RSA_set0_factors( + RSA * prsa, + BIGNUM * p, + BIGNUM * q + ) +{ + REQUIRE(prsa != NULL); + if (!((prsa->p || p) && (prsa->q || q))) + return 0; + + replace_bn_nn(&prsa->p, p); + replace_bn_nn(&prsa->q, q); + + return 1; +} + +int +sslshim_RSA_set0_crt_params( + RSA * prsa, + BIGNUM * dmp1, + BIGNUM * dmq1, + BIGNUM * iqmp + ) +{ + REQUIRE(prsa != NULL); + if (!((prsa->dmp1 || dmp1) && + (prsa->dmq1 || dmq1) && + (prsa->iqmp || iqmp) )) + return 0; + + replace_bn_nn(&prsa->dmp1, dmp1); + replace_bn_nn(&prsa->dmq1, dmq1); + replace_bn_nn(&prsa->iqmp, iqmp); + + return 1; +} + +/* -------------------------------------------------------------------- + * set/get DSA signature parameters + */ +void +sslshim_DSA_SIG_get0( + const DSA_SIG * psig, + const BIGNUM ** pr, + const BIGNUM ** ps + ) +{ + REQUIRE(psig != NULL); + + if (pr != NULL) + *pr = psig->r; + if (ps != NULL) + *ps = psig->s; +} + +int +sslshim_DSA_SIG_set0( + DSA_SIG * psig, + BIGNUM * r, + BIGNUM * s + ) +{ + REQUIRE(psig != NULL); + if (!(r && s)) + return 0; + + replace_bn_nn(&psig->r, r); + replace_bn_nn(&psig->s, s); + + return 1; +} + +/* -------------------------------------------------------------------- + * get/set DSA parameters + */ +void +sslshim_DSA_get0_pqg( + const DSA * pdsa, + const BIGNUM ** pp, + const BIGNUM ** pq, + const BIGNUM ** pg + ) +{ + REQUIRE(pdsa != NULL); + + if (pp != NULL) + *pp = pdsa->p; + if (pq != NULL) + *pq = pdsa->q; + if (pg != NULL) + *pg = pdsa->g; +} + +int +sslshim_DSA_set0_pqg( + DSA * pdsa, + BIGNUM * p, + BIGNUM * q, + BIGNUM * g + ) +{ + if (!((pdsa->p || p) && (pdsa->q || q) && (pdsa->g || g))) + return 0; + + replace_bn_nn(&pdsa->p, p); + replace_bn_nn(&pdsa->q, q); + replace_bn_nn(&pdsa->g, g); + + return 1; +} + +void +sslshim_DSA_get0_key( + const DSA * pdsa, + const BIGNUM ** ppub_key, + const BIGNUM ** ppriv_key + ) +{ + REQUIRE(pdsa != NULL); + + if (ppub_key != NULL) + *ppub_key = pdsa->pub_key; + if (ppriv_key != NULL) + *ppriv_key = pdsa->priv_key; +} + +int +sslshim_DSA_set0_key( + DSA * pdsa, + BIGNUM * pub_key, + BIGNUM * priv_key + ) +{ + REQUIRE(pdsa != NULL); + if (!(pdsa->pub_key || pub_key)) + return 0; + + replace_bn_nn(&pdsa->pub_key, pub_key); + replace_bn_nn(&pdsa->priv_key, priv_key); + + return 1; +} + +int +sslshim_X509_get_signature_nid( + const X509 *x + ) +{ + return OBJ_obj2nid(x->sig_alg->algorithm); +} + +/* ----------------------------------------------------------------- */ +#else /* OPENSSL_VERSION_NUMBER >= v1.1.0 */ +/* ----------------------------------------------------------------- */ + +NONEMPTY_TRANSLATION_UNIT + +/* ----------------------------------------------------------------- */ +#endif +/* ----------------------------------------------------------------- */ diff --git a/contrib/ntp/libntp/machines.c b/contrib/ntp/libntp/machines.c new file mode 100644 index 000000000000..7a29ac07ea5f --- /dev/null +++ b/contrib/ntp/libntp/machines.c @@ -0,0 +1,533 @@ +/* machines.c - provide special support for peculiar architectures + * + * Real bummers unite ! + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ntp.h" +#include "ntp_machine.h" +#include "ntp_syslog.h" +#include "ntp_stdlib.h" +#include "ntp_unixtime.h" +#include "lib_strbuf.h" +#include "ntp_debug.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef SYS_WINNT +int _getch(void); /* Declare the one function rather than include conio.h */ +#else + +#ifdef SYS_VXWORKS +#include "taskLib.h" +#include "sysLib.h" +#include "time.h" +#include "ntp_syslog.h" + +/* some translations to the world of vxWorkings -casey */ +/* first some netdb type things */ +#include "ioLib.h" +#include <socket.h> +int h_errno; + +struct hostent *gethostbyname(char *name) + { + struct hostent *host1; + h_errno = 0; /* we are always successful!!! */ + host1 = (struct hostent *) emalloc (sizeof(struct hostent)); + host1->h_name = name; + host1->h_addrtype = AF_INET; + host1->h_aliases = name; + host1->h_length = 4; + host1->h_addr_list[0] = (char *)hostGetByName (name); + host1->h_addr_list[1] = NULL; + return host1; + } + +struct hostent *gethostbyaddr(char *name, int size, int addr_type) + { + struct hostent *host1; + h_errno = 0; /* we are always successful!!! */ + host1 = (struct hostent *) emalloc (sizeof(struct hostent)); + host1->h_name = name; + host1->h_addrtype = AF_INET; + host1->h_aliases = name; + host1->h_length = 4; + host1->h_addr_list = NULL; + return host1; + } + +struct servent *getservbyname (char *name, char *type) + { + struct servent *serv1; + serv1 = (struct servent *) emalloc (sizeof(struct servent)); + serv1->s_name = "ntp"; /* official service name */ + serv1->s_aliases = NULL; /* alias list */ + serv1->s_port = 123; /* port # */ + serv1->s_proto = "udp"; /* protocol to use */ + return serv1; + } + +/* second + * vxworks thinks it has insomnia + * we have to sleep for number of seconds + */ + +#define CLKRATE sysClkRateGet() + +/* I am not sure how valid the granularity is - it is from G. Eger's port */ +#define CLK_GRANULARITY 1 /* Granularity of system clock in usec */ + /* Used to round down # usecs/tick */ + /* On a VCOM-100, PIT gets 8 MHz clk, */ + /* & it prescales by 32, thus 4 usec */ + /* on mv167, granularity is 1usec anyway*/ + /* To defeat rounding, set to 1 */ +#define USECS_PER_SEC MILLION /* Microseconds per second */ +#define TICK (((USECS_PER_SEC / CLKRATE) / CLK_GRANULARITY) * CLK_GRANULARITY) + +/* emulate unix sleep + * casey + */ +void sleep(int seconds) + { + taskDelay(seconds*TICK); + } +/* emulate unix alarm + * that pauses and calls SIGALRM after the seconds are up... + * so ... taskDelay() fudged for seconds should amount to the same thing. + * casey + */ +void alarm (int seconds) + { + sleep(seconds); + } + +#endif /* SYS_VXWORKS */ + +#ifdef SYS_PTX /* Does PTX still need this? */ +/*#include <sys/types.h> */ +#include <sys/procstats.h> + +int +gettimeofday( + struct timeval *tvp + ) +{ + /* + * hi, this is Sequents sneak path to get to a clock + * this is also the most logical syscall for such a function + */ + return (get_process_stats(tvp, PS_SELF, (struct procstats *) 0, + (struct procstats *) 0)); +} +#endif /* SYS_PTX */ + +#ifdef MPE +/* This is a substitute for bind() that if called for an AF_INET socket +port less than 1024, GETPRIVMODE() and GETUSERMODE() calls will be done. */ + +#undef bind +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> + +extern void GETPRIVMODE(void); +extern void GETUSERMODE(void); + +int __ntp_mpe_bind(int s, void *addr, int addrlen); + +int __ntp_mpe_bind(int s, void *addr, int addrlen) { + int priv = 0; + int result; + +if (addrlen == sizeof(struct sockaddr_in)) { /* AF_INET */ + if (((struct sockaddr_in *)addr)->sin_port > 0 && + ((struct sockaddr_in *)addr)->sin_port < 1024) { + priv = 1; + GETPRIVMODE(); + } +/* ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; */ + result = bind(s,addr,addrlen); + if (priv == 1) GETUSERMODE(); +} else /* AF_UNIX */ + result = bind(s,addr,addrlen); + +return result; +} + +/* + * MPE stupidly requires sfcntl() to be used on sockets instead of fcntl(), + * so we define a wrapper to analyze the file descriptor and call the correct + * function. + */ + +#undef fcntl +#include <errno.h> +#include <fcntl.h> + +int __ntp_mpe_fcntl(int fd, int cmd, int arg); + +int __ntp_mpe_fcntl(int fd, int cmd, int arg) { + int len; + struct sockaddr sa; + + extern int sfcntl(int, int, int); + + len = sizeof sa; + if (getsockname(fd, &sa, &len) == -1) { + if (errno == EAFNOSUPPORT) /* AF_UNIX socket */ + return sfcntl(fd, cmd, arg); + if (errno == ENOTSOCK) /* file or pipe */ + return fcntl(fd, cmd, arg); + return (-1); /* unknown getsockname() failure */ + } else /* AF_INET socket */ + return sfcntl(fd, cmd, arg); +} + +/* + * Setitimer emulation support. Note that we implement this using alarm(), + * and since alarm() only delivers one signal, we must re-enable the alarm + * by enabling our own SIGALRM setitimer_mpe_handler routine to be called + * before the real handler routine and re-enable the alarm at that time. + * + * Note that this solution assumes that sigaction(SIGALRM) is called before + * calling setitimer(). If it should ever to become necessary to support + * sigaction(SIGALRM) after calling setitimer(), it will be necessary to trap + * those sigaction() calls. + */ + +#include <limits.h> +#include <signal.h> + +/* + * Some global data that needs to be shared between setitimer() and + * setitimer_mpe_handler(). + */ + +struct { + unsigned long current_msec; /* current alarm() value in effect */ + unsigned long interval_msec; /* next alarm() value from setitimer */ + unsigned long value_msec; /* first alarm() value from setitimer */ + struct itimerval current_itimerval; /* current itimerval in effect */ + struct sigaction oldact; /* SIGALRM state saved by setitimer */ +} setitimer_mpe_ctx = { 0, 0, 0 }; + +/* + * Undocumented, unsupported function to do alarm() in milliseconds. + */ + +extern unsigned int px_alarm(unsigned long, int *); + +/* + * The SIGALRM handler routine enabled by setitimer(). Re-enable the alarm or + * restore the original SIGALRM setting if no more alarms are needed. Then + * call the original SIGALRM handler (if any). + */ + +static RETSIGTYPE setitimer_mpe_handler(int sig) +{ +int alarm_hpe_status; + +/* Update the new current alarm value */ + +setitimer_mpe_ctx.current_msec = setitimer_mpe_ctx.interval_msec; + +if (setitimer_mpe_ctx.interval_msec > 0) { + /* Additional intervals needed; re-arm the alarm timer */ + px_alarm(setitimer_mpe_ctx.interval_msec,&alarm_hpe_status); +} else { + /* No more intervals, so restore previous original SIGALRM handler */ + sigaction(SIGALRM, &setitimer_mpe_ctx.oldact, NULL); +} + +/* Call the original SIGALRM handler if it is a function and not just a flag */ + +if (setitimer_mpe_ctx.oldact.sa_handler != SIG_DFL && + setitimer_mpe_ctx.oldact.sa_handler != SIG_ERR && + setitimer_mpe_ctx.oldact.sa_handler != SIG_IGN) + (*setitimer_mpe_ctx.oldact.sa_handler)(SIGALRM); + +} + +/* + * Our implementation of setitimer(). + */ + +int +setitimer(int which, struct itimerval *value, + struct itimerval *ovalue) +{ + +int alarm_hpe_status; +unsigned long remaining_msec, value_msec, interval_msec; +struct sigaction newact; + +/* + * Convert the initial interval to milliseconds + */ + +if (value->it_value.tv_sec > (UINT_MAX / 1000)) + value_msec = UINT_MAX; +else + value_msec = value->it_value.tv_sec * 1000; + +value_msec += value->it_value.tv_usec / 1000; + +/* + * Convert the reset interval to milliseconds + */ + +if (value->it_interval.tv_sec > (UINT_MAX / 1000)) + interval_msec = UINT_MAX; +else + interval_msec = value->it_interval.tv_sec * 1000; + +interval_msec += value->it_interval.tv_usec / 1000; + +if (value_msec > 0 && interval_msec > 0) { + /* + * We'll be starting an interval timer that will be repeating, so we need to + * insert our own SIGALRM signal handler to schedule the repeats. + */ + + /* Read the current SIGALRM action */ + + if (sigaction(SIGALRM, NULL, &setitimer_mpe_ctx.oldact) < 0) { + fprintf(stderr,"MPE setitimer old handler failed, errno=%d\n",errno); + return -1; + } + + /* Initialize the new action to call our SIGALRM handler instead */ + + newact.sa_handler = &setitimer_mpe_handler; + newact.sa_mask = setitimer_mpe_ctx.oldact.sa_mask; + newact.sa_flags = setitimer_mpe_ctx.oldact.sa_flags; + + if (sigaction(SIGALRM, &newact, NULL) < 0) { + fprintf(stderr,"MPE setitimer new handler failed, errno=%d\n",errno); + return -1; + } +} + +/* + * Return previous itimerval if desired + */ + +if (ovalue != NULL) *ovalue = setitimer_mpe_ctx.current_itimerval; + +/* + * Save current parameters for later usage + */ + +setitimer_mpe_ctx.current_itimerval = *value; +setitimer_mpe_ctx.current_msec = value_msec; +setitimer_mpe_ctx.value_msec = value_msec; +setitimer_mpe_ctx.interval_msec = interval_msec; + +/* + * Schedule the first alarm + */ + +remaining_msec = px_alarm(value_msec, &alarm_hpe_status); +if (alarm_hpe_status == 0) + return (0); +else + return (-1); +} + +/* + * MPE lacks gettimeofday(), so we define our own. + */ + +int gettimeofday(struct timeval *tvp) + +{ +/* Documented, supported MPE functions. */ +extern void GETPRIVMODE(void); +extern void GETUSERMODE(void); + +/* Undocumented, unsupported MPE functions. */ +extern long long get_time(void); +extern void get_time_change_info(long long *, char *, char *); +extern long long ticks_to_micro(long long); + +char pwf_since_boot, recover_pwf_time; +long long mpetime, offset_ticks, offset_usec; + +GETPRIVMODE(); +mpetime = get_time(); /* MPE local time usecs since Jan 1 1970 */ +get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); +offset_usec = ticks_to_micro(offset_ticks); /* UTC offset usecs */ +GETUSERMODE(); + +mpetime = mpetime - offset_usec; /* Convert from local time to UTC */ +tvp->tv_sec = mpetime / 1000000LL; +tvp->tv_usec = mpetime % 1000000LL; + +return 0; +} + +/* + * MPE lacks settimeofday(), so we define our own. + */ + +#define HAVE_SETTIMEOFDAY + +int settimeofday(struct timeval *tvp) + +{ +/* Documented, supported MPE functions. */ +extern void GETPRIVMODE(void); +extern void GETUSERMODE(void); + +/* Undocumented, unsupported MPE functions. */ +extern void get_time_change_info(long long *, char *, char *); +extern void initialize_system_time(long long, int); +extern void set_time_correction(long long, int, int); +extern long long ticks_to_micro(long long); + +char pwf_since_boot, recover_pwf_time; +long long big_sec, big_usec, mpetime, offset_ticks, offset_usec; + +big_sec = tvp->tv_sec; +big_usec = tvp->tv_usec; +mpetime = (big_sec * 1000000LL) + big_usec; /* Desired UTC microseconds */ + +GETPRIVMODE(); +set_time_correction(0LL,0,0); /* Cancel previous time correction, if any */ +get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time); +offset_usec = ticks_to_micro(offset_ticks); /* UTC offset microseconds */ +mpetime = mpetime + offset_usec; /* Convert from UTC to local time */ +initialize_system_time(mpetime,1); +GETUSERMODE(); + +return 0; +} +#endif /* MPE */ + +#define SET_TOD_UNDETERMINED 0 +#define SET_TOD_CLOCK_SETTIME 1 +#define SET_TOD_SETTIMEOFDAY 2 +#define SET_TOD_STIME 3 + +const char * const set_tod_used[] = { + "undetermined", + "clock_settime", + "settimeofday", + "stime" +}; + +pset_tod_using set_tod_using = NULL; + + +int +ntp_set_tod( + struct timeval *tvp, + void *tzp + ) +{ + static int tod; + int rc; + int saved_errno; + + TRACE(1, ("In ntp_set_tod\n")); + rc = -1; + saved_errno = 0; + +#ifdef HAVE_CLOCK_SETTIME + if (rc && (SET_TOD_CLOCK_SETTIME == tod || !tod)) { + struct timespec ts; + + /* Convert timeval to timespec */ + ts.tv_sec = tvp->tv_sec; + ts.tv_nsec = 1000 * tvp->tv_usec; + + errno = 0; + rc = clock_settime(CLOCK_REALTIME, &ts); + saved_errno = errno; + TRACE(1, ("ntp_set_tod: clock_settime: %d %m\n", rc)); + if (!tod && !rc) + tod = SET_TOD_CLOCK_SETTIME; + + } +#endif /* HAVE_CLOCK_SETTIME */ +#ifdef HAVE_SETTIMEOFDAY + if (rc && (SET_TOD_SETTIMEOFDAY == tod || !tod)) { + struct timeval adjtv; + + /* + * Some broken systems don't reset adjtime() when the + * clock is stepped. + */ + adjtv.tv_sec = adjtv.tv_usec = 0; + adjtime(&adjtv, NULL); + errno = 0; + rc = SETTIMEOFDAY(tvp, tzp); + saved_errno = errno; + TRACE(1, ("ntp_set_tod: settimeofday: %d %m\n", rc)); + if (!tod && !rc) + tod = SET_TOD_SETTIMEOFDAY; + } +#endif /* HAVE_SETTIMEOFDAY */ +#ifdef HAVE_STIME + if (rc && (SET_TOD_STIME == tod || !tod)) { + long tp = tvp->tv_sec; + + errno = 0; + rc = stime(&tp); /* lie as bad as SysVR4 */ + saved_errno = errno; + TRACE(1, ("ntp_set_tod: stime: %d %m\n", rc)); + if (!tod && !rc) + tod = SET_TOD_STIME; + } +#endif /* HAVE_STIME */ + + errno = saved_errno; /* for %m below */ + TRACE(1, ("ntp_set_tod: Final result: %s: %d %m\n", + set_tod_used[tod], rc)); + /* + * Say how we're setting the time of day + */ + if (!rc && NULL != set_tod_using) { + (*set_tod_using)(set_tod_used[tod]); + set_tod_using = NULL; + } + + if (rc) + errno = saved_errno; + + return rc; +} + +#endif /* not SYS_WINNT */ + +#if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE) +/* getpass is used in ntpq.c and ntpdc.c */ + +char * +getpass(const char * prompt) +{ + int c, i; + static char password[32]; + + fprintf(stderr, "%s", prompt); + fflush(stderr); + + for (i=0; i<sizeof(password)-1 && ((c=_getch())!='\n' && c!='\r'); i++) { + password[i] = (char) c; + } + password[i] = '\0'; + + fputc('\n', stderr); + fflush(stderr); + + return password; +} +#endif /* SYS_WINNT */ diff --git a/contrib/ntp/libntp/mktime.c b/contrib/ntp/libntp/mktime.c new file mode 100644 index 000000000000..50d2a0810408 --- /dev/null +++ b/contrib/ntp/libntp/mktime.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 1987, 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +/*static char *sccsid = "from: @(#)ctime.c 5.26 (Berkeley) 2/23/91";*/ + +/* + * This implementation of mktime is lifted straight from the NetBSD (BSD 4.4) + * version. I modified it slightly to divorce it from the internals of the + * ctime library. Thus this version can't use details of the internal + * timezone state file to figure out strange unnormalized struct tm values, + * as might result from someone doing date math on the tm struct then passing + * it to mktime. + * + * It just does as well as it can at normalizing the tm input, then does a + * binary search of the time space using the system's localtime() function. + * + * The original binary search was defective in that it didn't consider the + * setting of tm_isdst when comparing tm values, causing the search to be + * flubbed for times near the dst/standard time changeover. The original + * code seems to make up for this by grubbing through the timezone info + * whenever the binary search barfed. Since I don't have that luxury in + * portable code, I have to take care of tm_isdst in the comparison routine. + * This requires knowing how many minutes offset dst is from standard time. + * + * So, if you live somewhere in the world where dst is not 60 minutes offset, + * and your vendor doesn't supply mktime(), you'll have to edit this variable + * by hand. Sorry about that. + */ + +#include <config.h> +#include "ntp_machine.h" + +#if !defined(HAVE_MKTIME) || ( !defined(HAVE_TIMEGM) && defined(WANT_TIMEGM) ) + +#if SIZEOF_TIME_T >= 8 +#error libntp supplied mktime()/timegm() do not support 64-bit time_t +#endif + +#ifndef DSTMINUTES +#define DSTMINUTES 60 +#endif + +#define FALSE 0 +#define TRUE 1 + +/* some constants from tzfile.h */ +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 +#define TM_YEAR_BASE 1900 +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +static int mon_lengths[2][MONSPERYEAR] = { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static int year_lengths[2] = { + DAYSPERNYEAR, DAYSPERLYEAR +}; + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static void +normalize( + int * tensptr, + int * unitsptr, + int base + ) +{ + if (*unitsptr >= base) { + *tensptr += *unitsptr / base; + *unitsptr %= base; + } else if (*unitsptr < 0) { + --*tensptr; + *unitsptr += base; + if (*unitsptr < 0) { + *tensptr -= 1 + (-*unitsptr) / base; + *unitsptr = base - (-*unitsptr) % base; + } + } +} + +static struct tm * +mkdst( + struct tm * tmp + ) +{ + /* jds */ + static struct tm tmbuf; + + tmbuf = *tmp; + tmbuf.tm_isdst = 1; + tmbuf.tm_min += DSTMINUTES; + normalize(&tmbuf.tm_hour, &tmbuf.tm_min, MINSPERHOUR); + return &tmbuf; +} + +static int +tmcomp( + register struct tm * atmp, + register struct tm * btmp + ) +{ + register int result; + + /* compare down to the same day */ + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0) + result = (atmp->tm_mday - btmp->tm_mday); + + if(result != 0) + return result; + + /* get rid of one-sided dst bias */ + + if(atmp->tm_isdst == 1 && !btmp->tm_isdst) + btmp = mkdst(btmp); + else if(btmp->tm_isdst == 1 && !atmp->tm_isdst) + atmp = mkdst(atmp); + + /* compare the rest of the way */ + + if ((result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + + +static time_t +time2( + struct tm * tmp, + int * okayp, + int usezn + ) +{ + register int dir; + register int bits; + register int i; + register int saved_seconds; + time_t t; + struct tm yourtm, mytm; + + *okayp = FALSE; + yourtm = *tmp; + if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0) + normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN); + normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR); + normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY); + normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR); + while (yourtm.tm_mday <= 0) { + --yourtm.tm_year; + yourtm.tm_mday += + year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; + } + for ( ; ; ) { + i = mon_lengths[isleap(yourtm.tm_year + + TM_YEAR_BASE)][yourtm.tm_mon]; + if (yourtm.tm_mday <= i) + break; + yourtm.tm_mday -= i; + if (++yourtm.tm_mon >= MONSPERYEAR) { + yourtm.tm_mon = 0; + ++yourtm.tm_year; + } + } + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + if (usezn) + mytm = *localtime(&t); + else + mytm = *gmtime(&t); + dir = tmcomp(&mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) + break; + + return WRONG; + } + t += saved_seconds; + if (usezn) + *tmp = *localtime(&t); + else + *tmp = *gmtime(&t); + *okayp = TRUE; + return t; +} +#else +int mktime_bs; +#endif /* !HAVE_MKTIME || !HAVE_TIMEGM */ + +#ifndef HAVE_MKTIME +static time_t +time1( + struct tm * tmp + ) +{ + register time_t t; + int okay; + + if (tmp->tm_isdst > 1) + tmp->tm_isdst = 1; + t = time2(tmp, &okay, 1); + if (okay || tmp->tm_isdst < 0) + return t; + + return WRONG; +} + +time_t +mktime( + struct tm * tmp + ) +{ + return time1(tmp); +} +#endif /* !HAVE_MKTIME */ + +#ifdef WANT_TIMEGM +#ifndef HAVE_TIMEGM +time_t +timegm( + struct tm * tmp + ) +{ + register time_t t; + int okay; + + tmp->tm_isdst = 0; + t = time2(tmp, &okay, 0); + if (okay || tmp->tm_isdst < 0) + return t; + + return WRONG; +} +#endif /* !HAVE_TIMEGM */ +#endif /* WANT_TIMEGM */ diff --git a/contrib/ntp/libntp/modetoa.c b/contrib/ntp/libntp/modetoa.c new file mode 100644 index 000000000000..6f13d20580bf --- /dev/null +++ b/contrib/ntp/libntp/modetoa.c @@ -0,0 +1,35 @@ +/* + * modetoa - return an asciized mode + */ +#include <config.h> +#include <stdio.h> + +#include "lib_strbuf.h" +#include "ntp_stdlib.h" + +const char * +modetoa( + size_t mode + ) +{ + char *bp; + static const char * const modestrings[] = { + "unspec", + "sym_active", + "sym_passive", + "client", + "server", + "broadcast", + "control", + "private", + "bclient", + }; + + if (mode >= COUNTOF(modestrings)) { + LIB_GETBUF(bp); + snprintf(bp, LIB_BUFLENGTH, "mode#%zu", mode); + return bp; + } + + return modestrings[mode]; +} diff --git a/contrib/ntp/libntp/mstolfp.c b/contrib/ntp/libntp/mstolfp.c new file mode 100644 index 000000000000..7da20dc911e2 --- /dev/null +++ b/contrib/ntp/libntp/mstolfp.c @@ -0,0 +1,100 @@ +/* + * mstolfp - convert an ascii string in milliseconds to an l_fp number + */ +#include <config.h> +#include <stdio.h> +#include <ctype.h> + +#include "ntp_fp.h" +#include "ntp_stdlib.h" + +int +mstolfp( + const char *str, + l_fp *lfp + ) +{ + register const char *cp; + register char *bp; + register const char *cpdec; + char buf[100]; + + /* + * We understand numbers of the form: + * + * [spaces][-][digits][.][digits][spaces|\n|\0] + * + * This is one enormous hack. Since I didn't feel like + * rewriting the decoding routine for milliseconds, what + * is essentially done here is to make a copy of the string + * with the decimal moved over three places so the seconds + * decoding routine can be used. + */ + bp = buf; + cp = str; + while (isspace((unsigned char)*cp)) + cp++; + + if (*cp == '-') { + *bp++ = '-'; + cp++; + } + + if (*cp != '.' && !isdigit((unsigned char)*cp)) + return 0; + + + /* + * Search forward for the decimal point or the end of the string. + */ + cpdec = cp; + while (isdigit((unsigned char)*cpdec)) + cpdec++; + + /* + * Found something. If we have more than three digits copy the + * excess over, else insert a leading 0. + */ + if ((cpdec - cp) > 3) { + do { + *bp++ = (char)*cp++; + } while ((cpdec - cp) > 3); + } else { + *bp++ = '0'; + } + + /* + * Stick the decimal in. If we've got less than three digits in + * front of the millisecond decimal we insert the appropriate number + * of zeros. + */ + *bp++ = '.'; + if ((cpdec - cp) < 3) { + size_t i = 3 - (cpdec - cp); + do { + *bp++ = '0'; + } while (--i > 0); + } + + /* + * Copy the remainder up to the millisecond decimal. If cpdec + * is pointing at a decimal point, copy in the trailing number too. + */ + while (cp < cpdec) + *bp++ = (char)*cp++; + + if (*cp == '.') { + cp++; + while (isdigit((unsigned char)*cp)) + *bp++ = (char)*cp++; + } + *bp = '\0'; + + /* + * Check to make sure the string is properly terminated. If + * so, give the buffer to the decoding routine. + */ + if (*cp != '\0' && !isspace((unsigned char)*cp)) + return 0; + return atolfp(buf, lfp); +} diff --git a/contrib/ntp/libntp/msyslog.c b/contrib/ntp/libntp/msyslog.c new file mode 100644 index 000000000000..9682d3002119 --- /dev/null +++ b/contrib/ntp/libntp/msyslog.c @@ -0,0 +1,584 @@ +/* + * msyslog - either send a message to the terminal or print it on + * the standard output. + * + * Converted to use varargs, much better ... jks + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdio.h> + +#include "ntp_string.h" +#include "ntp.h" +#include "ntp_debug.h" +#include "ntp_syslog.h" + +#ifdef SYS_WINNT +# include <stdarg.h> +# include "..\ports\winnt\libntp\messages.h" +#endif + + +int syslogit = TRUE; +int msyslog_term = FALSE; /* duplicate to stdout/err */ +int msyslog_term_pid = TRUE; +int msyslog_include_timestamp = TRUE; +FILE * syslog_file; +char * syslog_fname; +char * syslog_abs_fname; + +/* libntp default ntp_syslogmask is all bits lit */ +#define INIT_NTP_SYSLOGMASK ~(u_int32)0 +u_int32 ntp_syslogmask = INIT_NTP_SYSLOGMASK; + +extern char const * progname; + +/* Declare the local functions */ +void addto_syslog (int, const char *); +#ifndef VSNPRINTF_PERCENT_M +void format_errmsg (char *, size_t, const char *, int); + +/* format_errmsg() is under #ifndef VSNPRINTF_PERCENT_M above */ +void +format_errmsg( + char * nfmt, + size_t lennfmt, + const char * fmt, + int errval + ) +{ + char errmsg[256]; + char c; + char *n; + const char *f; + size_t len; + + n = nfmt; + f = fmt; + while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) { + if (c != '%') { + *n++ = c; + continue; + } + if ((c = *f++) != 'm') { + *n++ = '%'; + if ('\0' == c) + break; + *n++ = c; + continue; + } + errno_to_str(errval, errmsg, sizeof(errmsg)); + len = strlen(errmsg); + + /* Make sure we have enough space for the error message */ + if ((n + len) < (nfmt + lennfmt - 1)) { + memcpy(n, errmsg, len); + n += len; + } + } + *n = '\0'; +} +#endif /* VSNPRINTF_PERCENT_M */ + + +/* + * errno_to_str() - a thread-safe strerror() replacement. + * Hides the varied signatures of strerror_r(). + * For Windows, we have: + * #define errno_to_str isc_strerror + */ +#ifndef errno_to_str +void +errno_to_str( + int err, + char * buf, + size_t bufsiz + ) +{ +# if defined(STRERROR_R_CHAR_P) || !HAVE_DECL_STRERROR_R + char * pstatic; + + buf[0] = '\0'; +# ifdef STRERROR_R_CHAR_P + pstatic = strerror_r(err, buf, bufsiz); +# else + pstatic = strerror(err); +# endif + if (NULL == pstatic && '\0' == buf[0]) + snprintf(buf, bufsiz, "%s(%d): errno %d", +# ifdef STRERROR_R_CHAR_P + "strerror_r", +# else + "strerror", +# endif + err, errno); + /* protect against believing an int return is a pointer */ + else if (pstatic != buf && pstatic > (char *)bufsiz) + strlcpy(buf, pstatic, bufsiz); +# else + int rc; + + rc = strerror_r(err, buf, bufsiz); + if (rc < 0) + snprintf(buf, bufsiz, "strerror_r(%d): errno %d", + err, errno); +# endif +} +#endif /* errno_to_str */ + + +/* + * addto_syslog() + * This routine adds the contents of a buffer to the syslog or an + * application-specific logfile. + */ +void +addto_syslog( + int level, + const char * msg + ) +{ + static char const * prevcall_progname; + static char const * prog; + const char nl[] = "\n"; + const char empty[] = ""; + FILE * term_file; + int log_to_term; + int log_to_file; + int pid; + const char * nl_or_empty; + const char * human_time; + + /* setup program basename static var prog if needed */ + if (progname != prevcall_progname) { + prevcall_progname = progname; + prog = strrchr(progname, DIR_SEP); + if (prog != NULL) + prog++; + else + prog = progname; + } + + log_to_term = msyslog_term; + log_to_file = FALSE; +#if !defined(VMS) && !defined(SYS_VXWORKS) + if (syslogit) + syslog(level, "%s", msg); + else +#endif + if (syslog_file != NULL) + log_to_file = TRUE; + else + log_to_term = TRUE; +#if DEBUG + if (debug > 0) + log_to_term = TRUE; +#endif + if (!(log_to_file || log_to_term)) + return; + + /* syslog() adds the timestamp, name, and pid */ + if (msyslog_include_timestamp) + human_time = humanlogtime(); + else /* suppress gcc pot. uninit. warning */ + human_time = NULL; + if (msyslog_term_pid || log_to_file) + pid = getpid(); + else /* suppress gcc pot. uninit. warning */ + pid = -1; + + /* syslog() adds trailing \n if not present */ + if ('\n' != msg[strlen(msg) - 1]) + nl_or_empty = nl; + else + nl_or_empty = empty; + + if (log_to_term) { + term_file = (level <= LOG_ERR) + ? stderr + : stdout; + if (msyslog_include_timestamp) + fprintf(term_file, "%s ", human_time); + if (msyslog_term_pid) + fprintf(term_file, "%s[%d]: ", prog, pid); + fprintf(term_file, "%s%s", msg, nl_or_empty); + fflush(term_file); + } + + if (log_to_file) { + if (msyslog_include_timestamp) + fprintf(syslog_file, "%s ", human_time); + fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg, + nl_or_empty); + fflush(syslog_file); + } +} + + +int +mvsnprintf( + char * buf, + size_t bufsiz, + const char * fmt, + va_list ap + ) +{ +#ifndef VSNPRINTF_PERCENT_M + char nfmt[256]; +#else + const char * nfmt = fmt; +#endif + int errval; + + /* + * Save the error value as soon as possible + */ +#ifdef SYS_WINNT + errval = GetLastError(); + if (NO_ERROR == errval) +#endif /* SYS_WINNT */ + errval = errno; + +#ifndef VSNPRINTF_PERCENT_M + format_errmsg(nfmt, sizeof(nfmt), fmt, errval); +#else + errno = errval; +#endif + return vsnprintf(buf, bufsiz, nfmt, ap); +} + + +int +mvfprintf( + FILE * fp, + const char * fmt, + va_list ap + ) +{ +#ifndef VSNPRINTF_PERCENT_M + char nfmt[256]; +#else + const char * nfmt = fmt; +#endif + int errval; + + /* + * Save the error value as soon as possible + */ +#ifdef SYS_WINNT + errval = GetLastError(); + if (NO_ERROR == errval) +#endif /* SYS_WINNT */ + errval = errno; + +#ifndef VSNPRINTF_PERCENT_M + format_errmsg(nfmt, sizeof(nfmt), fmt, errval); +#else + errno = errval; +#endif + return vfprintf(fp, nfmt, ap); +} + + +int +mfprintf( + FILE * fp, + const char * fmt, + ... + ) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = mvfprintf(fp, fmt, ap); + va_end(ap); + + return rc; +} + + +int +mprintf( + const char * fmt, + ... + ) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = mvfprintf(stdout, fmt, ap); + va_end(ap); + + return rc; +} + + +int +msnprintf( + char * buf, + size_t bufsiz, + const char * fmt, + ... + ) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = mvsnprintf(buf, bufsiz, fmt, ap); + va_end(ap); + + return rc; +} + + +void +msyslog( + int level, + const char * fmt, + ... + ) +{ + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + mvsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + addto_syslog(level, buf); +} + +void +mvsyslog( + int level, + const char * fmt, + va_list ap + ) +{ + char buf[1024]; + mvsnprintf(buf, sizeof(buf), fmt, ap); + addto_syslog(level, buf); +} + + +/* + * Initialize the logging + * + * Called once per process, including forked children. + */ +void +init_logging( + const char * name, + u_int32 def_syslogmask, + int is_daemon + ) +{ + static int was_daemon; + char * cp; + const char * pname; + + /* + * ntpd defaults to only logging sync-category events, when + * NLOG() is used to conditionalize. Other libntp clients + * leave it alone so that all NLOG() conditionals will fire. + * This presumes all bits lit in ntp_syslogmask can't be + * configured via logconfig and all lit is thereby a sentinel + * that ntp_syslogmask is still at its default from libntp, + * keeping in mind this function is called in forked children + * where it has already been called in the parent earlier. + * Forked children pass 0 for def_syslogmask. + */ + if (INIT_NTP_SYSLOGMASK == ntp_syslogmask && + 0 != def_syslogmask) + ntp_syslogmask = def_syslogmask; /* set more via logconfig */ + + /* + * Logging. This may actually work on the gizmo board. Find a name + * to log with by using the basename + */ + cp = strrchr(name, DIR_SEP); + if (NULL == cp) + pname = name; + else + pname = 1 + cp; /* skip DIR_SEP */ + progname = estrdup(pname); +#ifdef SYS_WINNT /* strip ".exe" */ + cp = strrchr(progname, '.'); + if (NULL != cp && !strcasecmp(cp, ".exe")) + *cp = '\0'; +#endif + +#if !defined(VMS) + + if (is_daemon) + was_daemon = TRUE; +# ifndef LOG_DAEMON + openlog(progname, LOG_PID); +# else /* LOG_DAEMON */ + +# ifndef LOG_NTP +# define LOG_NTP LOG_DAEMON +# endif + openlog(progname, LOG_PID | LOG_NDELAY, (was_daemon) + ? LOG_NTP + : 0); +# ifdef DEBUG + if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); + else +# endif /* DEBUG */ + setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ +# endif /* LOG_DAEMON */ +#endif /* !VMS */ +} + + +/* + * change_logfile() + * + * Used to change from syslog to a logfile, or from one logfile to + * another, and to reopen logfiles after forking. On systems where + * ntpd forks, deals with converting relative logfile paths to + * absolute (root-based) because we reopen logfiles after the current + * directory has changed. + */ +int +change_logfile( + const char * fname, + int leave_crumbs + ) +{ + FILE * new_file; + const char * log_fname; + char * abs_fname; +#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS) + char curdir[512]; + size_t cd_octets; + size_t octets; +#endif /* POSIX */ + + REQUIRE(fname != NULL); + log_fname = fname; + + /* + * In a forked child of a parent which is logging to a file + * instead of syslog, syslog_file will be NULL and both + * syslog_fname and syslog_abs_fname will be non-NULL. + * If we are given the same filename previously opened + * and it's still open, there's nothing to do here. + */ + if (syslog_file != NULL && syslog_fname != NULL && + 0 == strcmp(syslog_fname, log_fname)) + return 0; + + if (0 == strcmp(log_fname, "stderr")) { + new_file = stderr; + abs_fname = estrdup(log_fname); + } else if (0 == strcmp(log_fname, "stdout")) { + new_file = stdout; + abs_fname = estrdup(log_fname); + } else { + if (syslog_fname != NULL && + 0 == strcmp(log_fname, syslog_fname)) + log_fname = syslog_abs_fname; +#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS) + if (log_fname != syslog_abs_fname && + DIR_SEP != log_fname[0] && + 0 != strcmp(log_fname, "stderr") && + 0 != strcmp(log_fname, "stdout") && + NULL != getcwd(curdir, sizeof(curdir))) { + cd_octets = strlen(curdir); + /* trim any trailing '/' */ + if (cd_octets > 1 && + DIR_SEP == curdir[cd_octets - 1]) + cd_octets--; + octets = cd_octets; + octets += 1; /* separator '/' */ + octets += strlen(log_fname); + octets += 1; /* NUL terminator */ + abs_fname = emalloc(octets); + snprintf(abs_fname, octets, "%.*s%c%s", + (int)cd_octets, curdir, DIR_SEP, + log_fname); + } else +#endif + abs_fname = estrdup(log_fname); + TRACE(1, ("attempting to open log %s\n", abs_fname)); + new_file = fopen(abs_fname, "a"); + } + + if (NULL == new_file) { + free(abs_fname); + return -1; + } + + /* leave a pointer in the old log */ + if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname)) + msyslog(LOG_NOTICE, "switching logging to file %s", + abs_fname); + + if (syslog_file != NULL && + syslog_file != stderr && syslog_file != stdout && + fileno(syslog_file) != fileno(new_file)) + fclose(syslog_file); + syslog_file = new_file; + if (log_fname == syslog_abs_fname) { + free(abs_fname); + } else { + if (syslog_abs_fname != NULL && + syslog_abs_fname != syslog_fname) + free(syslog_abs_fname); + if (syslog_fname != NULL) + free(syslog_fname); + syslog_fname = estrdup(log_fname); + syslog_abs_fname = abs_fname; + } + syslogit = FALSE; + + return 0; +} + + +/* + * setup_logfile() + * + * Redirect logging to a file if requested with -l/--logfile or via + * ntp.conf logfile directive. + * + * This routine is invoked three different times in the sequence of a + * typical daemon ntpd with DNS lookups to do. First it is invoked in + * the original ntpd process, then again in the daemon after closing + * all descriptors. In both of those cases, ntp.conf has not been + * processed, so only -l/--logfile will trigger logfile redirection in + * those invocations. Finally, if DNS names are resolved, the worker + * child invokes this routine after its fork and close of all + * descriptors. In this case, ntp.conf has been processed and any + * "logfile" directive needs to be honored in the child as well. + */ +void +setup_logfile( + const char * name + ) +{ + if (NULL == syslog_fname && NULL != name) { + if (-1 == change_logfile(name, TRUE)) + msyslog(LOG_ERR, "Cannot open log file %s, %m", + name); + return ; + } + if (NULL == syslog_fname) + return; + + if (-1 == change_logfile(syslog_fname, FALSE)) + msyslog(LOG_ERR, "Cannot reopen log file %s, %m", + syslog_fname); +} diff --git a/contrib/ntp/libntp/netof.c b/contrib/ntp/libntp/netof.c new file mode 100644 index 000000000000..c8831c3dd9cd --- /dev/null +++ b/contrib/ntp/libntp/netof.c @@ -0,0 +1,55 @@ +/* + * netof - return the net address part of an ip address in a sockaddr_storage structure + * (zero out host part) + */ +#include <config.h> +#include <stdio.h> +#include <syslog.h> + +#include "ntp_fp.h" +#include "ntp_net.h" +#include "ntp_stdlib.h" +#include "ntp.h" + +sockaddr_u * +netof( + sockaddr_u *hostaddr + ) +{ + static sockaddr_u netofbuf[8]; + static int next_netofbuf; + u_int32 netnum; + sockaddr_u * netaddr; + + netaddr = &netofbuf[next_netofbuf]; + next_netofbuf = (next_netofbuf + 1) % COUNTOF(netofbuf); + + memcpy(netaddr, hostaddr, sizeof(*netaddr)); + + if (IS_IPV4(netaddr)) { + netnum = SRCADR(netaddr); + + /* + * We live in a modern CIDR world where the basement nets, which + * used to be class A, are now probably associated with each + * host address. So, for class-A nets, all bits are significant. + */ + if (IN_CLASSC(netnum)) + netnum &= IN_CLASSC_NET; + else if (IN_CLASSB(netnum)) + netnum &= IN_CLASSB_NET; + + SET_ADDR4(netaddr, netnum); + + } else if (IS_IPV6(netaddr)) + /* assume the typical /64 subnet size */ + zero_mem(&NSRCADR6(netaddr)[8], 8); +#ifdef DEBUG + else { + msyslog(LOG_ERR, "netof unknown AF %d", AF(netaddr)); + exit(1); + } +#endif + + return netaddr; +} diff --git a/contrib/ntp/libntp/ntp_calendar.c b/contrib/ntp/libntp/ntp_calendar.c new file mode 100644 index 000000000000..4bfb0e723c01 --- /dev/null +++ b/contrib/ntp/libntp/ntp_calendar.c @@ -0,0 +1,1828 @@ +/* + * ntp_calendar.c - calendar and helper functions + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + * + * -------------------------------------------------------------------- + * Some notes on the implementation: + * + * Calendar algorithms thrive on the division operation, which is one of + * the slowest numerical operations in any CPU. What saves us here from + * abysmal performance is the fact that all divisions are divisions by + * constant numbers, and most compilers can do this by a multiplication + * operation. But this might not work when using the div/ldiv/lldiv + * function family, because many compilers are not able to do inline + * expansion of the code with following optimisation for the + * constant-divider case. + * + * Also div/ldiv/lldiv are defined in terms of int/long/longlong, which + * are inherently target dependent. Nothing that could not be cured with + * autoconf, but still a mess... + * + * Furthermore, we need floor division in many places. C either leaves + * the division behaviour undefined (< C99) or demands truncation to + * zero (>= C99), so additional steps are required to make sure the + * algorithms work. The {l,ll}div function family is requested to + * truncate towards zero, which is also the wrong direction for our + * purpose. + * + * For all this, all divisions by constant are coded manually, even when + * there is a joined div/mod operation: The optimiser should sort that + * out, if possible. Most of the calculations are done with unsigned + * types, explicitely using two's complement arithmetics where + * necessary. This minimises the dependecies to compiler and target, + * while still giving reasonable to good performance. + * + * The implementation uses a few tricks that exploit properties of the + * two's complement: Floor division on negative dividents can be + * executed by using the one's complement of the divident. One's + * complement can be easily created using XOR and a mask. + * + * Finally, check for overflow conditions is minimal. There are only two + * calculation steps in the whole calendar that suffer from an internal + * overflow, and these conditions are checked: errno is set to EDOM and + * the results are clamped/saturated in this case. All other functions + * do not suffer from internal overflow and simply return the result + * truncated to 32 bits. + * + * This is a sacrifice made for execution speed. Since a 32-bit day + * counter covers +/- 5,879,610 years and the clamp limits the effective + * range to +/-2.9 million years, this should not pose a problem here. + * + */ + +#include <config.h> +#include <sys/types.h> + +#include "ntp_types.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" +#include "ntp_fp.h" +#include "ntp_unixtime.h" + +/* For now, let's take the conservative approach: if the target property + * macros are not defined, check a few well-known compiler/architecture + * settings. Default is to assume that the representation of signed + * integers is unknown and shift-arithmetic-right is not available. + */ +#ifndef TARGET_HAS_2CPL +# if defined(__GNUC__) +# if defined(__i386__) || defined(__x86_64__) || defined(__arm__) +# define TARGET_HAS_2CPL 1 +# else +# define TARGET_HAS_2CPL 0 +# endif +# elif defined(_MSC_VER) +# if defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) +# define TARGET_HAS_2CPL 1 +# else +# define TARGET_HAS_2CPL 0 +# endif +# else +# define TARGET_HAS_2CPL 0 +# endif +#endif + +#ifndef TARGET_HAS_SAR +# define TARGET_HAS_SAR 0 +#endif + +/* + *--------------------------------------------------------------------- + * replacing the 'time()' function + *--------------------------------------------------------------------- + */ + +static systime_func_ptr systime_func = &time; +static inline time_t now(void); + + +systime_func_ptr +ntpcal_set_timefunc( + systime_func_ptr nfunc + ) +{ + systime_func_ptr res; + + res = systime_func; + if (NULL == nfunc) + nfunc = &time; + systime_func = nfunc; + + return res; +} + + +static inline time_t +now(void) +{ + return (*systime_func)(NULL); +} + +/* + *--------------------------------------------------------------------- + * Get sign extension mask and unsigned 2cpl rep for a signed integer + *--------------------------------------------------------------------- + */ + +static inline uint32_t +int32_sflag( + const int32_t v) +{ +# if TARGET_HAS_2CPL && TARGET_HAS_SAR && SIZEOF_INT >= 4 + + /* Let's assume that shift is the fastest way to get the sign + * extension of of a signed integer. This might not always be + * true, though -- On 8bit CPUs or machines without barrel + * shifter this will kill the performance. So we make sure + * we do this only if 'int' has at least 4 bytes. + */ + return (uint32_t)(v >> 31); + +# else + + /* This should be a rather generic approach for getting a sign + * extension mask... + */ + return UINT32_C(0) - (uint32_t)(v < 0); + +# endif +} + +static inline uint32_t +int32_to_uint32_2cpl( + const int32_t v) +{ + uint32_t vu; + +# if TARGET_HAS_2CPL + + /* Just copy through the 32 bits from the signed value if we're + * on a two's complement target. + */ + vu = (uint32_t)v; + +# else + + /* Convert from signed int to unsigned int two's complement. Do + * not make any assumptions about the representation of signed + * integers, but make sure signed integer overflow cannot happen + * here. A compiler on a two's complement target *might* find + * out that this is just a complicated cast (as above), but your + * mileage might vary. + */ + if (v < 0) + vu = ~(uint32_t)(-(v + 1)); + else + vu = (uint32_t)v; + +# endif + + return vu; +} + +static inline int32_t +uint32_2cpl_to_int32( + const uint32_t vu) +{ + int32_t v; + +# if TARGET_HAS_2CPL + + /* Just copy through the 32 bits from the unsigned value if + * we're on a two's complement target. + */ + v = (int32_t)vu; + +# else + + /* Convert to signed integer, making sure signed integer + * overflow cannot happen. Again, the optimiser might or might + * not find out that this is just a copy of 32 bits on a target + * with two's complement representation for signed integers. + */ + if (vu > INT32_MAX) + v = -(int32_t)(~vu) - 1; + else + v = (int32_t)vu; + +# endif + + return v; +} + +/* Some of the calculations need to multiply the input by 4 before doing + * a division. This can cause overflow and strange results. Therefore we + * clamp / saturate the input operand. And since we do the calculations + * in unsigned int with an extra sign flag/mask, we only loose one bit + * of the input value range. + */ +static inline uint32_t +uint32_saturate( + uint32_t vu, + uint32_t mu) +{ + static const uint32_t limit = UINT32_MAX/4u; + if ((mu ^ vu) > limit) { + vu = mu ^ limit; + errno = EDOM; + } + return vu; +} + +/* + *--------------------------------------------------------------------- + * Convert between 'time_t' and 'vint64' + *--------------------------------------------------------------------- + */ +vint64 +time_to_vint64( + const time_t * ptt + ) +{ + vint64 res; + time_t tt; + + tt = *ptt; + +# if SIZEOF_TIME_T <= 4 + + res.D_s.hi = 0; + if (tt < 0) { + res.D_s.lo = (uint32_t)-tt; + M_NEG(res.D_s.hi, res.D_s.lo); + } else { + res.D_s.lo = (uint32_t)tt; + } + +# elif defined(HAVE_INT64) + + res.q_s = tt; + +# else + /* + * shifting negative signed quantities is compiler-dependent, so + * we better avoid it and do it all manually. And shifting more + * than the width of a quantity is undefined. Also a don't do! + */ + if (tt < 0) { + tt = -tt; + res.D_s.lo = (uint32_t)tt; + res.D_s.hi = (uint32_t)(tt >> 32); + M_NEG(res.D_s.hi, res.D_s.lo); + } else { + res.D_s.lo = (uint32_t)tt; + res.D_s.hi = (uint32_t)(tt >> 32); + } + +# endif + + return res; +} + + +time_t +vint64_to_time( + const vint64 *tv + ) +{ + time_t res; + +# if SIZEOF_TIME_T <= 4 + + res = (time_t)tv->D_s.lo; + +# elif defined(HAVE_INT64) + + res = (time_t)tv->q_s; + +# else + + res = ((time_t)tv->d_s.hi << 32) | tv->D_s.lo; + +# endif + + return res; +} + +/* + *--------------------------------------------------------------------- + * Get the build date & time + *--------------------------------------------------------------------- + */ +int +ntpcal_get_build_date( + struct calendar * jd + ) +{ + /* The C standard tells us the format of '__DATE__': + * + * __DATE__ The date of translation of the preprocessing + * translation unit: a character string literal of the form "Mmm + * dd yyyy", where the names of the months are the same as those + * generated by the asctime function, and the first character of + * dd is a space character if the value is less than 10. If the + * date of translation is not available, an + * implementation-defined valid date shall be supplied. + * + * __TIME__ The time of translation of the preprocessing + * translation unit: a character string literal of the form + * "hh:mm:ss" as in the time generated by the asctime + * function. If the time of translation is not available, an + * implementation-defined valid time shall be supplied. + * + * Note that MSVC declares DATE and TIME to be in the local time + * zone, while neither the C standard nor the GCC docs make any + * statement about this. As a result, we may be +/-12hrs off + * UTC. But for practical purposes, this should not be a + * problem. + * + */ +# ifdef MKREPRO_DATE + static const char build[] = MKREPRO_TIME "/" MKREPRO_DATE; +# else + static const char build[] = __TIME__ "/" __DATE__; +# endif + static const char mlist[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + char monstr[4]; + const char * cp; + unsigned short hour, minute, second, day, year; + /* Note: The above quantities are used for sscanf 'hu' format, + * so using 'uint16_t' is contra-indicated! + */ + +# ifdef DEBUG + static int ignore = 0; +# endif + + ZERO(*jd); + jd->year = 1970; + jd->month = 1; + jd->monthday = 1; + +# ifdef DEBUG + /* check environment if build date should be ignored */ + if (0 == ignore) { + const char * envstr; + envstr = getenv("NTPD_IGNORE_BUILD_DATE"); + ignore = 1 + (envstr && (!*envstr || !strcasecmp(envstr, "yes"))); + } + if (ignore > 1) + return FALSE; +# endif + + if (6 == sscanf(build, "%hu:%hu:%hu/%3s %hu %hu", + &hour, &minute, &second, monstr, &day, &year)) { + cp = strstr(mlist, monstr); + if (NULL != cp) { + jd->year = year; + jd->month = (uint8_t)((cp - mlist) / 3 + 1); + jd->monthday = (uint8_t)day; + jd->hour = (uint8_t)hour; + jd->minute = (uint8_t)minute; + jd->second = (uint8_t)second; + + return TRUE; + } + } + + return FALSE; +} + + +/* + *--------------------------------------------------------------------- + * basic calendar stuff + *--------------------------------------------------------------------- + */ + +/* month table for a year starting with March,1st */ +static const uint16_t shift_month_table[13] = { + 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337, 366 +}; + +/* month tables for years starting with January,1st; regular & leap */ +static const uint16_t real_month_table[2][13] = { + /* -*- table for regular years -*- */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* -*- table for leap years -*- */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } +}; + +/* + * Some notes on the terminology: + * + * We use the proleptic Gregorian calendar, which is the Gregorian + * calendar extended in both directions ad infinitum. This totally + * disregards the fact that this calendar was invented in 1582, and + * was adopted at various dates over the world; sometimes even after + * the start of the NTP epoch. + * + * Normally date parts are given as current cycles, while time parts + * are given as elapsed cycles: + * + * 1970-01-01/03:04:05 means 'IN the 1970st. year, IN the first month, + * ON the first day, with 3hrs, 4minutes and 5 seconds elapsed. + * + * The basic calculations for this calendar implementation deal with + * ELAPSED date units, which is the number of full years, full months + * and full days before a date: 1970-01-01 would be (1969, 0, 0) in + * that notation. + * + * To ease the numeric computations, month and day values outside the + * normal range are acceptable: 2001-03-00 will be treated as the day + * before 2001-03-01, 2000-13-32 will give the same result as + * 2001-02-01 and so on. + * + * 'rd' or 'RD' is used as an abbreviation for the latin 'rata die' + * (day number). This is the number of days elapsed since 0000-12-31 + * in the proleptic Gregorian calendar. The begin of the Christian Era + * (0001-01-01) is RD(1). + */ + +/* + * ==================================================================== + * + * General algorithmic stuff + * + * ==================================================================== + */ + +/* + *--------------------------------------------------------------------- + * Do a periodic extension of 'value' around 'pivot' with a period of + * 'cycle'. + * + * The result 'res' is a number that holds to the following properties: + * + * 1) res MOD cycle == value MOD cycle + * 2) pivot <= res < pivot + cycle + * (replace </<= with >/>= for negative cycles) + * + * where 'MOD' denotes the modulo operator for FLOOR DIVISION, which + * is not the same as the '%' operator in C: C requires division to be + * a truncated division, where remainder and dividend have the same + * sign if the remainder is not zero, whereas floor division requires + * divider and modulus to have the same sign for a non-zero modulus. + * + * This function has some useful applications: + * + * + let Y be a calendar year and V a truncated 2-digit year: then + * periodic_extend(Y-50, V, 100) + * is the closest expansion of the truncated year with respect to + * the full year, that is a 4-digit year with a difference of less + * than 50 years to the year Y. ("century unfolding") + * + * + let T be a UN*X time stamp and V be seconds-of-day: then + * perodic_extend(T-43200, V, 86400) + * is a time stamp that has the same seconds-of-day as the input + * value, with an absolute difference to T of <= 12hrs. ("day + * unfolding") + * + * + Wherever you have a truncated periodic value and a non-truncated + * base value and you want to match them somehow... + * + * Basically, the function delivers 'pivot + (value - pivot) % cycle', + * but the implementation takes some pains to avoid internal signed + * integer overflows in the '(value - pivot) % cycle' part and adheres + * to the floor division convention. + * + * If 64bit scalars where available on all intended platforms, writing a + * version that uses 64 bit ops would be easy; writing a general + * division routine for 64bit ops on a platform that can only do + * 32/16bit divisions and is still performant is a bit more + * difficult. Since most usecases can be coded in a way that does only + * require the 32-bit version a 64bit version is NOT provided here. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_periodic_extend( + int32_t pivot, + int32_t value, + int32_t cycle + ) +{ + uint32_t diff; + char cpl = 0; /* modulo complement flag */ + char neg = 0; /* sign change flag */ + + /* make the cycle positive and adjust the flags */ + if (cycle < 0) { + cycle = - cycle; + neg ^= 1; + cpl ^= 1; + } + /* guard against div by zero or one */ + if (cycle > 1) { + /* + * Get absolute difference as unsigned quantity and + * the complement flag. This is done by always + * subtracting the smaller value from the bigger + * one. + */ + if (value >= pivot) { + diff = int32_to_uint32_2cpl(value) + - int32_to_uint32_2cpl(pivot); + } else { + diff = int32_to_uint32_2cpl(pivot) + - int32_to_uint32_2cpl(value); + cpl ^= 1; + } + diff %= (uint32_t)cycle; + if (diff) { + if (cpl) + diff = (uint32_t)cycle - diff; + if (neg) + diff = ~diff + 1; + pivot += uint32_2cpl_to_int32(diff); + } + } + return pivot; +} + +/*--------------------------------------------------------------------- + * Note to the casual reader + * + * In the next two functions you will find (or would have found...) + * the expression + * + * res.Q_s -= 0x80000000; + * + * There was some ruckus about a possible programming error due to + * integer overflow and sign propagation. + * + * This assumption is based on a lack of understanding of the C + * standard. (Though this is admittedly not one of the most 'natural' + * aspects of the 'C' language and easily to get wrong.) + * + * see + * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf + * "ISO/IEC 9899:201x Committee Draft — April 12, 2011" + * 6.4.4.1 Integer constants, clause 5 + * + * why there is no sign extension/overflow problem here. + * + * But to ease the minds of the doubtful, I added back the 'u' qualifiers + * that somehow got lost over the last years. + */ + + +/* + *--------------------------------------------------------------------- + * Convert a timestamp in NTP scale to a 64bit seconds value in the UN*X + * scale with proper epoch unfolding around a given pivot or the current + * system time. This function happily accepts negative pivot values as + * timestamps befor 1970-01-01, so be aware of possible trouble on + * platforms with 32bit 'time_t'! + * + * This is also a periodic extension, but since the cycle is 2^32 and + * the shift is 2^31, we can do some *very* fast math without explicit + * divisions. + *--------------------------------------------------------------------- + */ +vint64 +ntpcal_ntp_to_time( + uint32_t ntp, + const time_t * pivot + ) +{ + vint64 res; + +# if defined(HAVE_INT64) + + res.q_s = (pivot != NULL) + ? *pivot + : now(); + res.Q_s -= 0x80000000u; /* unshift of half range */ + ntp -= (uint32_t)JAN_1970; /* warp into UN*X domain */ + ntp -= res.D_s.lo; /* cycle difference */ + res.Q_s += (uint64_t)ntp; /* get expanded time */ + +# else /* no 64bit scalars */ + + time_t tmp; + + tmp = (pivot != NULL) + ? *pivot + : now(); + res = time_to_vint64(&tmp); + M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u); + ntp -= (uint32_t)JAN_1970; /* warp into UN*X domain */ + ntp -= res.D_s.lo; /* cycle difference */ + M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp); + +# endif /* no 64bit scalars */ + + return res; +} + +/* + *--------------------------------------------------------------------- + * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP + * scale with proper epoch unfolding around a given pivot or the current + * system time. + * + * Note: The pivot must be given in the UN*X time domain! + * + * This is also a periodic extension, but since the cycle is 2^32 and + * the shift is 2^31, we can do some *very* fast math without explicit + * divisions. + *--------------------------------------------------------------------- + */ +vint64 +ntpcal_ntp_to_ntp( + uint32_t ntp, + const time_t *pivot + ) +{ + vint64 res; + +# if defined(HAVE_INT64) + + res.q_s = (pivot) + ? *pivot + : now(); + res.Q_s -= 0x80000000u; /* unshift of half range */ + res.Q_s += (uint32_t)JAN_1970; /* warp into NTP domain */ + ntp -= res.D_s.lo; /* cycle difference */ + res.Q_s += (uint64_t)ntp; /* get expanded time */ + +# else /* no 64bit scalars */ + + time_t tmp; + + tmp = (pivot) + ? *pivot + : now(); + res = time_to_vint64(&tmp); + M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u); + M_ADD(res.D_s.hi, res.D_s.lo, 0, (uint32_t)JAN_1970);/*into NTP */ + ntp -= res.D_s.lo; /* cycle difference */ + M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp); + +# endif /* no 64bit scalars */ + + return res; +} + + +/* + * ==================================================================== + * + * Splitting values to composite entities + * + * ==================================================================== + */ + +/* + *--------------------------------------------------------------------- + * Split a 64bit seconds value into elapsed days in 'res.hi' and + * elapsed seconds since midnight in 'res.lo' using explicit floor + * division. This function happily accepts negative time values as + * timestamps before the respective epoch start. + *--------------------------------------------------------------------- + */ +ntpcal_split +ntpcal_daysplit( + const vint64 *ts + ) +{ + ntpcal_split res; + uint32_t Q; + +# if defined(HAVE_INT64) + + /* Manual floor division by SECSPERDAY. This uses the one's + * complement trick, too, but without an extra flag value: The + * flag would be 64bit, and that's a bit of overkill on a 32bit + * target that has to use a register pair for a 64bit number. + */ + if (ts->q_s < 0) + Q = ~(uint32_t)(~ts->Q_s / SECSPERDAY); + else + Q = (uint32_t)(ts->Q_s / SECSPERDAY); + +# else + + uint32_t ah, al, sflag, A; + + /* get operand into ah/al (either ts or ts' one's complement, + * for later floor division) + */ + sflag = int32_sflag(ts->d_s.hi); + ah = sflag ^ ts->D_s.hi; + al = sflag ^ ts->D_s.lo; + + /* Since 86400 == 128*675 we can drop the least 7 bits and + * divide by 675 instead of 86400. Then the maximum remainder + * after each devision step is 674, and we need 10 bits for + * that. So in the next step we can shift in 22 bits from the + * numerator. + * + * Therefore we load the accu with the top 13 bits (51..63) in + * the first shot. We don't have to remember the quotient -- it + * would be shifted out anyway. + */ + A = ah >> 19; + if (A >= 675) + A = (A % 675u); + + /* Now assemble the remainder with bits 29..50 from the + * numerator and divide. This creates the upper ten bits of the + * quotient. (Well, the top 22 bits of a 44bit result. But that + * will be truncated to 32 bits anyway.) + */ + A = (A << 19) | (ah & 0x0007FFFFu); + A = (A << 3) | (al >> 29); + Q = A / 675u; + A = A % 675u; + + /* Now assemble the remainder with bits 7..28 from the numerator + * and do a final division step. + */ + A = (A << 22) | ((al >> 7) & 0x003FFFFFu); + Q = (Q << 22) | (A / 675u); + + /* The last 7 bits get simply dropped, as they have no affect on + * the quotient when dividing by 86400. + */ + + /* apply sign correction and calculate the true floor + * remainder. + */ + Q ^= sflag; + +# endif + + res.hi = uint32_2cpl_to_int32(Q); + res.lo = ts->D_s.lo - Q * SECSPERDAY; + + return res; +} + +/* + *--------------------------------------------------------------------- + * Split a 32bit seconds value into h/m/s and excessive days. This + * function happily accepts negative time values as timestamps before + * midnight. + *--------------------------------------------------------------------- + */ +static int32_t +priv_timesplit( + int32_t split[3], + int32_t ts + ) +{ + /* Do 3 chained floor divisions by positive constants, using the + * one's complement trick and factoring out the intermediate XOR + * ops to reduce the number of operations. + */ + uint32_t us, um, uh, ud, sflag; + + sflag = int32_sflag(ts); + us = int32_to_uint32_2cpl(ts); + + um = (sflag ^ us) / SECSPERMIN; + uh = um / MINSPERHR; + ud = uh / HRSPERDAY; + + um ^= sflag; + uh ^= sflag; + ud ^= sflag; + + split[0] = (int32_t)(uh - ud * HRSPERDAY ); + split[1] = (int32_t)(um - uh * MINSPERHR ); + split[2] = (int32_t)(us - um * SECSPERMIN); + + return uint32_2cpl_to_int32(ud); +} + +/* + *--------------------------------------------------------------------- + * Given the number of elapsed days in the calendar era, split this + * number into the number of elapsed years in 'res.hi' and the number + * of elapsed days of that year in 'res.lo'. + * + * if 'isleapyear' is not NULL, it will receive an integer that is 0 for + * regular years and a non-zero value for leap years. + *--------------------------------------------------------------------- + */ +ntpcal_split +ntpcal_split_eradays( + int32_t days, + int *isleapyear + ) +{ + /* Use the fast cyclesplit algorithm here, to calculate the + * centuries and years in a century with one division each. This + * reduces the number of division operations to two, but is + * susceptible to internal range overflow. We make sure the + * input operands are in the safe range; this still gives us + * approx +/-2.9 million years. + */ + ntpcal_split res; + int32_t n100, n001; /* calendar year cycles */ + uint32_t uday, Q, sflag; + + /* split off centuries first */ + sflag = int32_sflag(days); + uday = uint32_saturate(int32_to_uint32_2cpl(days), sflag); + uday = (4u * uday) | 3u; + Q = sflag ^ ((sflag ^ uday) / GREGORIAN_CYCLE_DAYS); + uday = uday - Q * GREGORIAN_CYCLE_DAYS; + n100 = uint32_2cpl_to_int32(Q); + + /* Split off years in century -- days >= 0 here, and we're far + * away from integer overflow trouble now. */ + uday |= 3; + n001 = uday / GREGORIAN_NORMAL_LEAP_CYCLE_DAYS; + uday = uday % GREGORIAN_NORMAL_LEAP_CYCLE_DAYS; + + /* Assemble the year and day in year */ + res.hi = n100 * 100 + n001; + res.lo = uday / 4u; + + /* Eventually set the leap year flag. Note: 0 <= n001 <= 99 and + * Q is still the two's complement representation of the + * centuries: The modulo 4 ops can be done with masking here. + * We also shift the year and the century by one, so the tests + * can be done against zero instead of 3. + */ + if (isleapyear) + *isleapyear = !((n001+1) & 3) + && ((n001 != 99) || !((Q+1) & 3)); + + return res; +} + +/* + *--------------------------------------------------------------------- + * Given a number of elapsed days in a year and a leap year indicator, + * split the number of elapsed days into the number of elapsed months in + * 'res.hi' and the number of elapsed days of that month in 'res.lo'. + * + * This function will fail and return {-1,-1} if the number of elapsed + * days is not in the valid range! + *--------------------------------------------------------------------- + */ +ntpcal_split +ntpcal_split_yeardays( + int32_t eyd, + int isleapyear + ) +{ + ntpcal_split res; + const uint16_t *lt; /* month length table */ + + /* check leap year flag and select proper table */ + lt = real_month_table[(isleapyear != 0)]; + if (0 <= eyd && eyd < lt[12]) { + /* get zero-based month by approximation & correction step */ + res.hi = eyd >> 5; /* approx month; might be 1 too low */ + if (lt[res.hi + 1] <= eyd) /* fixup approximative month value */ + res.hi += 1; + res.lo = eyd - lt[res.hi]; + } else { + res.lo = res.hi = -1; + } + + return res; +} + +/* + *--------------------------------------------------------------------- + * Convert a RD into the date part of a 'struct calendar'. + *--------------------------------------------------------------------- + */ +int +ntpcal_rd_to_date( + struct calendar *jd, + int32_t rd + ) +{ + ntpcal_split split; + int leapy; + u_int ymask; + + /* Get day-of-week first. Since rd is signed, the remainder can + * be in the range [-6..+6], but the assignment to an unsigned + * variable maps the negative values to positive values >=7. + * This makes the sign correction look strange, but adding 7 + * causes the needed wrap-around into the desired value range of + * zero to six, both inclusive. + */ + jd->weekday = rd % DAYSPERWEEK; + if (jd->weekday >= DAYSPERWEEK) /* weekday is unsigned! */ + jd->weekday += DAYSPERWEEK; + + split = ntpcal_split_eradays(rd - 1, &leapy); + /* Get year and day-of-year, with overflow check. If any of the + * upper 16 bits is set after shifting to unity-based years, we + * will have an overflow when converting to an unsigned 16bit + * year. Shifting to the right is OK here, since it does not + * matter if the shift is logic or arithmetic. + */ + split.hi += 1; + ymask = 0u - ((split.hi >> 16) == 0); + jd->year = (uint16_t)(split.hi & ymask); + jd->yearday = (uint16_t)split.lo + 1; + + /* convert to month and mday */ + split = ntpcal_split_yeardays(split.lo, leapy); + jd->month = (uint8_t)split.hi + 1; + jd->monthday = (uint8_t)split.lo + 1; + + return ymask ? leapy : -1; +} + +/* + *--------------------------------------------------------------------- + * Convert a RD into the date part of a 'struct tm'. + *--------------------------------------------------------------------- + */ +int +ntpcal_rd_to_tm( + struct tm *utm, + int32_t rd + ) +{ + ntpcal_split split; + int leapy; + + /* get day-of-week first */ + utm->tm_wday = rd % DAYSPERWEEK; + if (utm->tm_wday < 0) + utm->tm_wday += DAYSPERWEEK; + + /* get year and day-of-year */ + split = ntpcal_split_eradays(rd - 1, &leapy); + utm->tm_year = split.hi - 1899; + utm->tm_yday = split.lo; /* 0-based */ + + /* convert to month and mday */ + split = ntpcal_split_yeardays(split.lo, leapy); + utm->tm_mon = split.hi; /* 0-based */ + utm->tm_mday = split.lo + 1; /* 1-based */ + + return leapy; +} + +/* + *--------------------------------------------------------------------- + * Take a value of seconds since midnight and split it into hhmmss in a + * 'struct calendar'. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_daysec_to_date( + struct calendar *jd, + int32_t sec + ) +{ + int32_t days; + int ts[3]; + + days = priv_timesplit(ts, sec); + jd->hour = (uint8_t)ts[0]; + jd->minute = (uint8_t)ts[1]; + jd->second = (uint8_t)ts[2]; + + return days; +} + +/* + *--------------------------------------------------------------------- + * Take a value of seconds since midnight and split it into hhmmss in a + * 'struct tm'. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_daysec_to_tm( + struct tm *utm, + int32_t sec + ) +{ + int32_t days; + int32_t ts[3]; + + days = priv_timesplit(ts, sec); + utm->tm_hour = ts[0]; + utm->tm_min = ts[1]; + utm->tm_sec = ts[2]; + + return days; +} + +/* + *--------------------------------------------------------------------- + * take a split representation for day/second-of-day and day offset + * and convert it to a 'struct calendar'. The seconds will be normalised + * into the range of a day, and the day will be adjusted accordingly. + * + * returns >0 if the result is in a leap year, 0 if in a regular + * year and <0 if the result did not fit into the calendar struct. + *--------------------------------------------------------------------- + */ +int +ntpcal_daysplit_to_date( + struct calendar *jd, + const ntpcal_split *ds, + int32_t dof + ) +{ + dof += ntpcal_daysec_to_date(jd, ds->lo); + return ntpcal_rd_to_date(jd, ds->hi + dof); +} + +/* + *--------------------------------------------------------------------- + * take a split representation for day/second-of-day and day offset + * and convert it to a 'struct tm'. The seconds will be normalised + * into the range of a day, and the day will be adjusted accordingly. + * + * returns 1 if the result is in a leap year and zero if in a regular + * year. + *--------------------------------------------------------------------- + */ +int +ntpcal_daysplit_to_tm( + struct tm *utm, + const ntpcal_split *ds , + int32_t dof + ) +{ + dof += ntpcal_daysec_to_tm(utm, ds->lo); + + return ntpcal_rd_to_tm(utm, ds->hi + dof); +} + +/* + *--------------------------------------------------------------------- + * Take a UN*X time and convert to a calendar structure. + *--------------------------------------------------------------------- + */ +int +ntpcal_time_to_date( + struct calendar *jd, + const vint64 *ts + ) +{ + ntpcal_split ds; + + ds = ntpcal_daysplit(ts); + ds.hi += ntpcal_daysec_to_date(jd, ds.lo); + ds.hi += DAY_UNIX_STARTS; + + return ntpcal_rd_to_date(jd, ds.hi); +} + + +/* + * ==================================================================== + * + * merging composite entities + * + * ==================================================================== + */ + +/* + *--------------------------------------------------------------------- + * Merge a number of days and a number of seconds into seconds, + * expressed in 64 bits to avoid overflow. + *--------------------------------------------------------------------- + */ +vint64 +ntpcal_dayjoin( + int32_t days, + int32_t secs + ) +{ + vint64 res; + +# if defined(HAVE_INT64) + + res.q_s = days; + res.q_s *= SECSPERDAY; + res.q_s += secs; + +# else + + uint32_t p1, p2; + int isneg; + + /* + * res = days *86400 + secs, using manual 16/32 bit + * multiplications and shifts. + */ + isneg = (days < 0); + if (isneg) + days = -days; + + /* assemble days * 675 */ + res.D_s.lo = (days & 0xFFFF) * 675u; + res.D_s.hi = 0; + p1 = (days >> 16) * 675u; + p2 = p1 >> 16; + p1 = p1 << 16; + M_ADD(res.D_s.hi, res.D_s.lo, p2, p1); + + /* mul by 128, using shift */ + res.D_s.hi = (res.D_s.hi << 7) | (res.D_s.lo >> 25); + res.D_s.lo = (res.D_s.lo << 7); + + /* fix sign */ + if (isneg) + M_NEG(res.D_s.hi, res.D_s.lo); + + /* properly add seconds */ + p2 = 0; + if (secs < 0) { + p1 = (uint32_t)-secs; + M_NEG(p2, p1); + } else { + p1 = (uint32_t)secs; + } + M_ADD(res.D_s.hi, res.D_s.lo, p2, p1); + +# endif + + return res; +} + +/* + *--------------------------------------------------------------------- + * get leap years since epoch in elapsed years + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_leapyears_in_years( + int32_t years + ) +{ + /* We use the in-out-in algorithm here, using the one's + * complement division trick for negative numbers. The chained + * division sequence by 4/25/4 gives the compiler the chance to + * get away with only one true division and doing shifts otherwise. + */ + + uint32_t sflag, sum, uyear; + + sflag = int32_sflag(years); + uyear = int32_to_uint32_2cpl(years); + uyear ^= sflag; + + sum = (uyear /= 4u); /* 4yr rule --> IN */ + sum -= (uyear /= 25u); /* 100yr rule --> OUT */ + sum += (uyear /= 4u); /* 400yr rule --> IN */ + + /* Thanks to the alternation of IN/OUT/IN we can do the sum + * directly and have a single one's complement operation + * here. (Only if the years are negative, of course.) Otherwise + * the one's complement would have to be done when + * adding/subtracting the terms. + */ + return uint32_2cpl_to_int32(sflag ^ sum); +} + +/* + *--------------------------------------------------------------------- + * Convert elapsed years in Era into elapsed days in Era. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_days_in_years( + int32_t years + ) +{ + return years * DAYSPERYEAR + ntpcal_leapyears_in_years(years); +} + +/* + *--------------------------------------------------------------------- + * Convert a number of elapsed month in a year into elapsed days in year. + * + * The month will be normalized, and 'res.hi' will contain the + * excessive years that must be considered when converting the years, + * while 'res.lo' will contain the number of elapsed days since start + * of the year. + * + * This code uses the shifted-month-approach to convert month to days, + * because then there is no need to have explicit leap year + * information. The slight disadvantage is that for most month values + * the result is a negative value, and the year excess is one; the + * conversion is then simply based on the start of the following year. + *--------------------------------------------------------------------- + */ +ntpcal_split +ntpcal_days_in_months( + int32_t m + ) +{ + ntpcal_split res; + + /* Add ten months and correct if needed. (It likely is...) */ + res.lo = m + 10; + res.hi = (res.lo >= 12); + if (res.hi) + res.lo -= 12; + + /* if still out of range, normalise by floor division ... */ + if (res.lo < 0 || res.lo >= 12) { + uint32_t mu, Q, sflag; + sflag = int32_sflag(res.lo); + mu = int32_to_uint32_2cpl(res.lo); + Q = sflag ^ ((sflag ^ mu) / 12u); + res.hi += uint32_2cpl_to_int32(Q); + res.lo = mu - Q * 12u; + } + + /* get cummulated days in year with unshift */ + res.lo = shift_month_table[res.lo] - 306; + + return res; +} + +/* + *--------------------------------------------------------------------- + * Convert ELAPSED years/months/days of gregorian calendar to elapsed + * days in Gregorian epoch. + * + * If you want to convert years and days-of-year, just give a month of + * zero. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_edate_to_eradays( + int32_t years, + int32_t mons, + int32_t mdays + ) +{ + ntpcal_split tmp; + int32_t res; + + if (mons) { + tmp = ntpcal_days_in_months(mons); + res = ntpcal_days_in_years(years + tmp.hi) + tmp.lo; + } else + res = ntpcal_days_in_years(years); + res += mdays; + + return res; +} + +/* + *--------------------------------------------------------------------- + * Convert ELAPSED years/months/days of gregorian calendar to elapsed + * days in year. + * + * Note: This will give the true difference to the start of the given + * year, even if months & days are off-scale. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_edate_to_yeardays( + int32_t years, + int32_t mons, + int32_t mdays + ) +{ + ntpcal_split tmp; + + if (0 <= mons && mons < 12) { + years += 1; + mdays += real_month_table[is_leapyear(years)][mons]; + } else { + tmp = ntpcal_days_in_months(mons); + mdays += tmp.lo + + ntpcal_days_in_years(years + tmp.hi) + - ntpcal_days_in_years(years); + } + + return mdays; +} + +/* + *--------------------------------------------------------------------- + * Convert elapsed days and the hour/minute/second information into + * total seconds. + * + * If 'isvalid' is not NULL, do a range check on the time specification + * and tell if the time input is in the normal range, permitting for a + * single leapsecond. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_etime_to_seconds( + int32_t hours, + int32_t minutes, + int32_t seconds + ) +{ + int32_t res; + + res = (hours * MINSPERHR + minutes) * SECSPERMIN + seconds; + + return res; +} + +/* + *--------------------------------------------------------------------- + * Convert the date part of a 'struct tm' (that is, year, month, + * day-of-month) into the RD of that day. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_tm_to_rd( + const struct tm *utm + ) +{ + return ntpcal_edate_to_eradays(utm->tm_year + 1899, + utm->tm_mon, + utm->tm_mday - 1) + 1; +} + +/* + *--------------------------------------------------------------------- + * Convert the date part of a 'struct calendar' (that is, year, month, + * day-of-month) into the RD of that day. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_date_to_rd( + const struct calendar *jd + ) +{ + return ntpcal_edate_to_eradays((int32_t)jd->year - 1, + (int32_t)jd->month - 1, + (int32_t)jd->monthday - 1) + 1; +} + +/* + *--------------------------------------------------------------------- + * convert a year number to rata die of year start + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_year_to_ystart( + int32_t year + ) +{ + return ntpcal_days_in_years(year - 1) + 1; +} + +/* + *--------------------------------------------------------------------- + * For a given RD, get the RD of the associated year start, + * that is, the RD of the last January,1st on or before that day. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_rd_to_ystart( + int32_t rd + ) +{ + /* + * Rather simple exercise: split the day number into elapsed + * years and elapsed days, then remove the elapsed days from the + * input value. Nice'n sweet... + */ + return rd - ntpcal_split_eradays(rd - 1, NULL).lo; +} + +/* + *--------------------------------------------------------------------- + * For a given RD, get the RD of the associated month start. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_rd_to_mstart( + int32_t rd + ) +{ + ntpcal_split split; + int leaps; + + split = ntpcal_split_eradays(rd - 1, &leaps); + split = ntpcal_split_yeardays(split.lo, leaps); + + return rd - split.lo; +} + +/* + *--------------------------------------------------------------------- + * take a 'struct calendar' and get the seconds-of-day from it. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_date_to_daysec( + const struct calendar *jd + ) +{ + return ntpcal_etime_to_seconds(jd->hour, jd->minute, + jd->second); +} + +/* + *--------------------------------------------------------------------- + * take a 'struct tm' and get the seconds-of-day from it. + *--------------------------------------------------------------------- + */ +int32_t +ntpcal_tm_to_daysec( + const struct tm *utm + ) +{ + return ntpcal_etime_to_seconds(utm->tm_hour, utm->tm_min, + utm->tm_sec); +} + +/* + *--------------------------------------------------------------------- + * take a 'struct calendar' and convert it to a 'time_t' + *--------------------------------------------------------------------- + */ +time_t +ntpcal_date_to_time( + const struct calendar *jd + ) +{ + vint64 join; + int32_t days, secs; + + days = ntpcal_date_to_rd(jd) - DAY_UNIX_STARTS; + secs = ntpcal_date_to_daysec(jd); + join = ntpcal_dayjoin(days, secs); + + return vint64_to_time(&join); +} + + +/* + * ==================================================================== + * + * extended and unchecked variants of caljulian/caltontp + * + * ==================================================================== + */ +int +ntpcal_ntp64_to_date( + struct calendar *jd, + const vint64 *ntp + ) +{ + ntpcal_split ds; + + ds = ntpcal_daysplit(ntp); + ds.hi += ntpcal_daysec_to_date(jd, ds.lo); + + return ntpcal_rd_to_date(jd, ds.hi + DAY_NTP_STARTS); +} + +int +ntpcal_ntp_to_date( + struct calendar *jd, + uint32_t ntp, + const time_t *piv + ) +{ + vint64 ntp64; + + /* + * Unfold ntp time around current time into NTP domain. Split + * into days and seconds, shift days into CE domain and + * process the parts. + */ + ntp64 = ntpcal_ntp_to_ntp(ntp, piv); + return ntpcal_ntp64_to_date(jd, &ntp64); +} + + +vint64 +ntpcal_date_to_ntp64( + const struct calendar *jd + ) +{ + /* + * Convert date to NTP. Ignore yearday, use d/m/y only. + */ + return ntpcal_dayjoin(ntpcal_date_to_rd(jd) - DAY_NTP_STARTS, + ntpcal_date_to_daysec(jd)); +} + + +uint32_t +ntpcal_date_to_ntp( + const struct calendar *jd + ) +{ + /* + * Get lower half of 64-bit NTP timestamp from date/time. + */ + return ntpcal_date_to_ntp64(jd).d_s.lo; +} + + + +/* + * ==================================================================== + * + * day-of-week calculations + * + * ==================================================================== + */ +/* + * Given a RataDie and a day-of-week, calculate a RDN that is reater-than, + * greater-or equal, closest, less-or-equal or less-than the given RDN + * and denotes the given day-of-week + */ +int32_t +ntpcal_weekday_gt( + int32_t rdn, + int32_t dow + ) +{ + return ntpcal_periodic_extend(rdn+1, dow, 7); +} + +int32_t +ntpcal_weekday_ge( + int32_t rdn, + int32_t dow + ) +{ + return ntpcal_periodic_extend(rdn, dow, 7); +} + +int32_t +ntpcal_weekday_close( + int32_t rdn, + int32_t dow + ) +{ + return ntpcal_periodic_extend(rdn-3, dow, 7); +} + +int32_t +ntpcal_weekday_le( + int32_t rdn, + int32_t dow + ) +{ + return ntpcal_periodic_extend(rdn, dow, -7); +} + +int32_t +ntpcal_weekday_lt( + int32_t rdn, + int32_t dow + ) +{ + return ntpcal_periodic_extend(rdn-1, dow, -7); +} + +/* + * ==================================================================== + * + * ISO week-calendar conversions + * + * The ISO8601 calendar defines a calendar of years, weeks and weekdays. + * It is related to the Gregorian calendar, and a ISO year starts at the + * Monday closest to Jan,1st of the corresponding Gregorian year. A ISO + * calendar year has always 52 or 53 weeks, and like the Grogrian + * calendar the ISO8601 calendar repeats itself every 400 years, or + * 146097 days, or 20871 weeks. + * + * While it is possible to write ISO calendar functions based on the + * Gregorian calendar functions, the following implementation takes a + * different approach, based directly on years and weeks. + * + * Analysis of the tabulated data shows that it is not possible to + * interpolate from years to weeks over a full 400 year range; cyclic + * shifts over 400 years do not provide a solution here. But it *is* + * possible to interpolate over every single century of the 400-year + * cycle. (The centennial leap year rule seems to be the culprit here.) + * + * It can be shown that a conversion from years to weeks can be done + * using a linear transformation of the form + * + * w = floor( y * a + b ) + * + * where the slope a must hold to + * + * 52.1780821918 <= a < 52.1791044776 + * + * and b must be chosen according to the selected slope and the number + * of the century in a 400-year period. + * + * The inverse calculation can also be done in this way. Careful scaling + * provides an unlimited set of integer coefficients a,k,b that enable + * us to write the calulation in the form + * + * w = (y * a + b ) / k + * y = (w * a' + b') / k' + * + * In this implementation the values of k and k' are chosen to be + * smallest possible powers of two, so the division can be implemented + * as shifts if the optimiser chooses to do so. + * + * ==================================================================== + */ + +/* + * Given a number of elapsed (ISO-)years since the begin of the + * christian era, return the number of elapsed weeks corresponding to + * the number of years. + */ +int32_t +isocal_weeks_in_years( + int32_t years + ) +{ + /* + * use: w = (y * 53431 + b[c]) / 1024 as interpolation + */ + static const uint16_t bctab[4] = { 157, 449, 597, 889 }; + + int32_t cs, cw; + uint32_t cc, ci, yu, sflag; + + sflag = int32_sflag(years); + yu = int32_to_uint32_2cpl(years); + + /* split off centuries, using floor division */ + cc = sflag ^ ((sflag ^ yu) / 100u); + yu -= cc * 100u; + + /* calculate century cycles shift and cycle index: + * Assuming a century is 5217 weeks, we have to add a cycle + * shift that is 3 for every 4 centuries, because 3 of the four + * centuries have 5218 weeks. So '(cc*3 + 1) / 4' is the actual + * correction, and the second century is the defective one. + * + * Needs floor division by 4, which is done with masking and + * shifting. + */ + ci = cc * 3u + 1; + cs = uint32_2cpl_to_int32(sflag ^ ((sflag ^ ci) / 4u)); + ci = ci % 4u; + + /* Get weeks in century. Can use plain division here as all ops + * are >= 0, and let the compiler sort out the possible + * optimisations. + */ + cw = (yu * 53431u + bctab[ci]) / 1024u; + + return uint32_2cpl_to_int32(cc) * 5217 + cs + cw; +} + +/* + * Given a number of elapsed weeks since the begin of the christian + * era, split this number into the number of elapsed years in res.hi + * and the excessive number of weeks in res.lo. (That is, res.lo is + * the number of elapsed weeks in the remaining partial year.) + */ +ntpcal_split +isocal_split_eraweeks( + int32_t weeks + ) +{ + /* + * use: y = (w * 157 + b[c]) / 8192 as interpolation + */ + + static const uint16_t bctab[4] = { 85, 130, 17, 62 }; + + ntpcal_split res; + int32_t cc, ci; + uint32_t sw, cy, Q, sflag; + + /* Use two fast cycle-split divisions here. This is again + * susceptible to internal overflow, so we check the range. This + * still permits more than +/-20 million years, so this is + * likely a pure academical problem. + * + * We want to execute '(weeks * 4 + 2) /% 20871' under floor + * division rules in the first step. + */ + sflag = int32_sflag(weeks); + sw = uint32_saturate(int32_to_uint32_2cpl(weeks), sflag); + sw = 4u * sw + 2; + Q = sflag ^ ((sflag ^ sw) / GREGORIAN_CYCLE_WEEKS); + sw -= Q * GREGORIAN_CYCLE_WEEKS; + ci = Q % 4u; + cc = uint32_2cpl_to_int32(Q); + + /* Split off years; sw >= 0 here! The scaled weeks in the years + * are scaled up by 157 afterwards. + */ + sw = (sw / 4u) * 157u + bctab[ci]; + cy = sw / 8192u; /* ws >> 13 , let the compiler sort it out */ + sw = sw % 8192u; /* ws & 8191, let the compiler sort it out */ + + /* assemble elapsed years and downscale the elapsed weeks in + * the year. + */ + res.hi = 100*cc + cy; + res.lo = sw / 157u; + + return res; +} + +/* + * Given a second in the NTP time scale and a pivot, expand the NTP + * time stamp around the pivot and convert into an ISO calendar time + * stamp. + */ +int +isocal_ntp64_to_date( + struct isodate *id, + const vint64 *ntp + ) +{ + ntpcal_split ds; + int32_t ts[3]; + uint32_t uw, ud, sflag; + + /* + * Split NTP time into days and seconds, shift days into CE + * domain and process the parts. + */ + ds = ntpcal_daysplit(ntp); + + /* split time part */ + ds.hi += priv_timesplit(ts, ds.lo); + id->hour = (uint8_t)ts[0]; + id->minute = (uint8_t)ts[1]; + id->second = (uint8_t)ts[2]; + + /* split days into days and weeks, using floor division in unsigned */ + ds.hi += DAY_NTP_STARTS - 1; /* shift from NTP to RDN */ + sflag = int32_sflag(ds.hi); + ud = int32_to_uint32_2cpl(ds.hi); + uw = sflag ^ ((sflag ^ ud) / DAYSPERWEEK); + ud -= uw * DAYSPERWEEK; + ds.hi = uint32_2cpl_to_int32(uw); + ds.lo = ud; + + id->weekday = (uint8_t)ds.lo + 1; /* weekday result */ + + /* get year and week in year */ + ds = isocal_split_eraweeks(ds.hi); /* elapsed years&week*/ + id->year = (uint16_t)ds.hi + 1; /* shift to current */ + id->week = (uint8_t )ds.lo + 1; + + return (ds.hi >= 0 && ds.hi < 0x0000FFFF); +} + +int +isocal_ntp_to_date( + struct isodate *id, + uint32_t ntp, + const time_t *piv + ) +{ + vint64 ntp64; + + /* + * Unfold ntp time around current time into NTP domain, then + * convert the full time stamp. + */ + ntp64 = ntpcal_ntp_to_ntp(ntp, piv); + return isocal_ntp64_to_date(id, &ntp64); +} + +/* + * Convert a ISO date spec into a second in the NTP time scale, + * properly truncated to 32 bit. + */ +vint64 +isocal_date_to_ntp64( + const struct isodate *id + ) +{ + int32_t weeks, days, secs; + + weeks = isocal_weeks_in_years((int32_t)id->year - 1) + + (int32_t)id->week - 1; + days = weeks * 7 + (int32_t)id->weekday; + /* days is RDN of ISO date now */ + secs = ntpcal_etime_to_seconds(id->hour, id->minute, id->second); + + return ntpcal_dayjoin(days - DAY_NTP_STARTS, secs); +} + +uint32_t +isocal_date_to_ntp( + const struct isodate *id + ) +{ + /* + * Get lower half of 64-bit NTP timestamp from date/time. + */ + return isocal_date_to_ntp64(id).d_s.lo; +} + +/* -*-EOF-*- */ diff --git a/contrib/ntp/libntp/ntp_crypto_rnd.c b/contrib/ntp/libntp/ntp_crypto_rnd.c new file mode 100644 index 000000000000..2a4f91affad5 --- /dev/null +++ b/contrib/ntp/libntp/ntp_crypto_rnd.c @@ -0,0 +1,114 @@ +/* + * Crypto-quality random number functions + * + * Author: Harlan Stenn, 2014 + * + * This file is Copyright (c) 2014 by Network Time Foundation. + * BSD terms apply: see the file COPYRIGHT in the distribution root for details. + */ + +#include "config.h" +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdio.h> + +#include <l_stdlib.h> +#include <ntp_random.h> +#include "safecast.h" + +#ifdef USE_OPENSSL_CRYPTO_RAND +#include <openssl/err.h> +#include <openssl/rand.h> + +int crypto_rand_init = 0; +#else + +# ifndef HAVE_ARC4RANDOM_BUF +static void +arc4random_buf(void *buf, size_t nbytes); + +void +evutil_secure_rng_get_bytes(void *buf, size_t nbytes); + +static void +arc4random_buf(void *buf, size_t nbytes) +{ + evutil_secure_rng_get_bytes(buf, nbytes); + return; +} +# endif +#endif + +/* + * As of late 2014, here's how we plan to provide cryptographic-quality + * random numbers: + * + * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes(). + * - Otherwise, use arc4random(). + * + * Use of arc4random() can be forced using configure --disable-openssl-random + * + * We can count on arc4random existing, thru the OS or thru libevent. + * The quality of arc4random depends on the implementor. + * + * RAND_poll() doesn't show up until XXX. If it's not present, we + * need to either provide our own or use arc4random(). + */ + +/* + * ntp_crypto_srandom: + * + * Initialize the random number generator, if needed by the underlying + * crypto random number generation mechanism. + */ + +void +ntp_crypto_srandom( + void + ) +{ +#ifdef USE_OPENSSL_CRYPTO_RAND + if (!crypto_rand_init) { + RAND_poll(); + crypto_rand_init = 1; + } +#else + /* No initialization needed for arc4random() */ +#endif +} + + +/* + * ntp_crypto_random_buf: + * + * Returns 0 on success, -1 on error. + */ +int +ntp_crypto_random_buf( + void *buf, + size_t nbytes + ) +{ +#ifdef USE_OPENSSL_CRYPTO_RAND + int rc; + + rc = RAND_bytes(buf, size2int_chk(nbytes)); + if (1 != rc) { + unsigned long err; + char *err_str; + + err = ERR_get_error(); + err_str = ERR_error_string(err, NULL); + /* XXX: Log the error */ + (void)&err_str; + + return -1; + } + return 0; +#else + arc4random_buf(buf, nbytes); + return 0; +#endif +} diff --git a/contrib/ntp/libntp/ntp_intres.c b/contrib/ntp/libntp/ntp_intres.c new file mode 100644 index 000000000000..7aa288af57b2 --- /dev/null +++ b/contrib/ntp/libntp/ntp_intres.c @@ -0,0 +1,1154 @@ +/* + * ntp_intres.c - Implements a generic blocking worker child or thread, + * initially to provide a nonblocking solution for DNS + * name to address lookups available with getaddrinfo(). + * + * This is a new implementation as of 2009 sharing the filename and + * very little else with the prior implementation, which used a + * temporary file to receive a single set of requests from the parent, + * and a NTP mode 7 authenticated request to push back responses. + * + * A primary goal in rewriting this code was the need to support the + * pool configuration directive's requirement to retrieve multiple + * addresses resolving a single name, which has previously been + * satisfied with blocking resolver calls from the ntpd mainline code. + * + * A secondary goal is to provide a generic mechanism for other + * blocking operations to be delegated to a worker using a common + * model for both Unix and Windows ntpd. ntp_worker.c, work_fork.c, + * and work_thread.c implement the generic mechanism. This file + * implements the two current consumers, getaddrinfo_sometime() and the + * presently unused getnameinfo_sometime(). + * + * Both routines deliver results to a callback and manage memory + * allocation, meaning there is no freeaddrinfo_sometime(). + * + * The initial implementation for Unix uses a pair of unidirectional + * pipes, one each for requests and responses, connecting the forked + * blocking child worker with the ntpd mainline. The threaded code + * uses arrays of pointers to queue requests and responses. + * + * The parent drives the process, including scheduling sleeps between + * retries. + * + * Memory is managed differently for a child process, which mallocs + * request buffers to read from the pipe into, whereas the threaded + * code mallocs a copy of the request to hand off to the worker via + * the queueing array. The resulting request buffer is free()d by + * platform-independent code. A wrinkle is the request needs to be + * available to the requestor during response processing. + * + * Response memory allocation is also platform-dependent. With a + * separate process and pipes, the response is free()d after being + * written to the pipe. With threads, the same memory is handed + * over and the requestor frees it after processing is completed. + * + * The code should be generalized to support threads on Unix using + * much of the same code used for Windows initially. + * + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "ntp_workimpl.h" + +#ifdef WORKER + +#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> +#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> +# ifdef HAVE_INT32_ONLY_WITH_DNS +# define HAVE_INT32 +# endif +# ifdef HAVE_U_INT32_ONLY_WITH_DNS +# define HAVE_U_INT32 +# endif +#endif + +#include "ntp.h" +#include "ntp_debug.h" +#include "ntp_malloc.h" +#include "ntp_syslog.h" +#include "ntp_unixtime.h" +#include "ntp_intres.h" +#include "intreswork.h" + + +/* + * Following are implementations of getaddrinfo_sometime() and + * getnameinfo_sometime(). Each is implemented in three routines: + * + * getaddrinfo_sometime() getnameinfo_sometime() + * blocking_getaddrinfo() blocking_getnameinfo() + * getaddrinfo_sometime_complete() getnameinfo_sometime_complete() + * + * The first runs in the parent and marshalls (or serializes) request + * parameters into a request blob which is processed in the child by + * the second routine, blocking_*(), which serializes the results into + * a response blob unpacked by the third routine, *_complete(), which + * calls the callback routine provided with the request and frees + * _request_ memory allocated by the first routine. Response memory + * is managed by the code which calls the *_complete routines. + */ + + +/* === typedefs === */ +typedef struct blocking_gai_req_tag { /* marshalled args */ + size_t octets; + u_int dns_idx; + time_t scheduled; + time_t earliest; + int retry; + struct addrinfo hints; + u_int qflags; + gai_sometime_callback callback; + void * context; + size_t nodesize; + size_t servsize; +} blocking_gai_req; + +typedef struct blocking_gai_resp_tag { + size_t octets; + int retcode; + int retry; + int gai_errno; /* for EAI_SYSTEM case */ + int ai_count; + /* + * Followed by ai_count struct addrinfo and then ai_count + * sockaddr_u and finally the canonical name strings. + */ +} blocking_gai_resp; + +typedef struct blocking_gni_req_tag { + size_t octets; + u_int dns_idx; + time_t scheduled; + time_t earliest; + int retry; + size_t hostoctets; + size_t servoctets; + int flags; + gni_sometime_callback callback; + void * context; + sockaddr_u socku; +} blocking_gni_req; + +typedef struct blocking_gni_resp_tag { + size_t octets; + int retcode; + int gni_errno; /* for EAI_SYSTEM case */ + int retry; + size_t hostoctets; + size_t servoctets; + /* + * Followed by hostoctets bytes of null-terminated host, + * then servoctets bytes of null-terminated service. + */ +} blocking_gni_resp; + +/* per-DNS-worker state in parent */ +typedef struct dnschild_ctx_tag { + u_int index; + time_t next_dns_timeslot; +} dnschild_ctx; + +/* per-DNS-worker state in worker */ +typedef struct dnsworker_ctx_tag { + blocking_child * c; + time_t ignore_scheduled_before; +#ifdef HAVE_RES_INIT + time_t next_res_init; +#endif +} dnsworker_ctx; + + +/* === variables === */ +dnschild_ctx ** dnschild_contexts; /* parent */ +u_int dnschild_contexts_alloc; +dnsworker_ctx ** dnsworker_contexts; /* child */ +u_int dnsworker_contexts_alloc; + +#ifdef HAVE_RES_INIT +static time_t next_res_init; +#endif + + +/* === forward declarations === */ +static u_int reserve_dnschild_ctx(void); +static u_int get_dnschild_ctx(void); +static dnsworker_ctx * get_worker_context(blocking_child *, u_int); +static void scheduled_sleep(time_t, time_t, + dnsworker_ctx *); +static void manage_dns_retry_interval(time_t *, time_t *, + int *, time_t *, + int/*BOOL*/); +static int should_retry_dns(int, int); +#ifdef HAVE_RES_INIT +static void reload_resolv_conf(dnsworker_ctx *); +#else +# define reload_resolv_conf(wc) \ + do { \ + (void)(wc); \ + } while (FALSE) +#endif +static void getaddrinfo_sometime_complete(blocking_work_req, + void *, size_t, + void *); +static void getnameinfo_sometime_complete(blocking_work_req, + void *, size_t, + void *); + + +/* === functions === */ +/* + * getaddrinfo_sometime - uses blocking child to call getaddrinfo then + * invokes provided callback completion function. + */ +int +getaddrinfo_sometime_ex( + const char * node, + const char * service, + const struct addrinfo * hints, + int retry, + gai_sometime_callback callback, + void * context, + u_int qflags + ) +{ + blocking_gai_req * gai_req; + u_int idx; + dnschild_ctx * child_ctx; + size_t req_size; + size_t nodesize; + size_t servsize; + time_t now; + + REQUIRE(NULL != node); + if (NULL != hints) { + REQUIRE(0 == hints->ai_addrlen); + REQUIRE(NULL == hints->ai_addr); + REQUIRE(NULL == hints->ai_canonname); + REQUIRE(NULL == hints->ai_next); + } + + idx = get_dnschild_ctx(); + child_ctx = dnschild_contexts[idx]; + + nodesize = strlen(node) + 1; + servsize = strlen(service) + 1; + req_size = sizeof(*gai_req) + nodesize + servsize; + + gai_req = emalloc_zero(req_size); + + gai_req->octets = req_size; + gai_req->dns_idx = idx; + now = time(NULL); + gai_req->scheduled = now; + gai_req->earliest = max(now, child_ctx->next_dns_timeslot); + child_ctx->next_dns_timeslot = gai_req->earliest; + if (hints != NULL) + gai_req->hints = *hints; + gai_req->retry = retry; + gai_req->callback = callback; + gai_req->context = context; + gai_req->nodesize = nodesize; + gai_req->servsize = servsize; + gai_req->qflags = qflags; + + memcpy((char *)gai_req + sizeof(*gai_req), node, nodesize); + memcpy((char *)gai_req + sizeof(*gai_req) + nodesize, service, + servsize); + + if (queue_blocking_request( + BLOCKING_GETADDRINFO, + gai_req, + req_size, + &getaddrinfo_sometime_complete, + gai_req)) { + + msyslog(LOG_ERR, "unable to queue getaddrinfo request"); + errno = EFAULT; + return -1; + } + + return 0; +} + +int +blocking_getaddrinfo( + blocking_child * c, + blocking_pipe_header * req + ) +{ + blocking_gai_req * gai_req; + dnsworker_ctx * worker_ctx; + blocking_pipe_header * resp; + blocking_gai_resp * gai_resp; + char * node; + char * service; + struct addrinfo * ai_res; + struct addrinfo * ai; + struct addrinfo * serialized_ai; + size_t canons_octets; + size_t this_octets; + size_t resp_octets; + char * cp; + time_t time_now; + + gai_req = (void *)((char *)req + sizeof(*req)); + node = (char *)gai_req + sizeof(*gai_req); + service = node + gai_req->nodesize; + + worker_ctx = get_worker_context(c, gai_req->dns_idx); + scheduled_sleep(gai_req->scheduled, gai_req->earliest, + worker_ctx); + reload_resolv_conf(worker_ctx); + + /* + * Take a shot at the final size, better to overestimate + * at first and then realloc to a smaller size. + */ + + resp_octets = sizeof(*resp) + sizeof(*gai_resp) + + 16 * (sizeof(struct addrinfo) + + sizeof(sockaddr_u)) + + 256; + resp = emalloc_zero(resp_octets); + gai_resp = (void *)(resp + 1); + + TRACE(2, ("blocking_getaddrinfo given node %s serv %s fam %d flags %x\n", + node, service, gai_req->hints.ai_family, + gai_req->hints.ai_flags)); +#ifdef DEBUG + if (debug >= 2) + fflush(stdout); +#endif + ai_res = NULL; + gai_resp->retcode = getaddrinfo(node, service, &gai_req->hints, + &ai_res); + gai_resp->retry = gai_req->retry; +#ifdef EAI_SYSTEM + if (EAI_SYSTEM == gai_resp->retcode) + gai_resp->gai_errno = errno; +#endif + canons_octets = 0; + + if (0 == gai_resp->retcode) { + ai = ai_res; + while (NULL != ai) { + gai_resp->ai_count++; + if (ai->ai_canonname) + canons_octets += strlen(ai->ai_canonname) + 1; + ai = ai->ai_next; + } + /* + * If this query succeeded only after retrying, DNS may have + * just become responsive. Ignore previously-scheduled + * retry sleeps once for each pending request, similar to + * the way scheduled_sleep() does when its worker_sleep() + * is interrupted. + */ + if (gai_resp->retry > INITIAL_DNS_RETRY) { + time_now = time(NULL); + worker_ctx->ignore_scheduled_before = time_now; + TRACE(1, ("DNS success after retry, ignoring sleeps scheduled before now (%s)\n", + humantime(time_now))); + } + } + + /* + * Our response consists of a header, followed by ai_count + * addrinfo structs followed by ai_count sockaddr_storage + * structs followed by the canonical names. + */ + gai_resp->octets = sizeof(*gai_resp) + + gai_resp->ai_count + * (sizeof(gai_req->hints) + + sizeof(sockaddr_u)) + + canons_octets; + + resp_octets = sizeof(*resp) + gai_resp->octets; + resp = erealloc(resp, resp_octets); + gai_resp = (void *)(resp + 1); + + /* cp serves as our current pointer while serializing */ + cp = (void *)(gai_resp + 1); + canons_octets = 0; + + if (0 == gai_resp->retcode) { + ai = ai_res; + while (NULL != ai) { + memcpy(cp, ai, sizeof(*ai)); + serialized_ai = (void *)cp; + cp += sizeof(*ai); + + /* transform ai_canonname into offset */ + if (NULL != serialized_ai->ai_canonname) { + serialized_ai->ai_canonname = (char *)canons_octets; + canons_octets += strlen(ai->ai_canonname) + 1; + } + + /* leave fixup of ai_addr pointer for receiver */ + + ai = ai->ai_next; + } + + ai = ai_res; + while (NULL != ai) { + INSIST(ai->ai_addrlen <= sizeof(sockaddr_u)); + memcpy(cp, ai->ai_addr, ai->ai_addrlen); + cp += sizeof(sockaddr_u); + + ai = ai->ai_next; + } + + ai = ai_res; + while (NULL != ai) { + if (NULL != ai->ai_canonname) { + this_octets = strlen(ai->ai_canonname) + 1; + memcpy(cp, ai->ai_canonname, this_octets); + cp += this_octets; + } + + ai = ai->ai_next; + } + freeaddrinfo(ai_res); + } + + /* + * make sure our walk and earlier calc match + */ + DEBUG_INSIST((size_t)(cp - (char *)resp) == resp_octets); + + if (queue_blocking_response(c, resp, resp_octets, req)) { + msyslog(LOG_ERR, "blocking_getaddrinfo can not queue response"); + return -1; + } + + return 0; +} + +int +getaddrinfo_sometime( + const char * node, + const char * service, + const struct addrinfo * hints, + int retry, + gai_sometime_callback callback, + void * context + ) +{ + return getaddrinfo_sometime_ex(node, service, hints, retry, + callback, context, 0); +} + + +static void +getaddrinfo_sometime_complete( + blocking_work_req rtype, + void * context, + size_t respsize, + void * resp + ) +{ + blocking_gai_req * gai_req; + blocking_gai_resp * gai_resp; + dnschild_ctx * child_ctx; + struct addrinfo * ai; + struct addrinfo * next_ai; + sockaddr_u * psau; + char * node; + char * service; + char * canon_start; + time_t time_now; + int again, noerr; + int af; + const char * fam_spec; + int i; + + gai_req = context; + gai_resp = resp; + + DEBUG_REQUIRE(BLOCKING_GETADDRINFO == rtype); + DEBUG_REQUIRE(respsize == gai_resp->octets); + + node = (char *)gai_req + sizeof(*gai_req); + service = node + gai_req->nodesize; + + child_ctx = dnschild_contexts[gai_req->dns_idx]; + + if (0 == gai_resp->retcode) { + /* + * If this query succeeded only after retrying, DNS may have + * just become responsive. + */ + if (gai_resp->retry > INITIAL_DNS_RETRY) { + time_now = time(NULL); + child_ctx->next_dns_timeslot = time_now; + TRACE(1, ("DNS success after retry, %u next_dns_timeslot reset (%s)\n", + gai_req->dns_idx, humantime(time_now))); + } + } else { + noerr = !!(gai_req->qflags & GAIR_F_IGNDNSERR); + again = noerr || should_retry_dns( + gai_resp->retcode, gai_resp->gai_errno); + /* + * exponential backoff of DNS retries to 64s + */ + if (gai_req->retry > 0 && again) { + /* log the first retry only */ + if (INITIAL_DNS_RETRY == gai_req->retry) + NLOG(NLOG_SYSINFO) { + af = gai_req->hints.ai_family; + fam_spec = (AF_INET6 == af) + ? " (AAAA)" + : (AF_INET == af) + ? " (A)" + : ""; +#ifdef EAI_SYSTEM + if (EAI_SYSTEM == gai_resp->retcode) { + errno = gai_resp->gai_errno; + msyslog(LOG_INFO, + "retrying DNS %s%s: EAI_SYSTEM %d: %m", + node, fam_spec, + gai_resp->gai_errno); + } else +#endif + msyslog(LOG_INFO, + "retrying DNS %s%s: %s (%d)", + node, fam_spec, + gai_strerror(gai_resp->retcode), + gai_resp->retcode); + } + manage_dns_retry_interval( + &gai_req->scheduled, &gai_req->earliest, + &gai_req->retry, &child_ctx->next_dns_timeslot, + noerr); + if (!queue_blocking_request( + BLOCKING_GETADDRINFO, + gai_req, + gai_req->octets, + &getaddrinfo_sometime_complete, + gai_req)) + return; + else + msyslog(LOG_ERR, + "unable to retry hostname %s", + node); + } + } + + /* + * fixup pointers in returned addrinfo array + */ + ai = (void *)((char *)gai_resp + sizeof(*gai_resp)); + next_ai = NULL; + for (i = gai_resp->ai_count - 1; i >= 0; i--) { + ai[i].ai_next = next_ai; + next_ai = &ai[i]; + } + + psau = (void *)((char *)ai + gai_resp->ai_count * sizeof(*ai)); + canon_start = (char *)psau + gai_resp->ai_count * sizeof(*psau); + + for (i = 0; i < gai_resp->ai_count; i++) { + if (NULL != ai[i].ai_addr) + ai[i].ai_addr = &psau->sa; + psau++; + if (NULL != ai[i].ai_canonname) + ai[i].ai_canonname += (size_t)canon_start; + } + + ENSURE((char *)psau == canon_start); + + if (!gai_resp->ai_count) + ai = NULL; + + (*gai_req->callback)(gai_resp->retcode, gai_resp->gai_errno, + gai_req->context, node, service, + &gai_req->hints, ai); + + free(gai_req); + /* gai_resp is part of block freed by process_blocking_resp() */ +} + + +#ifdef TEST_BLOCKING_WORKER +void gai_test_callback(int rescode, int gai_errno, void *context, const char *name, const char *service, const struct addrinfo *hints, const struct addrinfo *ai_res) +{ + sockaddr_u addr; + + if (rescode) { + TRACE(1, ("gai_test_callback context %p error rescode %d %s serv %s\n", + context, rescode, name, service)); + return; + } + while (!rescode && NULL != ai_res) { + ZERO_SOCK(&addr); + memcpy(&addr, ai_res->ai_addr, ai_res->ai_addrlen); + TRACE(1, ("ctx %p fam %d addr %s canon '%s' type %s at %p ai_addr %p ai_next %p\n", + context, + AF(&addr), + stoa(&addr), + (ai_res->ai_canonname) + ? ai_res->ai_canonname + : "", + (SOCK_DGRAM == ai_res->ai_socktype) + ? "DGRAM" + : (SOCK_STREAM == ai_res->ai_socktype) + ? "STREAM" + : "(other)", + ai_res, + ai_res->ai_addr, + ai_res->ai_next)); + + getnameinfo_sometime((sockaddr_u *)ai_res->ai_addr, 128, 32, 0, gni_test_callback, context); + + ai_res = ai_res->ai_next; + } +} +#endif /* TEST_BLOCKING_WORKER */ + + +int +getnameinfo_sometime( + sockaddr_u * psau, + size_t hostoctets, + size_t servoctets, + int flags, + gni_sometime_callback callback, + void * context + ) +{ + blocking_gni_req * gni_req; + u_int idx; + dnschild_ctx * child_ctx; + time_t time_now; + + REQUIRE(hostoctets); + REQUIRE(hostoctets + servoctets < 1024); + + idx = get_dnschild_ctx(); + child_ctx = dnschild_contexts[idx]; + + gni_req = emalloc_zero(sizeof(*gni_req)); + + gni_req->octets = sizeof(*gni_req); + gni_req->dns_idx = idx; + time_now = time(NULL); + gni_req->scheduled = time_now; + gni_req->earliest = max(time_now, child_ctx->next_dns_timeslot); + child_ctx->next_dns_timeslot = gni_req->earliest; + memcpy(&gni_req->socku, psau, SOCKLEN(psau)); + gni_req->hostoctets = hostoctets; + gni_req->servoctets = servoctets; + gni_req->flags = flags; + gni_req->retry = INITIAL_DNS_RETRY; + gni_req->callback = callback; + gni_req->context = context; + + if (queue_blocking_request( + BLOCKING_GETNAMEINFO, + gni_req, + sizeof(*gni_req), + &getnameinfo_sometime_complete, + gni_req)) { + + msyslog(LOG_ERR, "unable to queue getnameinfo request"); + errno = EFAULT; + return -1; + } + + return 0; +} + + +int +blocking_getnameinfo( + blocking_child * c, + blocking_pipe_header * req + ) +{ + blocking_gni_req * gni_req; + dnsworker_ctx * worker_ctx; + blocking_pipe_header * resp; + blocking_gni_resp * gni_resp; + size_t octets; + size_t resp_octets; + char * service; + char * cp; + int rc; + time_t time_now; + char host[1024]; + + gni_req = (void *)((char *)req + sizeof(*req)); + + octets = gni_req->hostoctets + gni_req->servoctets; + + /* + * Some alloca() implementations are fragile regarding + * large allocations. We only need room for the host + * and service names. + */ + REQUIRE(octets < sizeof(host)); + service = host + gni_req->hostoctets; + + worker_ctx = get_worker_context(c, gni_req->dns_idx); + scheduled_sleep(gni_req->scheduled, gni_req->earliest, + worker_ctx); + reload_resolv_conf(worker_ctx); + + /* + * Take a shot at the final size, better to overestimate + * then realloc to a smaller size. + */ + + resp_octets = sizeof(*resp) + sizeof(*gni_resp) + octets; + resp = emalloc_zero(resp_octets); + gni_resp = (void *)((char *)resp + sizeof(*resp)); + + TRACE(2, ("blocking_getnameinfo given addr %s flags 0x%x hostlen %lu servlen %lu\n", + stoa(&gni_req->socku), gni_req->flags, + (u_long)gni_req->hostoctets, (u_long)gni_req->servoctets)); + + gni_resp->retcode = getnameinfo(&gni_req->socku.sa, + SOCKLEN(&gni_req->socku), + host, + gni_req->hostoctets, + service, + gni_req->servoctets, + gni_req->flags); + gni_resp->retry = gni_req->retry; +#ifdef EAI_SYSTEM + if (EAI_SYSTEM == gni_resp->retcode) + gni_resp->gni_errno = errno; +#endif + + if (0 != gni_resp->retcode) { + gni_resp->hostoctets = 0; + gni_resp->servoctets = 0; + } else { + gni_resp->hostoctets = strlen(host) + 1; + gni_resp->servoctets = strlen(service) + 1; + /* + * If this query succeeded only after retrying, DNS may have + * just become responsive. Ignore previously-scheduled + * retry sleeps once for each pending request, similar to + * the way scheduled_sleep() does when its worker_sleep() + * is interrupted. + */ + if (gni_req->retry > INITIAL_DNS_RETRY) { + time_now = time(NULL); + worker_ctx->ignore_scheduled_before = time_now; + TRACE(1, ("DNS success after retrying, ignoring sleeps scheduled before now (%s)\n", + humantime(time_now))); + } + } + octets = gni_resp->hostoctets + gni_resp->servoctets; + /* + * Our response consists of a header, followed by the host and + * service strings, each null-terminated. + */ + resp_octets = sizeof(*resp) + sizeof(*gni_resp) + octets; + + resp = erealloc(resp, resp_octets); + gni_resp = (void *)(resp + 1); + + gni_resp->octets = sizeof(*gni_resp) + octets; + + /* cp serves as our current pointer while serializing */ + cp = (void *)(gni_resp + 1); + + if (0 == gni_resp->retcode) { + memcpy(cp, host, gni_resp->hostoctets); + cp += gni_resp->hostoctets; + memcpy(cp, service, gni_resp->servoctets); + cp += gni_resp->servoctets; + } + + INSIST((size_t)(cp - (char *)resp) == resp_octets); + INSIST(resp_octets - sizeof(*resp) == gni_resp->octets); + + rc = queue_blocking_response(c, resp, resp_octets, req); + if (rc) + msyslog(LOG_ERR, "blocking_getnameinfo unable to queue response"); + return rc; +} + + +static void +getnameinfo_sometime_complete( + blocking_work_req rtype, + void * context, + size_t respsize, + void * resp + ) +{ + blocking_gni_req * gni_req; + blocking_gni_resp * gni_resp; + dnschild_ctx * child_ctx; + char * host; + char * service; + time_t time_now; + int again; + + gni_req = context; + gni_resp = resp; + + DEBUG_REQUIRE(BLOCKING_GETNAMEINFO == rtype); + DEBUG_REQUIRE(respsize == gni_resp->octets); + + child_ctx = dnschild_contexts[gni_req->dns_idx]; + + if (0 == gni_resp->retcode) { + /* + * If this query succeeded only after retrying, DNS may have + * just become responsive. + */ + if (gni_resp->retry > INITIAL_DNS_RETRY) { + time_now = time(NULL); + child_ctx->next_dns_timeslot = time_now; + TRACE(1, ("DNS success after retry, %u next_dns_timeslot reset (%s)\n", + gni_req->dns_idx, humantime(time_now))); + } + } else { + again = should_retry_dns(gni_resp->retcode, gni_resp->gni_errno); + /* + * exponential backoff of DNS retries to 64s + */ + if (gni_req->retry > 0) + manage_dns_retry_interval(&gni_req->scheduled, + &gni_req->earliest, &gni_req->retry, + &child_ctx->next_dns_timeslot, FALSE); + + if (gni_req->retry > 0 && again) { + if (!queue_blocking_request( + BLOCKING_GETNAMEINFO, + gni_req, + gni_req->octets, + &getnameinfo_sometime_complete, + gni_req)) + return; + + msyslog(LOG_ERR, "unable to retry reverse lookup of %s", stoa(&gni_req->socku)); + } + } + + if (!gni_resp->hostoctets) { + host = NULL; + service = NULL; + } else { + host = (char *)gni_resp + sizeof(*gni_resp); + service = (gni_resp->servoctets) + ? host + gni_resp->hostoctets + : NULL; + } + + (*gni_req->callback)(gni_resp->retcode, gni_resp->gni_errno, + &gni_req->socku, gni_req->flags, host, + service, gni_req->context); + + free(gni_req); + /* gni_resp is part of block freed by process_blocking_resp() */ +} + + +#ifdef TEST_BLOCKING_WORKER +void gni_test_callback(int rescode, int gni_errno, sockaddr_u *psau, int flags, const char *host, const char *service, void *context) +{ + if (!rescode) + TRACE(1, ("gni_test_callback got host '%s' serv '%s' for addr %s context %p\n", + host, service, stoa(psau), context)); + else + TRACE(1, ("gni_test_callback context %p rescode %d gni_errno %d flags 0x%x addr %s\n", + context, rescode, gni_errno, flags, stoa(psau))); +} +#endif /* TEST_BLOCKING_WORKER */ + + +#ifdef HAVE_RES_INIT +static void +reload_resolv_conf( + dnsworker_ctx * worker_ctx + ) +{ + time_t time_now; + + /* + * This is ad-hoc. Reload /etc/resolv.conf once per minute + * to pick up on changes from the DHCP client. [Bug 1226] + * When using threads for the workers, this needs to happen + * only once per minute process-wide. + */ + time_now = time(NULL); +# ifdef WORK_THREAD + worker_ctx->next_res_init = next_res_init; +# endif + if (worker_ctx->next_res_init <= time_now) { + if (worker_ctx->next_res_init != 0) + res_init(); + worker_ctx->next_res_init = time_now + 60; +# ifdef WORK_THREAD + next_res_init = worker_ctx->next_res_init; +# endif + } +} +#endif /* HAVE_RES_INIT */ + + +static u_int +reserve_dnschild_ctx(void) +{ + const size_t ps = sizeof(dnschild_contexts[0]); + const size_t cs = sizeof(*dnschild_contexts[0]); + u_int c; + u_int new_alloc; + size_t octets; + size_t new_octets; + + c = 0; + while (TRUE) { + for ( ; c < dnschild_contexts_alloc; c++) { + if (NULL == dnschild_contexts[c]) { + dnschild_contexts[c] = emalloc_zero(cs); + + return c; + } + } + new_alloc = dnschild_contexts_alloc + 20; + new_octets = new_alloc * ps; + octets = dnschild_contexts_alloc * ps; + dnschild_contexts = erealloc_zero(dnschild_contexts, + new_octets, octets); + dnschild_contexts_alloc = new_alloc; + } +} + + +static u_int +get_dnschild_ctx(void) +{ + static u_int shared_ctx = UINT_MAX; + + if (worker_per_query) + return reserve_dnschild_ctx(); + + if (UINT_MAX == shared_ctx) + shared_ctx = reserve_dnschild_ctx(); + + return shared_ctx; +} + + +static dnsworker_ctx * +get_worker_context( + blocking_child * c, + u_int idx + ) +{ + u_int min_new_alloc; + u_int new_alloc; + size_t octets; + size_t new_octets; + dnsworker_ctx * retv; + + worker_global_lock(TRUE); + + if (dnsworker_contexts_alloc <= idx) { + min_new_alloc = 1 + idx; + /* round new_alloc up to nearest multiple of 4 */ + new_alloc = (min_new_alloc + 4) & ~(4 - 1); + new_octets = new_alloc * sizeof(dnsworker_ctx*); + octets = dnsworker_contexts_alloc * sizeof(dnsworker_ctx*); + dnsworker_contexts = erealloc_zero(dnsworker_contexts, + new_octets, octets); + dnsworker_contexts_alloc = new_alloc; + retv = emalloc_zero(sizeof(dnsworker_ctx)); + dnsworker_contexts[idx] = retv; + } else if (NULL == (retv = dnsworker_contexts[idx])) { + retv = emalloc_zero(sizeof(dnsworker_ctx)); + dnsworker_contexts[idx] = retv; + } + + worker_global_lock(FALSE); + + ZERO(*retv); + retv->c = c; + return retv; +} + + +static void +scheduled_sleep( + time_t scheduled, + time_t earliest, + dnsworker_ctx * worker_ctx + ) +{ + time_t now; + + if (scheduled < worker_ctx->ignore_scheduled_before) { + TRACE(1, ("ignoring sleep until %s scheduled at %s (before %s)\n", + humantime(earliest), humantime(scheduled), + humantime(worker_ctx->ignore_scheduled_before))); + return; + } + + now = time(NULL); + + if (now < earliest) { + TRACE(1, ("sleep until %s scheduled at %s (>= %s)\n", + humantime(earliest), humantime(scheduled), + humantime(worker_ctx->ignore_scheduled_before))); + if (-1 == worker_sleep(worker_ctx->c, earliest - now)) { + /* our sleep was interrupted */ + now = time(NULL); + worker_ctx->ignore_scheduled_before = now; +#ifdef HAVE_RES_INIT + worker_ctx->next_res_init = now + 60; + next_res_init = worker_ctx->next_res_init; + res_init(); +#endif + TRACE(1, ("sleep interrupted by daemon, ignoring sleeps scheduled before now (%s)\n", + humantime(worker_ctx->ignore_scheduled_before))); + } + } +} + + +/* + * manage_dns_retry_interval is a helper used by + * getaddrinfo_sometime_complete and getnameinfo_sometime_complete + * to calculate the new retry interval and schedule the next query. + */ +static void +manage_dns_retry_interval( + time_t * pscheduled, + time_t * pwhen, + int * pretry, + time_t * pnext_timeslot, + int forever + ) +{ + time_t now; + time_t when; + int retry; + int retmax; + + now = time(NULL); + retry = *pretry; + when = max(now + retry, *pnext_timeslot); + *pnext_timeslot = when; + + /* this exponential backoff is slower than doubling up: The + * sequence goes 2-3-4-6-8-12-16-24-32... and the upper limit is + * 64 seconds for things that should not repeat forever, and + * 1024 when repeated forever. + */ + retmax = forever ? 1024 : 64; + retry <<= 1; + if (retry & (retry - 1)) + retry &= (retry - 1); + else + retry -= (retry >> 2); + retry = min(retmax, retry); + + *pscheduled = now; + *pwhen = when; + *pretry = retry; +} + +/* + * should_retry_dns is a helper used by getaddrinfo_sometime_complete + * and getnameinfo_sometime_complete which implements ntpd's DNS retry + * policy. + */ +static int +should_retry_dns( + int rescode, + int res_errno + ) +{ + static int eai_again_seen; + int again; +#if defined (EAI_SYSTEM) && defined(DEBUG) + char msg[256]; +#endif + + /* + * If the resolver failed, see if the failure is + * temporary. If so, return success. + */ + again = 0; + + switch (rescode) { + + case EAI_FAIL: + again = 1; + break; + + case EAI_AGAIN: + again = 1; + eai_again_seen = 1; /* [Bug 1178] */ + break; + + case EAI_NONAME: +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif + again = !eai_again_seen; /* [Bug 1178] */ + break; + +#ifdef EAI_SYSTEM + case EAI_SYSTEM: + /* + * EAI_SYSTEM means the real error is in errno. We should be more + * discriminating about which errno values require retrying, but + * this matches existing behavior. + */ + again = 1; +# ifdef DEBUG + errno_to_str(res_errno, msg, sizeof(msg)); + TRACE(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n", + res_errno, msg)); +# endif + break; +#endif + } + + TRACE(2, ("intres: resolver returned: %s (%d), %sretrying\n", + gai_strerror(rescode), rescode, again ? "" : "not ")); + + return again; +} + +#else /* !WORKER follows */ +int ntp_intres_nonempty_compilation_unit; +#endif diff --git a/contrib/ntp/libntp/ntp_libopts.c b/contrib/ntp/libntp/ntp_libopts.c new file mode 100644 index 000000000000..c504f8bf18cc --- /dev/null +++ b/contrib/ntp/libntp/ntp_libopts.c @@ -0,0 +1,58 @@ +/* + * ntp_libopts.c + * + * Common code interfacing with Autogen's libopts command-line option + * processing. + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stddef.h> +#include "ntp_libopts.h" +#include "ntp_stdlib.h" + +extern const char *Version; /* version.c for each program */ + + +/* + * ntpOptionProcess() was a clone of libopts' optionProcess which + * overrode the --version output, appending detail from version.c + * which was not available at Autogen time. This is now done via + * AutoOpts' version-proc = override in copyright.def, so this + * routine is a straightforward wrapper of optionProcess(). + */ +int +ntpOptionProcess( + tOptions * pOpts, + int argc, + char ** argv + ) +{ + return optionProcess(pOpts, argc, argv); +} + + +/* + * ntpOptionPrintVersion() replaces the stock optionPrintVersion() via + * version-proc = ntpOptionPrintVersion; in copyright.def. It differs + * from the stock function by displaying the complete version string, + * including compile time which was unknown when Autogen ran. + * + * Like optionPrintVersion() this function must exit(0) rather than + * return. + */ +void +ntpOptionPrintVersion( + tOptions * pOpts, + tOptDesc * pOD + ) +{ + UNUSED_ARG(pOpts); + UNUSED_ARG(pOD); + + printf("%s\n", Version); + fflush(stdout); + exit(EXIT_SUCCESS); +} diff --git a/contrib/ntp/libntp/ntp_lineedit.c b/contrib/ntp/libntp/ntp_lineedit.c new file mode 100644 index 000000000000..ebd456ac5df1 --- /dev/null +++ b/contrib/ntp/libntp/ntp_lineedit.c @@ -0,0 +1,246 @@ +/* + * ntp_lineedit.c - generic interface to various line editing libs + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#if defined(HAVE_READLINE_HISTORY) && \ + (!defined(HAVE_READLINE_HISTORY_H) || \ + !defined(HAVE_READLINE_READLINE_H)) +# undef HAVE_READLINE_HISTORY +#endif +#if defined(HAVE_READLINE_HISTORY) +# include <readline/readline.h> +# include <readline/history.h> +# define LE_READLINE +#elif defined(HAVE_HISTEDIT_H) +# include <histedit.h> +# define LE_EDITLINE +#else +# define LE_NONE +#endif + +#include "ntp.h" +#include "ntp_stdlib.h" +#include "ntp_lineedit.h" +#include "safecast.h" + +#define MAXEDITLINE 512 + +/* + * external references + */ + +extern char const * progname; + +/* + * globals, private prototypes + */ + +static int ntp_readline_initted; +static char * lineedit_prompt; + + +#ifdef LE_EDITLINE +# ifndef H_SETSIZE +# define H_SETSIZE H_EVENT +# endif +static EditLine * ntp_el; +static History * ntp_hist; +static HistEvent hev; + +char * ntp_prompt_callback(EditLine *); +#endif /* LE_EDITLINE */ + + +/* + * ntp_readline_init - setup, set or reset prompt string + */ +int +ntp_readline_init( + const char * prompt + ) +{ + int success; + + success = 1; + + if (prompt) { + if (lineedit_prompt) + free(lineedit_prompt); + lineedit_prompt = estrdup(prompt); + } + +#ifdef LE_EDITLINE + if (NULL == ntp_el) { + +# if 4 == EL_INIT_ARGS + ntp_el = el_init(progname, stdin, stdout, stderr); +# else + ntp_el = el_init(progname, stdin, stdout); +# endif + if (ntp_el) { + + el_set(ntp_el, EL_PROMPT, ntp_prompt_callback); + el_set(ntp_el, EL_EDITOR, "emacs"); + + ntp_hist = history_init(); + + if (NULL == ntp_hist) { + + mfprintf(stderr, "history_init(): %m\n"); + fflush(stderr); + + el_end(ntp_el); + ntp_el = NULL; + + success = 0; + + } else { + ZERO(hev); +#ifdef H_SETSIZE + history(ntp_hist, &hev, H_SETSIZE, 128); +#endif + el_set(ntp_el, EL_HIST, history, + ntp_hist); + /* use any .editrc */ + el_source(ntp_el, NULL); + } + } else + success = 0; + } +#endif /* LE_EDITLINE */ + + ntp_readline_initted = success; + + return success; +} + + +/* + * ntp_readline_uninit - release resources + */ +void +ntp_readline_uninit( + void + ) +{ +#ifdef LE_EDITLINE + if (ntp_el) { + el_end(ntp_el); + ntp_el = NULL; + + history_end(ntp_hist); + ntp_hist = NULL; + } +#endif /* LE_EDITLINE */ + + if (lineedit_prompt) { + free(lineedit_prompt); + lineedit_prompt = NULL; + } + + ntp_readline_initted = 0; +} + + +/* + * ntp_readline - read a line with the line editor available + * + * The string returned must be released with free() + */ + +char * +ntp_readline( + int * pcount + ) +{ + char * line; +#ifdef LE_NONE + char line_buf[MAXEDITLINE]; +#endif +#ifdef LE_EDITLINE + const char * cline; +#endif + + if (!ntp_readline_initted) + return NULL; + + *pcount = 0; + +#ifdef LE_READLINE + line = readline(lineedit_prompt ? lineedit_prompt : ""); + if (NULL != line) { + if (*line) { + add_history(line); + } + *pcount = strlen(line); + } +#endif /* LE_READLINE */ + +#ifdef LE_EDITLINE + cline = el_gets(ntp_el, pcount); + + if (NULL != cline) { + history(ntp_hist, &hev, H_ENTER, cline); + line = estrdup(cline); + } else if (*pcount == -1) { + line = NULL; + } else { + line = estrdup(""); + } +#endif /* LE_EDITLINE */ + +#ifdef LE_NONE + /* stone hammers */ + if (lineedit_prompt) { +# ifdef VMS + /* + * work around problem mixing + * stdout & stderr + */ + fputs("", stdout); +# endif /* VMS */ + + fputs(lineedit_prompt, stderr); + fflush(stderr); + } + + line = fgets(line_buf, sizeof(line_buf), stdin); + if (NULL != line && *line) { + *pcount = (int)strlen(line); /* cannot overflow here */ + line = estrdup(line); + } else + line = NULL; + +#endif /* LE_NONE */ + + + if (!line) /* EOF */ + fputs("\n", stderr); + + return line; +} + + +#ifdef LE_EDITLINE +/* + * ntp_prompt_callback - return prompt string to el_gets() + */ +char * +ntp_prompt_callback( + EditLine *el + ) +{ + UNUSED_ARG(el); + + return lineedit_prompt; +} +#endif /* LE_EDITLINE */ + diff --git a/contrib/ntp/libntp/ntp_random.c b/contrib/ntp/libntp/ntp_random.c new file mode 100644 index 000000000000..0ada44f256b0 --- /dev/null +++ b/contrib/ntp/libntp/ntp_random.c @@ -0,0 +1,499 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/stdlib/random.c,v 1.4.2.2 1999/09/05 11:16:45 peter Exp $ + * + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95"; +#endif /* LIBC_SCCS and not lint */ + +#include "config.h" +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdio.h> + +#include <l_stdlib.h> +#include <ntp_random.h> +#include <ntp_unixtime.h> + +/* + * random.c: + * + * An improved random number generation package. In addition to the standard + * rand()/srand() like interface, this package also has a special state info + * interface. The initstate() routine is called with a seed, an array of + * bytes, and a count of how many bytes are being passed in; this array is + * then initialized to contain information for random number generation with + * that much state information. Good sizes for the amount of state + * information are 32, 64, 128, and 256 bytes. The state can be switched by + * calling the setstate() routine with the same array as was initiallized + * with initstate(). By default, the package runs with 128 bytes of state + * information and generates far better random numbers than a linear + * congruential generator. If the amount of state information is less than + * 32 bytes, a simple linear congruential R.N.G. is used. + * + * Internally, the state information is treated as an array of longs; the + * zeroeth element of the array is the type of R.N.G. being used (small + * integer); the remainder of the array is the state information for the + * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of + * state information, which will allow a degree seven polynomial. (Note: + * the zeroeth word of state information also has some other information + * stored in it -- see setstate() for details). + * + * The random number generation technique is a linear feedback shift register + * approach, employing trinomials (since there are fewer terms to sum up that + * way). In this approach, the least significant bit of all the numbers in + * the state table will act as a linear feedback shift register, and will + * have period 2^deg - 1 (where deg is the degree of the polynomial being + * used, assuming that the polynomial is irreducible and primitive). The + * higher order bits will have longer periods, since their values are also + * influenced by pseudo-random carries out of the lower bits. The total + * period of the generator is approximately deg*(2**deg - 1); thus doubling + * the amount of state information has a vast influence on the period of the + * generator. Note: the deg*(2**deg - 1) is an approximation only good for + * large deg, when the period of the shift register is the dominant factor. + * With deg equal to seven, the period is actually much longer than the + * 7*(2**7 - 1) predicted by this formula. + * + * Modified 28 December 1994 by Jacob S. Rosenberg. + * The following changes have been made: + * All references to the type u_int have been changed to unsigned long. + * All references to type int have been changed to type long. Other + * cleanups have been made as well. A warning for both initstate and + * setstate has been inserted to the effect that on Sparc platforms + * the 'arg_state' variable must be forced to begin on word boundaries. + * This can be easily done by casting a long integer array to char *. + * The overall logic has been left STRICTLY alone. This software was + * tested on both a VAX and Sun SpacsStation with exactly the same + * results. The new version and the original give IDENTICAL results. + * The new version is somewhat faster than the original. As the + * documentation says: "By default, the package runs with 128 bytes of + * state information and generates far better random numbers than a linear + * congruential generator. If the amount of state information is less than + * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of + * 128 bytes, this new version runs about 19 percent faster and for a 16 + * byte buffer it is about 5 percent faster. + */ + +/* + * For each of the currently supported random number generators, we have a + * break value on the amount of state information (you need at least this + * many bytes of state info to support this random number generator), a degree + * for the polynomial (actually a trinomial) that the R.N.G. is based on, and + * the separation between the two lower order coefficients of the trinomial. + */ +#define TYPE_0 0 /* linear congruential */ +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +#define TYPE_1 1 /* x**7 + x**3 + 1 */ +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +#define TYPE_2 2 /* x**15 + x + 1 */ +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +#define TYPE_3 3 /* x**31 + x**3 + 1 */ +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +#define TYPE_4 4 /* x**63 + x + 1 */ +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + +#define MAX_TYPES 5 /* max number of types above */ + +/* + * Initially, everything is set up as if from: + * + * initstate(1, randtbl, 128); + * + * Note that this initialization takes advantage of the fact that srandom() + * advances the front and rear pointers 10*rand_deg times, and hence the + * rear pointer which starts at 0 will also end up at zero; thus the zeroeth + * element of the state information, which contains info about the current + * position of the rear pointer is just + * + * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. + */ + +static unsigned long randtbl[DEG_3 + 1] = { + TYPE_3, +#ifdef USE_WEAK_SEEDING +/* Historic implementation compatibility */ +/* The random sequences do not vary much with the seed */ + 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, + 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, + 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, + 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, + 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, + 0x27fb47b9, +#else /* !USE_WEAK_SEEDING */ + 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05, + 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454, + 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471, + 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1, + 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41, + 0xf3bec5da +#endif /* !USE_WEAK_SEEDING */ +}; + +/* + * fptr and rptr are two pointers into the state info, a front and a rear + * pointer. These two pointers are always rand_sep places aparts, as they + * cycle cyclically through the state information. (Yes, this does mean we + * could get away with just one pointer, but the code for random() is more + * efficient this way). The pointers are left positioned as they would be + * from the call + * + * initstate(1, randtbl, 128); + * + * (The position of the rear pointer, rptr, is really 0 (as explained above + * in the initialization of randtbl) because the state table pointer is set + * to point to randtbl[1] (as explained below). + */ +static unsigned long *fptr = &randtbl[SEP_3 + 1]; +static unsigned long *rptr = &randtbl[1]; + +/* + * The following things are the pointer to the state information table, the + * type of the current generator, the degree of the current polynomial being + * used, and the separation between the two pointers. Note that for efficiency + * of random(), we remember the first location of the state information, not + * the zeroeth. Hence it is valid to access state[-1], which is used to + * store the type of the R.N.G. Also, we remember the last location, since + * this is more efficient than indexing every time to find the address of + * the last element to see if the front and rear pointers have wrapped. + */ +static unsigned long *state = &randtbl[1]; +static long rand_type = TYPE_3; +static long rand_deg = DEG_3; +static long rand_sep = SEP_3; +static unsigned long *end_ptr = &randtbl[DEG_3 + 1]; + +static inline long good_rand (long); + +static inline long +good_rand ( + register long x + ) +{ +#ifdef USE_WEAK_SEEDING +/* + * Historic implementation compatibility. + * The random sequences do not vary much with the seed, + * even with overflowing. + */ + return (1103515245 * x + 12345); +#else /* !USE_WEAK_SEEDING */ +/* + * Compute x = (7^5 * x) mod (2^31 - 1) + * wihout overflowing 31 bits: + * (2^31 - 1) = 127773 * (7^5) + 2836 + * From "Random number generators: good ones are hard to find", + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + register long hi, lo; + + hi = x / 127773; + lo = x % 127773; + x = 16807 * lo - 2836 * hi; + if (x <= 0) + x += 0x7fffffff; + return (x); +#endif /* !USE_WEAK_SEEDING */ +} + +/* + * srandom: + * + * Initialize the random number generator based on the given seed. If the + * type is the trivial no-state-information type, just remember the seed. + * Otherwise, initializes state[] based on the given "seed" via a linear + * congruential generator. Then, the pointers are set to known locations + * that are exactly rand_sep places apart. Lastly, it cycles the state + * information a given number of times to get rid of any initial dependencies + * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + * for default usage relies on values produced by this routine. + */ +void +ntp_srandom( + unsigned long x + ) +{ + long i; + + if (rand_type == TYPE_0) { + state[0] = x; + } else { + state[0] = x; + for (i = 1; i < rand_deg; i++) + state[i] = good_rand(state[i - 1]); + fptr = &state[rand_sep]; + rptr = &state[0]; + for (i = 0; i < 10 * rand_deg; i++) + x = ntp_random(); + } + + /* seed the likely faster (and poorer) rand() as well */ + srand((u_int)x); +} + +/* + * srandomdev: + * + * Many programs choose the seed value in a totally predictable manner. + * This often causes problems. We seed the generator using the much more + * secure urandom(4) interface. Note that this particular seeding + * procedure can generate states which are impossible to reproduce by + * calling srandom() with any value, since the succeeding terms in the + * state buffer are no longer derived from the LC algorithm applied to + * a fixed seed. + */ +#ifdef NEED_SRANDOMDEV +void +ntp_srandomdev( void ) +{ + struct timeval tv; + unsigned long junk; /* Purposely used uninitialized */ + + GETTIMEOFDAY(&tv, NULL); + ntp_srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk); + return; +} +#endif + + +/* + * ntp_initstate() and ntp_setstate() are unused in our codebase and + * trigger warnings due to casting to a more-strictly-aligned pointer + * on alignment-sensitive platforms. #ifdef them away to save noise, + * build time, and binary space, but retain the code in case we find a + * use. + */ +#ifdef COMPILE_UNUSED_FUNCTIONS +/* + * Array versions of the above information to make code run faster -- + * relies on fact that TYPE_i == i. + */ +#define MAX_TYPES 5 /* max number of types above */ + +static long degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; +static long seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; + +/* + * initstate: + * + * Initialize the state information in the given array of n bytes for future + * random number generation. Based on the number of bytes we are given, and + * the break values for the different R.N.G.'s, we choose the best (largest) + * one we can and set things up for it. srandom() is then called to + * initialize the state information. + * + * Note that on return from srandom(), we set state[-1] to be the type + * multiplexed with the current value of the rear pointer; this is so + * successive calls to initstate() won't lose this information and will be + * able to restart with setstate(). + * + * Note: the first thing we do is save the current state, if any, just like + * setstate() so that it doesn't matter when initstate is called. + * + * Returns a pointer to the old state. + * + * Note: The Sparc platform requires that arg_state begin on a long + * word boundary; otherwise a bus error will occur. Even so, lint will + * complain about mis-alignment, but you should disregard these messages. + */ +char * +ntp_initstate( + unsigned long seed, /* seed for R.N.G. */ + char *arg_state, /* pointer to state array */ + long n /* # bytes of state info */ + ) +{ + register char *ostate = (char *)(&state[-1]); + register long *long_arg_state = (long *) arg_state; + + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = MAX_TYPES * (rptr - state) + rand_type; + if (n < BREAK_0) { + (void)fprintf(stderr, + "random: not enough state (%ld bytes); ignored.\n", n); + return(0); + } + if (n < BREAK_1) { + rand_type = TYPE_0; + rand_deg = DEG_0; + rand_sep = SEP_0; + } else if (n < BREAK_2) { + rand_type = TYPE_1; + rand_deg = DEG_1; + rand_sep = SEP_1; + } else if (n < BREAK_3) { + rand_type = TYPE_2; + rand_deg = DEG_2; + rand_sep = SEP_2; + } else if (n < BREAK_4) { + rand_type = TYPE_3; + rand_deg = DEG_3; + rand_sep = SEP_3; + } else { + rand_type = TYPE_4; + rand_deg = DEG_4; + rand_sep = SEP_4; + } + state = (unsigned long *) (long_arg_state + 1); /* first location */ + end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ + ntp_srandom(seed); + if (rand_type == TYPE_0) + long_arg_state[0] = rand_type; + else + long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type; + return(ostate); +} + +/* + * setstate: + * + * Restore the state from the given state array. + * + * Note: it is important that we also remember the locations of the pointers + * in the current state information, and restore the locations of the pointers + * from the old state information. This is done by multiplexing the pointer + * location into the zeroeth word of the state information. + * + * Note that due to the order in which things are done, it is OK to call + * setstate() with the same state as the current state. + * + * Returns a pointer to the old state information. + * + * Note: The Sparc platform requires that arg_state begin on a long + * word boundary; otherwise a bus error will occur. Even so, lint will + * complain about mis-alignment, but you should disregard these messages. + */ +char * +ntp_setstate( + char *arg_state /* pointer to state array */ + ) +{ + register unsigned long *new_state = (unsigned long *) arg_state; + register long type = new_state[0] % MAX_TYPES; + register long rear = new_state[0] / MAX_TYPES; + char *ostate = (char *)(&state[-1]); + + if (rand_type == TYPE_0) + state[-1] = rand_type; + else + state[-1] = MAX_TYPES * (rptr - state) + rand_type; + switch(type) { + case TYPE_0: + case TYPE_1: + case TYPE_2: + case TYPE_3: + case TYPE_4: + rand_type = type; + rand_deg = degrees[type]; + rand_sep = seps[type]; + break; + default: + (void)fprintf(stderr, + "random: state info corrupted; not changed.\n"); + } + state = (new_state + 1); + if (rand_type != TYPE_0) { + rptr = &state[rear]; + fptr = &state[(rear + rand_sep) % rand_deg]; + } + end_ptr = &state[rand_deg]; /* set end_ptr too */ + return(ostate); +} +#endif /* COMPILE_UNUSED_FUNCTIONS */ + + +/* + * random: + * + * If we are using the trivial TYPE_0 R.N.G., just do the old linear + * congruential bit. Otherwise, we do our fancy trinomial stuff, which is + * the same in all the other cases due to all the global variables that have + * been set up. The basic operation is to add the number at the rear pointer + * into the one at the front pointer. Then both pointers are advanced to + * the next location cyclically in the table. The value returned is the sum + * generated, reduced to 31 bits by throwing away the "least random" low bit. + * + * Note: the code takes advantage of the fact that both the front and + * rear pointers can't wrap on the same call by not testing the rear + * pointer if the front one has wrapped. + * + * Returns a 31-bit random number. + */ +long +ntp_random( void ) +{ + register long i; + register unsigned long *f, *r; + + if (rand_type == TYPE_0) { + i = state[0]; + state[0] = i = (good_rand(i)) & 0x7fffffff; + } else { + /* + * Use local variables rather than static variables for speed. + */ + f = fptr; r = rptr; + *f += *r; + i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */ + if (++f >= end_ptr) { + f = state; + ++r; + } + else if (++r >= end_ptr) { + r = state; + } + + fptr = f; rptr = r; + } + return(i); +} diff --git a/contrib/ntp/libntp/ntp_rfc2553.c b/contrib/ntp/libntp/ntp_rfc2553.c new file mode 100644 index 000000000000..840962905f67 --- /dev/null +++ b/contrib/ntp/libntp/ntp_rfc2553.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Compatability shims with the rfc2553 API to simplify ntp. + */ + +#include <config.h> + +#include <sys/types.h> +#include <ctype.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#include <isc/net.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#include "ntp_rfc2553.h" + +#include "ntpd.h" +#include "ntp_malloc.h" +#include "ntp_string.h" +#include "ntp_debug.h" + + +/* + * copy_addrinfo() - copy a single addrinfo to malloc()'d block. + * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block. + * + * Copies an addrinfo list and its associated data to a contiguous block + * of storage from emalloc(). Callback routines invoked via + * getaddrinfo_sometime() have access to the resulting addrinfo list + * only until they return. This routine provides an easy way to make a + * persistent copy. Although the list provided to gai_sometime_callback + * routines is similarly contiguous, to keep this code usable in any + * context where we might want to duplicate an addrinfo list, it does + * not require the input list be contiguous. + * + * The returned list head pointer is passed to free() to release the + * entire list. + * + * In keeping with the rest of the NTP distribution, sockaddr_u is used + * in preference to struct sockaddr_storage, which is a member of the + * former union and so compatible. + * + * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6 + * not being defined, copy_addrinfo_*() are exceptions. + */ +struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int +#ifdef EREALLOC_CALLSITE + , + const char *, int +#endif + ); + + +struct addrinfo * +copy_addrinfo_impl( + const struct addrinfo * src +#ifdef EREALLOC_CALLSITE + , + const char * caller_file, + int caller_line +#endif + ) +{ + return copy_addrinfo_common(src, TRUE +#ifdef EREALLOC_CALLSITE + , + caller_file, caller_line +#endif + ); +} + + +struct addrinfo * +copy_addrinfo_list_impl( + const struct addrinfo * src +#ifdef EREALLOC_CALLSITE + , + const char * caller_file, + int caller_line +#endif + ) +{ + return copy_addrinfo_common(src, FALSE +#ifdef EREALLOC_CALLSITE + , + caller_file, caller_line +#endif + ); +} + + +struct addrinfo * +copy_addrinfo_common( + const struct addrinfo * src, + int just_one +#ifdef EREALLOC_CALLSITE + , + const char * caller_file, + int caller_line +#endif + ) +{ + const struct addrinfo * ai_src; + const struct addrinfo * ai_nxt; + struct addrinfo * ai_cpy; + struct addrinfo * dst; + sockaddr_u * psau; + char * pcanon; + u_int elements; + size_t octets; + size_t canons_octets; + size_t str_octets; + + elements = 0; + canons_octets = 0; + + for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) { + if (just_one) + ai_nxt = NULL; + else + ai_nxt = ai_src->ai_next; + ++elements; + if (NULL != ai_src->ai_canonname) + canons_octets += 1 + strlen(ai_src->ai_canonname); + } + + octets = elements * (sizeof(*ai_cpy) + sizeof(*psau)); + octets += canons_octets; + + dst = erealloczsite(NULL, octets, 0, TRUE, caller_file, + caller_line); + ai_cpy = dst; + psau = (void *)(ai_cpy + elements); + pcanon = (void *)(psau + elements); + + for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) { + if (just_one) + ai_nxt = NULL; + else + ai_nxt = ai_src->ai_next; + *ai_cpy = *ai_src; + DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname); + INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u)); + memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen); + ai_cpy->ai_addr = &psau->sa; + ++psau; + if (NULL != ai_src->ai_canonname) { + ai_cpy->ai_canonname = pcanon; + str_octets = 1 + strlen(ai_src->ai_canonname); + memcpy(pcanon, ai_src->ai_canonname, str_octets); + pcanon += str_octets; + } + if (NULL != ai_cpy->ai_next) { + if (just_one) + ai_cpy->ai_next = NULL; + else + ai_cpy->ai_next = ai_cpy + 1; + } + ++ai_cpy; + } + ENSURE(pcanon == ((char *)dst + octets)); + + return dst; +} + + +#ifndef ISC_PLATFORM_HAVEIPV6 + +static char *ai_errlist[] = { + "Success", + "Address family for hostname not supported", /* EAI_ADDRFAMILY */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* EAI_NODATA */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Unknown error", /* EAI_MAX */ +}; + +/* + * Local declaration + */ +int +DNSlookup_name( + const char *name, + int ai_family, + struct hostent **Addresses +); + +#ifndef SYS_WINNT +/* + * Encapsulate gethostbyname to control the error code + */ +int +DNSlookup_name( + const char *name, + int ai_family, + struct hostent **Addresses +) +{ + *Addresses = gethostbyname(name); + return (h_errno); +} +#endif + +static int do_nodename (const char *nodename, struct addrinfo *ai, + const struct addrinfo *hints); + +int +getaddrinfo (const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + int rval; + struct servent *sp; + struct addrinfo *ai = NULL; + int port; + const char *proto = NULL; + int family, socktype, flags, protocol; + + + /* + * If no name is provide just return an error + */ + if (nodename == NULL && servname == NULL) + return (EAI_NONAME); + + ai = calloc(sizeof(struct addrinfo), 1); + if (ai == NULL) + return (EAI_MEMORY); + + /* + * Copy default values from hints, if available + */ + if (hints != NULL) { + ai->ai_flags = hints->ai_flags; + ai->ai_family = hints->ai_family; + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + + switch (family) { + case AF_UNSPEC: + switch (hints->ai_socktype) { + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + } + break; + case AF_INET: + case AF_INET6: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_RAW: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#ifdef AF_LOCAL + case AF_LOCAL: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + break; + case SOCK_DGRAM: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#endif + default: + return (EAI_FAMILY); + } + } else { + protocol = 0; + family = 0; + socktype = 0; + flags = 0; + } + + rval = do_nodename(nodename, ai, hints); + if (rval != 0) { + freeaddrinfo(ai); + return (rval); + } + + /* + * First, look up the service name (port) if it was + * requested. If the socket type wasn't specified, then + * try and figure it out. + */ + if (servname != NULL) { + char *e; + + port = strtol(servname, &e, 10); + if (*e == '\0') { + if (socktype == 0) + return (EAI_SOCKTYPE); + if (port < 0 || port > 65535) + return (EAI_SERVICE); + port = htons((unsigned short) port); + } else { + sp = getservbyname(servname, proto); + if (sp == NULL) + return (EAI_SERVICE); + port = sp->s_port; + if (socktype == 0) { + if (strcmp(sp->s_proto, "tcp") == 0) + socktype = SOCK_STREAM; + else if (strcmp(sp->s_proto, "udp") == 0) + socktype = SOCK_DGRAM; + } + } + } else + port = 0; + + /* + * + * Set up the port number + */ + if (ai->ai_family == AF_INET) + ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port; + else if (ai->ai_family == AF_INET6) + ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port; + *res = ai; + return (0); +} + +void +freeaddrinfo(struct addrinfo *ai) +{ + if (ai->ai_canonname != NULL) + { + free(ai->ai_canonname); + ai->ai_canonname = NULL; + } + if (ai->ai_addr != NULL) + { + free(ai->ai_addr); + ai->ai_addr = NULL; + } + free(ai); + ai = NULL; +} + +int +getnameinfo (const struct sockaddr *sa, u_int salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct hostent *hp; + + if (sa->sa_family != AF_INET) + return (EAI_FAMILY); + hp = gethostbyaddr( + (const char *)&((const struct sockaddr_in *)sa)->sin_addr, + 4, AF_INET); + if (hp == NULL) { + if (h_errno == TRY_AGAIN) + return (EAI_AGAIN); + else + return (EAI_FAIL); + } + if (host != NULL && hostlen > 0) + strlcpy(host, hp->h_name, hostlen); + return (0); +} + +char * +gai_strerror(int ecode) +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} + +static int +do_nodename( + const char *nodename, + struct addrinfo *ai, + const struct addrinfo *hints) +{ + struct hostent *hp = NULL; + struct sockaddr_in *sockin; + struct sockaddr_in6 *sockin6; + int errval; + + ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1); + if (ai->ai_addr == NULL) + return (EAI_MEMORY); + + /* + * For an empty node name just use the wildcard. + * NOTE: We need to assume that the address family is + * set elsewhere so that we can set the appropriate wildcard + */ + if (nodename == NULL) { + if (ai->ai_family == AF_INET) + { + ai->ai_addrlen = sizeof(struct sockaddr_in); + sockin = (struct sockaddr_in *)ai->ai_addr; + sockin->sin_family = (short) ai->ai_family; + sockin->sin_addr.s_addr = htonl(INADDR_ANY); + } + else + { + ai->ai_addrlen = sizeof(struct sockaddr_in6); + sockin6 = (struct sockaddr_in6 *)ai->ai_addr; + sockin6->sin6_family = (short) ai->ai_family; + /* + * we have already zeroed out the address + * so we don't actually need to do this + * This assignment is causing problems so + * we don't do what this would do. + sockin6->sin6_addr = in6addr_any; + */ + } +#ifdef ISC_PLATFORM_HAVESALEN + ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr); +#endif + + return (0); + } + + /* + * See if we have an IPv6 address + */ + if(strchr(nodename, ':') != NULL) { + if (inet_pton(AF_INET6, nodename, + &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) { + ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6; + ai->ai_family = AF_INET6; + ai->ai_addrlen = sizeof(struct sockaddr_in6); + return (0); + } + } + + /* + * See if we have an IPv4 address + */ + if (inet_pton(AF_INET, nodename, + &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) { + ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET; + ai->ai_family = AF_INET; + ai->ai_addrlen = sizeof(struct sockaddr_in); + return (0); + } + + /* + * If the numeric host flag is set, don't attempt resolution + */ + if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST)) + return (EAI_NONAME); + + /* + * Look for a name + */ + + errval = DNSlookup_name(nodename, AF_INET, &hp); + + if (hp == NULL) { + if (errval == TRY_AGAIN || errval == EAI_AGAIN) + return (EAI_AGAIN); + else if (errval == EAI_NONAME) { + if (inet_pton(AF_INET, nodename, + &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) { + ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET; + ai->ai_family = AF_INET; + ai->ai_addrlen = sizeof(struct sockaddr_in); + return (0); + } + return (errval); + } + else + { + return (errval); + } + } + ai->ai_family = hp->h_addrtype; + ai->ai_addrlen = sizeof(struct sockaddr); + sockin = (struct sockaddr_in *)ai->ai_addr; + memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length); + ai->ai_addr->sa_family = hp->h_addrtype; +#ifdef ISC_PLATFORM_HAVESALEN + ai->ai_addr->sa_len = sizeof(struct sockaddr); +#endif + if (hints != NULL && (hints->ai_flags & AI_CANONNAME)) + ai->ai_canonname = estrdup(hp->h_name); + return (0); +} + +#endif /* !ISC_PLATFORM_HAVEIPV6 */ diff --git a/contrib/ntp/libntp/ntp_worker.c b/contrib/ntp/libntp/ntp_worker.c new file mode 100644 index 000000000000..d1d09c0ee849 --- /dev/null +++ b/contrib/ntp/libntp/ntp_worker.c @@ -0,0 +1,368 @@ +/* + * ntp_worker.c + */ +#include <config.h> +#include "ntp_workimpl.h" + +#ifdef WORKER + +#include <stdio.h> +#include <ctype.h> +#include <signal.h> + +#include "iosignal.h" +#include "ntp_stdlib.h" +#include "ntp_malloc.h" +#include "ntp_syslog.h" +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_assert.h" +#include "ntp_unixtime.h" +#include "intreswork.h" + + +#define CHILD_MAX_IDLE (3 * 60) /* seconds, idle worker limit */ + +blocking_child ** blocking_children; +size_t blocking_children_alloc; +int worker_per_query; /* boolean */ +int intres_req_pending; +volatile u_int blocking_child_ready_seen; +volatile u_int blocking_child_ready_done; + + +#ifndef HAVE_IO_COMPLETION_PORT +/* + * pipe_socketpair() + * + * Provides an AF_UNIX socketpair on systems which have them, otherwise + * pair of unidirectional pipes. + */ +int +pipe_socketpair( + int caller_fds[2], + int * is_pipe + ) +{ + int rc; + int fds[2]; + int called_pipe; + +#ifdef HAVE_SOCKETPAIR + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, &fds[0]); +#else + rc = -1; +#endif + + if (-1 == rc) { + rc = pipe(&fds[0]); + called_pipe = TRUE; + } else { + called_pipe = FALSE; + } + + if (-1 == rc) + return rc; + + caller_fds[0] = fds[0]; + caller_fds[1] = fds[1]; + if (is_pipe != NULL) + *is_pipe = called_pipe; + + return 0; +} + + +/* + * close_all_except() + * + * Close all file descriptors except the given keep_fd. + */ +void +close_all_except( + int keep_fd + ) +{ + int fd; + + for (fd = 0; fd < keep_fd; fd++) + close(fd); + + close_all_beyond(keep_fd); +} + + +/* + * close_all_beyond() + * + * Close all file descriptors after the given keep_fd, which is the + * highest fd to keep open. + */ +void +close_all_beyond( + int keep_fd + ) +{ +# ifdef HAVE_CLOSEFROM + closefrom(keep_fd + 1); +# elif defined(F_CLOSEM) + /* + * From 'Writing Reliable AIX Daemons,' SG24-4946-00, + * by Eric Agar (saves us from doing 32767 system + * calls) + */ + if (fcntl(keep_fd + 1, F_CLOSEM, 0) == -1) + msyslog(LOG_ERR, "F_CLOSEM(%d): %m", keep_fd + 1); +# else /* !HAVE_CLOSEFROM && !F_CLOSEM follows */ + int fd; + int max_fd; + + max_fd = GETDTABLESIZE(); + for (fd = keep_fd + 1; fd < max_fd; fd++) + close(fd); +# endif /* !HAVE_CLOSEFROM && !F_CLOSEM */ +} +#endif /* HAVE_IO_COMPLETION_PORT */ + + +u_int +available_blocking_child_slot(void) +{ + const size_t each = sizeof(blocking_children[0]); + u_int slot; + size_t prev_alloc; + size_t new_alloc; + size_t prev_octets; + size_t octets; + + for (slot = 0; slot < blocking_children_alloc; slot++) { + if (NULL == blocking_children[slot]) + return slot; + if (blocking_children[slot]->reusable) { + blocking_children[slot]->reusable = FALSE; + return slot; + } + } + + prev_alloc = blocking_children_alloc; + prev_octets = prev_alloc * each; + new_alloc = blocking_children_alloc + 4; + octets = new_alloc * each; + blocking_children = erealloc_zero(blocking_children, octets, + prev_octets); + blocking_children_alloc = new_alloc; + + /* assume we'll never have enough workers to overflow u_int */ + return (u_int)prev_alloc; +} + + +int +queue_blocking_request( + blocking_work_req rtype, + void * req, + size_t reqsize, + blocking_work_callback done_func, + void * context + ) +{ + static u_int intres_slot = UINT_MAX; + u_int child_slot; + blocking_child * c; + blocking_pipe_header req_hdr; + + req_hdr.octets = sizeof(req_hdr) + reqsize; + req_hdr.magic_sig = BLOCKING_REQ_MAGIC; + req_hdr.rtype = rtype; + req_hdr.done_func = done_func; + req_hdr.context = context; + + child_slot = UINT_MAX; + if (worker_per_query || UINT_MAX == intres_slot || + blocking_children[intres_slot]->reusable) + child_slot = available_blocking_child_slot(); + if (!worker_per_query) { + if (UINT_MAX == intres_slot) + intres_slot = child_slot; + else + child_slot = intres_slot; + if (0 == intres_req_pending) + intres_timeout_req(0); + } + intres_req_pending++; + INSIST(UINT_MAX != child_slot); + c = blocking_children[child_slot]; + if (NULL == c) { + c = emalloc_zero(sizeof(*c)); +#ifdef WORK_FORK + c->req_read_pipe = -1; + c->req_write_pipe = -1; +#endif +#ifdef WORK_PIPE + c->resp_read_pipe = -1; + c->resp_write_pipe = -1; +#endif + blocking_children[child_slot] = c; + } + req_hdr.child_idx = child_slot; + + return send_blocking_req_internal(c, &req_hdr, req); +} + + +int queue_blocking_response( + blocking_child * c, + blocking_pipe_header * resp, + size_t respsize, + const blocking_pipe_header * req + ) +{ + resp->octets = respsize; + resp->magic_sig = BLOCKING_RESP_MAGIC; + resp->rtype = req->rtype; + resp->context = req->context; + resp->done_func = req->done_func; + + return send_blocking_resp_internal(c, resp); +} + + +void +process_blocking_resp( + blocking_child * c + ) +{ + blocking_pipe_header * resp; + void * data; + + /* + * On Windows send_blocking_resp_internal() may signal the + * blocking_response_ready event multiple times while we're + * processing a response, so always consume all available + * responses before returning to test the event again. + */ +#ifdef WORK_THREAD + do { +#endif + resp = receive_blocking_resp_internal(c); + if (NULL != resp) { + DEBUG_REQUIRE(BLOCKING_RESP_MAGIC == + resp->magic_sig); + data = (char *)resp + sizeof(*resp); + intres_req_pending--; + (*resp->done_func)(resp->rtype, resp->context, + resp->octets - sizeof(*resp), + data); + free(resp); + } +#ifdef WORK_THREAD + } while (NULL != resp); +#endif + if (!worker_per_query && 0 == intres_req_pending) + intres_timeout_req(CHILD_MAX_IDLE); + else if (worker_per_query) + req_child_exit(c); +} + +void +harvest_blocking_responses(void) +{ + size_t idx; + blocking_child* cp; + u_int scseen, scdone; + + scseen = blocking_child_ready_seen; + scdone = blocking_child_ready_done; + if (scdone != scseen) { + blocking_child_ready_done = scseen; + for (idx = 0; idx < blocking_children_alloc; idx++) { + cp = blocking_children[idx]; + if (NULL == cp) + continue; + scseen = cp->resp_ready_seen; + scdone = cp->resp_ready_done; + if (scdone != scseen) { + cp->resp_ready_done = scseen; + process_blocking_resp(cp); + } + } + } +} + + +/* + * blocking_child_common runs as a forked child or a thread + */ +int +blocking_child_common( + blocking_child *c + ) +{ + int say_bye; + blocking_pipe_header *req; + + say_bye = FALSE; + while (!say_bye) { + req = receive_blocking_req_internal(c); + if (NULL == req) { + say_bye = TRUE; + continue; + } + + DEBUG_REQUIRE(BLOCKING_REQ_MAGIC == req->magic_sig); + + switch (req->rtype) { + case BLOCKING_GETADDRINFO: + if (blocking_getaddrinfo(c, req)) + say_bye = TRUE; + break; + + case BLOCKING_GETNAMEINFO: + if (blocking_getnameinfo(c, req)) + say_bye = TRUE; + break; + + default: + msyslog(LOG_ERR, "unknown req %d to blocking worker", req->rtype); + say_bye = TRUE; + } + + free(req); + } + + return 0; +} + + +/* + * worker_idle_timer_fired() + * + * The parent starts this timer when the last pending response has been + * received from the child, making it idle, and clears the timer when a + * request is dispatched to the child. Once the timer expires, the + * child is sent packing. + * + * This is called when worker_idle_timer is nonzero and less than or + * equal to current_time. + */ +void +worker_idle_timer_fired(void) +{ + u_int idx; + blocking_child * c; + + DEBUG_REQUIRE(0 == intres_req_pending); + + intres_timeout_req(0); + for (idx = 0; idx < blocking_children_alloc; idx++) { + c = blocking_children[idx]; + if (NULL == c) + continue; + req_child_exit(c); + } +} + + +#else /* !WORKER follows */ +int ntp_worker_nonempty_compilation_unit; +#endif diff --git a/contrib/ntp/libntp/numtoa.c b/contrib/ntp/libntp/numtoa.c new file mode 100644 index 000000000000..5efbe942e3b4 --- /dev/null +++ b/contrib/ntp/libntp/numtoa.c @@ -0,0 +1,59 @@ +/* + * numtoa - return asciized network numbers store in local array space + */ +#include <config.h> + +#include <sys/types.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> /* ntohl */ +#endif + +#include <stdio.h> + +#include "ntp_fp.h" +#include "lib_strbuf.h" +#include "ntp_stdlib.h" + +char * +numtoa( + u_int32 num + ) +{ + register u_int32 netnum; + register char *buf; + + netnum = ntohl(num); + LIB_GETBUF(buf); + snprintf(buf, LIB_BUFLENGTH, "%lu.%lu.%lu.%lu", + ((u_long)netnum >> 24) & 0xff, + ((u_long)netnum >> 16) & 0xff, + ((u_long)netnum >> 8) & 0xff, + (u_long)netnum & 0xff); + return buf; +} + + +/* Convert a refid & stratum to a string */ +const char * +refid_str( + u_int32 refid, + int stratum + ) +{ + char * text; + size_t tlen; + + if (stratum > 1) + return numtoa(refid); + + LIB_GETBUF(text); + text[0] = '.'; + memcpy(&text[1], &refid, sizeof(refid)); + text[1 + sizeof(refid)] = '\0'; + tlen = strlen(text); + text[tlen] = '.'; + text[tlen + 1] = '\0'; + + return text; +} + diff --git a/contrib/ntp/libntp/numtohost.c b/contrib/ntp/libntp/numtohost.c new file mode 100644 index 000000000000..6b250d602de0 --- /dev/null +++ b/contrib/ntp/libntp/numtohost.c @@ -0,0 +1,43 @@ +/* + * numtohost - convert network number to host name. + */ +#include <config.h> + +#include <sys/types.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> /* ntohl */ +#endif + +#include "ntp_fp.h" +#include "ntp_stdlib.h" +#include "lib_strbuf.h" + +#define LOOPBACKNET 0x7f000000 +#define LOOPBACKHOST 0x7f000001 +#define LOOPBACKNETMASK 0xff000000 + +char * +numtohost( + u_int32 netnum + ) +{ + char *bp; + struct hostent *hp; + + /* + * This is really gross, but saves lots of hanging looking for + * hostnames for the radio clocks. Don't bother looking up + * addresses on the loopback network except for the loopback + * host itself. + */ + if ((((ntohl(netnum) & LOOPBACKNETMASK) == LOOPBACKNET) + && (ntohl(netnum) != LOOPBACKHOST)) + || ((hp = gethostbyaddr((char *)&netnum, sizeof netnum, AF_INET)) + == 0)) + return numtoa(netnum); + + LIB_GETBUF(bp); + strlcpy(bp, hp->h_name, LIB_BUFLENGTH); + + return bp; +} diff --git a/contrib/ntp/libntp/octtoint.c b/contrib/ntp/libntp/octtoint.c new file mode 100644 index 000000000000..e519601d067e --- /dev/null +++ b/contrib/ntp/libntp/octtoint.c @@ -0,0 +1,36 @@ +/* + * octtoint - convert an ascii string in octal to an unsigned + * long, with error checking + */ +#include <config.h> +#include <stdio.h> +#include <ctype.h> + +#include "ntp_stdlib.h" + +int +octtoint( + const char *str, + u_long *ival + ) +{ + register u_long u; + register const char *cp; + + cp = str; + + if (*cp == '\0') + return 0; + + u = 0; + while (*cp != '\0') { + if (!isdigit((unsigned char)*cp) || *cp == '8' || *cp == '9') + return 0; + if (u >= 0x20000000) + return 0; /* overflow */ + u <<= 3; + u += *cp++ - '0'; /* ascii dependent */ + } + *ival = u; + return 1; +} diff --git a/contrib/ntp/libntp/prettydate.c b/contrib/ntp/libntp/prettydate.c new file mode 100644 index 000000000000..25b085ef28fb --- /dev/null +++ b/contrib/ntp/libntp/prettydate.c @@ -0,0 +1,231 @@ +/* + * prettydate - convert a time stamp to something readable + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" /* includes <sys/time.h> */ +#include "lib_strbuf.h" +#include "ntp_stdlib.h" +#include "ntp_assert.h" +#include "ntp_calendar.h" + +#if SIZEOF_TIME_T < 4 +# error sizeof(time_t) < 4 -- this will not work! +#endif + +static char *common_prettydate(l_fp *, int); + +const char * const months[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +const char * const daynames[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +/* Helper function to handle possible wraparound of the ntp epoch. + * + * Works by periodic extension of the ntp time stamp in the UN*X epoch. + * If the 'time_t' is 32 bit, use solar cycle warping to get the value + * in a suitable range. Also uses solar cycle warping to work around + * really buggy implementations of 'gmtime()' / 'localtime()' that + * cannot work with a negative time value, that is, times before + * 1970-01-01. (MSVCRT...) + * + * Apart from that we're assuming that the localtime/gmtime library + * functions have been updated so that they work... + * + * An explanation: The julian calendar repeats ever 28 years, because + * it's the LCM of 7 and 1461, the week and leap year cycles. This is + * called a 'solar cycle'. The gregorian calendar does the same as + * long as no centennial year (divisible by 100, but not 400) goes in + * the way. So between 1901 and 2099 (inclusive) we can warp time + * stamps by 28 years to make them suitable for localtime() and + * gmtime() if we have trouble. Of course this will play hubbubb with + * the DST zone switches, so we should do it only if necessary; but as + * we NEED a proper conversion to dates via gmtime() we should try to + * cope with as many idiosyncrasies as possible. + * + */ + +/* + * solar cycle in unsigned secs and years, and the cycle limits. + */ +#define SOLAR_CYCLE_SECS 0x34AADC80UL /* 7*1461*86400*/ +#define SOLAR_CYCLE_YEARS 28 +#define MINFOLD -3 +#define MAXFOLD 3 + +static struct tm * +get_struct_tm( + const vint64 *stamp, + int local) +{ + struct tm *tm = NULL; + int32 folds = 0; + time_t ts; + +#ifdef HAVE_INT64 + + int64 tl; + ts = tl = stamp->q_s; + + /* + * If there is chance of truncation, try to fix it. Let the + * compiler find out if this can happen at all. + */ + while (ts != tl) { /* truncation? */ + if (tl < 0) { + if (--folds < MINFOLD) + return NULL; + tl += SOLAR_CYCLE_SECS; + } else { + if (++folds > MAXFOLD) + return NULL; + tl -= SOLAR_CYCLE_SECS; + } + ts = tl; /* next try... */ + } +#else + + /* + * since we do not have 64-bit scalars, it's not likely we have + * 64-bit time_t. Assume 32 bits and properly reduce the value. + */ + u_int32 hi, lo; + + hi = stamp->D_s.hi; + lo = stamp->D_s.lo; + + while ((hi && ~hi) || ((hi ^ lo) & 0x80000000u)) { + if (M_ISNEG(hi, lo)) { + if (--folds < MINFOLD) + return NULL; + M_ADD(hi, lo, 0, SOLAR_CYCLE_SECS); + } else { + if (++folds > MAXFOLD) + return NULL; + M_SUB(hi, lo, 0, SOLAR_CYCLE_SECS); + } + } + ts = (int32)lo; + +#endif + + /* + * 'ts' should be a suitable value by now. Just go ahead, but + * with care: + * + * There are some pathological implementations of 'gmtime()' + * and 'localtime()' out there. No matter if we have 32-bit or + * 64-bit 'time_t', try to fix this by solar cycle warping + * again... + * + * At least the MSDN says that the (Microsoft) Windoze + * versions of 'gmtime()' and 'localtime()' will bark on time + * stamps < 0. + */ + while ((tm = (*(local ? localtime : gmtime))(&ts)) == NULL) + if (ts < 0) { + if (--folds < MINFOLD) + return NULL; + ts += SOLAR_CYCLE_SECS; + } else if (ts >= (time_t)SOLAR_CYCLE_SECS) { + if (++folds > MAXFOLD) + return NULL; + ts -= SOLAR_CYCLE_SECS; + } else + return NULL; /* That's truly pathological! */ + + /* 'tm' surely not NULL here! */ + INSIST(tm != NULL); + if (folds != 0) { + tm->tm_year += folds * SOLAR_CYCLE_YEARS; + if (tm->tm_year <= 0 || tm->tm_year >= 200) + return NULL; /* left warp range... can't help here! */ + } + + return tm; +} + +static char * +common_prettydate( + l_fp *ts, + int local + ) +{ + static const char pfmt0[] = + "%08lx.%08lx %s, %s %2d %4d %2d:%02d:%02d.%03u"; + static const char pfmt1[] = + "%08lx.%08lx [%s, %s %2d %4d %2d:%02d:%02d.%03u UTC]"; + + char *bp; + struct tm *tm; + u_int msec; + u_int32 ntps; + vint64 sec; + + LIB_GETBUF(bp); + + /* get & fix milliseconds */ + ntps = ts->l_ui; + msec = ts->l_uf / 4294967; /* fract / (2 ** 32 / 1000) */ + if (msec >= 1000u) { + msec -= 1000u; + ntps++; + } + sec = ntpcal_ntp_to_time(ntps, NULL); + tm = get_struct_tm(&sec, local); + if (!tm) { + /* + * get a replacement, but always in UTC, using + * ntpcal_time_to_date() + */ + struct calendar jd; + ntpcal_time_to_date(&jd, &sec); + snprintf(bp, LIB_BUFLENGTH, local ? pfmt1 : pfmt0, + (u_long)ts->l_ui, (u_long)ts->l_uf, + daynames[jd.weekday], months[jd.month-1], + jd.monthday, jd.year, jd.hour, + jd.minute, jd.second, msec); + } else + snprintf(bp, LIB_BUFLENGTH, pfmt0, + (u_long)ts->l_ui, (u_long)ts->l_uf, + daynames[tm->tm_wday], months[tm->tm_mon], + tm->tm_mday, 1900 + tm->tm_year, tm->tm_hour, + tm->tm_min, tm->tm_sec, msec); + return bp; +} + + +char * +prettydate( + l_fp *ts + ) +{ + return common_prettydate(ts, 1); +} + + +char * +gmprettydate( + l_fp *ts + ) +{ + return common_prettydate(ts, 0); +} + + +struct tm * +ntp2unix_tm( + u_int32 ntp, int local + ) +{ + vint64 vl; + vl = ntpcal_ntp_to_time(ntp, NULL); + return get_struct_tm(&vl, local); +} + diff --git a/contrib/ntp/libntp/recvbuff.c b/contrib/ntp/libntp/recvbuff.c new file mode 100644 index 000000000000..f8889503c071 --- /dev/null +++ b/contrib/ntp/libntp/recvbuff.c @@ -0,0 +1,328 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#include "ntp_assert.h" +#include "ntp_syslog.h" +#include "ntp_stdlib.h" +#include "ntp_lists.h" +#include "recvbuff.h" +#include "iosignal.h" + + +/* + * Memory allocation + */ +static u_long volatile full_recvbufs; /* recvbufs on full_recv_fifo */ +static u_long volatile free_recvbufs; /* recvbufs on free_recv_list */ +static u_long volatile total_recvbufs; /* total recvbufs currently in use */ +static u_long volatile lowater_adds; /* number of times we have added memory */ +static u_long volatile buffer_shortfall;/* number of missed free receive buffers + between replenishments */ + +static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo; +static recvbuf_t * free_recv_list; + +#if defined(SYS_WINNT) + +/* + * For Windows we need to set up a lock to manipulate the + * recv buffers to prevent corruption. We keep it lock for as + * short a time as possible + */ +static CRITICAL_SECTION RecvLock; +# define LOCK() EnterCriticalSection(&RecvLock) +# define UNLOCK() LeaveCriticalSection(&RecvLock) +#else +# define LOCK() do {} while (FALSE) +# define UNLOCK() do {} while (FALSE) +#endif + +#ifdef DEBUG +static void uninit_recvbuff(void); +#endif + + +u_long +free_recvbuffs (void) +{ + return free_recvbufs; +} + +u_long +full_recvbuffs (void) +{ + return full_recvbufs; +} + +u_long +total_recvbuffs (void) +{ + return total_recvbufs; +} + +u_long +lowater_additions(void) +{ + return lowater_adds; +} + +static inline void +initialise_buffer(recvbuf_t *buff) +{ + ZERO(*buff); +} + +static void +create_buffers(int nbufs) +{ + register recvbuf_t *bufp; + int i, abuf; + + abuf = nbufs + buffer_shortfall; + buffer_shortfall = 0; + +#ifndef DEBUG + bufp = emalloc_zero(abuf * sizeof(*bufp)); +#endif + + for (i = 0; i < abuf; i++) { +#ifdef DEBUG + /* + * Allocate each buffer individually so they can be + * free()d during ntpd shutdown on DEBUG builds to + * keep them out of heap leak reports. + */ + bufp = emalloc_zero(sizeof(*bufp)); +#endif + LINK_SLIST(free_recv_list, bufp, link); + bufp++; + free_recvbufs++; + total_recvbufs++; + } + lowater_adds++; +} + +void +init_recvbuff(int nbufs) +{ + + /* + * Init buffer free list and stat counters + */ + free_recvbufs = total_recvbufs = 0; + full_recvbufs = lowater_adds = 0; + + create_buffers(nbufs); + +#if defined(SYS_WINNT) + InitializeCriticalSection(&RecvLock); +#endif + +#ifdef DEBUG + atexit(&uninit_recvbuff); +#endif +} + + +#ifdef DEBUG +static void +uninit_recvbuff(void) +{ + recvbuf_t *rbunlinked; + + for (;;) { + UNLINK_FIFO(rbunlinked, full_recv_fifo, link); + if (rbunlinked == NULL) + break; + free(rbunlinked); + } + + for (;;) { + UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link); + if (rbunlinked == NULL) + break; + free(rbunlinked); + } +} +#endif /* DEBUG */ + + +/* + * freerecvbuf - make a single recvbuf available for reuse + */ +void +freerecvbuf(recvbuf_t *rb) +{ + if (rb) { + LOCK(); + rb->used--; + if (rb->used != 0) + msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used); + LINK_SLIST(free_recv_list, rb, link); + free_recvbufs++; + UNLOCK(); + } +} + + +void +add_full_recv_buffer(recvbuf_t *rb) +{ + if (rb == NULL) { + msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer"); + return; + } + LOCK(); + LINK_FIFO(full_recv_fifo, rb, link); + full_recvbufs++; + UNLOCK(); +} + + +recvbuf_t * +get_free_recv_buffer(void) +{ + recvbuf_t *buffer; + + LOCK(); + UNLINK_HEAD_SLIST(buffer, free_recv_list, link); + if (buffer != NULL) { + free_recvbufs--; + initialise_buffer(buffer); + buffer->used++; + } else { + buffer_shortfall++; + } + UNLOCK(); + + return buffer; +} + + +#ifdef HAVE_IO_COMPLETION_PORT +recvbuf_t * +get_free_recv_buffer_alloc(void) +{ + recvbuf_t *buffer; + + buffer = get_free_recv_buffer(); + if (NULL == buffer) { + create_buffers(RECV_INC); + buffer = get_free_recv_buffer(); + } + ENSURE(buffer != NULL); + return (buffer); +} +#endif + + +recvbuf_t * +get_full_recv_buffer(void) +{ + recvbuf_t * rbuf; + + LOCK(); + +#ifdef HAVE_SIGNALED_IO + /* + * make sure there are free buffers when we + * wander off to do lengthy packet processing with + * any buffer we grab from the full list. + * + * fixes malloc() interrupted by SIGIO risk + * (Bug 889) + */ + if (NULL == free_recv_list || buffer_shortfall > 0) { + /* + * try to get us some more buffers + */ + create_buffers(RECV_INC); + } +#endif + + /* + * try to grab a full buffer + */ + UNLINK_FIFO(rbuf, full_recv_fifo, link); + if (rbuf != NULL) + full_recvbufs--; + UNLOCK(); + + return rbuf; +} + + +/* + * purge_recv_buffers_for_fd() - purges any previously-received input + * from a given file descriptor. + */ +void +purge_recv_buffers_for_fd( + int fd + ) +{ + recvbuf_t *rbufp; + recvbuf_t *next; + recvbuf_t *punlinked; + + LOCK(); + + for (rbufp = HEAD_FIFO(full_recv_fifo); + rbufp != NULL; + rbufp = next) { + next = rbufp->link; +# ifdef HAVE_IO_COMPLETION_PORT + if (rbufp->dstadr == NULL && rbufp->fd == fd) +# else + if (rbufp->fd == fd) +# endif + { + UNLINK_MID_FIFO(punlinked, full_recv_fifo, + rbufp, link, recvbuf_t); + INSIST(punlinked == rbufp); + full_recvbufs--; + freerecvbuf(rbufp); + } + } + + UNLOCK(); +} + + +/* + * Checks to see if there are buffers to process + */ +isc_boolean_t has_full_recv_buffer(void) +{ + if (HEAD_FIFO(full_recv_fifo) != NULL) + return (ISC_TRUE); + else + return (ISC_FALSE); +} + + +#ifdef NTP_DEBUG_LISTS_H +void +check_gen_fifo_consistency(void *fifo) +{ + gen_fifo *pf; + gen_node *pthis; + gen_node **pptail; + + pf = fifo; + REQUIRE((NULL == pf->phead && NULL == pf->pptail) || + (NULL != pf->phead && NULL != pf->pptail)); + + pptail = &pf->phead; + for (pthis = pf->phead; + pthis != NULL; + pthis = pthis->link) + if (NULL != pthis->link) + pptail = &pthis->link; + + REQUIRE(NULL == pf->pptail || pptail == pf->pptail); +} +#endif /* NTP_DEBUG_LISTS_H */ diff --git a/contrib/ntp/libntp/refidsmear.c b/contrib/ntp/libntp/refidsmear.c new file mode 100644 index 000000000000..fef428e8a226 --- /dev/null +++ b/contrib/ntp/libntp/refidsmear.c @@ -0,0 +1,58 @@ +#include <config.h> + +#include <ntp.h> +#include <ntp_fp.h> +#include <refidsmear.h> + +/* + * we want to test a refid format of: + * 254.x.y.x + * + * where x.y.z are 24 bits containing 2 (signed) integer bits + * and 22 fractional bits. + * + */ + + +l_fp +convertRefIDToLFP(uint32_t r) +{ + l_fp temp; + + r = ntohl(r); + + // printf("%03d %08x: ", (r >> 24) & 0xFF, (r & 0x00FFFFFF) ); + + temp.l_uf = (r << 10); /* 22 fractional bits */ + + temp.l_ui = (r >> 22) & 0x3; + temp.l_ui |= ~(temp.l_ui & 2) + 1; + + return temp; +} + + +uint32_t +convertLFPToRefID(l_fp num) +{ + uint32_t temp; + + /* round the input with the highest bit to shift out from the + * fraction, then keep just two bits from the integral part. + * + * TODO: check for overflows; should we clamp/saturate or just + * complain? + */ + L_ADDUF(&num, 0x200); + num.l_ui &= 3; + + /* combine integral and fractional part to 24 bits */ + temp = (num.l_ui << 22) | (num.l_uf >> 10); + + /* put in the leading 254.0.0.0 */ + temp |= UINT32_C(0xFE000000); + + // printf("%03d %08x: ", (temp >> 24) & 0xFF, (temp & 0x00FFFFFF) ); + + return htonl(temp); +} diff --git a/contrib/ntp/libntp/refnumtoa.c b/contrib/ntp/libntp/refnumtoa.c new file mode 100644 index 000000000000..e6ca55aef868 --- /dev/null +++ b/contrib/ntp/libntp/refnumtoa.c @@ -0,0 +1,36 @@ +/* + * refnumtoa - return asciized refclock addresses stored in local array space + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_net.h" +#include "lib_strbuf.h" +#include "ntp_stdlib.h" + +const char * +refnumtoa( + sockaddr_u *num + ) +{ + u_int32 netnum; + char *buf; + const char *rclock; + + if (!ISREFCLOCKADR(num)) + return socktoa(num); + + LIB_GETBUF(buf); + netnum = SRCADR(num); + rclock = clockname((int)((u_long)netnum >> 8) & 0xff); + + if (rclock != NULL) + snprintf(buf, LIB_BUFLENGTH, "%s(%lu)", + rclock, (u_long)netnum & 0xff); + else + snprintf(buf, LIB_BUFLENGTH, "REFCLK(%lu,%lu)", + ((u_long)netnum >> 8) & 0xff, + (u_long)netnum & 0xff); + + return buf; +} diff --git a/contrib/ntp/libntp/snprintf.c b/contrib/ntp/libntp/snprintf.c new file mode 100644 index 000000000000..f4685e1ad4b6 --- /dev/null +++ b/contrib/ntp/libntp/snprintf.c @@ -0,0 +1,2132 @@ +/* + * Modified by Dave Hart for integration into NTP 4.2.7 <hart@ntp.org> + * + * Changed in a backwards-incompatible way to separate HAVE_SNPRINTF + * from HW_WANT_RPL_SNPRINTF, etc. for each of the four replaced + * functions. + * + * Changed to honor hw_force_rpl_snprintf=yes, etc. This is used by NTP + * to test rpl_snprintf() and rpl_vsnprintf() on platforms which provide + * C99-compliant implementations. + */ + +/* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */ + +/* + * Copyright (c) 1995 Patrick Powell. + * + * This code is based on code written by Patrick Powell <papowell@astart.com>. + * It may be used for any purpose as long as this notice remains intact on all + * source code distributions. + */ + +/* + * Copyright (c) 2008 Holger Weiss. + * + * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>. + * My changes to the code may freely be used, modified and/or redistributed for + * any purpose. It would be nice if additions and fixes to this file (including + * trivial code cleanups) would be sent back in order to let me include them in + * the version available at <http://www.jhweiss.de/software/snprintf.html>. + * However, this is not a requirement for using or redistributing (possibly + * modified) versions of this file, nor is leaving this notice intact mandatory. + */ + +/* + * History + * + * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1: + * + * Fixed the detection of infinite floating point values on IRIX (and + * possibly other systems) and applied another few minor cleanups. + * + * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0: + * + * Added a lot of new features, fixed many bugs, and incorporated various + * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery + * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller + * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH + * projects. The additions include: support the "e", "E", "g", "G", and + * "F" conversion specifiers (and use conversion style "f" or "F" for the + * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", + * "t", and "z" length modifiers; support the "#" flag and the (non-C99) + * "'" flag; use localeconv(3) (if available) to get both the current + * locale's decimal point character and the separator between groups of + * digits; fix the handling of various corner cases of field width and + * precision specifications; fix various floating point conversion bugs; + * handle infinite and NaN floating point values; don't attempt to write to + * the output buffer (which may be NULL) if a size of zero was specified; + * check for integer overflow of the field width, precision, and return + * values and during the floating point conversion; use the OUTCHAR() macro + * instead of a function for better performance; provide asprintf(3) and + * vasprintf(3) functions; add new test cases. The replacement functions + * have been renamed to use an "rpl_" prefix, the function calls in the + * main project (and in this file) must be redefined accordingly for each + * replacement function which is needed (by using Autoconf or other means). + * Various other minor improvements have been applied and the coding style + * was cleaned up for consistency. + * + * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13: + * + * C99 compliant snprintf(3) and vsnprintf(3) functions return the number + * of characters that would have been written to a sufficiently sized + * buffer (excluding the '\0'). The original code simply returned the + * length of the resulting output string, so that's been fixed. + * + * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8: + * + * The original code assumed that both snprintf(3) and vsnprintf(3) were + * missing. Some systems only have snprintf(3) but not vsnprintf(3), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i: + * + * The PGP code was using unsigned hexadecimal formats. Unfortunately, + * unsigned formats simply didn't work. + * + * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1: + * + * Ok, added some minimal floating point support, which means this probably + * requires libm on most operating systems. Don't yet support the exponent + * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just + * wasn't being exercised in ways which showed it, so that's been fixed. + * Also, formatted the code to Mutt conventions, and removed dead code left + * over from the original. Also, there is now a builtin-test, run with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf + * + * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43: + * + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything from the + * normal C string format, at least as far as I can tell from the Solaris + * 2.5 printf(3S) man page. + */ + +/* + * ToDo + * + * - Add wide character support. + * - Add support for "%a" and "%A" conversions. + * - Create test routines which predefine the expected results. Our test cases + * usually expose bugs in system implementations rather than in ours :-) + */ + +/* + * Usage + * + * 1) The following preprocessor macros should be defined to 1 if the feature or + * file in question is available on the target system (by using Autoconf or + * other means), though basic functionality should be available as long as + * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: + * + * HW_WANT_RPL_VSNPRINTF + * HW_WANT_RPL_SNPRINTF + * HW_WANT_RPL_VASPRINTF + * HW_WANT_RPL_ASPRINTF + * HAVE_VSNPRINTF // define to 1 #if HW_WANT_RPL_VSNPRINTF + * HAVE_SNPRINTF // define to 1 #if HW_WANT_RPL_SNPRINTF + * HAVE_VASPRINTF // define to 1 #if HW_WANT_RPL_VASPRINTF + * HAVE_ASPRINTF // define to 1 #if HW_WANT_RPL_ASPRINTF + * HAVE_STDARG_H + * HAVE_STDDEF_H + * HAVE_STDINT_H + * HAVE_STDLIB_H + * HAVE_INTTYPES_H + * HAVE_LOCALE_H + * HAVE_LOCALECONV + * HAVE_LCONV_DECIMAL_POINT + * HAVE_LCONV_THOUSANDS_SEP + * HAVE_LONG_DOUBLE + * HAVE_LONG_LONG_INT + * HAVE_UNSIGNED_LONG_LONG_INT + * HAVE_INTMAX_T + * HAVE_UINTMAX_T + * HAVE_UINTPTR_T + * HAVE_PTRDIFF_T + * HAVE_VA_COPY + * HAVE___VA_COPY + * + * 2) The calls to the functions which should be replaced must be redefined + * throughout the project files (by using Autoconf or other means): + * + * #if HW_WANT_RPL_VSNPRINTF + * #define vsnprintf rpl_vsnprintf + * #endif + * #if HW_WANT_RPL_SNPRINTF + * #define snprintf rpl_snprintf + * #endif + * #if HW_WANT_RPL_VASPRINTF + * #define vasprintf rpl_vasprintf + * #endif + * #if HW_WANT_RPL_ASPRINTF + * #define asprintf rpl_asprintf + * #endif + * + * 3) The required replacement functions should be declared in some header file + * included throughout the project files: + * + * #if HAVE_CONFIG_H + * #include <config.h> + * #endif + * #if HAVE_STDARG_H + * #include <stdarg.h> + * #if HW_WANT_RPL_VSNPRINTF + * int rpl_vsnprintf(char *, size_t, const char *, va_list); + * #endif + * #if HW_WANT_RPL_SNPRINTF + * int rpl_snprintf(char *, size_t, const char *, ...); + * #endif + * #if HW_WANT_RPL_VASPRINTF + * int rpl_vasprintf(char **, const char *, va_list); + * #endif + * #if HW_WANT_RPL_ASPRINTF + * int rpl_asprintf(char **, const char *, ...); + * #endif + * #endif + * + * Autoconf macros for handling step 1 and step 2 are available at + * <http://www.jhweiss.de/software/snprintf.html>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#if TEST_SNPRINTF +#include <math.h> /* For pow(3), NAN, and INFINITY. */ +#include <string.h> /* For strcmp(3). */ +#if defined(__NetBSD__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NeXT__) || \ + defined(__bsd__) +#define OS_BSD 1 +#elif defined(sgi) || defined(__sgi) +#ifndef __c99 +#define __c99 /* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */ +#endif /* !defined(__c99) */ +#define OS_IRIX 1 +#define OS_SYSV 1 +#elif defined(__svr4__) +#define OS_SYSV 1 +#elif defined(__linux__) +#define OS_LINUX 1 +#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */ +#if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */ +#ifdef HAVE_SNPRINTF +#undef HAVE_SNPRINTF +#endif /* defined(HAVE_SNPRINTF) */ +#ifdef HAVE_VSNPRINTF +#undef HAVE_VSNPRINTF +#endif /* defined(HAVE_VSNPRINTF) */ +#ifdef HAVE_ASPRINTF +#undef HAVE_ASPRINTF +#endif /* defined(HAVE_ASPRINTF) */ +#ifdef HAVE_VASPRINTF +#undef HAVE_VASPRINTF +#endif /* defined(HAVE_VASPRINTF) */ +#ifdef snprintf +#undef snprintf +#endif /* defined(snprintf) */ +#ifdef vsnprintf +#undef vsnprintf +#endif /* defined(vsnprintf) */ +#ifdef asprintf +#undef asprintf +#endif /* defined(asprintf) */ +#ifdef vasprintf +#undef vasprintf +#endif /* defined(vasprintf) */ +#else /* By default, we assume a modern system for testing. */ +#ifndef HAVE_STDARG_H +#define HAVE_STDARG_H 1 +#endif /* HAVE_STDARG_H */ +#ifndef HAVE_STDDEF_H +#define HAVE_STDDEF_H 1 +#endif /* HAVE_STDDEF_H */ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 1 +#endif /* HAVE_STDINT_H */ +#ifndef HAVE_STDLIB_H +#define HAVE_STDLIB_H 1 +#endif /* HAVE_STDLIB_H */ +#ifndef HAVE_INTTYPES_H +#define HAVE_INTTYPES_H 1 +#endif /* HAVE_INTTYPES_H */ +#ifndef HAVE_LOCALE_H +#define HAVE_LOCALE_H 1 +#endif /* HAVE_LOCALE_H */ +#ifndef HAVE_LOCALECONV +#define HAVE_LOCALECONV 1 +#endif /* !defined(HAVE_LOCALECONV) */ +#ifndef HAVE_LCONV_DECIMAL_POINT +#define HAVE_LCONV_DECIMAL_POINT 1 +#endif /* HAVE_LCONV_DECIMAL_POINT */ +#ifndef HAVE_LCONV_THOUSANDS_SEP +#define HAVE_LCONV_THOUSANDS_SEP 1 +#endif /* HAVE_LCONV_THOUSANDS_SEP */ +#ifndef HAVE_LONG_DOUBLE +#define HAVE_LONG_DOUBLE 1 +#endif /* !defined(HAVE_LONG_DOUBLE) */ +#ifndef HAVE_LONG_LONG_INT +#define HAVE_LONG_LONG_INT 1 +#endif /* !defined(HAVE_LONG_LONG_INT) */ +#ifndef HAVE_UNSIGNED_LONG_LONG_INT +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */ +#ifndef HAVE_INTMAX_T +#define HAVE_INTMAX_T 1 +#endif /* !defined(HAVE_INTMAX_T) */ +#ifndef HAVE_UINTMAX_T +#define HAVE_UINTMAX_T 1 +#endif /* !defined(HAVE_UINTMAX_T) */ +#ifndef HAVE_UINTPTR_T +#define HAVE_UINTPTR_T 1 +#endif /* !defined(HAVE_UINTPTR_T) */ +#ifndef HAVE_PTRDIFF_T +#define HAVE_PTRDIFF_T 1 +#endif /* !defined(HAVE_PTRDIFF_T) */ +#ifndef HAVE_VA_COPY +#define HAVE_VA_COPY 1 +#endif /* !defined(HAVE_VA_COPY) */ +#ifndef HAVE___VA_COPY +#define HAVE___VA_COPY 1 +#endif /* !defined(HAVE___VA_COPY) */ +#endif /* HAVE_CONFIG_H */ +#define snprintf rpl_snprintf +#define vsnprintf rpl_vsnprintf +#define asprintf rpl_asprintf +#define vasprintf rpl_vasprintf +#endif /* TEST_SNPRINTF */ + +#if HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || HW_WANT_RPL_VASPRINTF +#include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ +#ifdef VA_START +#undef VA_START +#endif /* defined(VA_START) */ +#ifdef VA_SHIFT +#undef VA_SHIFT +#endif /* defined(VA_SHIFT) */ +#if HAVE_STDARG_H +#include <stdarg.h> +#define VA_START(ap, last) va_start(ap, last) +#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ +#else /* Assume <varargs.h> is available. */ +#include <varargs.h> +#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ +#define VA_SHIFT(ap, value, type) value = va_arg(ap, type) +#endif /* HAVE_STDARG_H */ + +#if HW_WANT_RPL_VASPRINTF +#if HAVE_STDLIB_H +#include <stdlib.h> /* For malloc(3). */ +#endif /* HAVE_STDLIB_H */ +#ifdef VA_COPY +#undef VA_COPY +#endif /* defined(VA_COPY) */ +#ifdef VA_END_COPY +#undef VA_END_COPY +#endif /* defined(VA_END_COPY) */ +#if HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#define VA_END_COPY(ap) va_end(ap) +#elif HAVE___VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#define VA_END_COPY(ap) va_end(ap) +#else +#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) +#define VA_END_COPY(ap) /* No-op. */ +#define NEED_MYMEMCPY 1 +static void *mymemcpy(void *, void *, size_t); +#endif /* HAVE_VA_COPY */ +#endif /* HW_WANT_RPL_VASPRINTF */ + +#if HW_WANT_RPL_VSNPRINTF +#include <errno.h> /* For ERANGE and errno. */ +#include <limits.h> /* For *_MAX. */ +#if HAVE_INTTYPES_H +#include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */ +#endif /* HAVE_INTTYPES_H */ +#if HAVE_LOCALE_H +#include <locale.h> /* For localeconv(3). */ +#endif /* HAVE_LOCALE_H */ +#if HAVE_STDDEF_H +#include <stddef.h> /* For ptrdiff_t. */ +#endif /* HAVE_STDDEF_H */ +#if HAVE_STDINT_H +#include <stdint.h> /* For intmax_t. */ +#endif /* HAVE_STDINT_H */ + +/* Support for unsigned long long int. We may also need ULLONG_MAX. */ +#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ +#ifdef UINT_MAX +#define ULONG_MAX UINT_MAX +#else +#define ULONG_MAX INT_MAX +#endif /* defined(UINT_MAX) */ +#endif /* !defined(ULONG_MAX) */ +#ifdef ULLONG +#undef ULLONG +#endif /* defined(ULLONG) */ +#if HAVE_UNSIGNED_LONG_LONG_INT +#define ULLONG unsigned long long int +#ifndef ULLONG_MAX +#define ULLONG_MAX ULONG_MAX +#endif /* !defined(ULLONG_MAX) */ +#else +#define ULLONG unsigned long int +#ifdef ULLONG_MAX +#undef ULLONG_MAX +#endif /* defined(ULLONG_MAX) */ +#define ULLONG_MAX ULONG_MAX +#endif /* HAVE_LONG_LONG_INT */ + +/* Support for uintmax_t. We also need UINTMAX_MAX. */ +#ifdef UINTMAX_T +#undef UINTMAX_T +#endif /* defined(UINTMAX_T) */ +#if HAVE_UINTMAX_T || defined(uintmax_t) +#define UINTMAX_T uintmax_t +#ifndef UINTMAX_MAX +#define UINTMAX_MAX ULLONG_MAX +#endif /* !defined(UINTMAX_MAX) */ +#else +#define UINTMAX_T ULLONG +#ifdef UINTMAX_MAX +#undef UINTMAX_MAX +#endif /* defined(UINTMAX_MAX) */ +#define UINTMAX_MAX ULLONG_MAX +#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ + +/* Support for long double. */ +#ifndef LDOUBLE +#if HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif /* HAVE_LONG_DOUBLE */ +#endif /* !defined(LDOUBLE) */ + +/* Support for long long int. */ +#ifndef LLONG +#if HAVE_LONG_LONG_INT +#define LLONG long long int +#else +#define LLONG long int +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !defined(LLONG) */ + +/* Support for intmax_t. */ +#ifndef INTMAX_T +#if HAVE_INTMAX_T || defined(intmax_t) +#define INTMAX_T intmax_t +#else +#define INTMAX_T LLONG +#endif /* HAVE_INTMAX_T || defined(intmax_t) */ +#endif /* !defined(INTMAX_T) */ + +/* Support for uintptr_t. */ +#ifndef UINTPTR_T +#if HAVE_UINTPTR_T || defined(uintptr_t) +#define UINTPTR_T uintptr_t +#else +#define UINTPTR_T unsigned long int +#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ +#endif /* !defined(UINTPTR_T) */ + +/* Support for ptrdiff_t. */ +#ifndef PTRDIFF_T +#if HAVE_PTRDIFF_T || defined(ptrdiff_t) +#define PTRDIFF_T ptrdiff_t +#else +#define PTRDIFF_T long int +#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ +#endif /* !defined(PTRDIFF_T) */ + +/* + * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: + * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an + * unsigned type if necessary. This should work just fine in practice. + */ +#ifndef UPTRDIFF_T +#define UPTRDIFF_T PTRDIFF_T +#endif /* !defined(UPTRDIFF_T) */ + +/* + * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). + * However, we'll simply use size_t and convert it to a signed type if + * necessary. This should work just fine in practice. + */ +#ifndef SSIZE_T +#define SSIZE_T size_t +#endif /* !defined(SSIZE_T) */ + +/* Either ERANGE or E2BIG should be available everywhere. */ +#ifndef ERANGE +#define ERANGE E2BIG +#endif /* !defined(ERANGE) */ +#ifndef EOVERFLOW +#define EOVERFLOW ERANGE +#endif /* !defined(EOVERFLOW) */ + +/* + * Buffer size to hold the octal string representation of UINT128_MAX without + * nul-termination ("3777777777777777777777777777777777777777777"). + */ +#ifdef MAX_CONVERT_LENGTH +#undef MAX_CONVERT_LENGTH +#endif /* defined(MAX_CONVERT_LENGTH) */ +#define MAX_CONVERT_LENGTH 43 + +/* Format read states. */ +#define PRINT_S_DEFAULT 0 +#define PRINT_S_FLAGS 1 +#define PRINT_S_WIDTH 2 +#define PRINT_S_DOT 3 +#define PRINT_S_PRECISION 4 +#define PRINT_S_MOD 5 +#define PRINT_S_CONV 6 + +/* Format flags. */ +#define PRINT_F_MINUS (1 << 0) +#define PRINT_F_PLUS (1 << 1) +#define PRINT_F_SPACE (1 << 2) +#define PRINT_F_NUM (1 << 3) +#define PRINT_F_ZERO (1 << 4) +#define PRINT_F_QUOTE (1 << 5) +#define PRINT_F_UP (1 << 6) +#define PRINT_F_UNSIGNED (1 << 7) +#define PRINT_F_TYPE_G (1 << 8) +#define PRINT_F_TYPE_E (1 << 9) + +/* Conversion flags. */ +#define PRINT_C_CHAR 1 +#define PRINT_C_SHORT 2 +#define PRINT_C_LONG 3 +#define PRINT_C_LLONG 4 +#define PRINT_C_LDOUBLE 5 +#define PRINT_C_SIZE 6 +#define PRINT_C_PTRDIFF 7 +#define PRINT_C_INTMAX 8 + +#ifndef MAX +#define MAX(x, y) ((x >= y) ? x : y) +#endif /* !defined(MAX) */ +#ifndef CHARTOINT +#define CHARTOINT(ch) (ch - '0') +#endif /* !defined(CHARTOINT) */ +#ifndef ISDIGIT +#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') +#endif /* !defined(ISDIGIT) */ +#ifndef ISNAN +#define ISNAN(x) (x != x) +#endif /* !defined(ISNAN) */ +#ifndef ISINF +#define ISINF(x) (x != 0.0 && x + x == x) +#endif /* !defined(ISINF) */ + +#ifdef OUTCHAR +#undef OUTCHAR +#endif /* defined(OUTCHAR) */ +#define OUTCHAR(str, len, size, ch) \ +do { \ + if (len + 1 < size) \ + str[len] = ch; \ + (len)++; \ +} while (/* CONSTCOND */ 0) + +static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); +static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); +static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); +static void printsep(char *, size_t *, size_t); +static int getnumsep(int); +static int getexponent(LDOUBLE); +static int convert(UINTMAX_T, char *, size_t, int, int); +static UINTMAX_T cast(LDOUBLE); +static UINTMAX_T myround(LDOUBLE); +static LDOUBLE mypow10(int); + +int +rpl_vsnprintf(char *str, size_t size, const char *format, va_list args); + +int +rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + LDOUBLE fvalue; + INTMAX_T value; + unsigned char cvalue; + const char *strvalue; + INTMAX_T *intmaxptr; + PTRDIFF_T *ptrdiffptr; + SSIZE_T *sizeptr; + LLONG *llongptr; + long int *longptr; + int *intptr; + short int *shortptr; + signed char *charptr; + size_t len = 0; + int overflow = 0; + int base = 0; + int cflags = 0; + int flags = 0; + int width = 0; + int precision = -1; + int state = PRINT_S_DEFAULT; + char ch = *format++; + + /* + * C99 says: "If `n' is zero, nothing is written, and `s' may be a null + * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer + * even if a size larger than zero was specified. At least NetBSD's + * snprintf(3) does the same, as well as other versions of this file. + * (Though some of these versions will write to a non-NULL buffer even + * if a size of zero was specified, which violates the standard.) + */ + if (str == NULL && size != 0) + size = 0; + + while (ch != '\0') + switch (state) { + case PRINT_S_DEFAULT: + if (ch == '%') + state = PRINT_S_FLAGS; + else + OUTCHAR(str, len, size, ch); + ch = *format++; + break; + case PRINT_S_FLAGS: + switch (ch) { + case '-': + flags |= PRINT_F_MINUS; + ch = *format++; + break; + case '+': + flags |= PRINT_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= PRINT_F_SPACE; + ch = *format++; + break; + case '#': + flags |= PRINT_F_NUM; + ch = *format++; + break; + case '0': + flags |= PRINT_F_ZERO; + ch = *format++; + break; + case '\'': /* SUSv2 flag (not in C99). */ + flags |= PRINT_F_QUOTE; + ch = *format++; + break; + default: + state = PRINT_S_WIDTH; + break; + } + break; + case PRINT_S_WIDTH: + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (width > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + width = 10 * width + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative field width argument is + * taken as a `-' flag followed by a positive + * field width." (7.19.6.1, 5) + */ + if ((width = va_arg(args, int)) < 0) { + flags |= PRINT_F_MINUS; + width = -width; + } + ch = *format++; + state = PRINT_S_DOT; + } else + state = PRINT_S_DOT; + break; + case PRINT_S_DOT: + if (ch == '.') { + state = PRINT_S_PRECISION; + ch = *format++; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_PRECISION: + if (precision == -1) + precision = 0; + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (precision > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + precision = 10 * precision + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative precision argument is + * taken as if the precision were omitted." + * (7.19.6.1, 5) + */ + if ((precision = va_arg(args, int)) < 0) + precision = -1; + ch = *format++; + state = PRINT_S_MOD; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_MOD: + switch (ch) { + case 'h': + ch = *format++; + if (ch == 'h') { /* It's a char. */ + ch = *format++; + cflags = PRINT_C_CHAR; + } else + cflags = PRINT_C_SHORT; + break; + case 'l': + ch = *format++; + if (ch == 'l') { /* It's a long long. */ + ch = *format++; + cflags = PRINT_C_LLONG; + } else + cflags = PRINT_C_LONG; + break; + case 'L': + cflags = PRINT_C_LDOUBLE; + ch = *format++; + break; + case 'j': + cflags = PRINT_C_INTMAX; + ch = *format++; + break; + case 't': + cflags = PRINT_C_PTRDIFF; + ch = *format++; + break; + case 'z': + cflags = PRINT_C_SIZE; + ch = *format++; + break; + } + state = PRINT_S_CONV; + break; + case PRINT_S_CONV: + switch (ch) { + case 'd': + /* FALLTHROUGH */ + case 'i': + switch (cflags) { + case PRINT_C_CHAR: + value = (signed char)va_arg(args, int); + break; + case PRINT_C_SHORT: + value = (short int)va_arg(args, int); + break; + case PRINT_C_LONG: + value = va_arg(args, long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, LLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, SSIZE_T); + break; + case PRINT_C_INTMAX: + value = va_arg(args, INTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, PTRDIFF_T); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(str, &len, size, value, 10, width, + precision, flags); + break; + case 'X': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'x': + base = 16; + /* FALLTHROUGH */ + case 'o': + if (base == 0) + base = 8; + /* FALLTHROUGH */ + case 'u': + if (base == 0) + base = 10; + flags |= PRINT_F_UNSIGNED; + switch (cflags) { + case PRINT_C_CHAR: + value = (unsigned char)va_arg(args, + unsigned int); + break; + case PRINT_C_SHORT: + value = (unsigned short int)va_arg(args, + unsigned int); + break; + case PRINT_C_LONG: + value = va_arg(args, unsigned long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, ULLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, size_t); + break; + case PRINT_C_INTMAX: + value = va_arg(args, UINTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, UPTRDIFF_T); + break; + default: + value = va_arg(args, unsigned int); + break; + } + fmtint(str, &len, size, value, base, width, + precision, flags); + break; + case 'A': + /* Not yet supported, we'll use "%F". */ + /* FALLTHROUGH */ + case 'F': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'a': + /* Not yet supported, we'll use "%f". */ + /* FALLTHROUGH */ + case 'f': + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'E': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'e': + flags |= PRINT_F_TYPE_E; + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'G': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'g': + flags |= PRINT_F_TYPE_G; + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + /* + * If the precision is zero, it is treated as + * one (cf. C99: 7.19.6.1, 8). + */ + if (precision == 0) + precision = 1; + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'c': + cvalue = va_arg(args, int); + OUTCHAR(str, len, size, cvalue); + break; + case 's': + strvalue = va_arg(args, char *); + fmtstr(str, &len, size, strvalue, width, + precision, flags); + break; + case 'p': + /* + * C99 says: "The value of the pointer is + * converted to a sequence of printing + * characters, in an implementation-defined + * manner." (C99: 7.19.6.1, 8) + */ + if ((strvalue = va_arg(args, void *)) == NULL) + /* + * We use the glibc format. BSD prints + * "0x0", SysV "0". + */ + fmtstr(str, &len, size, "(nil)", width, + -1, flags); + else { + /* + * We use the BSD/glibc format. SysV + * omits the "0x" prefix (which we emit + * using the PRINT_F_NUM flag). + */ + flags |= PRINT_F_NUM; + flags |= PRINT_F_UNSIGNED; + fmtint(str, &len, size, + (UINTPTR_T)strvalue, 16, width, + precision, flags); + } + break; + case 'n': + switch (cflags) { + case PRINT_C_CHAR: + charptr = va_arg(args, signed char *); + *charptr = (signed char)len; + break; + case PRINT_C_SHORT: + shortptr = va_arg(args, short int *); + *shortptr = (short int)len; + break; + case PRINT_C_LONG: + longptr = va_arg(args, long int *); + *longptr = (long int)len; + break; + case PRINT_C_LLONG: + llongptr = va_arg(args, LLONG *); + *llongptr = (LLONG)len; + break; + case PRINT_C_SIZE: + /* + * C99 says that with the "z" length + * modifier, "a following `n' conversion + * specifier applies to a pointer to a + * signed integer type corresponding to + * size_t argument." (7.19.6.1, 7) + */ + sizeptr = va_arg(args, SSIZE_T *); + *sizeptr = (SSIZE_T)len; + break; + case PRINT_C_INTMAX: + intmaxptr = va_arg(args, INTMAX_T *); + *intmaxptr = (INTMAX_T)len; + break; + case PRINT_C_PTRDIFF: + ptrdiffptr = va_arg(args, PTRDIFF_T *); + *ptrdiffptr = (PTRDIFF_T)len; + break; + default: + intptr = va_arg(args, int *); + *intptr = (int)len; + break; + } + break; + case '%': /* Print a "%" character verbatim. */ + OUTCHAR(str, len, size, ch); + break; + default: /* Skip other characters. */ + break; + } + ch = *format++; + state = PRINT_S_DEFAULT; + base = cflags = flags = width = 0; + precision = -1; + break; + } +out: + if (len < size) + str[len] = '\0'; + else if (size > 0) + str[size - 1] = '\0'; + + if (overflow || len >= INT_MAX) { + errno = overflow ? EOVERFLOW : ERANGE; + return -1; + } + return (int)len; +} + +static void +fmtstr(char *str, size_t *len, size_t size, const char *value, int width, + int precision, int flags) +{ + int padlen, strln; /* Amount to pad. */ + int noprecision = (precision == -1); + + if (value == NULL) /* We're forgiving. */ + value = "(null)"; + + /* If a precision was specified, don't read the string past it. */ + for (strln = 0; value[strln] != '\0' && + (noprecision || strln < precision); strln++) + continue; + + if ((padlen = width - strln) < 0) + padlen = 0; + if (flags & PRINT_F_MINUS) /* Left justify. */ + padlen = -padlen; + + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + while (*value != '\0' && (noprecision || precision-- > 0)) { + OUTCHAR(str, *len, size, *value); + value++; + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void +fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, + int precision, int flags) +{ + UINTMAX_T uvalue; + char iconvert[MAX_CONVERT_LENGTH]; + char sign = 0; + char hexprefix = 0; + int spadlen = 0; /* Amount to space pad. */ + int zpadlen = 0; /* Amount to zero pad. */ + int pos; + int separators = (flags & PRINT_F_QUOTE); + int noprecision = (precision == -1); + + if (flags & PRINT_F_UNSIGNED) + uvalue = value; + else { + uvalue = (value >= 0) ? value : -value; + if (value < 0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + } + + pos = convert(uvalue, iconvert, sizeof(iconvert), base, + flags & PRINT_F_UP); + + if (flags & PRINT_F_NUM && uvalue != 0) { + /* + * C99 says: "The result is converted to an `alternative form'. + * For `o' conversion, it increases the precision, if and only + * if necessary, to force the first digit of the result to be a + * zero (if the value and precision are both 0, a single 0 is + * printed). For `x' (or `X') conversion, a nonzero result has + * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) + */ + switch (base) { + case 8: + if (precision <= pos) + precision = pos + 1; + break; + case 16: + hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; + break; + } + } + + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(pos); + + zpadlen = precision - pos - separators; + spadlen = width /* Minimum field width. */ + - separators /* Number of separators. */ + - MAX(precision, pos) /* Number of integer digits. */ + - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ + - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ + + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a + * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justify. */ + spadlen = -spadlen; + else if (flags & PRINT_F_ZERO && noprecision) { + zpadlen += spadlen; + spadlen = 0; + } + while (spadlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ + OUTCHAR(str, *len, size, '0'); + OUTCHAR(str, *len, size, hexprefix); + } + while (zpadlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + zpadlen--; + } + while (pos > 0) { /* The actual digits. */ + pos--; + OUTCHAR(str, *len, size, iconvert[pos]); + if (separators > 0 && pos > 0 && pos % 3 == 0) + printsep(str, len, size); + } + while (spadlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen++; + } +} + +static void +fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, + int precision, int flags, int *overflow) +{ + LDOUBLE ufvalue; + UINTMAX_T intpart; + UINTMAX_T fracpart; + UINTMAX_T mask; + const char *infnan = NULL; + char iconvert[MAX_CONVERT_LENGTH]; + char fconvert[MAX_CONVERT_LENGTH]; + char econvert[4]; /* "e-12" (without nul-termination). */ + char esign = 0; + char sign = 0; + int leadfraczeros = 0; + int exponent = 0; + int emitpoint = 0; + int omitzeros = 0; + int omitcount = 0; + int padlen = 0; + int epos = 0; + int fpos = 0; + int ipos = 0; + int separators = (flags & PRINT_F_QUOTE); + int estyle = (flags & PRINT_F_TYPE_E); +#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT + struct lconv *lc = localeconv(); +#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ + + /* + * AIX' man page says the default is 0, but C99 and at least Solaris' + * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX + * defaults to 6. + */ + if (precision == -1) + precision = 6; + + if (fvalue < 0.0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + + if (ISNAN(fvalue)) + infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; + else if (ISINF(fvalue)) + infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; + + if (infnan != NULL) { + if (sign != 0) + iconvert[ipos++] = sign; + while (*infnan != '\0') + iconvert[ipos++] = *infnan++; + fmtstr(str, len, size, iconvert, width, ipos, flags); + return; + } + + /* "%e" (or "%E") or "%g" (or "%G") conversion. */ + if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { + if (flags & PRINT_F_TYPE_G) { + /* + * For "%g" (and "%G") conversions, the precision + * specifies the number of significant digits, which + * includes the digits in the integer part. The + * conversion will or will not be using "e-style" (like + * "%e" or "%E" conversions) depending on the precision + * and on the exponent. However, the exponent can be + * affected by rounding the converted value, so we'll + * leave this decision for later. Until then, we'll + * assume that we're going to do an "e-style" conversion + * (in order to get the exponent calculated). For + * "e-style", the precision must be decremented by one. + */ + precision--; + /* + * For "%g" (and "%G") conversions, trailing zeros are + * removed from the fractional portion of the result + * unless the "#" flag was specified. + */ + if (!(flags & PRINT_F_NUM)) + omitzeros = 1; + } + exponent = getexponent(fvalue); + estyle = 1; + } + +again: + /* + * Sorry, we only support 9, 19, or 38 digits (that is, the number of + * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value + * minus one) past the decimal point due to our conversion method. + */ + switch (sizeof(UINTMAX_T)) { + case 16: + if (precision > 38) + precision = 38; + break; + case 8: + if (precision > 19) + precision = 19; + break; + default: + if (precision > 9) + precision = 9; + break; + } + + ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; + if (estyle) /* We want exactly one integer digit. */ + ufvalue /= mypow10(exponent); + + if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { + *overflow = 1; + return; + } + + /* + * Factor of ten with the number of digits needed for the fractional + * part. For example, if the precision is 3, the mask will be 1000. + */ + mask = (UINTMAX_T)mypow10(precision); + /* + * We "cheat" by converting the fractional part to integer by + * multiplying by a factor of ten. + */ + if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { + /* + * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 + * (because precision = 3). Now, myround(1000 * 0.99962) will + * return 1000. So, the integer part must be incremented by one + * and the fractional part must be set to zero. + */ + intpart++; + fracpart = 0; + if (estyle && intpart == 10) { + /* + * The value was rounded up to ten, but we only want one + * integer digit if using "e-style". So, the integer + * part must be set to one and the exponent must be + * incremented by one. + */ + intpart = 1; + exponent++; + } + } + + /* + * Now that we know the real exponent, we can check whether or not to + * use "e-style" for "%g" (and "%G") conversions. If we don't need + * "e-style", the precision must be adjusted and the integer and + * fractional parts must be recalculated from the original value. + * + * C99 says: "Let P equal the precision if nonzero, 6 if the precision + * is omitted, or 1 if the precision is zero. Then, if a conversion + * with style `E' would have an exponent of X: + * + * - if P > X >= -4, the conversion is with style `f' (or `F') and + * precision P - (X + 1). + * + * - otherwise, the conversion is with style `e' (or `E') and precision + * P - 1." (7.19.6.1, 8) + * + * Note that we had decremented the precision by one. + */ + if (flags & PRINT_F_TYPE_G && estyle && + precision + 1 > exponent && exponent >= -4) { + precision -= exponent; + estyle = 0; + goto again; + } + + if (estyle) { + if (exponent < 0) { + exponent = -exponent; + esign = '-'; + } else + esign = '+'; + + /* + * Convert the exponent. The sizeof(econvert) is 4. So, the + * econvert buffer can hold e.g. "e+99" and "e-99". We don't + * support an exponent which contains more than two digits. + * Therefore, the following stores are safe. + */ + epos = convert(exponent, econvert, 2, 10, 0); + /* + * C99 says: "The exponent always contains at least two digits, + * and only as many more digits as necessary to represent the + * exponent." (7.19.6.1, 8) + */ + if (epos == 1) + econvert[epos++] = '0'; + econvert[epos++] = esign; + econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; + } + + /* Convert the integer part and the fractional part. */ + ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); + if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ + fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); + + leadfraczeros = precision - fpos; + + if (omitzeros) { + if (fpos > 0) /* Omit trailing fractional part zeros. */ + while (omitcount < fpos && fconvert[omitcount] == '0') + omitcount++; + else { /* The fractional part is zero, omit it completely. */ + omitcount = precision; + leadfraczeros = 0; + } + precision -= omitcount; + } + + /* + * Print a decimal point if either the fractional part is non-zero + * and/or the "#" flag was specified. + */ + if (precision > 0 || flags & PRINT_F_NUM) + emitpoint = 1; + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(ipos); + + padlen = width /* Minimum field width. */ + - ipos /* Number of integer digits. */ + - epos /* Number of exponent characters. */ + - precision /* Number of fractional digits. */ + - separators /* Number of group separators. */ + - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ + - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ + + if (padlen < 0) + padlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justifty. */ + padlen = -padlen; + else if (flags & PRINT_F_ZERO && padlen > 0) { + if (sign != 0) { /* Sign. */ + OUTCHAR(str, *len, size, sign); + sign = 0; + } + while (padlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + padlen--; + } + } + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + while (ipos > 0) { /* Integer part. */ + ipos--; + OUTCHAR(str, *len, size, iconvert[ipos]); + if (separators > 0 && ipos > 0 && ipos % 3 == 0) + printsep(str, len, size); + } + if (emitpoint) { /* Decimal point. */ +#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT + if (lc->decimal_point != NULL && *lc->decimal_point != '\0') + OUTCHAR(str, *len, size, *lc->decimal_point); + else /* We'll always print some decimal point character. */ +#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ + OUTCHAR(str, *len, size, '.'); + } + while (leadfraczeros > 0) { /* Leading fractional part zeros. */ + OUTCHAR(str, *len, size, '0'); + leadfraczeros--; + } + while (fpos > omitcount) { /* The remaining fractional part. */ + fpos--; + OUTCHAR(str, *len, size, fconvert[fpos]); + } + while (epos > 0) { /* Exponent. */ + epos--; + OUTCHAR(str, *len, size, econvert[epos]); + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void +printsep(char *str, size_t *len, size_t size) +{ +#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP + struct lconv *lc = localeconv(); + int i; + + if (lc->thousands_sep != NULL) + for (i = 0; lc->thousands_sep[i] != '\0'; i++) + OUTCHAR(str, *len, size, lc->thousands_sep[i]); + else +#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ + OUTCHAR(str, *len, size, ','); +} + +static int +getnumsep(int digits) +{ + int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; +#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP + int strln; + struct lconv *lc = localeconv(); + + /* We support an arbitrary separator length (including zero). */ + if (lc->thousands_sep != NULL) { + for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) + continue; + separators *= strln; + } +#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ + return separators; +} + +static int +getexponent(LDOUBLE value) +{ + LDOUBLE tmp = (value >= 0.0) ? value : -value; + int exponent = 0; + + /* + * We check for 99 > exponent > -99 in order to work around possible + * endless loops which could happen (at least) in the second loop (at + * least) if we're called with an infinite value. However, we checked + * for infinity before calling this function using our ISINF() macro, so + * this might be somewhat paranoid. + */ + while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) + tmp *= 10; + while (tmp >= 10.0 && ++exponent < 99) + tmp /= 10; + + return exponent; +} + +static int +convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) +{ + const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + size_t pos = 0; + + /* We return an unterminated buffer with the digits in reverse order. */ + do { + buf[pos++] = digits[value % base]; + value /= base; + } while (value != 0 && pos < size); + + return (int)pos; +} + +static UINTMAX_T +cast(LDOUBLE value) +{ + UINTMAX_T result; + + /* + * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be + * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), + * it may be increased to the nearest higher representable value for the + * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE + * value although converting the latter to UINTMAX_T would overflow. + */ + if (value >= UINTMAX_MAX) + return UINTMAX_MAX; + + result = (UINTMAX_T)value; + /* + * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to + * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates + * the standard). Sigh. + */ + return (result <= value) ? result : result - 1; +} + +static UINTMAX_T +myround(LDOUBLE value) +{ + UINTMAX_T intpart = cast(value); + + return ((value -= intpart) < 0.5) ? intpart : intpart + 1; +} + +static LDOUBLE +mypow10(int exponent) +{ + LDOUBLE result = 1; + + while (exponent > 0) { + result *= 10; + exponent--; + } + while (exponent < 0) { + result /= 10; + exponent++; + } + return result; +} +#endif /* HW_WANT_RPL_VSNPRINTF */ + +#if HW_WANT_RPL_VASPRINTF +#if NEED_MYMEMCPY +void * +mymemcpy(void *dst, void *src, size_t len) +{ + const char *from = src; + char *to = dst; + + /* No need for optimization, we use this only to replace va_copy(3). */ + while (len-- > 0) + *to++ = *from++; + return dst; +} +#endif /* NEED_MYMEMCPY */ + +int +rpl_vasprintf(char **ret, const char *format, va_list ap); + +int +rpl_vasprintf(char **ret, const char *format, va_list ap) +{ + size_t size; + int len; + va_list aq; + + VA_COPY(aq, ap); + len = vsnprintf(NULL, 0, format, aq); + VA_END_COPY(aq); + if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) + return -1; + return vsnprintf(*ret, size, format, ap); +} +#endif /* HW_WANT_RPL_VASPRINTF */ + +#if HW_WANT_RPL_SNPRINTF +#if HAVE_STDARG_H +int +rpl_snprintf(char *str, size_t size, const char *format, ...); + +int +rpl_snprintf(char *str, size_t size, const char *format, ...) +#else +int +rpl_snprintf(va_alist) va_dcl +#endif /* HAVE_STDARG_H */ +{ +#if !HAVE_STDARG_H + char *str; + size_t size; + char *format; +#endif /* HAVE_STDARG_H */ + va_list ap; + int len; + + VA_START(ap, format); + VA_SHIFT(ap, str, char *); + VA_SHIFT(ap, size, size_t); + VA_SHIFT(ap, format, const char *); + len = vsnprintf(str, size, format, ap); + va_end(ap); + return len; +} +#endif /* HW_WANT_RPL_SNPRINTF */ + +#if HW_WANT_RPL_ASPRINTF +#if HAVE_STDARG_H +int +rpl_asprintf(char **ret, const char *format, ...); + +int +rpl_asprintf(char **ret, const char *format, ...) +#else +int +rpl_asprintf(va_alist) va_dcl +#endif /* HAVE_STDARG_H */ +{ +#if !HAVE_STDARG_H + char **ret; + char *format; +#endif /* HAVE_STDARG_H */ + va_list ap; + int len; + + VA_START(ap, format); + VA_SHIFT(ap, ret, char **); + VA_SHIFT(ap, format, const char *); + len = vasprintf(ret, format, ap); + va_end(ap); + return len; +} +#endif /* HW_WANT_RPL_ASPRINTF */ +#else /* Dummy declaration to avoid empty translation unit warnings. */ +int main(void); +#endif /* HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || [...] */ + +#if TEST_SNPRINTF +int +main(void) +{ + const char *float_fmt[] = { + /* "%E" and "%e" formats. */ +#if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX + "%.16e", + "%22.16e", + "%022.16e", + "%-22.16e", + "%#+'022.16e", +#endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */ + "foo|%#+0123.9E|bar", + "%-123.9e", + "%123.9e", + "%+23.9e", + "%+05.8e", + "%-05.8e", + "%05.8e", + "%+5.8e", + "%-5.8e", + "% 5.8e", + "%5.8e", + "%+4.9e", +#if !OS_LINUX /* glibc sometimes gets these wrong. */ + "%+#010.0e", + "%#10.1e", + "%10.5e", + "% 10.5e", + "%5.0e", + "%5.e", + "%#5.0e", + "%#5.e", + "%3.2e", + "%3.1e", + "%-1.5e", + "%1.5e", + "%01.3e", + "%1.e", + "%.1e", + "%#.0e", + "%+.0e", + "% .0e", + "%.0e", + "%#.e", + "%+.e", + "% .e", + "%.e", + "%4e", + "%e", + "%E", +#endif /* !OS_LINUX */ + /* "%F" and "%f" formats. */ +#if !OS_BSD && !OS_IRIX + "% '022f", + "%+'022f", + "%-'22f", + "%'22f", +#if HAVE_LONG_LONG_INT + "%.16f", + "%22.16f", + "%022.16f", + "%-22.16f", + "%#+'022.16f", +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !OS_BSD && !OS_IRIX */ + "foo|%#+0123.9F|bar", + "%-123.9f", + "%123.9f", + "%+23.9f", + "%+#010.0f", + "%#10.1f", + "%10.5f", + "% 10.5f", + "%+05.8f", + "%-05.8f", + "%05.8f", + "%+5.8f", + "%-5.8f", + "% 5.8f", + "%5.8f", + "%5.0f", + "%5.f", + "%#5.0f", + "%#5.f", + "%+4.9f", + "%3.2f", + "%3.1f", + "%-1.5f", + "%1.5f", + "%01.3f", + "%1.f", + "%.1f", + "%#.0f", + "%+.0f", + "% .0f", + "%.0f", + "%#.f", + "%+.f", + "% .f", + "%.f", + "%4f", + "%f", + "%F", + /* "%G" and "%g" formats. */ +#if !OS_BSD && !OS_IRIX && !OS_LINUX + "% '022g", + "%+'022g", + "%-'22g", + "%'22g", +#if HAVE_LONG_LONG_INT + "%.16g", + "%22.16g", + "%022.16g", + "%-22.16g", + "%#+'022.16g", +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */ + "foo|%#+0123.9G|bar", + "%-123.9g", + "%123.9g", + "%+23.9g", + "%+05.8g", + "%-05.8g", + "%05.8g", + "%+5.8g", + "%-5.8g", + "% 5.8g", + "%5.8g", + "%+4.9g", +#if !OS_LINUX /* glibc sometimes gets these wrong. */ + "%+#010.0g", + "%#10.1g", + "%10.5g", + "% 10.5g", + "%5.0g", + "%5.g", + "%#5.0g", + "%#5.g", + "%3.2g", + "%3.1g", + "%-1.5g", + "%1.5g", + "%01.3g", + "%1.g", + "%.1g", + "%#.0g", + "%+.0g", + "% .0g", + "%.0g", + "%#.g", + "%+.g", + "% .g", + "%.g", + "%4g", + "%g", + "%G", +#endif /* !OS_LINUX */ + NULL + }; + double float_val[] = { + -4.136, + -134.52, + -5.04030201, + -3410.01234, + -999999.999999, + -913450.29876, + -913450.2, + -91345.2, + -9134.2, + -913.2, + -91.2, + -9.2, + -9.9, + 4.136, + 134.52, + 5.04030201, + 3410.01234, + 999999.999999, + 913450.29876, + 913450.2, + 91345.2, + 9134.2, + 913.2, + 91.2, + 9.2, + 9.9, + 9.96, + 9.996, + 9.9996, + 9.99996, + 9.999996, + 9.9999996, + 9.99999996, + 0.99999996, + 0.99999999, + 0.09999999, + 0.00999999, + 0.00099999, + 0.00009999, + 0.00000999, + 0.00000099, + 0.00000009, + 0.00000001, + 0.0000001, + 0.000001, + 0.00001, + 0.0001, + 0.001, + 0.01, + 0.1, + 1.0, + 1.5, + -1.5, + -1.0, + -0.1, +#if !OS_BSD /* BSD sometimes gets these wrong. */ +#ifdef INFINITY + INFINITY, + -INFINITY, +#endif /* defined(INFINITY) */ +#ifdef NAN + NAN, +#endif /* defined(NAN) */ +#endif /* !OS_BSD */ + 0 + }; + const char *long_fmt[] = { + "foo|%0123ld|bar", +#if !OS_IRIX + "% '0123ld", + "%+'0123ld", + "%-'123ld", + "%'123ld", +#endif /* !OS_IRiX */ + "%123.9ld", + "% 123.9ld", + "%+123.9ld", + "%-123.9ld", + "%0123ld", + "% 0123ld", + "%+0123ld", + "%-0123ld", + "%10.5ld", + "% 10.5ld", + "%+10.5ld", + "%-10.5ld", + "%010ld", + "% 010ld", + "%+010ld", + "%-010ld", + "%4.2ld", + "% 4.2ld", + "%+4.2ld", + "%-4.2ld", + "%04ld", + "% 04ld", + "%+04ld", + "%-04ld", + "%5.5ld", + "%+22.33ld", + "%01.3ld", + "%1.5ld", + "%-1.5ld", + "%44ld", + "%4ld", + "%4.0ld", + "%4.ld", + "%.44ld", + "%.4ld", + "%.0ld", + "%.ld", + "%ld", + NULL + }; + long int long_val[] = { +#ifdef LONG_MAX + LONG_MAX, +#endif /* LONG_MAX */ +#ifdef LONG_MIN + LONG_MIN, +#endif /* LONG_MIN */ + -91340, + 91340, + 341, + 134, + 0203, + -1, + 1, + 0 + }; + const char *ulong_fmt[] = { + /* "%u" formats. */ + "foo|%0123lu|bar", +#if !OS_IRIX + "% '0123lu", + "%+'0123lu", + "%-'123lu", + "%'123lu", +#endif /* !OS_IRiX */ + "%123.9lu", + "% 123.9lu", + "%+123.9lu", + "%-123.9lu", + "%0123lu", + "% 0123lu", + "%+0123lu", + "%-0123lu", + "%5.5lu", + "%+22.33lu", + "%01.3lu", + "%1.5lu", + "%-1.5lu", + "%44lu", + "%lu", + /* "%o" formats. */ + "foo|%#0123lo|bar", + "%#123.9lo", + "%# 123.9lo", + "%#+123.9lo", + "%#-123.9lo", + "%#0123lo", + "%# 0123lo", + "%#+0123lo", + "%#-0123lo", + "%#5.5lo", + "%#+22.33lo", + "%#01.3lo", + "%#1.5lo", + "%#-1.5lo", + "%#44lo", + "%#lo", + "%123.9lo", + "% 123.9lo", + "%+123.9lo", + "%-123.9lo", + "%0123lo", + "% 0123lo", + "%+0123lo", + "%-0123lo", + "%5.5lo", + "%+22.33lo", + "%01.3lo", + "%1.5lo", + "%-1.5lo", + "%44lo", + "%lo", + /* "%X" and "%x" formats. */ + "foo|%#0123lX|bar", + "%#123.9lx", + "%# 123.9lx", + "%#+123.9lx", + "%#-123.9lx", + "%#0123lx", + "%# 0123lx", + "%#+0123lx", + "%#-0123lx", + "%#5.5lx", + "%#+22.33lx", + "%#01.3lx", + "%#1.5lx", + "%#-1.5lx", + "%#44lx", + "%#lx", + "%#lX", + "%123.9lx", + "% 123.9lx", + "%+123.9lx", + "%-123.9lx", + "%0123lx", + "% 0123lx", + "%+0123lx", + "%-0123lx", + "%5.5lx", + "%+22.33lx", + "%01.3lx", + "%1.5lx", + "%-1.5lx", + "%44lx", + "%lx", + "%lX", + NULL + }; + unsigned long int ulong_val[] = { +#ifdef ULONG_MAX + ULONG_MAX, +#endif /* ULONG_MAX */ + 91340, + 341, + 134, + 0203, + 1, + 0 + }; + const char *llong_fmt[] = { + "foo|%0123lld|bar", + "%123.9lld", + "% 123.9lld", + "%+123.9lld", + "%-123.9lld", + "%0123lld", + "% 0123lld", + "%+0123lld", + "%-0123lld", + "%5.5lld", + "%+22.33lld", + "%01.3lld", + "%1.5lld", + "%-1.5lld", + "%44lld", + "%lld", + NULL + }; + LLONG llong_val[] = { +#ifdef LLONG_MAX + LLONG_MAX, +#endif /* LLONG_MAX */ +#ifdef LLONG_MIN + LLONG_MIN, +#endif /* LLONG_MIN */ + -91340, + 91340, + 341, + 134, + 0203, + -1, + 1, + 0 + }; + const char *string_fmt[] = { + "foo|%10.10s|bar", + "%-10.10s", + "%10.10s", + "%10.5s", + "%5.10s", + "%10.1s", + "%1.10s", + "%10.0s", + "%0.10s", + "%-42.5s", + "%2.s", + "%.10s", + "%.1s", + "%.0s", + "%.s", + "%4s", + "%s", + NULL + }; + const char *string_val[] = { + "Hello", + "Hello, world!", + "Sound check: One, two, three.", + "This string is a little longer than the other strings.", + "1", + "", + NULL + }; +#if !OS_SYSV /* SysV uses a different format than we do. */ + const char *pointer_fmt[] = { + "foo|%p|bar", + "%42p", + "%p", + NULL + }; + const char *pointer_val[] = { + *pointer_fmt, + *string_fmt, + *string_val, + NULL + }; +#endif /* !OS_SYSV */ + char buf1[1024], buf2[1024]; + double value, digits = 9.123456789012345678901234567890123456789; + int i, j, r1, r2, failed = 0, num = 0; + +/* + * Use -DTEST_NILS in order to also test the conversion of nil values. Might + * segfault on systems which don't support converting a NULL pointer with "%s" + * and lets some test cases fail against BSD and glibc due to bugs in their + * implementations. + */ +#ifndef TEST_NILS +#define TEST_NILS 0 +#elif TEST_NILS +#undef TEST_NILS +#define TEST_NILS 1 +#endif /* !defined(TEST_NILS) */ +#ifdef TEST +#undef TEST +#endif /* defined(TEST) */ +#define TEST(fmt, val) \ +do { \ + for (i = 0; fmt[i] != NULL; i++) \ + for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \ + r1 = sprintf(buf1, fmt[i], val[j]); \ + r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \ + if (strcmp(buf1, buf2) != 0 || r1 != r2) { \ + (void)printf("Results don't match, " \ + "format string: %s\n" \ + "\t sprintf(3): [%s] (%d)\n" \ + "\tsnprintf(3): [%s] (%d)\n", \ + fmt[i], buf1, r1, buf2, r2); \ + failed++; \ + } \ + num++; \ + } \ +} while (/* CONSTCOND */ 0) + +#if HAVE_LOCALE_H + (void)setlocale(LC_ALL, ""); +#endif /* HAVE_LOCALE_H */ + + (void)puts("Testing our snprintf(3) against your system's sprintf(3)."); + TEST(float_fmt, float_val); + TEST(long_fmt, long_val); + TEST(ulong_fmt, ulong_val); + TEST(llong_fmt, llong_val); + TEST(string_fmt, string_val); +#if !OS_SYSV /* SysV uses a different format than we do. */ + TEST(pointer_fmt, pointer_val); +#endif /* !OS_SYSV */ + (void)printf("Result: %d out of %d tests failed.\n", failed, num); + + (void)fputs("Checking how many digits we support: ", stdout); + for (i = 0; i < 100; i++) { + value = pow(10, i) * digits; + (void)sprintf(buf1, "%.1f", value); + (void)snprintf(buf2, sizeof(buf2), "%.1f", value); + if (strcmp(buf1, buf2) != 0) { + (void)printf("apparently %d.\n", i); + break; + } + } + return (failed == 0) ? 0 : 1; +} +#endif /* TEST_SNPRINTF */ + +/* vim: set joinspaces textwidth=80: */ diff --git a/contrib/ntp/libntp/socket.c b/contrib/ntp/libntp/socket.c new file mode 100644 index 000000000000..11fb004690c4 --- /dev/null +++ b/contrib/ntp/libntp/socket.c @@ -0,0 +1,218 @@ +/* + * socket.c - low-level socket operations + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#include "ntp.h" +#include "ntp_io.h" +#include "ntp_net.h" +#include "ntp_debug.h" + +/* + * Windows C runtime ioctl() can't deal properly with sockets, + * map to ioctlsocket for this source file. + */ +#ifdef SYS_WINNT +#define ioctl(fd, opt, val) ioctlsocket(fd, opt, (u_long *)(val)) +#endif + +/* + * on Unix systems the stdio library typically + * makes use of file descriptors in the lower + * integer range. stdio usually will make use + * of the file descriptors in the range of + * [0..FOPEN_MAX) + * in order to keep this range clean, for socket + * file descriptors we attempt to move them above + * 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: + * - keep a current socket fd boundary initialized with + * max(0, min(GETDTABLESIZE() - FD_CHUNK, FOPEN_MAX)) + * - attempt to move the descriptor to the boundary or + * above. + * - if that fails and boundary > 0 set boundary + * to min(0, socket_fd_boundary - FD_CHUNK) + * -> retry + * if failure and boundary == 0 return old fd + * - on success close old fd return new fd + * + * effects: + * - fds will be moved above the socket fd boundary + * if at all possible. + * - the socket boundary will be reduced until + * allocation is possible or 0 is reached - at this + * point the algrithm will be disabled + */ +SOCKET +move_fd( + SOCKET fd + ) +{ +#if !defined(SYS_WINNT) && defined(F_DUPFD) +#ifndef FD_CHUNK +#define FD_CHUNK 10 +#endif +#ifndef FOPEN_MAX +#define FOPEN_MAX 20 +#endif +/* + * number of fds we would like to have for + * stdio FILE* available. + * we can pick a "low" number as our use of + * FILE* is limited to log files and temporarily + * to data and config files. Except for log files + * we don't keep the other FILE* open beyond the + * scope of the function that opened it. + */ +#ifndef FD_PREFERRED_SOCKBOUNDARY +#define FD_PREFERRED_SOCKBOUNDARY 48 +#endif + + static SOCKET socket_boundary = -1; + SOCKET newfd; + + REQUIRE((int)fd >= 0); + + /* + * check whether boundary has be set up + * already + */ + if (socket_boundary == -1) { + socket_boundary = max(0, min(GETDTABLESIZE() - FD_CHUNK, + min(FOPEN_MAX, FD_PREFERRED_SOCKBOUNDARY))); + TRACE(1, ("move_fd: estimated max descriptors: %d, " + "initial socket boundary: %d\n", + GETDTABLESIZE(), socket_boundary)); + } + + /* + * Leave a space for stdio to work in. potentially moving the + * socket_boundary lower until allocation succeeds. + */ + do { + if (fd >= 0 && fd < socket_boundary) { + /* inside reserved range: attempt to move fd */ + newfd = fcntl(fd, F_DUPFD, socket_boundary); + + if (newfd != -1) { + /* success: drop the old one - return the new one */ + close(fd); + return newfd; + } + } else { + /* outside reserved range: no work - return the original one */ + return fd; + } + socket_boundary = max(0, socket_boundary - FD_CHUNK); + TRACE(1, ("move_fd: selecting new socket boundary: %d\n", + socket_boundary)); + } while (socket_boundary > 0); +#else + ENSURE((int)fd >= 0); +#endif /* !defined(SYS_WINNT) && defined(F_DUPFD) */ + return fd; +} + + +/* + * make_socket_nonblocking() - set up descriptor to be non blocking + */ +void +make_socket_nonblocking( + SOCKET fd + ) +{ + /* + * set non-blocking, + */ + +#ifdef USE_FIONBIO + /* in vxWorks we use FIONBIO, but the others are defined for old + * systems, so all hell breaks loose if we leave them defined + */ +#undef O_NONBLOCK +#undef FNDELAY +#undef O_NDELAY +#endif + +#if defined(O_NONBLOCK) /* POSIX */ + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + msyslog(LOG_ERR, + "fcntl(O_NONBLOCK) fails on fd #%d: %m", fd); + exit(1); + } +#elif defined(FNDELAY) + if (fcntl(fd, F_SETFL, FNDELAY) < 0) { + msyslog(LOG_ERR, "fcntl(FNDELAY) fails on fd #%d: %m", + fd); + exit(1); + } +#elif defined(O_NDELAY) /* generally the same as FNDELAY */ + if (fcntl(fd, F_SETFL, O_NDELAY) < 0) { + msyslog(LOG_ERR, "fcntl(O_NDELAY) fails on fd #%d: %m", + fd); + exit(1); + } +#elif defined(FIONBIO) + { + int on = 1; + + if (ioctl(fd, FIONBIO, &on) < 0) { + msyslog(LOG_ERR, + "ioctl(FIONBIO) fails on fd #%d: %m", + fd); + exit(1); + } + } +#elif defined(FIOSNBIO) + if (ioctl(fd, FIOSNBIO, &on) < 0) { + msyslog(LOG_ERR, + "ioctl(FIOSNBIO) fails on fd #%d: %m", fd); + exit(1); + } +#else +# include "Bletch: Need non-blocking I/O!" +#endif +} + +#if 0 + +/* The following subroutines should probably be moved here */ + +static SOCKET +open_socket( + sockaddr_u * addr, + int bcast, + int turn_off_reuse, + endpt * interf + ) +void +sendpkt( + sockaddr_u * dest, + struct interface * ep, + int ttl, + struct pkt * pkt, + int len + ) + +static inline int +read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts) + +static inline int +read_network_packet( + SOCKET fd, + struct interface * itf, + l_fp ts + ) + +void +kill_asyncio(int startfd) + +#endif /* 0 */ diff --git a/contrib/ntp/libntp/socktoa.c b/contrib/ntp/libntp/socktoa.c new file mode 100644 index 000000000000..98abe7c42036 --- /dev/null +++ b/contrib/ntp/libntp/socktoa.c @@ -0,0 +1,170 @@ +/* + * socktoa.c socktoa(), sockporttoa(), and sock_hash() + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <stdio.h> +#include <arpa/inet.h> +#include <isc/result.h> +#include <isc/netaddr.h> +#include <isc/sockaddr.h> + +#include "ntp_fp.h" +#include "lib_strbuf.h" +#include "ntp_stdlib.h" +#include "ntp.h" + +/* + * socktoa - return a numeric host name from a sockaddr_storage structure + */ +const char * +socktoa( + const sockaddr_u *sock + ) +{ + int saved_errno; + char * res; + char * addr; + u_long scope; + + saved_errno = socket_errno(); + LIB_GETBUF(res); + + if (NULL == sock) { + strlcpy(res, "(null)", LIB_BUFLENGTH); + } else { + switch(AF(sock)) { + + case AF_INET: + case AF_UNSPEC: + inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, + LIB_BUFLENGTH); + break; + + case AF_INET6: + inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, + LIB_BUFLENGTH); + scope = SCOPE_VAR(sock); + if (0 != scope && !strchr(res, '%')) { + addr = res; + LIB_GETBUF(res); + snprintf(res, LIB_BUFLENGTH, "%s%%%lu", + addr, scope); + res[LIB_BUFLENGTH - 1] = '\0'; + } + break; + + default: + snprintf(res, LIB_BUFLENGTH, + "(socktoa unknown family %d)", + AF(sock)); + } + } + errno = saved_errno; + + return res; +} + + +const char * +sockporttoa( + const sockaddr_u *sock + ) +{ + int saved_errno; + const char * atext; + char * buf; + + saved_errno = socket_errno(); + atext = socktoa(sock); + LIB_GETBUF(buf); + snprintf(buf, LIB_BUFLENGTH, + (IS_IPV6(sock)) + ? "[%s]:%hu" + : "%s:%hu", + atext, SRCPORT(sock)); + errno = saved_errno; + + return buf; +} + + +/* + * sock_hash - hash a sockaddr_u structure + */ +u_short +sock_hash( + const sockaddr_u *addr + ) +{ + u_int hashVal; + u_int j; + size_t len; + const 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. + */ + pch = (const void *)&AF(addr); + hashVal = 37 * hashVal + *pch; + if (sizeof(AF(addr)) > 1) { + pch++; + hashVal = 37 * hashVal + *pch; + } + switch(AF(addr)) { + case AF_INET: + pch = (const void *)&SOCK_ADDR4(addr); + len = sizeof(SOCK_ADDR4(addr)); + break; + + case AF_INET6: + pch = (const void *)&SOCK_ADDR6(addr); + len = sizeof(SOCK_ADDR6(addr)); + break; + } + + for (j = 0; j < len ; j++) + hashVal = 37 * hashVal + pch[j]; + + return (u_short)(hashVal & USHRT_MAX); +} + + +int +sockaddr_masktoprefixlen( + const sockaddr_u * psa + ) +{ + isc_netaddr_t isc_na; + isc_sockaddr_t isc_sa; + u_int pfxlen; + isc_result_t result; + int rc; + + ZERO(isc_sa); + memcpy(&isc_sa.type, psa, + min(sizeof(isc_sa.type), sizeof(*psa))); + isc_netaddr_fromsockaddr(&isc_na, &isc_sa); + result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); + rc = (ISC_R_SUCCESS == result) + ? (int)pfxlen + : -1; + + return rc; +} diff --git a/contrib/ntp/libntp/socktohost.c b/contrib/ntp/libntp/socktohost.c new file mode 100644 index 000000000000..fdf9adb9e2e6 --- /dev/null +++ b/contrib/ntp/libntp/socktohost.c @@ -0,0 +1,118 @@ +/* + * socktoa - return a numeric host name from a sockaddr_storage structure + */ +#include <config.h> +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <arpa/inet.h> + +#include <stdio.h> + +#include "ntp_fp.h" +#include "lib_strbuf.h" +#include "ntp_stdlib.h" +#include "ntp.h" +#include "ntp_debug.h" + + +const char * +socktohost( + const sockaddr_u *sock + ) +{ + const char svc[] = "ntp"; + char * pbuf; + char * pliar; + int gni_flags; + struct addrinfo hints; + struct addrinfo * alist; + struct addrinfo * ai; + sockaddr_u addr; + size_t octets; + int a_info; + int saved_errno; + + saved_errno = socket_errno(); + + /* reverse the address to purported DNS name */ + LIB_GETBUF(pbuf); + gni_flags = NI_DGRAM | NI_NAMEREQD; + if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH, + NULL, 0, gni_flags)) { + errno = saved_errno; + return stoa(sock); /* use address */ + } + + TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf)); + + /* + * Resolve the reversed name and make sure the reversed address + * is among the results. + */ + ZERO(hints); + hints.ai_family = AF(sock); + hints.ai_protocol = IPPROTO_UDP; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = 0; + alist = NULL; + + a_info = getaddrinfo(pbuf, svc, &hints, &alist); + if (a_info == EAI_NONAME +#ifdef EAI_NODATA + || a_info == EAI_NODATA +#endif + ) { + hints.ai_flags = AI_CANONNAME; +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif + a_info = getaddrinfo(pbuf, svc, &hints, &alist); + } +#ifdef AI_ADDRCONFIG + /* Some older implementations don't like AI_ADDRCONFIG. */ + if (a_info == EAI_BADFLAGS) { + hints.ai_flags &= ~AI_ADDRCONFIG; + a_info = getaddrinfo(pbuf, svc, &hints, &alist); + } +#endif + if (a_info) + goto forward_fail; + + INSIST(alist != NULL); + + for (ai = alist; ai != NULL; ai = ai->ai_next) { + /* + * Make a convenience sockaddr_u copy from ai->ai_addr + * because casting from sockaddr * to sockaddr_u * is + * risking alignment problems on platforms where + * sockaddr_u has stricter alignment than sockaddr, + * such as sparc. + */ + ZERO_SOCK(&addr); + octets = min(sizeof(addr), ai->ai_addrlen); + memcpy(&addr, ai->ai_addr, octets); + if (SOCK_EQ(sock, &addr)) + break; + } + freeaddrinfo(alist); + + if (ai != NULL) { + errno = saved_errno; + return pbuf; /* forward check passed */ + } + + forward_fail: + TRACE(1, ("%s forward check lookup fail: %s\n", pbuf, + gai_strerror(a_info))); + LIB_GETBUF(pliar); + snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf); + + errno = saved_errno; + return pliar; +} diff --git a/contrib/ntp/libntp/ssl_init.c b/contrib/ntp/libntp/ssl_init.c new file mode 100644 index 000000000000..ef0f1c185a88 --- /dev/null +++ b/contrib/ntp/libntp/ssl_init.c @@ -0,0 +1,192 @@ +/* + * ssl_init.c Common OpenSSL initialization code for the various + * programs which use it. + * + * Moved from ntpd/ntp_crypto.c crypto_setup() + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <ctype.h> +#include <ntp.h> +#include <ntp_debug.h> +#include <lib_strbuf.h> + +#ifdef OPENSSL +#include "openssl/err.h" +#include "openssl/evp.h" +#include "libssl_compat.h" + +void atexit_ssl_cleanup(void); + +int ssl_init_done; + +void +ssl_init(void) +{ + init_lib(); + + if (ssl_init_done) + return; + + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + atexit(&atexit_ssl_cleanup); + + ssl_init_done = TRUE; +} + + +void +atexit_ssl_cleanup(void) +{ + if (!ssl_init_done) + return; + + ssl_init_done = FALSE; + EVP_cleanup(); + ERR_free_strings(); +} + + +void +ssl_check_version(void) +{ + if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { + msyslog(LOG_WARNING, + "OpenSSL version mismatch. Built against %lx, you have %lx", + (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); + fprintf(stderr, + "OpenSSL version mismatch. Built against %lx, you have %lx\n", + (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); + } + + INIT_SSL(); +} + +#endif /* OPENSSL */ + + +/* + * keytype_from_text returns OpenSSL NID for digest by name, and + * optionally the associated digest length. + * + * Used by ntpd authreadkeys(), ntpq and ntpdc keytype() + */ +int +keytype_from_text( + const char *text, + size_t *pdigest_len + ) +{ + int key_type; + u_int digest_len; +#ifdef OPENSSL + const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); + u_char digest[EVP_MAX_MD_SIZE]; + char * upcased; + char * pch; + + /* + * OpenSSL digest short names are capitalized, so uppercase the + * digest name before passing to OBJ_sn2nid(). If it is not + * recognized but begins with 'M' use NID_md5 to be consistent + * with past behavior. + */ + INIT_SSL(); + LIB_GETBUF(upcased); + strlcpy(upcased, text, LIB_BUFLENGTH); + for (pch = upcased; '\0' != *pch; pch++) + *pch = (char)toupper((unsigned char)*pch); + key_type = OBJ_sn2nid(upcased); +#else + key_type = 0; +#endif + + if (!key_type && 'm' == tolower((unsigned char)text[0])) + key_type = NID_md5; + + if (!key_type) + return 0; + + if (NULL != pdigest_len) { +#ifdef OPENSSL + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_new(); + EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); + EVP_DigestFinal(ctx, digest, &digest_len); + EVP_MD_CTX_free(ctx); + if (digest_len > max_digest_len) { + fprintf(stderr, + "key type %s %u octet digests are too big, max %lu\n", + keytype_name(key_type), digest_len, + max_digest_len); + msyslog(LOG_ERR, + "key type %s %u octet digests are too big, max %lu", + keytype_name(key_type), digest_len, + max_digest_len); + return 0; + } +#else + digest_len = 16; +#endif + *pdigest_len = digest_len; + } + + return key_type; +} + + +/* + * keytype_name returns OpenSSL short name for digest by NID. + * + * Used by ntpq and ntpdc keytype() + */ +const char * +keytype_name( + int nid + ) +{ + static const char unknown_type[] = "(unknown key type)"; + const char *name; + +#ifdef OPENSSL + INIT_SSL(); + name = OBJ_nid2sn(nid); + if (NULL == name) + name = unknown_type; +#else /* !OPENSSL follows */ + if (NID_md5 == nid) + name = "MD5"; + else + name = unknown_type; +#endif + return name; +} + + +/* + * Use getpassphrase() if configure.ac detected it, as Suns that + * have it truncate the password in getpass() to 8 characters. + */ +#ifdef HAVE_GETPASSPHRASE +# define getpass(str) getpassphrase(str) +#endif + +/* + * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely + * related to the rest of ssl_init.c. + */ +char * +getpass_keytype( + int keytype + ) +{ + char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */ + + snprintf(pass_prompt, sizeof(pass_prompt), + "%.64s Password: ", keytype_name(keytype)); + + return getpass(pass_prompt); +} diff --git a/contrib/ntp/libntp/statestr.c b/contrib/ntp/libntp/statestr.c new file mode 100644 index 000000000000..313cd46bebfe --- /dev/null +++ b/contrib/ntp/libntp/statestr.c @@ -0,0 +1,501 @@ +/* + * pretty printing of status information + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include "ntp_stdlib.h" +#include "ntp_fp.h" +#include "ntp.h" +#include "lib_strbuf.h" +#include "ntp_refclock.h" +#include "ntp_control.h" +#include "ntp_string.h" +#ifdef KERNEL_PLL +# include "ntp_syscall.h" +#endif + + +/* + * Structure for turning various constants into a readable string. + */ +struct codestring { + int code; + const char * const string; +}; + +/* + * Leap status (leap) + */ +static const struct codestring leap_codes[] = { + { LEAP_NOWARNING, "leap_none" }, + { LEAP_ADDSECOND, "leap_add_sec" }, + { LEAP_DELSECOND, "leap_del_sec" }, + { LEAP_NOTINSYNC, "leap_alarm" }, + { -1, "leap" } +}; + +/* + * Clock source status (sync) + */ +static const struct codestring sync_codes[] = { + { CTL_SST_TS_UNSPEC, "sync_unspec" }, + { CTL_SST_TS_ATOM, "sync_pps" }, + { CTL_SST_TS_LF, "sync_lf_radio" }, + { CTL_SST_TS_HF, "sync_hf_radio" }, + { CTL_SST_TS_UHF, "sync_uhf_radio" }, + { CTL_SST_TS_LOCAL, "sync_local" }, + { CTL_SST_TS_NTP, "sync_ntp" }, + { CTL_SST_TS_UDPTIME, "sync_other" }, + { CTL_SST_TS_WRSTWTCH, "sync_wristwatch" }, + { CTL_SST_TS_TELEPHONE, "sync_telephone" }, + { -1, "sync" } +}; + +/* + * Peer selection status (sel) + */ +static const struct codestring select_codes[] = { + { CTL_PST_SEL_REJECT, "sel_reject" }, + { CTL_PST_SEL_SANE, "sel_falsetick" }, + { CTL_PST_SEL_CORRECT, "sel_excess" }, + { CTL_PST_SEL_SELCAND, "sel_outlier" }, + { CTL_PST_SEL_SYNCCAND, "sel_candidate" }, + { CTL_PST_SEL_EXCESS, "sel_backup" }, + { CTL_PST_SEL_SYSPEER, "sel_sys.peer" }, + { CTL_PST_SEL_PPS, "sel_pps.peer" }, + { -1, "sel" } +}; + +/* + * Clock status (clk) + */ +static const struct codestring clock_codes[] = { + { CTL_CLK_OKAY, "clk_unspec" }, + { CTL_CLK_NOREPLY, "clk_no_reply" }, + { CTL_CLK_BADFORMAT, "clk_bad_format" }, + { CTL_CLK_FAULT, "clk_fault" }, + { CTL_CLK_PROPAGATION, "clk_bad_signal" }, + { CTL_CLK_BADDATE, "clk_bad_date" }, + { CTL_CLK_BADTIME, "clk_bad_time" }, + { -1, "clk" } +}; + + +#ifdef FLASH_CODES_UNUSED +/* + * Flash bits -- see ntpq.c tstflags & tstflagnames + */ +static const struct codestring flash_codes[] = { + { TEST1, "pkt_dup" }, + { TEST2, "pkt_bogus" }, + { TEST3, "pkt_unsync" }, + { TEST4, "pkt_denied" }, + { TEST5, "pkt_auth" }, + { TEST6, "pkt_stratum" }, + { TEST7, "pkt_header" }, + { TEST8, "pkt_autokey" }, + { TEST9, "pkt_crypto" }, + { TEST10, "peer_stratum" }, + { TEST11, "peer_dist" }, + { TEST12, "peer_loop" }, + { TEST13, "peer_unreach" }, + { -1, "flash" } +}; +#endif + + +/* + * System events (sys) + */ +static const struct codestring sys_codes[] = { + { EVNT_UNSPEC, "unspecified" }, + { EVNT_NSET, "freq_not_set" }, + { EVNT_FSET, "freq_set" }, + { EVNT_SPIK, "spike_detect" }, + { EVNT_FREQ, "freq_mode" }, + { EVNT_SYNC, "clock_sync" }, + { EVNT_SYSRESTART, "restart" }, + { EVNT_SYSFAULT, "panic_stop" }, + { EVNT_NOPEER, "no_sys_peer" }, + { EVNT_ARMED, "leap_armed" }, + { EVNT_DISARMED, "leap_disarmed" }, + { EVNT_LEAP, "leap_event" }, + { EVNT_CLOCKRESET, "clock_step" }, + { EVNT_KERN, "kern" }, + { EVNT_TAI, "TAI" }, + { EVNT_LEAPVAL, "stale_leapsecond_values" }, + { -1, "" } +}; + +/* + * Peer events (peer) + */ +static const struct codestring peer_codes[] = { + { PEVNT_MOBIL & ~PEER_EVENT, "mobilize" }, + { PEVNT_DEMOBIL & ~PEER_EVENT, "demobilize" }, + { PEVNT_UNREACH & ~PEER_EVENT, "unreachable" }, + { PEVNT_REACH & ~PEER_EVENT, "reachable" }, + { PEVNT_RESTART & ~PEER_EVENT, "restart" }, + { PEVNT_REPLY & ~PEER_EVENT, "no_reply" }, + { PEVNT_RATE & ~PEER_EVENT, "rate_exceeded" }, + { PEVNT_DENY & ~PEER_EVENT, "access_denied" }, + { PEVNT_ARMED & ~PEER_EVENT, "leap_armed" }, + { PEVNT_NEWPEER & ~PEER_EVENT, "sys_peer" }, + { PEVNT_CLOCK & ~PEER_EVENT, "clock_event" }, + { PEVNT_AUTH & ~PEER_EVENT, "bad_auth" }, + { PEVNT_POPCORN & ~PEER_EVENT, "popcorn" }, + { PEVNT_XLEAVE & ~PEER_EVENT, "interleave_mode" }, + { PEVNT_XERR & ~PEER_EVENT, "interleave_error" }, + { -1, "" } +}; + +/* + * Peer status bits + */ +static const struct codestring peer_st_bits[] = { + { CTL_PST_CONFIG, "conf" }, + { CTL_PST_AUTHENABLE, "authenb" }, + { CTL_PST_AUTHENTIC, "auth" }, + { CTL_PST_REACH, "reach" }, + { CTL_PST_BCAST, "bcast" }, + /* not used with getcode(), no terminating entry needed */ +}; + +/* + * Restriction match bits + */ +static const struct codestring res_match_bits[] = { + { RESM_NTPONLY, "ntpport" }, + { RESM_INTERFACE, "interface" }, + { RESM_SOURCE, "source" }, + /* not used with getcode(), no terminating entry needed */ +}; + +/* + * Restriction access bits + */ +static const struct codestring res_access_bits[] = { + { RES_IGNORE, "ignore" }, + { RES_DONTSERVE, "noserve" }, + { RES_DONTTRUST, "notrust" }, + { RES_NOQUERY, "noquery" }, + { RES_NOMODIFY, "nomodify" }, + { RES_NOPEER, "nopeer" }, + { RES_NOTRAP, "notrap" }, + { RES_LPTRAP, "lptrap" }, + { RES_LIMITED, "limited" }, + { RES_VERSION, "version" }, + { RES_KOD, "kod" }, + { RES_FLAKE, "flake" }, + /* not used with getcode(), no terminating entry needed */ +}; + +#ifdef AUTOKEY +/* + * Crypto events (cryp) + */ +static const struct codestring crypto_codes[] = { + { XEVNT_OK & ~CRPT_EVENT, "success" }, + { XEVNT_LEN & ~CRPT_EVENT, "bad_field_format_or_length" }, + { XEVNT_TSP & ~CRPT_EVENT, "bad_timestamp" }, + { XEVNT_FSP & ~CRPT_EVENT, "bad_filestamp" }, + { XEVNT_PUB & ~CRPT_EVENT, "bad_or_missing_public_key" }, + { XEVNT_MD & ~CRPT_EVENT, "unsupported_digest_type" }, + { XEVNT_KEY & ~CRPT_EVENT, "unsupported_identity_type" }, + { XEVNT_SGL & ~CRPT_EVENT, "bad_signature_length" }, + { XEVNT_SIG & ~CRPT_EVENT, "signature_not_verified" }, + { XEVNT_VFY & ~CRPT_EVENT, "certificate_not_verified" }, + { XEVNT_PER & ~CRPT_EVENT, "host_certificate_expired" }, + { XEVNT_CKY & ~CRPT_EVENT, "bad_or_missing_cookie" }, + { XEVNT_DAT & ~CRPT_EVENT, "bad_or_missing_leapseconds" }, + { XEVNT_CRT & ~CRPT_EVENT, "bad_or_missing_certificate" }, + { XEVNT_ID & ~CRPT_EVENT, "bad_or_missing_group key" }, + { XEVNT_ERR & ~CRPT_EVENT, "protocol_error" }, + { -1, "" } +}; +#endif /* AUTOKEY */ + +#ifdef KERNEL_PLL +/* + * kernel discipline status bits + */ +static const struct codestring k_st_bits[] = { +# ifdef STA_PLL + { STA_PLL, "pll" }, +# endif +# ifdef STA_PPSFREQ + { STA_PPSFREQ, "ppsfreq" }, +# endif +# ifdef STA_PPSTIME + { STA_PPSTIME, "ppstime" }, +# endif +# ifdef STA_FLL + { STA_FLL, "fll" }, +# endif +# ifdef STA_INS + { STA_INS, "ins" }, +# endif +# ifdef STA_DEL + { STA_DEL, "del" }, +# endif +# ifdef STA_UNSYNC + { STA_UNSYNC, "unsync" }, +# endif +# ifdef STA_FREQHOLD + { STA_FREQHOLD, "freqhold" }, +# endif +# ifdef STA_PPSSIGNAL + { STA_PPSSIGNAL, "ppssignal" }, +# endif +# ifdef STA_PPSJITTER + { STA_PPSJITTER, "ppsjitter" }, +# endif +# ifdef STA_PPSWANDER + { STA_PPSWANDER, "ppswander" }, +# endif +# ifdef STA_PPSERROR + { STA_PPSERROR, "ppserror" }, +# endif +# ifdef STA_CLOCKERR + { STA_CLOCKERR, "clockerr" }, +# endif +# ifdef STA_NANO + { STA_NANO, "nano" }, +# endif +# ifdef STA_MODE + { STA_MODE, "mode=fll" }, +# endif +# ifdef STA_CLK + { STA_CLK, "src=B" }, +# endif + /* not used with getcode(), no terminating entry needed */ +}; +#endif /* KERNEL_PLL */ + +/* Forwards */ +static const char * getcode(int, const struct codestring *); +static const char * getevents(int); +static const char * peer_st_flags(u_char pst); + +/* + * getcode - return string corresponding to code + */ +static const char * +getcode( + int code, + const struct codestring * codetab + ) +{ + char * buf; + + while (codetab->code != -1) { + if (codetab->code == code) + return codetab->string; + codetab++; + } + + LIB_GETBUF(buf); + snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string, code); + + return buf; +} + +/* + * getevents - return a descriptive string for the event count + */ +static const char * +getevents( + int cnt + ) +{ + char * buf; + + if (cnt == 0) + return "no events"; + + LIB_GETBUF(buf); + snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt, + (1 == cnt) + ? "" + : "s"); + + return buf; +} + + +/* + * decode_bitflags() + * + * returns a human-readable string with a keyword from tab for each bit + * set in bits, separating multiple entries with text of sep2. + */ +static const char * +decode_bitflags( + int bits, + const char * sep2, + const struct codestring * tab, + size_t tab_ct + ) +{ + const char * sep; + char * buf; + char * pch; + char * lim; + size_t b; + int rc; + int saved_errno; /* for use in DPRINTF with %m */ + + saved_errno = errno; + LIB_GETBUF(buf); + pch = buf; + lim = buf + LIB_BUFLENGTH; + sep = ""; + + for (b = 0; b < tab_ct; b++) { + if (tab[b].code & bits) { + rc = snprintf(pch, (lim - pch), "%s%s", sep, + tab[b].string); + if (rc < 0) + goto toosmall; + pch += (u_int)rc; + if (pch >= lim) + goto toosmall; + sep = sep2; + } + } + + return buf; + + toosmall: + snprintf(buf, LIB_BUFLENGTH, + "decode_bitflags(%s) can't decode 0x%x in %d bytes", + (tab == peer_st_bits) + ? "peer_st" + : +#ifdef KERNEL_PLL + (tab == k_st_bits) + ? "kern_st" + : +#endif + "", + bits, (int)LIB_BUFLENGTH); + errno = saved_errno; + + return buf; +} + + +static const char * +peer_st_flags( + u_char pst + ) +{ + return decode_bitflags(pst, ", ", peer_st_bits, + COUNTOF(peer_st_bits)); +} + + +const char * +res_match_flags( + u_short mf + ) +{ + return decode_bitflags(mf, " ", res_match_bits, + COUNTOF(res_match_bits)); +} + + +const char * +res_access_flags( + u_short af + ) +{ + return decode_bitflags(af, " ", res_access_bits, + COUNTOF(res_access_bits)); +} + + +#ifdef KERNEL_PLL +const char * +k_st_flags( + u_int32 st + ) +{ + return decode_bitflags(st, " ", k_st_bits, COUNTOF(k_st_bits)); +} +#endif /* KERNEL_PLL */ + + +/* + * statustoa - return a descriptive string for a peer status + */ +char * +statustoa( + int type, + int st + ) +{ + char * cb; + char * cc; + u_char pst; + + LIB_GETBUF(cb); + + switch (type) { + + case TYPE_SYS: + snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s", + getcode(CTL_SYS_LI(st), leap_codes), + getcode(CTL_SYS_SOURCE(st), sync_codes), + getevents(CTL_SYS_NEVNT(st)), + getcode(CTL_SYS_EVENT(st), sys_codes)); + break; + + case TYPE_PEER: + pst = (u_char)CTL_PEER_STATVAL(st); + snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s", + peer_st_flags(pst), + getcode(pst & 0x7, select_codes), + getevents(CTL_PEER_NEVNT(st))); + if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) { + cc = cb + strlen(cb); + snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s", + getcode(CTL_PEER_EVENT(st), + peer_codes)); + } + break; + + case TYPE_CLOCK: + snprintf(cb, LIB_BUFLENGTH, "%s, %s", + getevents(CTL_SYS_NEVNT(st)), + getcode((st) & 0xf, clock_codes)); + break; + } + + return cb; +} + +const char * +eventstr( + int num + ) +{ + if (num & PEER_EVENT) + return (getcode(num & ~PEER_EVENT, peer_codes)); +#ifdef AUTOKEY + else if (num & CRPT_EVENT) + return (getcode(num & ~CRPT_EVENT, crypto_codes)); +#endif /* AUTOKEY */ + else + return (getcode(num, sys_codes)); +} + +const char * +ceventstr( + int num + ) +{ + return getcode(num, clock_codes); +} diff --git a/contrib/ntp/libntp/strdup.c b/contrib/ntp/libntp/strdup.c new file mode 100644 index 000000000000..62d5a16d433c --- /dev/null +++ b/contrib/ntp/libntp/strdup.c @@ -0,0 +1,29 @@ +#include <config.h> + +#include <ntp_assert.h> +#include "ntp_malloc.h" +#include <string.h> + +#ifndef HAVE_STRDUP + +char *strdup(const char *s); + +char * +strdup( + const char *s + ) +{ + size_t octets; + char * cp; + + REQUIRE(s); + octets = strlen(s) + 1; + if ((cp = malloc(octets)) == NULL) + return NULL; + memcpy(cp, s, octets); + + return cp; +} +#else +int strdup_c_nonempty_compilation_unit; +#endif diff --git a/contrib/ntp/libntp/strl_obsd.c b/contrib/ntp/libntp/strl_obsd.c new file mode 100644 index 000000000000..cb8d4f35981f --- /dev/null +++ b/contrib/ntp/libntp/strl_obsd.c @@ -0,0 +1,123 @@ +/* + * Why use strlcpy()/strlcat() instead of standard strncpy()/strncat()? + * To reduce likelihood of bugs and avoid wasteful zero fills. See: + * http://www.gratisoft.us/todd/papers/strlcpy.html + */ + +/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> /* + marks local changes */ +#ifdef HAVE_SYS_TYPES_H /* + */ +#include <sys/types.h> +#endif /* + */ +#include <string.h> + +#include "ntp_stdlib.h" /* + strlcpy, strlcat prototypes */ + +#ifndef HAVE_STRLCPY /* + */ +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif /* + */ + + +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* #include <sys/types.h> */ /* + */ +/* #include <string.h> */ /* + */ + +#ifndef HAVE_STRLCAT /* + */ +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} +#endif /* + */ diff --git a/contrib/ntp/libntp/syssignal.c b/contrib/ntp/libntp/syssignal.c new file mode 100644 index 000000000000..5e496a95f26d --- /dev/null +++ b/contrib/ntp/libntp/syssignal.c @@ -0,0 +1,188 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <sys/types.h> +#include <signal.h> + +#include "ntp_syslog.h" +#include "ntp_stdlib.h" + +static ctrl_c_fn ctrl_c_hook; +#ifndef SYS_WINNT +RETSIGTYPE sigint_handler(int); +#else +BOOL WINAPI console_event_handler(DWORD); +#endif + + +#ifdef HAVE_SIGACTION + +# ifdef SA_RESTART +# define Z_SA_RESTART SA_RESTART +# else +# define Z_SA_RESTART 0 +# endif + +void +signal_no_reset( + int sig, + void (*func)(int) + ) +{ + int n; + struct sigaction vec; + struct sigaction ovec; + + ZERO(vec); + sigemptyset(&vec.sa_mask); + vec.sa_handler = func; + + /* Added for PPS clocks on Solaris 7 which get EINTR errors */ +# ifdef SIGPOLL + if (SIGPOLL == sig) + vec.sa_flags = Z_SA_RESTART; +# endif +# ifdef SIGIO + if (SIGIO == sig) + vec.sa_flags = Z_SA_RESTART; +# endif + + do + n = sigaction(sig, &vec, &ovec); + while (-1 == n && EINTR == errno); + if (-1 == n) { + perror("sigaction"); + exit(1); + } +} + +#elif HAVE_SIGVEC + +void +signal_no_reset( + int sig, + RETSIGTYPE (*func)(int) + ) +{ + struct sigvec sv; + int n; + + ZERO(sv); + sv.sv_handler = func; + n = sigvec(sig, &sv, (struct sigvec *)NULL); + if (-1 == n) { + perror("sigvec"); + exit(1); + } +} + +#elif HAVE_SIGSET + +void +signal_no_reset( + int sig, + RETSIGTYPE (*func)(int) + ) +{ + int n; + + n = sigset(sig, func); + if (-1 == n) { + perror("sigset"); + exit(1); + } +} + +#else + +/* Beware! This implementation resets the signal to SIG_DFL */ +void +signal_no_reset( + int sig, + RETSIGTYPE (*func)(int) + ) +{ +#ifndef SIG_ERR +# define SIG_ERR (-1) +#endif + if (SIG_ERR == signal(sig, func)) { + perror("signal"); + exit(1); + } +} + +#endif + +#ifndef SYS_WINNT +/* + * POSIX implementation of set_ctrl_c_hook() + */ +RETSIGTYPE +sigint_handler( + int signum + ) +{ + UNUSED_ARG(signum); + if (ctrl_c_hook != NULL) + (*ctrl_c_hook)(); +} + +void +set_ctrl_c_hook( + ctrl_c_fn c_hook + ) +{ + RETSIGTYPE (*handler)(int); + + if (NULL == c_hook) { + handler = SIG_DFL; + ctrl_c_hook = NULL; + } else { + handler = &sigint_handler; + ctrl_c_hook = c_hook; + } + signal_no_reset(SIGINT, handler); +} +#else /* SYS_WINNT follows */ +/* + * Windows implementation of set_ctrl_c_hook() + */ +BOOL WINAPI +console_event_handler( + DWORD dwCtrlType + ) +{ + BOOL handled; + + if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { + (*ctrl_c_hook)(); + handled = TRUE; + } else { + handled = FALSE; + } + + return handled; +} +void +set_ctrl_c_hook( + ctrl_c_fn c_hook + ) +{ + BOOL install; + + if (NULL == c_hook) { + ctrl_c_hook = NULL; + install = FALSE; + } else { + ctrl_c_hook = c_hook; + install = TRUE; + } + if (!SetConsoleCtrlHandler(&console_event_handler, install)) + msyslog(LOG_ERR, "Can't %s console control handler: %m", + (install) + ? "add" + : "remove"); +} +#endif /* SYS_WINNT */ diff --git a/contrib/ntp/libntp/systime.c b/contrib/ntp/libntp/systime.c new file mode 100644 index 000000000000..29f1e86375e2 --- /dev/null +++ b/contrib/ntp/libntp/systime.c @@ -0,0 +1,599 @@ +/* + * systime -- routines to fiddle a UNIX clock. + * + * ATTENTION: Get approval from Dave Mills on all changes to this file! + * + */ +#include <config.h> + +#include "ntp.h" +#include "ntp_syslog.h" +#include "ntp_stdlib.h" +#include "ntp_random.h" +#include "iosignal.h" +#include "timevalops.h" +#include "timespecops.h" +#include "ntp_calendar.h" + +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifdef HAVE_UTMP_H +# include <utmp.h> +#endif /* HAVE_UTMP_H */ +#ifdef HAVE_UTMPX_H +# include <utmpx.h> +#endif /* HAVE_UTMPX_H */ + +int allow_panic = FALSE; /* allow panic correction (-g) */ +int enable_panic_check = TRUE; /* Can we check allow_panic's state? */ + +#ifndef USE_COMPILETIME_PIVOT +# define USE_COMPILETIME_PIVOT 1 +#endif + +/* + * These routines (get_systime, step_systime, adj_systime) implement an + * interface between the system independent NTP clock and the Unix + * system clock in various architectures and operating systems. Time is + * a precious quantity in these routines and every effort is made to + * minimize errors by unbiased rounding and amortizing adjustment + * residues. + * + * In order to improve the apparent resolution, provide unbiased + * rounding and most importantly ensure that the readings cannot be + * predicted, the low-order unused portion of the time below the minimum + * time to read the clock is filled with an unbiased random fuzz. + * + * The sys_tick variable specifies the system clock tick interval in + * seconds, for stepping clocks, defined as those which return times + * less than MINSTEP greater than the previous reading. For systems that + * use a high-resolution counter such that each clock reading is always + * at least MINSTEP greater than the prior, sys_tick is the time to read + * the system clock. + * + * The sys_fuzz variable measures the minimum time to read the system + * clock, regardless of its precision. When reading the system clock + * using get_systime() after sys_tick and sys_fuzz have been determined, + * ntpd ensures each unprocessed clock reading is no less than sys_fuzz + * later than the prior unprocessed reading, and then fuzzes the bits + * below sys_fuzz in the timestamp returned, ensuring each of its + * resulting readings is strictly later than the previous. + * + * When slewing the system clock using adj_systime() (with the kernel + * loop discipline unavailable or disabled), adjtime() offsets are + * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which + * is to say if the OS presents a stepping clock. Otherwise, offsets + * are quantized to the microsecond resolution of adjtime()'s timeval + * input. The remaining correction sys_residual is carried into the + * next adjtime() and meanwhile is also factored into get_systime() + * readings. + */ +double sys_tick = 0; /* tick size or time to read (s) */ +double sys_fuzz = 0; /* min. time to read the clock (s) */ +long sys_fuzz_nsec = 0; /* min. time to read the clock (ns) */ +double measured_tick; /* non-overridable sys_tick (s) */ +double sys_residual = 0; /* adjustment residue (s) */ +int trunc_os_clock; /* sys_tick > measured_tick */ +time_stepped_callback step_callback; + +#ifndef SIM +/* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock + * backstepping, this could probably become a local variable in + * 'get_systime()' and the cruft associated with communicating via a + * static value could be removed after the v4.2.8 release. + */ +static int lamport_violated; /* clock was stepped back */ +#endif /* !SIM */ + +#ifdef DEBUG +static int systime_init_done; +# define DONE_SYSTIME_INIT() systime_init_done = TRUE +#else +# define DONE_SYSTIME_INIT() do {} while (FALSE) +#endif + +#ifdef HAVE_SIGNALED_IO +int using_sigio; +#endif + +#ifdef SYS_WINNT +CRITICAL_SECTION get_systime_cs; +#endif + + +void +set_sys_fuzz( + double fuzz_val + ) +{ + sys_fuzz = fuzz_val; + INSIST(sys_fuzz >= 0); + INSIST(sys_fuzz <= 1.0); + sys_fuzz_nsec = (long)(sys_fuzz * 1e9 + 0.5); +} + + +void +init_systime(void) +{ + INIT_GET_SYSTIME_CRITSEC(); + INIT_WIN_PRECISE_TIME(); + DONE_SYSTIME_INIT(); +} + + +#ifndef SIM /* ntpsim.c has get_systime() and friends for sim */ + +static inline void +get_ostime( + struct timespec * tsp + ) +{ + int rc; + long ticks; + +#if defined(HAVE_CLOCK_GETTIME) + rc = clock_gettime(CLOCK_REALTIME, tsp); +#elif defined(HAVE_GETCLOCK) + rc = getclock(TIMEOFDAY, tsp); +#else + struct timeval tv; + + rc = GETTIMEOFDAY(&tv, NULL); + tsp->tv_sec = tv.tv_sec; + tsp->tv_nsec = tv.tv_usec * 1000; +#endif + if (rc < 0) { + msyslog(LOG_ERR, "read system clock failed: %m (%d)", + errno); + exit(1); + } + + if (trunc_os_clock) { + ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick); + tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick); + } +} + + +/* + * get_systime - return system time in NTP timestamp format. + */ +void +get_systime( + l_fp *now /* system time */ + ) +{ + static struct timespec ts_last; /* last sampled os time */ + static struct timespec ts_prev; /* prior os time */ + static l_fp lfp_prev; /* prior result */ + static double dfuzz_prev; /* prior fuzz */ + struct timespec ts; /* seconds and nanoseconds */ + struct timespec ts_min; /* earliest permissible */ + struct timespec ts_lam; /* lamport fictional increment */ + struct timespec ts_prev_log; /* for msyslog only */ + double dfuzz; + double ddelta; + l_fp result; + l_fp lfpfuzz; + l_fp lfpdelta; + + get_ostime(&ts); + DEBUG_REQUIRE(systime_init_done); + ENTER_GET_SYSTIME_CRITSEC(); + + /* First check if here was a Lamport violation, that is, two + * successive calls to 'get_ostime()' resulted in negative + * time difference. Use a few milliseconds of permissible + * tolerance -- being too sharp can hurt here. (This is intented + * for the Win32 target, where the HPC interpolation might + * introduce small steps backward. It should not be an issue on + * systems where get_ostime() results in a true syscall.) + */ + if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) + lamport_violated = 1; + ts_last = ts; + + /* + * After default_get_precision() has set a nonzero sys_fuzz, + * ensure every reading of the OS clock advances by at least + * sys_fuzz over the prior reading, thereby assuring each + * fuzzed result is strictly later than the prior. Limit the + * necessary fiction to 1 second. + */ + if (!USING_SIGIO()) { + ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec); + if (cmp_tspec(ts, ts_min) < 0) { + ts_lam = sub_tspec(ts_min, ts); + if (ts_lam.tv_sec > 0 && !lamport_violated) { + msyslog(LOG_ERR, + "get_systime Lamport advance exceeds one second (%.9f)", + ts_lam.tv_sec + + 1e-9 * ts_lam.tv_nsec); + exit(1); + } + if (!lamport_violated) + ts = ts_min; + } + ts_prev_log = ts_prev; + ts_prev = ts; + } else { + /* + * Quiet "ts_prev_log.tv_sec may be used uninitialized" + * warning from x86 gcc 4.5.2. + */ + ZERO(ts_prev_log); + } + + /* convert from timespec to l_fp fixed-point */ + result = tspec_stamp_to_lfp(ts); + + /* + * Add in the fuzz. + */ + dfuzz = ntp_random() * 2. / FRAC * sys_fuzz; + DTOLFP(dfuzz, &lfpfuzz); + L_ADD(&result, &lfpfuzz); + + /* + * Ensure result is strictly greater than prior result (ignoring + * sys_residual's effect for now) once sys_fuzz has been + * determined. + */ + if (!USING_SIGIO()) { + if (!L_ISZERO(&lfp_prev) && !lamport_violated) { + if (!L_ISGTU(&result, &lfp_prev) && + sys_fuzz > 0.) { + msyslog(LOG_ERR, "ts_prev %s ts_min %s", + tspectoa(ts_prev_log), + tspectoa(ts_min)); + msyslog(LOG_ERR, "ts %s", tspectoa(ts)); + msyslog(LOG_ERR, "sys_fuzz %ld nsec, prior fuzz %.9f", + sys_fuzz_nsec, dfuzz_prev); + msyslog(LOG_ERR, "this fuzz %.9f", + dfuzz); + lfpdelta = lfp_prev; + L_SUB(&lfpdelta, &result); + LFPTOD(&lfpdelta, ddelta); + msyslog(LOG_ERR, + "prev get_systime 0x%x.%08x is %.9f later than 0x%x.%08x", + lfp_prev.l_ui, lfp_prev.l_uf, + ddelta, result.l_ui, result.l_uf); + } + } + lfp_prev = result; + dfuzz_prev = dfuzz; + if (lamport_violated) + lamport_violated = FALSE; + } + LEAVE_GET_SYSTIME_CRITSEC(); + *now = result; +} + + +/* + * adj_systime - adjust system time by the argument. + */ +#if !defined SYS_WINNT +int /* 0 okay, 1 error */ +adj_systime( + double now /* adjustment (s) */ + ) +{ + struct timeval adjtv; /* new adjustment */ + struct timeval oadjtv; /* residual adjustment */ + double quant; /* quantize to multiples of */ + double dtemp; + long ticks; + int isneg = 0; + + /* + * The Windows port adj_systime() depends on being called each + * second even when there's no additional correction, to allow + * emulation of adjtime() behavior on top of an API that simply + * sets the current rate. This POSIX implementation needs to + * ignore invocations with zero correction, otherwise ongoing + * EVNT_NSET adjtime() can be aborted by a tiny adjtime() + * triggered by sys_residual. + */ + if (0. == now) { + if (enable_panic_check && allow_panic) { + msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); + INSIST(!allow_panic); + } + return TRUE; + } + + /* + * 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; + if (sys_tick > sys_fuzz) + quant = sys_tick; + else + quant = 1e-6; + ticks = (long)(dtemp / quant + .5); + adjtv.tv_usec = (long)(ticks * quant * 1.e6 + .5); + /* The rounding in the conversions could us push over the + * limits: make sure the result is properly normalised! + * note: sign comes later, all numbers non-negative here. + */ + if (adjtv.tv_usec >= 1000000) { + adjtv.tv_sec += 1; + adjtv.tv_usec -= 1000000; + dtemp -= 1.; + } + /* set the new residual with leftover from correction */ + sys_residual = dtemp - adjtv.tv_usec * 1.e-6; + + /* + * 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; + } + if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) { + if (adjtime(&adjtv, &oadjtv) < 0) { + msyslog(LOG_ERR, "adj_systime: %m"); + if (enable_panic_check && allow_panic) { + msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); + } + return FALSE; + } + } + if (enable_panic_check && allow_panic) { + msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!"); + } + return TRUE; +} +#endif + + +/* + * step_systime - step the system clock. + */ + +int +step_systime( + double step + ) +{ + time_t pivot; /* for ntp era unfolding */ + struct timeval timetv, tvlast, tvdiff; + struct timespec timets; + struct calendar jd; + l_fp fp_ofs, fp_sys; /* offset and target system time in FP */ + + /* + * Get pivot time for NTP era unfolding. Since we don't step + * very often, we can afford to do the whole calculation from + * scratch. And we're not in the time-critical path yet. + */ +#if SIZEOF_TIME_T > 4 + /* + * This code makes sure the resulting time stamp for the new + * system time is in the 2^32 seconds starting at 1970-01-01, + * 00:00:00 UTC. + */ + pivot = 0x80000000; +#if USE_COMPILETIME_PIVOT + /* + * Add the compile time minus 10 years to get a possible target + * area of (compile time - 10 years) to (compile time + 126 + * years). This should be sufficient for a given binary of + * NTPD. + */ + if (ntpcal_get_build_date(&jd)) { + jd.year -= 10; + pivot += ntpcal_date_to_time(&jd); + } else { + msyslog(LOG_ERR, + "step-systime: assume 1970-01-01 as build date"); + } +#else + UNUSED_LOCAL(jd); +#endif /* USE_COMPILETIME_PIVOT */ +#else + UNUSED_LOCAL(jd); + /* This makes sure the resulting time stamp is on or after + * 1969-12-31/23:59:59 UTC and gives us additional two years, + * from the change of NTP era in 2036 to the UNIX rollover in + * 2038. (Minus one second, but that won't hurt.) We *really* + * need a longer 'time_t' after that! Or a different baseline, + * but that would cause other serious trouble, too. + */ + pivot = 0x7FFFFFFF; +#endif + + /* get the complete jump distance as l_fp */ + DTOLFP(sys_residual, &fp_sys); + DTOLFP(step, &fp_ofs); + L_ADD(&fp_ofs, &fp_sys); + + /* ---> time-critical path starts ---> */ + + /* get the current time as l_fp (without fuzz) and as struct timeval */ + get_ostime(&timets); + fp_sys = tspec_stamp_to_lfp(timets); + tvlast.tv_sec = timets.tv_sec; + tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; + + /* get the target time as l_fp */ + L_ADD(&fp_sys, &fp_ofs); + + /* unfold the new system time */ + timetv = lfp_stamp_to_tval(fp_sys, &pivot); + + /* now set new system time */ + if (ntp_set_tod(&timetv, NULL) != 0) { + msyslog(LOG_ERR, "step-systime: %m"); + if (enable_panic_check && allow_panic) { + msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); + } + return FALSE; + } + + /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ + + sys_residual = 0; + lamport_violated = (step < 0); + if (step_callback) + (*step_callback)(); + +#ifdef NEED_HPUX_ADJTIME + /* + * CHECKME: is this correct when called by ntpdate????? + */ + _clear_adjtime(); +#endif + + /* + * FreeBSD, for example, has: + * struct utmp { + * char ut_line[UT_LINESIZE]; + * char ut_name[UT_NAMESIZE]; + * char ut_host[UT_HOSTSIZE]; + * long ut_time; + * }; + * and appends line="|", name="date", host="", time for the OLD + * and appends line="{", name="date", host="", time for the NEW // } + * to _PATH_WTMP . + * + * Some OSes have utmp, some have utmpx. + */ + + /* + * Write old and new time entries in utmp and wtmp if step + * adjustment is greater than one second. + * + * This might become even Uglier... + */ + tvdiff = abs_tval(sub_tval(timetv, tvlast)); + if (tvdiff.tv_sec > 0) { +#ifdef HAVE_UTMP_H + struct utmp ut; +#endif +#ifdef HAVE_UTMPX_H + struct utmpx utx; +#endif + +#ifdef HAVE_UTMP_H + ZERO(ut); +#endif +#ifdef HAVE_UTMPX_H + ZERO(utx); +#endif + + /* UTMP */ + +#ifdef UPDATE_UTMP +# ifdef HAVE_PUTUTLINE +# ifndef _PATH_UTMP +# define _PATH_UTMP UTMP_FILE +# endif + utmpname(_PATH_UTMP); + ut.ut_type = OLD_TIME; + strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); + ut.ut_time = tvlast.tv_sec; + setutent(); + pututline(&ut); + ut.ut_type = NEW_TIME; + strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); + ut.ut_time = timetv.tv_sec; + setutent(); + pututline(&ut); + endutent(); +# else /* not HAVE_PUTUTLINE */ +# endif /* not HAVE_PUTUTLINE */ +#endif /* UPDATE_UTMP */ + + /* UTMPX */ + +#ifdef UPDATE_UTMPX +# ifdef HAVE_PUTUTXLINE + utx.ut_type = OLD_TIME; + strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); + utx.ut_tv = tvlast; + setutxent(); + pututxline(&utx); + utx.ut_type = NEW_TIME; + strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); + utx.ut_tv = timetv; + setutxent(); + pututxline(&utx); + endutxent(); +# else /* not HAVE_PUTUTXLINE */ +# endif /* not HAVE_PUTUTXLINE */ +#endif /* UPDATE_UTMPX */ + + /* WTMP */ + +#ifdef UPDATE_WTMP +# ifdef HAVE_PUTUTLINE +# ifndef _PATH_WTMP +# define _PATH_WTMP WTMP_FILE +# endif + utmpname(_PATH_WTMP); + ut.ut_type = OLD_TIME; + strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line)); + ut.ut_time = tvlast.tv_sec; + setutent(); + pututline(&ut); + ut.ut_type = NEW_TIME; + strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line)); + ut.ut_time = timetv.tv_sec; + setutent(); + pututline(&ut); + endutent(); +# else /* not HAVE_PUTUTLINE */ +# endif /* not HAVE_PUTUTLINE */ +#endif /* UPDATE_WTMP */ + + /* WTMPX */ + +#ifdef UPDATE_WTMPX +# ifdef HAVE_PUTUTXLINE + utx.ut_type = OLD_TIME; + utx.ut_tv = tvlast; + strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line)); +# ifdef HAVE_UPDWTMPX + updwtmpx(WTMPX_FILE, &utx); +# else /* not HAVE_UPDWTMPX */ +# endif /* not HAVE_UPDWTMPX */ +# else /* not HAVE_PUTUTXLINE */ +# endif /* not HAVE_PUTUTXLINE */ +# ifdef HAVE_PUTUTXLINE + utx.ut_type = NEW_TIME; + utx.ut_tv = timetv; + strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line)); +# ifdef HAVE_UPDWTMPX + updwtmpx(WTMPX_FILE, &utx); +# else /* not HAVE_UPDWTMPX */ +# endif /* not HAVE_UPDWTMPX */ +# else /* not HAVE_PUTUTXLINE */ +# endif /* not HAVE_PUTUTXLINE */ +#endif /* UPDATE_WTMPX */ + + } + if (enable_panic_check && allow_panic) { + msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); + INSIST(!allow_panic); + } + return TRUE; +} + +#endif /* !SIM */ diff --git a/contrib/ntp/libntp/systime_s.c b/contrib/ntp/libntp/systime_s.c new file mode 100644 index 000000000000..87621220b035 --- /dev/null +++ b/contrib/ntp/libntp/systime_s.c @@ -0,0 +1,2 @@ +#define SIM +#include "systime.c" diff --git a/contrib/ntp/libntp/timetoa.c b/contrib/ntp/libntp/timetoa.c new file mode 100644 index 000000000000..f294e16107f9 --- /dev/null +++ b/contrib/ntp/libntp/timetoa.c @@ -0,0 +1,106 @@ +/* + * timetoa.c -- time_t related string formatting + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + * + * Printing a 'time_t' has a lot of portability pitfalls, due to it's + * opaque base type. The only requirement imposed by the standard is + * that it must be a numeric type. For all practical purposes it's a + * signed int, and 32 bits are common. + * + * Since the UN*X time epoch will cause a signed integer overflow for + * 32-bit signed int in the year 2038, implementations slowly move to + * 64bit base types for time_t, even in 32-bit environments. + * + * As the printf() family has no standardised type specifier for time_t, + * guessing the right output format specifier is a bit troublesome and + * best done with the help of the preprocessor and "config.h". + */ + +#include "config.h" + +#include <math.h> +#include <stdio.h> + +#include "timetoa.h" +#include "ntp_assert.h" +#include "lib_strbuf.h" + +/* + * Formatting to string needs at max 40 bytes (even with 64 bit time_t), + * so we check LIB_BUFLENGTH is big enough for our purpose. + */ +#if LIB_BUFLENGTH < 40 +# include "GRONK: LIB_BUFLENGTH is not sufficient" +#endif + +/* + * general fractional timestamp formatting + * + * Many pieces of ntpd require a machine with two's complement + * representation of signed integers, so we don't go through the whole + * rigamarole of creating fully portable code here. But we have to stay + * away from signed integer overflow, as this might cause trouble even + * with two's complement representation. + */ +const char * +format_time_fraction( + time_t secs, + long frac, + int prec + ) +{ + char * cp; + u_int prec_u; + u_time secs_u; + u_int u; + long fraclimit; + int notneg; /* flag for non-negative value */ + ldiv_t qr; + + DEBUG_REQUIRE(prec != 0); + + LIB_GETBUF(cp); + secs_u = (u_time)secs; + + /* check if we need signed or unsigned mode */ + notneg = (prec < 0); + prec_u = abs(prec); + /* fraclimit = (long)pow(10, prec_u); */ + for (fraclimit = 10, u = 1; u < prec_u; u++) { + DEBUG_INSIST(fraclimit < fraclimit * 10); + fraclimit *= 10; + } + + /* + * Since conversion to string uses lots of divisions anyway, + * there's no big extra penalty for normalisation. We do it for + * consistency. + */ + if (frac < 0 || frac >= fraclimit) { + qr = ldiv(frac, fraclimit); + if (qr.rem < 0) { + qr.quot--; + qr.rem += fraclimit; + } + secs_u += (time_t)qr.quot; + frac = qr.rem; + } + + /* Get the absolute value of the split representation time. */ + notneg = notneg || ((time_t)secs_u >= 0); + if (!notneg) { + secs_u = ~secs_u; + if (0 == frac) + secs_u++; + else + frac = fraclimit - frac; + } + + /* finally format the data and return the result */ + snprintf(cp, LIB_BUFLENGTH, "%s%" UTIME_FORMAT ".%0*ld", + notneg? "" : "-", secs_u, prec_u, frac); + + return cp; +} diff --git a/contrib/ntp/libntp/timevalops.c b/contrib/ntp/libntp/timevalops.c new file mode 100644 index 000000000000..55f7bb57312b --- /dev/null +++ b/contrib/ntp/libntp/timevalops.c @@ -0,0 +1,297 @@ +/* + * timevalops.c -- calculations on 'struct timeval' values + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + */ + +#include <config.h> + +#include "timevalops.h" + +#ifdef USE_TSF_USEC_TABLES +/* + * Tables to calculate time stamp fractions from usecs. The entries + * in these tables are offset into using each of the two low order + * bytes plus the next 4 bits in a usec value (from a struct timeval). + * These are summed to produce the time stamp fraction. + * + * Note that these tables are rounded (not truncated) to the nearest + * low order bit in the fraction. The timestamp computed should be + * +- 1.5 low order bits. + */ + +const u_int32 ustotslo[256] = { + 0x00000000, 0x000010c7, 0x0000218e, 0x00003255, + 0x0000431c, 0x000053e3, 0x000064aa, 0x00007571, + 0x00008638, 0x000096ff, 0x0000a7c6, 0x0000b88d, + 0x0000c954, 0x0000da1b, 0x0000eae2, 0x0000fba9, + 0x00010c6f, 0x00011d36, 0x00012dfd, 0x00013ec4, + 0x00014f8b, 0x00016052, 0x00017119, 0x000181e0, + 0x000192a7, 0x0001a36e, 0x0001b435, 0x0001c4fc, + 0x0001d5c3, 0x0001e68a, 0x0001f751, 0x00020818, + 0x000218df, 0x000229a6, 0x00023a6d, 0x00024b34, + 0x00025bfb, 0x00026cc2, 0x00027d89, 0x00028e50, + 0x00029f17, 0x0002afde, 0x0002c0a5, 0x0002d16c, + 0x0002e233, 0x0002f2fa, 0x000303c0, 0x00031487, + 0x0003254e, 0x00033615, 0x000346dc, 0x000357a3, + 0x0003686a, 0x00037931, 0x000389f8, 0x00039abf, + 0x0003ab86, 0x0003bc4d, 0x0003cd14, 0x0003dddb, + 0x0003eea2, 0x0003ff69, 0x00041030, 0x000420f7, + 0x000431be, 0x00044285, 0x0004534c, 0x00046413, + 0x000474da, 0x000485a1, 0x00049668, 0x0004a72f, + 0x0004b7f6, 0x0004c8bd, 0x0004d984, 0x0004ea4b, + 0x0004fb12, 0x00050bd8, 0x00051c9f, 0x00052d66, + 0x00053e2d, 0x00054ef4, 0x00055fbb, 0x00057082, + 0x00058149, 0x00059210, 0x0005a2d7, 0x0005b39e, + 0x0005c465, 0x0005d52c, 0x0005e5f3, 0x0005f6ba, + 0x00060781, 0x00061848, 0x0006290f, 0x000639d6, + 0x00064a9d, 0x00065b64, 0x00066c2b, 0x00067cf2, + 0x00068db9, 0x00069e80, 0x0006af47, 0x0006c00e, + 0x0006d0d5, 0x0006e19c, 0x0006f263, 0x0007032a, + 0x000713f0, 0x000724b7, 0x0007357e, 0x00074645, + 0x0007570c, 0x000767d3, 0x0007789a, 0x00078961, + 0x00079a28, 0x0007aaef, 0x0007bbb6, 0x0007cc7d, + 0x0007dd44, 0x0007ee0b, 0x0007fed2, 0x00080f99, + 0x00082060, 0x00083127, 0x000841ee, 0x000852b5, + 0x0008637c, 0x00087443, 0x0008850a, 0x000895d1, + 0x0008a698, 0x0008b75f, 0x0008c826, 0x0008d8ed, + 0x0008e9b4, 0x0008fa7b, 0x00090b41, 0x00091c08, + 0x00092ccf, 0x00093d96, 0x00094e5d, 0x00095f24, + 0x00096feb, 0x000980b2, 0x00099179, 0x0009a240, + 0x0009b307, 0x0009c3ce, 0x0009d495, 0x0009e55c, + 0x0009f623, 0x000a06ea, 0x000a17b1, 0x000a2878, + 0x000a393f, 0x000a4a06, 0x000a5acd, 0x000a6b94, + 0x000a7c5b, 0x000a8d22, 0x000a9de9, 0x000aaeb0, + 0x000abf77, 0x000ad03e, 0x000ae105, 0x000af1cc, + 0x000b0293, 0x000b1359, 0x000b2420, 0x000b34e7, + 0x000b45ae, 0x000b5675, 0x000b673c, 0x000b7803, + 0x000b88ca, 0x000b9991, 0x000baa58, 0x000bbb1f, + 0x000bcbe6, 0x000bdcad, 0x000bed74, 0x000bfe3b, + 0x000c0f02, 0x000c1fc9, 0x000c3090, 0x000c4157, + 0x000c521e, 0x000c62e5, 0x000c73ac, 0x000c8473, + 0x000c953a, 0x000ca601, 0x000cb6c8, 0x000cc78f, + 0x000cd856, 0x000ce91d, 0x000cf9e4, 0x000d0aaa, + 0x000d1b71, 0x000d2c38, 0x000d3cff, 0x000d4dc6, + 0x000d5e8d, 0x000d6f54, 0x000d801b, 0x000d90e2, + 0x000da1a9, 0x000db270, 0x000dc337, 0x000dd3fe, + 0x000de4c5, 0x000df58c, 0x000e0653, 0x000e171a, + 0x000e27e1, 0x000e38a8, 0x000e496f, 0x000e5a36, + 0x000e6afd, 0x000e7bc4, 0x000e8c8b, 0x000e9d52, + 0x000eae19, 0x000ebee0, 0x000ecfa7, 0x000ee06e, + 0x000ef135, 0x000f01fc, 0x000f12c2, 0x000f2389, + 0x000f3450, 0x000f4517, 0x000f55de, 0x000f66a5, + 0x000f776c, 0x000f8833, 0x000f98fa, 0x000fa9c1, + 0x000fba88, 0x000fcb4f, 0x000fdc16, 0x000fecdd, + 0x000ffda4, 0x00100e6b, 0x00101f32, 0x00102ff9, + 0x001040c0, 0x00105187, 0x0010624e, 0x00107315, + 0x001083dc, 0x001094a3, 0x0010a56a, 0x0010b631 +}; + +const u_int32 ustotsmid[256] = { + 0x00000000, 0x0010c6f8, 0x00218def, 0x003254e7, + 0x00431bdf, 0x0053e2d6, 0x0064a9ce, 0x007570c5, + 0x008637bd, 0x0096feb5, 0x00a7c5ac, 0x00b88ca4, + 0x00c9539c, 0x00da1a93, 0x00eae18b, 0x00fba882, + 0x010c6f7a, 0x011d3672, 0x012dfd69, 0x013ec461, + 0x014f8b59, 0x01605250, 0x01711948, 0x0181e03f, + 0x0192a737, 0x01a36e2f, 0x01b43526, 0x01c4fc1e, + 0x01d5c316, 0x01e68a0d, 0x01f75105, 0x020817fc, + 0x0218def4, 0x0229a5ec, 0x023a6ce3, 0x024b33db, + 0x025bfad3, 0x026cc1ca, 0x027d88c2, 0x028e4fb9, + 0x029f16b1, 0x02afdda9, 0x02c0a4a0, 0x02d16b98, + 0x02e23290, 0x02f2f987, 0x0303c07f, 0x03148777, + 0x03254e6e, 0x03361566, 0x0346dc5d, 0x0357a355, + 0x03686a4d, 0x03793144, 0x0389f83c, 0x039abf34, + 0x03ab862b, 0x03bc4d23, 0x03cd141a, 0x03dddb12, + 0x03eea20a, 0x03ff6901, 0x04102ff9, 0x0420f6f1, + 0x0431bde8, 0x044284e0, 0x04534bd7, 0x046412cf, + 0x0474d9c7, 0x0485a0be, 0x049667b6, 0x04a72eae, + 0x04b7f5a5, 0x04c8bc9d, 0x04d98394, 0x04ea4a8c, + 0x04fb1184, 0x050bd87b, 0x051c9f73, 0x052d666b, + 0x053e2d62, 0x054ef45a, 0x055fbb51, 0x05708249, + 0x05814941, 0x05921038, 0x05a2d730, 0x05b39e28, + 0x05c4651f, 0x05d52c17, 0x05e5f30e, 0x05f6ba06, + 0x060780fe, 0x061847f5, 0x06290eed, 0x0639d5e5, + 0x064a9cdc, 0x065b63d4, 0x066c2acc, 0x067cf1c3, + 0x068db8bb, 0x069e7fb2, 0x06af46aa, 0x06c00da2, + 0x06d0d499, 0x06e19b91, 0x06f26289, 0x07032980, + 0x0713f078, 0x0724b76f, 0x07357e67, 0x0746455f, + 0x07570c56, 0x0767d34e, 0x07789a46, 0x0789613d, + 0x079a2835, 0x07aaef2c, 0x07bbb624, 0x07cc7d1c, + 0x07dd4413, 0x07ee0b0b, 0x07fed203, 0x080f98fa, + 0x08205ff2, 0x083126e9, 0x0841ede1, 0x0852b4d9, + 0x08637bd0, 0x087442c8, 0x088509c0, 0x0895d0b7, + 0x08a697af, 0x08b75ea6, 0x08c8259e, 0x08d8ec96, + 0x08e9b38d, 0x08fa7a85, 0x090b417d, 0x091c0874, + 0x092ccf6c, 0x093d9664, 0x094e5d5b, 0x095f2453, + 0x096feb4a, 0x0980b242, 0x0991793a, 0x09a24031, + 0x09b30729, 0x09c3ce21, 0x09d49518, 0x09e55c10, + 0x09f62307, 0x0a06e9ff, 0x0a17b0f7, 0x0a2877ee, + 0x0a393ee6, 0x0a4a05de, 0x0a5accd5, 0x0a6b93cd, + 0x0a7c5ac4, 0x0a8d21bc, 0x0a9de8b4, 0x0aaeafab, + 0x0abf76a3, 0x0ad03d9b, 0x0ae10492, 0x0af1cb8a, + 0x0b029281, 0x0b135979, 0x0b242071, 0x0b34e768, + 0x0b45ae60, 0x0b567558, 0x0b673c4f, 0x0b780347, + 0x0b88ca3e, 0x0b999136, 0x0baa582e, 0x0bbb1f25, + 0x0bcbe61d, 0x0bdcad15, 0x0bed740c, 0x0bfe3b04, + 0x0c0f01fc, 0x0c1fc8f3, 0x0c308feb, 0x0c4156e2, + 0x0c521dda, 0x0c62e4d2, 0x0c73abc9, 0x0c8472c1, + 0x0c9539b9, 0x0ca600b0, 0x0cb6c7a8, 0x0cc78e9f, + 0x0cd85597, 0x0ce91c8f, 0x0cf9e386, 0x0d0aaa7e, + 0x0d1b7176, 0x0d2c386d, 0x0d3cff65, 0x0d4dc65c, + 0x0d5e8d54, 0x0d6f544c, 0x0d801b43, 0x0d90e23b, + 0x0da1a933, 0x0db2702a, 0x0dc33722, 0x0dd3fe19, + 0x0de4c511, 0x0df58c09, 0x0e065300, 0x0e1719f8, + 0x0e27e0f0, 0x0e38a7e7, 0x0e496edf, 0x0e5a35d6, + 0x0e6afcce, 0x0e7bc3c6, 0x0e8c8abd, 0x0e9d51b5, + 0x0eae18ad, 0x0ebedfa4, 0x0ecfa69c, 0x0ee06d94, + 0x0ef1348b, 0x0f01fb83, 0x0f12c27a, 0x0f238972, + 0x0f34506a, 0x0f451761, 0x0f55de59, 0x0f66a551, + 0x0f776c48, 0x0f883340, 0x0f98fa37, 0x0fa9c12f, + 0x0fba8827, 0x0fcb4f1e, 0x0fdc1616, 0x0fecdd0e, + 0x0ffda405, 0x100e6afd, 0x101f31f4, 0x102ff8ec, + 0x1040bfe4, 0x105186db, 0x10624dd3, 0x107314cb, + 0x1083dbc2, 0x1094a2ba, 0x10a569b1, 0x10b630a9 +}; + +const u_int32 ustotshi[16] = { + 0x00000000, 0x10c6f7a1, 0x218def41, 0x3254e6e2, + 0x431bde83, 0x53e2d624, 0x64a9cdc4, 0x7570c565, + 0x8637bd06, 0x96feb4a6, 0xa7c5ac47, 0xb88ca3e8, + 0xc9539b89, 0xda1a9329, 0xeae18aca, 0xfba8826b +}; + +/* + * Tables to convert from a time stamp fraction to usecs. Note that + * the units of these tables are actually (usec<<3). We carry three + * guard bits so that the result can be properly truncated (or rounded) + * to be correct to the least significant bit. + * + * These tables are rounded. + */ + +const u_int32 tstoushi[256] = { + 0x000000, 0x007a12, 0x00f424, 0x016e36, + 0x01e848, 0x02625a, 0x02dc6c, 0x03567e, + 0x03d090, 0x044aa2, 0x04c4b4, 0x053ec6, + 0x05b8d8, 0x0632ea, 0x06acfc, 0x07270e, + 0x07a120, 0x081b32, 0x089544, 0x090f56, + 0x098968, 0x0a037a, 0x0a7d8c, 0x0af79e, + 0x0b71b0, 0x0bebc2, 0x0c65d4, 0x0cdfe6, + 0x0d59f8, 0x0dd40a, 0x0e4e1c, 0x0ec82e, + 0x0f4240, 0x0fbc52, 0x103664, 0x10b076, + 0x112a88, 0x11a49a, 0x121eac, 0x1298be, + 0x1312d0, 0x138ce2, 0x1406f4, 0x148106, + 0x14fb18, 0x15752a, 0x15ef3c, 0x16694e, + 0x16e360, 0x175d72, 0x17d784, 0x185196, + 0x18cba8, 0x1945ba, 0x19bfcc, 0x1a39de, + 0x1ab3f0, 0x1b2e02, 0x1ba814, 0x1c2226, + 0x1c9c38, 0x1d164a, 0x1d905c, 0x1e0a6e, + 0x1e8480, 0x1efe92, 0x1f78a4, 0x1ff2b6, + 0x206cc8, 0x20e6da, 0x2160ec, 0x21dafe, + 0x225510, 0x22cf22, 0x234934, 0x23c346, + 0x243d58, 0x24b76a, 0x25317c, 0x25ab8e, + 0x2625a0, 0x269fb2, 0x2719c4, 0x2793d6, + 0x280de8, 0x2887fa, 0x29020c, 0x297c1e, + 0x29f630, 0x2a7042, 0x2aea54, 0x2b6466, + 0x2bde78, 0x2c588a, 0x2cd29c, 0x2d4cae, + 0x2dc6c0, 0x2e40d2, 0x2ebae4, 0x2f34f6, + 0x2faf08, 0x30291a, 0x30a32c, 0x311d3e, + 0x319750, 0x321162, 0x328b74, 0x330586, + 0x337f98, 0x33f9aa, 0x3473bc, 0x34edce, + 0x3567e0, 0x35e1f2, 0x365c04, 0x36d616, + 0x375028, 0x37ca3a, 0x38444c, 0x38be5e, + 0x393870, 0x39b282, 0x3a2c94, 0x3aa6a6, + 0x3b20b8, 0x3b9aca, 0x3c14dc, 0x3c8eee, + 0x3d0900, 0x3d8312, 0x3dfd24, 0x3e7736, + 0x3ef148, 0x3f6b5a, 0x3fe56c, 0x405f7e, + 0x40d990, 0x4153a2, 0x41cdb4, 0x4247c6, + 0x42c1d8, 0x433bea, 0x43b5fc, 0x44300e, + 0x44aa20, 0x452432, 0x459e44, 0x461856, + 0x469268, 0x470c7a, 0x47868c, 0x48009e, + 0x487ab0, 0x48f4c2, 0x496ed4, 0x49e8e6, + 0x4a62f8, 0x4add0a, 0x4b571c, 0x4bd12e, + 0x4c4b40, 0x4cc552, 0x4d3f64, 0x4db976, + 0x4e3388, 0x4ead9a, 0x4f27ac, 0x4fa1be, + 0x501bd0, 0x5095e2, 0x510ff4, 0x518a06, + 0x520418, 0x527e2a, 0x52f83c, 0x53724e, + 0x53ec60, 0x546672, 0x54e084, 0x555a96, + 0x55d4a8, 0x564eba, 0x56c8cc, 0x5742de, + 0x57bcf0, 0x583702, 0x58b114, 0x592b26, + 0x59a538, 0x5a1f4a, 0x5a995c, 0x5b136e, + 0x5b8d80, 0x5c0792, 0x5c81a4, 0x5cfbb6, + 0x5d75c8, 0x5defda, 0x5e69ec, 0x5ee3fe, + 0x5f5e10, 0x5fd822, 0x605234, 0x60cc46, + 0x614658, 0x61c06a, 0x623a7c, 0x62b48e, + 0x632ea0, 0x63a8b2, 0x6422c4, 0x649cd6, + 0x6516e8, 0x6590fa, 0x660b0c, 0x66851e, + 0x66ff30, 0x677942, 0x67f354, 0x686d66, + 0x68e778, 0x69618a, 0x69db9c, 0x6a55ae, + 0x6acfc0, 0x6b49d2, 0x6bc3e4, 0x6c3df6, + 0x6cb808, 0x6d321a, 0x6dac2c, 0x6e263e, + 0x6ea050, 0x6f1a62, 0x6f9474, 0x700e86, + 0x708898, 0x7102aa, 0x717cbc, 0x71f6ce, + 0x7270e0, 0x72eaf2, 0x736504, 0x73df16, + 0x745928, 0x74d33a, 0x754d4c, 0x75c75e, + 0x764170, 0x76bb82, 0x773594, 0x77afa6, + 0x7829b8, 0x78a3ca, 0x791ddc, 0x7997ee +}; + +const u_int32 tstousmid[256] = { + 0x0000, 0x007a, 0x00f4, 0x016e, 0x01e8, 0x0262, 0x02dc, 0x0356, + 0x03d1, 0x044b, 0x04c5, 0x053f, 0x05b9, 0x0633, 0x06ad, 0x0727, + 0x07a1, 0x081b, 0x0895, 0x090f, 0x0989, 0x0a03, 0x0a7e, 0x0af8, + 0x0b72, 0x0bec, 0x0c66, 0x0ce0, 0x0d5a, 0x0dd4, 0x0e4e, 0x0ec8, + 0x0f42, 0x0fbc, 0x1036, 0x10b0, 0x112b, 0x11a5, 0x121f, 0x1299, + 0x1313, 0x138d, 0x1407, 0x1481, 0x14fb, 0x1575, 0x15ef, 0x1669, + 0x16e3, 0x175d, 0x17d8, 0x1852, 0x18cc, 0x1946, 0x19c0, 0x1a3a, + 0x1ab4, 0x1b2e, 0x1ba8, 0x1c22, 0x1c9c, 0x1d16, 0x1d90, 0x1e0a, + 0x1e84, 0x1eff, 0x1f79, 0x1ff3, 0x206d, 0x20e7, 0x2161, 0x21db, + 0x2255, 0x22cf, 0x2349, 0x23c3, 0x243d, 0x24b7, 0x2531, 0x25ac, + 0x2626, 0x26a0, 0x271a, 0x2794, 0x280e, 0x2888, 0x2902, 0x297c, + 0x29f6, 0x2a70, 0x2aea, 0x2b64, 0x2bde, 0x2c59, 0x2cd3, 0x2d4d, + 0x2dc7, 0x2e41, 0x2ebb, 0x2f35, 0x2faf, 0x3029, 0x30a3, 0x311d, + 0x3197, 0x3211, 0x328b, 0x3306, 0x3380, 0x33fa, 0x3474, 0x34ee, + 0x3568, 0x35e2, 0x365c, 0x36d6, 0x3750, 0x37ca, 0x3844, 0x38be, + 0x3938, 0x39b3, 0x3a2d, 0x3aa7, 0x3b21, 0x3b9b, 0x3c15, 0x3c8f, + 0x3d09, 0x3d83, 0x3dfd, 0x3e77, 0x3ef1, 0x3f6b, 0x3fe5, 0x405f, + 0x40da, 0x4154, 0x41ce, 0x4248, 0x42c2, 0x433c, 0x43b6, 0x4430, + 0x44aa, 0x4524, 0x459e, 0x4618, 0x4692, 0x470c, 0x4787, 0x4801, + 0x487b, 0x48f5, 0x496f, 0x49e9, 0x4a63, 0x4add, 0x4b57, 0x4bd1, + 0x4c4b, 0x4cc5, 0x4d3f, 0x4db9, 0x4e34, 0x4eae, 0x4f28, 0x4fa2, + 0x501c, 0x5096, 0x5110, 0x518a, 0x5204, 0x527e, 0x52f8, 0x5372, + 0x53ec, 0x5466, 0x54e1, 0x555b, 0x55d5, 0x564f, 0x56c9, 0x5743, + 0x57bd, 0x5837, 0x58b1, 0x592b, 0x59a5, 0x5a1f, 0x5a99, 0x5b13, + 0x5b8d, 0x5c08, 0x5c82, 0x5cfc, 0x5d76, 0x5df0, 0x5e6a, 0x5ee4, + 0x5f5e, 0x5fd8, 0x6052, 0x60cc, 0x6146, 0x61c0, 0x623a, 0x62b5, + 0x632f, 0x63a9, 0x6423, 0x649d, 0x6517, 0x6591, 0x660b, 0x6685, + 0x66ff, 0x6779, 0x67f3, 0x686d, 0x68e7, 0x6962, 0x69dc, 0x6a56, + 0x6ad0, 0x6b4a, 0x6bc4, 0x6c3e, 0x6cb8, 0x6d32, 0x6dac, 0x6e26, + 0x6ea0, 0x6f1a, 0x6f94, 0x700f, 0x7089, 0x7103, 0x717d, 0x71f7, + 0x7271, 0x72eb, 0x7365, 0x73df, 0x7459, 0x74d3, 0x754d, 0x75c7, + 0x7641, 0x76bc, 0x7736, 0x77b0, 0x782a, 0x78a4, 0x791e, 0x7998 +}; + +const u_int32 tstouslo[128] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, + 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, + 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, + 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79 +}; +#else /* !USE_TSF_USEC_TABLES follows */ +NONEMPTY_TRANSLATION_UNIT +#endif /* !USE_TSF_USEC_TABLES */ +/* -*- EOF -*- */ diff --git a/contrib/ntp/libntp/uglydate.c b/contrib/ntp/libntp/uglydate.c new file mode 100644 index 000000000000..66b5139096b4 --- /dev/null +++ b/contrib/ntp/libntp/uglydate.c @@ -0,0 +1,51 @@ +/* + * uglydate - convert a time stamp to something barely readable + * The string returned is 37 characters long. + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "lib_strbuf.h" +#include "ntp_stdlib.h" + + +char * +uglydate( + l_fp *ts + ) +{ + char *bp; + char *timep; + struct tm *tm; + time_t sec; + long msec; + int year; + + timep = ulfptoa(ts, 6); /* returns max 17 characters */ + LIB_GETBUF(bp); + sec = ts->l_ui - JAN_1970; + msec = ts->l_uf / 4294967; /* fract / (2**32/1000) */ + tm = gmtime(&sec); + if (ts->l_ui == 0) { + /* + * Probably not a real good thing to do. Oh, well. + */ + year = 0; + tm->tm_yday = 0; + tm->tm_hour = 0; + tm->tm_min = 0; + tm->tm_sec = 0; + } else { + year = tm->tm_year; + while (year >= 100) + year -= 100; + } + snprintf(bp, LIB_BUFLENGTH, + "%17s %02d:%03d:%02d:%02d:%02d.%03ld", timep, year, + tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, + msec); + + return bp; +} diff --git a/contrib/ntp/libntp/vint64ops.c b/contrib/ntp/libntp/vint64ops.c new file mode 100644 index 000000000000..5adbebbb51d4 --- /dev/null +++ b/contrib/ntp/libntp/vint64ops.c @@ -0,0 +1,284 @@ +/* + * vint64ops.c - operations on 'vint64' values + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + * ---------------------------------------------------------------------- + * This is an attempt to get the vint64 calculations stuff centralised. + */ + +#include <config.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include "ntp_types.h" +#include "ntp_fp.h" +#include "vint64ops.h" + +/* --------------------------------------------------------------------- + * GCC is rather sticky with its 'const' attribute. We have to do it more + * explicit than with a cast if we want to get rid of a CONST qualifier. + * Greetings from the PASCAL world, where casting was only possible via + * untagged unions... + */ +static inline void* +noconst( + const void* ptr + ) +{ + union { + const void * cp; + void * vp; + } tmp; + tmp.cp = ptr; + return tmp.vp; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +strtouv64( + const char * begp, + char ** endp, + int base + ) +{ + vint64 res; + u_char digit; + int sig, num; + const u_char *src; + + num = sig = 0; + src = (const u_char*)begp; + while (isspace(*src)) + src++; + + if (*src == '-') { + src++; + sig = 1; + } else if (*src == '+') { + src++; + } + + if (base == 0) { + base = 10; + if (*src == '0') { + base = 8; + if (toupper(*++src) == 'X') { + src++; + base = 16; + } + } + } else if (base == 16) { /* remove optional leading '0x' or '0X' */ + if (src[0] == '0' && toupper(src[1]) == 'X') + src += 2; + } else if (base <= 2 || base > 36) { + memset(&res, 0xFF, sizeof(res)); + errno = ERANGE; + return res; + } + + memset(&res, 0, sizeof(res)); + while (*src) { + if (isdigit(*src)) + digit = *src - '0'; + else if (isupper(*src)) + digit = *src - 'A' + 10; + else if (islower(*src)) + digit = *src - 'a' + 10; + else + break; + if (digit >= base) + break; + num = 1; +#if defined(HAVE_INT64) + res.Q_s = res.Q_s * base + digit; +#else + /* res *= base, using 16x16->32 bit + * multiplication. Slow but portable. + */ + { + uint32_t accu; + accu = (uint32_t)res.W_s.ll * base; + res.W_s.ll = (uint16_t)accu; + accu = (accu >> 16) + + (uint32_t)res.W_s.lh * base; + res.W_s.lh = (uint16_t)accu; + /* the upper bits can be done in one step: */ + res.D_s.hi = res.D_s.hi * base + (accu >> 16); + } + M_ADD(res.D_s.hi, res.D_s.lo, 0, digit); +#endif + src++; + } + if (!num) + errno = EINVAL; + if (endp) + *endp = (char*)noconst(src); + if (sig) + M_NEG(res.D_s.hi, res.D_s.lo); + return res; +} + +/* -------------------------------------------------------------------------*/ + +int +icmpv64( + const vint64 * lhs, + const vint64 * rhs + ) +{ + int res; + +#if defined(HAVE_INT64) + res = (lhs->q_s > rhs->q_s) + - (lhs->q_s < rhs->q_s); +#else + res = (lhs->d_s.hi > rhs->d_s.hi) + - (lhs->d_s.hi < rhs->d_s.hi); + if ( ! res ) + res = (lhs->D_s.lo > rhs->D_s.lo) + - (lhs->D_s.lo < rhs->D_s.lo); +#endif + + return res; +} + +/* -------------------------------------------------------------------------*/ + +int +ucmpv64( + const vint64 * lhs, + const vint64 * rhs + ) +{ + int res; + +#if defined(HAVE_INT64) + res = (lhs->Q_s > rhs->Q_s) + - (lhs->Q_s < rhs->Q_s); +#else + res = (lhs->D_s.hi > rhs->D_s.hi) + - (lhs->D_s.hi < rhs->D_s.hi); + if ( ! res ) + res = (lhs->D_s.lo > rhs->D_s.lo) + - (lhs->D_s.lo < rhs->D_s.lo); +#endif + return res; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +addv64( + const vint64 *lhs, + const vint64 *rhs + ) +{ + vint64 res; + +#if defined(HAVE_INT64) + res.Q_s = lhs->Q_s + rhs->Q_s; +#else + res = *lhs; + M_ADD(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo); +#endif + return res; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +subv64( + const vint64 *lhs, + const vint64 *rhs + ) +{ + vint64 res; + +#if defined(HAVE_INT64) + res.Q_s = lhs->Q_s - rhs->Q_s; +#else + res = *lhs; + M_SUB(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo); +#endif + return res; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +addv64i32( + const vint64 * lhs, + int32_t rhs + ) +{ + vint64 res; + + res = *lhs; +#if defined(HAVE_INT64) + res.q_s += rhs; +#else + M_ADD(res.D_s.hi, res.D_s.lo, -(rhs < 0), rhs); +#endif + return res; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +subv64i32( + const vint64 * lhs, + int32_t rhs + ) +{ + vint64 res; + + res = *lhs; +#if defined(HAVE_INT64) + res.q_s -= rhs; +#else + M_SUB(res.D_s.hi, res.D_s.lo, -(rhs < 0), rhs); +#endif + return res; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +addv64u32( + const vint64 * lhs, + uint32_t rhs + ) +{ + vint64 res; + + res = *lhs; +#if defined(HAVE_INT64) + res.Q_s += rhs; +#else + M_ADD(res.D_s.hi, res.D_s.lo, 0, rhs); +#endif + return res; +} + +/* -------------------------------------------------------------------------*/ + +vint64 +subv64u32( + const vint64 * lhs, + uint32_t rhs + ) +{ + vint64 res; + + res = *lhs; +#if defined(HAVE_INT64) + res.Q_s -= rhs; +#else + M_SUB(res.D_s.hi, res.D_s.lo, 0, rhs); +#endif + return res; +} diff --git a/contrib/ntp/libntp/work_fork.c b/contrib/ntp/libntp/work_fork.c new file mode 100644 index 000000000000..8223fdd2f9b2 --- /dev/null +++ b/contrib/ntp/libntp/work_fork.c @@ -0,0 +1,558 @@ +/* + * work_fork.c - fork implementation for blocking worker child. + */ +#include <config.h> +#include "ntp_workimpl.h" + +#ifdef WORK_FORK +#include <stdio.h> +#include <ctype.h> +#include <signal.h> +#include <sys/wait.h> + +#include "iosignal.h" +#include "ntp_stdlib.h" +#include "ntp_malloc.h" +#include "ntp_syslog.h" +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_assert.h" +#include "ntp_unixtime.h" +#include "ntp_worker.h" + +/* === variables === */ + int worker_process; + addremove_io_fd_func addremove_io_fd; +static volatile int worker_sighup_received; + +/* === function prototypes === */ +static void fork_blocking_child(blocking_child *); +static RETSIGTYPE worker_sighup(int); +static void send_worker_home_atexit(void); +static void cleanup_after_child(blocking_child *); + +/* === functions === */ +/* + * exit_worker() + * + * On some systems _exit() is preferred to exit() for forked children. + * For example, http://netbsd.gw.com/cgi-bin/man-cgi?fork++NetBSD-5.0 + * recommends _exit() to avoid double-flushing C runtime stream buffers + * and also to avoid calling the parent's atexit() routines in the + * child. On those systems WORKER_CHILD_EXIT is _exit. Since _exit + * bypasses CRT cleanup, fflush() files we know might have output + * buffered. + */ +void +exit_worker( + int exitcode + ) +{ + if (syslog_file != NULL) + fflush(syslog_file); + fflush(stdout); + fflush(stderr); + WORKER_CHILD_EXIT (exitcode); /* space before ( required */ +} + + +static RETSIGTYPE +worker_sighup( + int sig + ) +{ + if (SIGHUP == sig) + worker_sighup_received = 1; +} + + +int +worker_sleep( + blocking_child * c, + time_t seconds + ) +{ + u_int sleep_remain; + + sleep_remain = (u_int)seconds; + do { + if (!worker_sighup_received) + sleep_remain = sleep(sleep_remain); + if (worker_sighup_received) { + TRACE(1, ("worker SIGHUP with %us left to sleep", + sleep_remain)); + worker_sighup_received = 0; + return -1; + } + } while (sleep_remain); + + return 0; +} + + +void +interrupt_worker_sleep(void) +{ + u_int idx; + blocking_child * c; + int rc; + + for (idx = 0; idx < blocking_children_alloc; idx++) { + c = blocking_children[idx]; + + if (NULL == c || c->reusable == TRUE) + continue; + + rc = kill(c->pid, SIGHUP); + if (rc < 0) + msyslog(LOG_ERR, + "Unable to signal HUP to wake child pid %d: %m", + c->pid); + } +} + + +/* + * harvest_child_status() runs in the parent. + * + * Note the error handling -- this is an interaction with SIGCHLD. + * SIG_IGN on SIGCHLD on some OSes means do not wait but reap + * automatically. Since we're not really interested in the result code, + * we simply ignore the error. + */ +static void +harvest_child_status( + blocking_child * c + ) +{ + if (c->pid) { + /* Wait on the child so it can finish terminating */ + if (waitpid(c->pid, NULL, 0) == c->pid) + TRACE(4, ("harvested child %d\n", c->pid)); + else if (errno != ECHILD) + msyslog(LOG_ERR, "error waiting on child %d: %m", c->pid); + c->pid = 0; + } +} + +/* + * req_child_exit() runs in the parent. + */ +int +req_child_exit( + blocking_child * c + ) +{ + if (-1 != c->req_write_pipe) { + close(c->req_write_pipe); + c->req_write_pipe = -1; + return 0; + } + /* Closing the pipe forces the child to exit */ + harvest_child_status(c); + return -1; +} + + +/* + * cleanup_after_child() runs in parent. + */ +static void +cleanup_after_child( + blocking_child * c + ) +{ + harvest_child_status(c); + if (-1 != c->resp_read_pipe) { + (*addremove_io_fd)(c->resp_read_pipe, c->ispipe, TRUE); + close(c->resp_read_pipe); + c->resp_read_pipe = -1; + } + c->resp_read_ctx = NULL; + DEBUG_INSIST(-1 == c->req_read_pipe); + DEBUG_INSIST(-1 == c->resp_write_pipe); + c->reusable = TRUE; +} + + +static void +send_worker_home_atexit(void) +{ + u_int idx; + blocking_child * c; + + if (worker_process) + return; + + for (idx = 0; idx < blocking_children_alloc; idx++) { + c = blocking_children[idx]; + if (NULL == c) + continue; + req_child_exit(c); + } +} + + +int +send_blocking_req_internal( + blocking_child * c, + blocking_pipe_header * hdr, + void * data + ) +{ + int octets; + int rc; + + DEBUG_REQUIRE(hdr != NULL); + DEBUG_REQUIRE(data != NULL); + DEBUG_REQUIRE(BLOCKING_REQ_MAGIC == hdr->magic_sig); + + if (-1 == c->req_write_pipe) { + fork_blocking_child(c); + DEBUG_INSIST(-1 != c->req_write_pipe); + } + + octets = sizeof(*hdr); + rc = write(c->req_write_pipe, hdr, octets); + + if (rc == octets) { + octets = hdr->octets - sizeof(*hdr); + rc = write(c->req_write_pipe, data, octets); + + if (rc == octets) + return 0; + } + + if (rc < 0) + msyslog(LOG_ERR, + "send_blocking_req_internal: pipe write: %m"); + else + msyslog(LOG_ERR, + "send_blocking_req_internal: short write %d of %d", + rc, octets); + + /* Fatal error. Clean up the child process. */ + req_child_exit(c); + exit(1); /* otherwise would be return -1 */ +} + + +blocking_pipe_header * +receive_blocking_req_internal( + blocking_child * c + ) +{ + blocking_pipe_header hdr; + blocking_pipe_header * req; + int rc; + long octets; + + DEBUG_REQUIRE(-1 != c->req_read_pipe); + + req = NULL; + + do { + rc = read(c->req_read_pipe, &hdr, sizeof(hdr)); + } while (rc < 0 && EINTR == errno); + + if (rc < 0) { + msyslog(LOG_ERR, + "receive_blocking_req_internal: pipe read %m"); + } else if (0 == rc) { + TRACE(4, ("parent closed request pipe, child %d terminating\n", + c->pid)); + } else if (rc != sizeof(hdr)) { + msyslog(LOG_ERR, + "receive_blocking_req_internal: short header read %d of %lu", + rc, (u_long)sizeof(hdr)); + } else { + INSIST(sizeof(hdr) < hdr.octets && hdr.octets < 4 * 1024); + req = emalloc(hdr.octets); + memcpy(req, &hdr, sizeof(*req)); + octets = hdr.octets - sizeof(hdr); + rc = read(c->req_read_pipe, (char *)req + sizeof(*req), + octets); + + if (rc < 0) + msyslog(LOG_ERR, + "receive_blocking_req_internal: pipe data read %m"); + else if (rc != octets) + msyslog(LOG_ERR, + "receive_blocking_req_internal: short read %d of %ld", + rc, octets); + else if (BLOCKING_REQ_MAGIC != req->magic_sig) + msyslog(LOG_ERR, + "receive_blocking_req_internal: packet header mismatch (0x%x)", + req->magic_sig); + else + return req; + } + + if (req != NULL) + free(req); + + return NULL; +} + + +int +send_blocking_resp_internal( + blocking_child * c, + blocking_pipe_header * resp + ) +{ + long octets; + int rc; + + DEBUG_REQUIRE(-1 != c->resp_write_pipe); + + octets = resp->octets; + rc = write(c->resp_write_pipe, resp, octets); + free(resp); + + if (octets == rc) + return 0; + + if (rc < 0) + TRACE(1, ("send_blocking_resp_internal: pipe write %m\n")); + else + TRACE(1, ("send_blocking_resp_internal: short write %d of %ld\n", + rc, octets)); + + return -1; +} + + +blocking_pipe_header * +receive_blocking_resp_internal( + blocking_child * c + ) +{ + blocking_pipe_header hdr; + blocking_pipe_header * resp; + int rc; + long octets; + + DEBUG_REQUIRE(c->resp_read_pipe != -1); + + resp = NULL; + rc = read(c->resp_read_pipe, &hdr, sizeof(hdr)); + + if (rc < 0) { + TRACE(1, ("receive_blocking_resp_internal: pipe read %m\n")); + } else if (0 == rc) { + /* this is the normal child exited indication */ + } else if (rc != sizeof(hdr)) { + TRACE(1, ("receive_blocking_resp_internal: short header read %d of %lu\n", + rc, (u_long)sizeof(hdr))); + } else if (BLOCKING_RESP_MAGIC != hdr.magic_sig) { + TRACE(1, ("receive_blocking_resp_internal: header mismatch (0x%x)\n", + hdr.magic_sig)); + } else { + INSIST(sizeof(hdr) < hdr.octets && + hdr.octets < 16 * 1024); + resp = emalloc(hdr.octets); + memcpy(resp, &hdr, sizeof(*resp)); + octets = hdr.octets - sizeof(hdr); + rc = read(c->resp_read_pipe, + (char *)resp + sizeof(*resp), + octets); + + if (rc < 0) + TRACE(1, ("receive_blocking_resp_internal: pipe data read %m\n")); + else if (rc < octets) + TRACE(1, ("receive_blocking_resp_internal: short read %d of %ld\n", + rc, octets)); + else + return resp; + } + + cleanup_after_child(c); + + if (resp != NULL) + free(resp); + + return NULL; +} + + +#if defined(HAVE_DROPROOT) && defined(WORK_FORK) +void +fork_deferred_worker(void) +{ + u_int idx; + blocking_child * c; + + REQUIRE(droproot && root_dropped); + + for (idx = 0; idx < blocking_children_alloc; idx++) { + c = blocking_children[idx]; + if (NULL == c) + continue; + if (-1 != c->req_write_pipe && 0 == c->pid) + fork_blocking_child(c); + } +} +#endif + + +static void +fork_blocking_child( + blocking_child * c + ) +{ + static int atexit_installed; + static int blocking_pipes[4] = { -1, -1, -1, -1 }; + int rc; + int was_pipe; + int is_pipe; + int saved_errno = 0; + int childpid; + int keep_fd; + int fd; + + /* + * parent and child communicate via a pair of pipes. + * + * 0 child read request + * 1 parent write request + * 2 parent read response + * 3 child write response + */ + if (-1 == c->req_write_pipe) { + rc = pipe_socketpair(&blocking_pipes[0], &was_pipe); + if (0 != rc) { + saved_errno = errno; + } else { + rc = pipe_socketpair(&blocking_pipes[2], &is_pipe); + if (0 != rc) { + saved_errno = errno; + close(blocking_pipes[0]); + close(blocking_pipes[1]); + } else { + INSIST(was_pipe == is_pipe); + } + } + if (0 != rc) { + errno = saved_errno; + msyslog(LOG_ERR, "unable to create worker pipes: %m"); + exit(1); + } + + /* + * Move the descriptors the parent will keep open out of the + * low descriptors preferred by C runtime buffered FILE *. + */ + c->req_write_pipe = move_fd(blocking_pipes[1]); + c->resp_read_pipe = move_fd(blocking_pipes[2]); + /* + * wake any worker child on orderly shutdown of the + * daemon so that it can notice the broken pipes and + * go away promptly. + */ + if (!atexit_installed) { + atexit(&send_worker_home_atexit); + atexit_installed = TRUE; + } + } + +#if defined(HAVE_DROPROOT) && !defined(NEED_EARLY_FORK) + /* defer the fork until after root is dropped */ + if (droproot && !root_dropped) + return; +#endif + if (syslog_file != NULL) + fflush(syslog_file); + fflush(stdout); + fflush(stderr); + + /* [BUG 3050] setting SIGCHLD to SIG_IGN likely causes unwanted + * or undefined effects. We don't do it and leave SIGCHLD alone. + */ + /* signal_no_reset(SIGCHLD, SIG_IGN); */ + + childpid = fork(); + if (-1 == childpid) { + msyslog(LOG_ERR, "unable to fork worker: %m"); + exit(1); + } + + if (childpid) { + /* this is the parent */ + TRACE(1, ("forked worker child (pid %d)\n", childpid)); + c->pid = childpid; + c->ispipe = is_pipe; + + /* close the child's pipe descriptors. */ + close(blocking_pipes[0]); + close(blocking_pipes[3]); + + memset(blocking_pipes, -1, sizeof(blocking_pipes)); + + /* wire into I/O loop */ + (*addremove_io_fd)(c->resp_read_pipe, is_pipe, FALSE); + + return; /* parent returns */ + } + + /* + * The parent gets the child pid as the return value of fork(). + * The child must work for it. + */ + c->pid = getpid(); + worker_process = TRUE; + + /* + * In the child, close all files except stdin, stdout, stderr, + * and the two child ends of the pipes. + */ + DEBUG_INSIST(-1 == c->req_read_pipe); + DEBUG_INSIST(-1 == c->resp_write_pipe); + c->req_read_pipe = blocking_pipes[0]; + c->resp_write_pipe = blocking_pipes[3]; + + kill_asyncio(0); + closelog(); + if (syslog_file != NULL) { + fclose(syslog_file); + syslog_file = NULL; + syslogit = TRUE; + } + keep_fd = max(c->req_read_pipe, c->resp_write_pipe); + for (fd = 3; fd < keep_fd; fd++) + if (fd != c->req_read_pipe && + fd != c->resp_write_pipe) + close(fd); + close_all_beyond(keep_fd); + /* + * We get signals from refclock serial I/O on NetBSD in the + * worker if we do not reset SIGIO's handler to the default. + * It is not conditionalized for NetBSD alone because on + * systems where it is not needed, it is harmless, and that + * allows us to handle unknown others with NetBSD behavior. + * [Bug 1386] + */ +#if defined(USE_SIGIO) + signal_no_reset(SIGIO, SIG_DFL); +#elif defined(USE_SIGPOLL) + signal_no_reset(SIGPOLL, SIG_DFL); +#endif + signal_no_reset(SIGHUP, worker_sighup); + init_logging("ntp_intres", 0, FALSE); + setup_logfile(NULL); + + /* + * And now back to the portable code + */ + exit_worker(blocking_child_common(c)); +} + + +void worker_global_lock(int inOrOut) +{ + (void)inOrOut; +} + +#else /* !WORK_FORK follows */ +char work_fork_nonempty_compilation_unit; +#endif diff --git a/contrib/ntp/libntp/work_thread.c b/contrib/ntp/libntp/work_thread.c new file mode 100644 index 000000000000..82f6064fb359 --- /dev/null +++ b/contrib/ntp/libntp/work_thread.c @@ -0,0 +1,928 @@ +/* + * work_thread.c - threads implementation for blocking worker child. + */ +#include <config.h> +#include "ntp_workimpl.h" + +#ifdef WORK_THREAD + +#include <stdio.h> +#include <ctype.h> +#include <signal.h> +#ifndef SYS_WINNT +#include <pthread.h> +#endif + +#include "ntp_stdlib.h" +#include "ntp_malloc.h" +#include "ntp_syslog.h" +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_assert.h" +#include "ntp_unixtime.h" +#include "timespecops.h" +#include "ntp_worker.h" + +#define CHILD_EXIT_REQ ((blocking_pipe_header *)(intptr_t)-1) +#define CHILD_GONE_RESP CHILD_EXIT_REQ +/* Queue size increments: + * The request queue grows a bit faster than the response queue -- the + * deamon can push requests and pull results faster on avarage than the + * worker can process requests and push results... If this really pays + * off is debatable. + */ +#define WORKITEMS_ALLOC_INC 16 +#define RESPONSES_ALLOC_INC 4 + +/* Fiddle with min/max stack sizes. 64kB minimum seems to work, so we + * set the maximum to 256kB. If the minimum goes below the + * system-defined minimum stack size, we have to adjust accordingly. + */ +#ifndef THREAD_MINSTACKSIZE +# define THREAD_MINSTACKSIZE (64U * 1024) +#endif +#ifndef __sun +#if defined(PTHREAD_STACK_MIN) && THREAD_MINSTACKSIZE < PTHREAD_STACK_MIN +# undef THREAD_MINSTACKSIZE +# define THREAD_MINSTACKSIZE PTHREAD_STACK_MIN +#endif +#endif + +#ifndef THREAD_MAXSTACKSIZE +# define THREAD_MAXSTACKSIZE (256U * 1024) +#endif +#if THREAD_MAXSTACKSIZE < THREAD_MINSTACKSIZE +# undef THREAD_MAXSTACKSIZE +# define THREAD_MAXSTACKSIZE THREAD_MINSTACKSIZE +#endif + + +#ifdef SYS_WINNT + +# define thread_exit(c) _endthreadex(c) +# define tickle_sem(sh) ReleaseSemaphore((sh->shnd), 1, NULL) +u_int WINAPI blocking_thread(void *); +static BOOL same_os_sema(const sem_ref obj, void * osobj); + +#else + +# define thread_exit(c) pthread_exit((void*)(size_t)(c)) +# define tickle_sem sem_post +void * blocking_thread(void *); +static void block_thread_signals(sigset_t *); + +#endif + +#ifdef WORK_PIPE +addremove_io_fd_func addremove_io_fd; +#else +addremove_io_semaphore_func addremove_io_semaphore; +#endif + +static void start_blocking_thread(blocking_child *); +static void start_blocking_thread_internal(blocking_child *); +static void prepare_child_sems(blocking_child *); +static int wait_for_sem(sem_ref, struct timespec *); +static int ensure_workitems_empty_slot(blocking_child *); +static int ensure_workresp_empty_slot(blocking_child *); +static int queue_req_pointer(blocking_child *, blocking_pipe_header *); +static void cleanup_after_child(blocking_child *); + +static sema_type worker_mmutex; +static sem_ref worker_memlock; + +/* -------------------------------------------------------------------- + * locking the global worker state table (and other global stuff) + */ +void +worker_global_lock( + int inOrOut) +{ + if (worker_memlock) { + if (inOrOut) + wait_for_sem(worker_memlock, NULL); + else + tickle_sem(worker_memlock); + } +} + +/* -------------------------------------------------------------------- + * implementation isolation wrapper + */ +void +exit_worker( + int exitcode + ) +{ + thread_exit(exitcode); /* see #define thread_exit */ +} + +/* -------------------------------------------------------------------- + * sleep for a given time or until the wakup semaphore is tickled. + */ +int +worker_sleep( + blocking_child * c, + time_t seconds + ) +{ + struct timespec until; + int rc; + +# ifdef HAVE_CLOCK_GETTIME + if (0 != clock_gettime(CLOCK_REALTIME, &until)) { + msyslog(LOG_ERR, "worker_sleep: clock_gettime() failed: %m"); + return -1; + } +# else + if (0 != getclock(TIMEOFDAY, &until)) { + msyslog(LOG_ERR, "worker_sleep: getclock() failed: %m"); + return -1; + } +# endif + until.tv_sec += seconds; + rc = wait_for_sem(c->wake_scheduled_sleep, &until); + if (0 == rc) + return -1; + if (-1 == rc && ETIMEDOUT == errno) + return 0; + msyslog(LOG_ERR, "worker_sleep: sem_timedwait: %m"); + return -1; +} + + +/* -------------------------------------------------------------------- + * Wake up a worker that takes a nap. + */ +void +interrupt_worker_sleep(void) +{ + u_int idx; + blocking_child * c; + + for (idx = 0; idx < blocking_children_alloc; idx++) { + c = blocking_children[idx]; + if (NULL == c || NULL == c->wake_scheduled_sleep) + continue; + tickle_sem(c->wake_scheduled_sleep); + } +} + +/* -------------------------------------------------------------------- + * Make sure there is an empty slot at the head of the request + * queue. Tell if the queue is currently empty. + */ +static int +ensure_workitems_empty_slot( + blocking_child *c + ) +{ + /* + ** !!! PRECONDITION: caller holds access lock! + ** + ** This simply tries to increase the size of the buffer if it + ** becomes full. The resize operation does *not* maintain the + ** order of requests, but that should be irrelevant since the + ** processing is considered asynchronous anyway. + ** + ** Return if the buffer is currently empty. + */ + + static const size_t each = + sizeof(blocking_children[0]->workitems[0]); + + size_t new_alloc; + size_t slots_used; + size_t sidx; + + slots_used = c->head_workitem - c->tail_workitem; + if (slots_used >= c->workitems_alloc) { + new_alloc = c->workitems_alloc + WORKITEMS_ALLOC_INC; + c->workitems = erealloc(c->workitems, new_alloc * each); + for (sidx = c->workitems_alloc; sidx < new_alloc; ++sidx) + c->workitems[sidx] = NULL; + c->tail_workitem = 0; + c->head_workitem = c->workitems_alloc; + c->workitems_alloc = new_alloc; + } + INSIST(NULL == c->workitems[c->head_workitem % c->workitems_alloc]); + return (0 == slots_used); +} + +/* -------------------------------------------------------------------- + * Make sure there is an empty slot at the head of the response + * queue. Tell if the queue is currently empty. + */ +static int +ensure_workresp_empty_slot( + blocking_child *c + ) +{ + /* + ** !!! PRECONDITION: caller holds access lock! + ** + ** Works like the companion function above. + */ + + static const size_t each = + sizeof(blocking_children[0]->responses[0]); + + size_t new_alloc; + size_t slots_used; + size_t sidx; + + slots_used = c->head_response - c->tail_response; + if (slots_used >= c->responses_alloc) { + new_alloc = c->responses_alloc + RESPONSES_ALLOC_INC; + c->responses = erealloc(c->responses, new_alloc * each); + for (sidx = c->responses_alloc; sidx < new_alloc; ++sidx) + c->responses[sidx] = NULL; + c->tail_response = 0; + c->head_response = c->responses_alloc; + c->responses_alloc = new_alloc; + } + INSIST(NULL == c->responses[c->head_response % c->responses_alloc]); + return (0 == slots_used); +} + + +/* -------------------------------------------------------------------- + * queue_req_pointer() - append a work item or idle exit request to + * blocking_workitems[]. Employ proper locking. + */ +static int +queue_req_pointer( + blocking_child * c, + blocking_pipe_header * hdr + ) +{ + size_t qhead; + + /* >>>> ACCESS LOCKING STARTS >>>> */ + wait_for_sem(c->accesslock, NULL); + ensure_workitems_empty_slot(c); + qhead = c->head_workitem; + c->workitems[qhead % c->workitems_alloc] = hdr; + c->head_workitem = 1 + qhead; + tickle_sem(c->accesslock); + /* <<<< ACCESS LOCKING ENDS <<<< */ + + /* queue consumer wake-up notification */ + tickle_sem(c->workitems_pending); + + return 0; +} + +/* -------------------------------------------------------------------- + * API function to make sure a worker is running, a proper private copy + * of the data is made, the data eneterd into the queue and the worker + * is signalled. + */ +int +send_blocking_req_internal( + blocking_child * c, + blocking_pipe_header * hdr, + void * data + ) +{ + blocking_pipe_header * threadcopy; + size_t payload_octets; + + REQUIRE(hdr != NULL); + REQUIRE(data != NULL); + DEBUG_REQUIRE(BLOCKING_REQ_MAGIC == hdr->magic_sig); + + if (hdr->octets <= sizeof(*hdr)) + return 1; /* failure */ + payload_octets = hdr->octets - sizeof(*hdr); + + if (NULL == c->thread_ref) + start_blocking_thread(c); + threadcopy = emalloc(hdr->octets); + memcpy(threadcopy, hdr, sizeof(*hdr)); + memcpy((char *)threadcopy + sizeof(*hdr), data, payload_octets); + + return queue_req_pointer(c, threadcopy); +} + +/* -------------------------------------------------------------------- + * Wait for the 'incoming queue no longer empty' signal, lock the shared + * structure and dequeue an item. + */ +blocking_pipe_header * +receive_blocking_req_internal( + blocking_child * c + ) +{ + blocking_pipe_header * req; + size_t qhead, qtail; + + req = NULL; + do { + /* wait for tickle from the producer side */ + wait_for_sem(c->workitems_pending, NULL); + + /* >>>> ACCESS LOCKING STARTS >>>> */ + wait_for_sem(c->accesslock, NULL); + qhead = c->head_workitem; + do { + qtail = c->tail_workitem; + if (qhead == qtail) + break; + c->tail_workitem = qtail + 1; + qtail %= c->workitems_alloc; + req = c->workitems[qtail]; + c->workitems[qtail] = NULL; + } while (NULL == req); + tickle_sem(c->accesslock); + /* <<<< ACCESS LOCKING ENDS <<<< */ + + } while (NULL == req); + + INSIST(NULL != req); + if (CHILD_EXIT_REQ == req) { /* idled out */ + send_blocking_resp_internal(c, CHILD_GONE_RESP); + req = NULL; + } + + return req; +} + +/* -------------------------------------------------------------------- + * Push a response into the return queue and eventually tickle the + * receiver. + */ +int +send_blocking_resp_internal( + blocking_child * c, + blocking_pipe_header * resp + ) +{ + size_t qhead; + int empty; + + /* >>>> ACCESS LOCKING STARTS >>>> */ + wait_for_sem(c->accesslock, NULL); + empty = ensure_workresp_empty_slot(c); + qhead = c->head_response; + c->responses[qhead % c->responses_alloc] = resp; + c->head_response = 1 + qhead; + tickle_sem(c->accesslock); + /* <<<< ACCESS LOCKING ENDS <<<< */ + + /* queue consumer wake-up notification */ + if (empty) + { +# ifdef WORK_PIPE + write(c->resp_write_pipe, "", 1); +# else + tickle_sem(c->responses_pending); +# endif + } + return 0; +} + + +#ifndef WORK_PIPE + +/* -------------------------------------------------------------------- + * Check if a (Windows-)hanndle to a semaphore is actually the same we + * are using inside the sema wrapper. + */ +static BOOL +same_os_sema( + const sem_ref obj, + void* osh + ) +{ + return obj && osh && (obj->shnd == (HANDLE)osh); +} + +/* -------------------------------------------------------------------- + * Find the shared context that associates to an OS handle and make sure + * the data is dequeued and processed. + */ +void +handle_blocking_resp_sem( + void * context + ) +{ + blocking_child * c; + u_int idx; + + c = NULL; + for (idx = 0; idx < blocking_children_alloc; idx++) { + c = blocking_children[idx]; + if (c != NULL && + c->thread_ref != NULL && + same_os_sema(c->responses_pending, context)) + break; + } + if (idx < blocking_children_alloc) + process_blocking_resp(c); +} +#endif /* !WORK_PIPE */ + +/* -------------------------------------------------------------------- + * Fetch the next response from the return queue. In case of signalling + * via pipe, make sure the pipe is flushed, too. + */ +blocking_pipe_header * +receive_blocking_resp_internal( + blocking_child * c + ) +{ + blocking_pipe_header * removed; + size_t qhead, qtail, slot; + +#ifdef WORK_PIPE + int rc; + char scratch[32]; + + do + rc = read(c->resp_read_pipe, scratch, sizeof(scratch)); + while (-1 == rc && EINTR == errno); +#endif + + /* >>>> ACCESS LOCKING STARTS >>>> */ + wait_for_sem(c->accesslock, NULL); + qhead = c->head_response; + qtail = c->tail_response; + for (removed = NULL; !removed && (qhead != qtail); ++qtail) { + slot = qtail % c->responses_alloc; + removed = c->responses[slot]; + c->responses[slot] = NULL; + } + c->tail_response = qtail; + tickle_sem(c->accesslock); + /* <<<< ACCESS LOCKING ENDS <<<< */ + + if (NULL != removed) { + DEBUG_ENSURE(CHILD_GONE_RESP == removed || + BLOCKING_RESP_MAGIC == removed->magic_sig); + } + if (CHILD_GONE_RESP == removed) { + cleanup_after_child(c); + removed = NULL; + } + + return removed; +} + +/* -------------------------------------------------------------------- + * Light up a new worker. + */ +static void +start_blocking_thread( + blocking_child * c + ) +{ + + DEBUG_INSIST(!c->reusable); + + prepare_child_sems(c); + start_blocking_thread_internal(c); +} + +/* -------------------------------------------------------------------- + * Create a worker thread. There are several differences between POSIX + * and Windows, of course -- most notably the Windows thread is no + * detached thread, and we keep the handle around until we want to get + * rid of the thread. The notification scheme also differs: Windows + * makes use of semaphores in both directions, POSIX uses a pipe for + * integration with 'select()' or alike. + */ +static void +start_blocking_thread_internal( + blocking_child * c + ) +#ifdef SYS_WINNT +{ + BOOL resumed; + + c->thread_ref = NULL; + (*addremove_io_semaphore)(c->responses_pending->shnd, FALSE); + c->thr_table[0].thnd = + (HANDLE)_beginthreadex( + NULL, + 0, + &blocking_thread, + c, + CREATE_SUSPENDED, + NULL); + + if (NULL == c->thr_table[0].thnd) { + msyslog(LOG_ERR, "start blocking thread failed: %m"); + exit(-1); + } + /* remember the thread priority is only within the process class */ + if (!SetThreadPriority(c->thr_table[0].thnd, + THREAD_PRIORITY_BELOW_NORMAL)) + msyslog(LOG_ERR, "Error lowering blocking thread priority: %m"); + + resumed = ResumeThread(c->thr_table[0].thnd); + DEBUG_INSIST(resumed); + c->thread_ref = &c->thr_table[0]; +} +#else /* pthreads start_blocking_thread_internal() follows */ +{ +# ifdef NEED_PTHREAD_INIT + static int pthread_init_called; +# endif + pthread_attr_t thr_attr; + int rc; + int pipe_ends[2]; /* read then write */ + int is_pipe; + int flags; + size_t ostacksize; + size_t nstacksize; + sigset_t saved_sig_mask; + + c->thread_ref = NULL; + +# ifdef NEED_PTHREAD_INIT + /* + * from lib/isc/unix/app.c: + * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this. + */ + if (!pthread_init_called) { + pthread_init(); + pthread_init_called = TRUE; + } +# endif + + rc = pipe_socketpair(&pipe_ends[0], &is_pipe); + if (0 != rc) { + msyslog(LOG_ERR, "start_blocking_thread: pipe_socketpair() %m"); + exit(1); + } + c->resp_read_pipe = move_fd(pipe_ends[0]); + c->resp_write_pipe = move_fd(pipe_ends[1]); + c->ispipe = is_pipe; + flags = fcntl(c->resp_read_pipe, F_GETFL, 0); + if (-1 == flags) { + msyslog(LOG_ERR, "start_blocking_thread: fcntl(F_GETFL) %m"); + exit(1); + } + rc = fcntl(c->resp_read_pipe, F_SETFL, O_NONBLOCK | flags); + if (-1 == rc) { + msyslog(LOG_ERR, + "start_blocking_thread: fcntl(F_SETFL, O_NONBLOCK) %m"); + exit(1); + } + (*addremove_io_fd)(c->resp_read_pipe, c->ispipe, FALSE); + pthread_attr_init(&thr_attr); + pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED); +#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ + defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) + rc = pthread_attr_getstacksize(&thr_attr, &ostacksize); + if (0 != rc) { + msyslog(LOG_ERR, + "start_blocking_thread: pthread_attr_getstacksize() -> %s", + strerror(rc)); + } else { + if (ostacksize < THREAD_MINSTACKSIZE) + nstacksize = THREAD_MINSTACKSIZE; + else if (ostacksize > THREAD_MAXSTACKSIZE) + nstacksize = THREAD_MAXSTACKSIZE; + else + nstacksize = ostacksize; + if (nstacksize != ostacksize) + rc = pthread_attr_setstacksize(&thr_attr, nstacksize); + if (0 != rc) + msyslog(LOG_ERR, + "start_blocking_thread: pthread_attr_setstacksize(0x%lx -> 0x%lx) -> %s", + (u_long)ostacksize, (u_long)nstacksize, + strerror(rc)); + } +#else + UNUSED_ARG(nstacksize); + UNUSED_ARG(ostacksize); +#endif +#if defined(PTHREAD_SCOPE_SYSTEM) && defined(NEED_PTHREAD_SCOPE_SYSTEM) + pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM); +#endif + c->thread_ref = emalloc_zero(sizeof(*c->thread_ref)); + block_thread_signals(&saved_sig_mask); + rc = pthread_create(&c->thr_table[0], &thr_attr, + &blocking_thread, c); + pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL); + pthread_attr_destroy(&thr_attr); + if (0 != rc) { + msyslog(LOG_ERR, "start_blocking_thread: pthread_create() -> %s", + strerror(rc)); + exit(1); + } + c->thread_ref = &c->thr_table[0]; +} +#endif + +/* -------------------------------------------------------------------- + * block_thread_signals() + * + * Temporarily block signals used by ntpd main thread, so that signal + * mask inherited by child threads leaves them blocked. Returns prior + * active signal mask via pmask, to be restored by the main thread + * after pthread_create(). + */ +#ifndef SYS_WINNT +void +block_thread_signals( + sigset_t * pmask + ) +{ + sigset_t block; + + sigemptyset(&block); +# ifdef HAVE_SIGNALED_IO +# ifdef SIGIO + sigaddset(&block, SIGIO); +# endif +# ifdef SIGPOLL + sigaddset(&block, SIGPOLL); +# endif +# endif /* HAVE_SIGNALED_IO */ + sigaddset(&block, SIGALRM); + sigaddset(&block, MOREDEBUGSIG); + sigaddset(&block, LESSDEBUGSIG); +# ifdef SIGDIE1 + sigaddset(&block, SIGDIE1); +# endif +# ifdef SIGDIE2 + sigaddset(&block, SIGDIE2); +# endif +# ifdef SIGDIE3 + sigaddset(&block, SIGDIE3); +# endif +# ifdef SIGDIE4 + sigaddset(&block, SIGDIE4); +# endif +# ifdef SIGBUS + sigaddset(&block, SIGBUS); +# endif + sigemptyset(pmask); + pthread_sigmask(SIG_BLOCK, &block, pmask); +} +#endif /* !SYS_WINNT */ + + +/* -------------------------------------------------------------------- + * Create & destroy semaphores. This is sufficiently different between + * POSIX and Windows to warrant wrapper functions and close enough to + * use the concept of synchronization via semaphore for all platforms. + */ +static sem_ref +create_sema( + sema_type* semptr, + u_int inival, + u_int maxval) +{ +#ifdef SYS_WINNT + + long svini, svmax; + if (NULL != semptr) { + svini = (inival < LONG_MAX) + ? (long)inival : LONG_MAX; + svmax = (maxval < LONG_MAX && maxval > 0) + ? (long)maxval : LONG_MAX; + semptr->shnd = CreateSemaphore(NULL, svini, svmax, NULL); + if (NULL == semptr->shnd) + semptr = NULL; + } + +#else + + (void)maxval; + if (semptr && sem_init(semptr, FALSE, inival)) + semptr = NULL; + +#endif + + return semptr; +} + +/* ------------------------------------------------------------------ */ +static sem_ref +delete_sema( + sem_ref obj) +{ + +# ifdef SYS_WINNT + + if (obj) { + if (obj->shnd) + CloseHandle(obj->shnd); + obj->shnd = NULL; + } + +# else + + if (obj) + sem_destroy(obj); + +# endif + + return NULL; +} + +/* -------------------------------------------------------------------- + * prepare_child_sems() + * + * create sync & access semaphores + * + * All semaphores are cleared, only the access semaphore has 1 unit. + * Childs wait on 'workitems_pending', then grabs 'sema_access' + * and dequeues jobs. When done, 'sema_access' is given one unit back. + * + * The producer grabs 'sema_access', manages the queue, restores + * 'sema_access' and puts one unit into 'workitems_pending'. + * + * The story goes the same for the response queue. + */ +static void +prepare_child_sems( + blocking_child *c + ) +{ + if (NULL == worker_memlock) + worker_memlock = create_sema(&worker_mmutex, 1, 1); + + c->accesslock = create_sema(&c->sem_table[0], 1, 1); + c->workitems_pending = create_sema(&c->sem_table[1], 0, 0); + c->wake_scheduled_sleep = create_sema(&c->sem_table[2], 0, 1); +# ifndef WORK_PIPE + c->responses_pending = create_sema(&c->sem_table[3], 0, 0); +# endif +} + +/* -------------------------------------------------------------------- + * wait for semaphore. Where the wait can be interrupted, it will + * internally resume -- When this function returns, there is either no + * semaphore at all, a timeout occurred, or the caller could + * successfully take a token from the semaphore. + * + * For untimed wait, not checking the result of this function at all is + * definitely an option. + */ +static int +wait_for_sem( + sem_ref sem, + struct timespec * timeout /* wall-clock */ + ) +#ifdef SYS_WINNT +{ + struct timespec now; + struct timespec delta; + DWORD msec; + DWORD rc; + + if (!(sem && sem->shnd)) { + errno = EINVAL; + return -1; + } + + if (NULL == timeout) { + msec = INFINITE; + } else { + getclock(TIMEOFDAY, &now); + delta = sub_tspec(*timeout, now); + if (delta.tv_sec < 0) { + msec = 0; + } else if ((delta.tv_sec + 1) >= (MAXDWORD / 1000)) { + msec = INFINITE; + } else { + msec = 1000 * (DWORD)delta.tv_sec; + msec += delta.tv_nsec / (1000 * 1000); + } + } + rc = WaitForSingleObject(sem->shnd, msec); + if (WAIT_OBJECT_0 == rc) + return 0; + if (WAIT_TIMEOUT == rc) { + errno = ETIMEDOUT; + return -1; + } + msyslog(LOG_ERR, "WaitForSingleObject unexpected 0x%x", rc); + errno = EFAULT; + return -1; +} +#else /* pthreads wait_for_sem() follows */ +{ + int rc = -1; + + if (sem) do { + if (NULL == timeout) + rc = sem_wait(sem); + else + rc = sem_timedwait(sem, timeout); + } while (rc == -1 && errno == EINTR); + else + errno = EINVAL; + + return rc; +} +#endif + +/* -------------------------------------------------------------------- + * blocking_thread - thread functions have WINAPI (aka 'stdcall') + * calling conventions under Windows and POSIX-defined signature + * otherwise. + */ +#ifdef SYS_WINNT +u_int WINAPI +#else +void * +#endif +blocking_thread( + void * ThreadArg + ) +{ + blocking_child *c; + + c = ThreadArg; + exit_worker(blocking_child_common(c)); + + /* NOTREACHED */ + return 0; +} + +/* -------------------------------------------------------------------- + * req_child_exit() runs in the parent. + * + * This function is called from from the idle timer, too, and possibly + * without a thread being there any longer. Since we have folded up our + * tent in that case and all the semaphores are already gone, we simply + * ignore this request in this case. + * + * Since the existence of the semaphores is controlled exclusively by + * the parent, there's no risk of data race here. + */ +int +req_child_exit( + blocking_child *c + ) +{ + return (c->accesslock) + ? queue_req_pointer(c, CHILD_EXIT_REQ) + : 0; +} + +/* -------------------------------------------------------------------- + * cleanup_after_child() runs in parent. + */ +static void +cleanup_after_child( + blocking_child * c + ) +{ + DEBUG_INSIST(!c->reusable); + +# ifdef SYS_WINNT + /* The thread was not created in detached state, so we better + * clean up. + */ + if (c->thread_ref && c->thread_ref->thnd) { + WaitForSingleObject(c->thread_ref->thnd, INFINITE); + INSIST(CloseHandle(c->thread_ref->thnd)); + c->thread_ref->thnd = NULL; + } +# endif + c->thread_ref = NULL; + + /* remove semaphores and (if signalling vi IO) pipes */ + + c->accesslock = delete_sema(c->accesslock); + c->workitems_pending = delete_sema(c->workitems_pending); + c->wake_scheduled_sleep = delete_sema(c->wake_scheduled_sleep); + +# ifdef WORK_PIPE + DEBUG_INSIST(-1 != c->resp_read_pipe); + DEBUG_INSIST(-1 != c->resp_write_pipe); + (*addremove_io_fd)(c->resp_read_pipe, c->ispipe, TRUE); + close(c->resp_write_pipe); + close(c->resp_read_pipe); + c->resp_write_pipe = -1; + c->resp_read_pipe = -1; +# else + DEBUG_INSIST(NULL != c->responses_pending); + (*addremove_io_semaphore)(c->responses_pending->shnd, TRUE); + c->responses_pending = delete_sema(c->responses_pending); +# endif + + /* Is it necessary to check if there are pending requests and + * responses? If so, and if there are, what to do with them? + */ + + /* re-init buffer index sequencers */ + c->head_workitem = 0; + c->tail_workitem = 0; + c->head_response = 0; + c->tail_response = 0; + + c->reusable = TRUE; +} + + +#else /* !WORK_THREAD follows */ +char work_thread_nonempty_compilation_unit; +#endif diff --git a/contrib/ntp/libntp/ymd2yd.c b/contrib/ntp/libntp/ymd2yd.c new file mode 100644 index 000000000000..c6b3a0cad7dc --- /dev/null +++ b/contrib/ntp/libntp/ymd2yd.c @@ -0,0 +1,26 @@ +/* + * ymd2yd - compute the date in the year from y/m/d + * + * A thin wrapper around a more general calendar function. + */ + +#include <config.h> +#include "ntp_stdlib.h" +#include "ntp_calendar.h" + +int +ymd2yd( + int y, + int m, + int d) +{ + /* + * convert y/m/d to elapsed calendar units, convert that to + * elapsed days since the start of the given year and convert + * back to unity-based day in year. + * + * This does no further error checking, since the underlying + * function is assumed to work out how to handle the data. + */ + return ntpcal_edate_to_yeardays(y-1, m-1, d-1) + 1; +} |