diff --git a/configure b/configure index cde0e17..e4dab64 100755 --- a/configure +++ b/configure @@ -114,6 +114,8 @@ For better control, use the options below. --disable-linuxcaps Disable Linux capabilities support --disable-asyncdns Disable asynchronous name resolving --disable-forcednsretry Don't retry on permanent DNS error + --with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds + since 1970-01-01 [50*365 days ago] --with-user=USER Specify default chronyd user [root] --with-sendmail=PATH Path to sendmail binary [/usr/lib/sendmail] --enable-debug Enable debugging support @@ -194,6 +196,7 @@ try_setsched=0 try_lockmem=0 feat_asyncdns=1 feat_forcednsretry=1 +ntp_era_split="" default_user="root" mail_program="/usr/lib/sendmail" @@ -275,6 +278,9 @@ do --disable-forcednsretry) feat_forcednsretry=0 ;; + --with-ntp-era=* ) + ntp_era_split=`echo $option | sed -e 's/^.*=//;'` + ;; --with-user=* ) default_user=`echo $option | sed -e 's/^.*=//;'` ;; @@ -381,6 +387,33 @@ if test_code '64-bit time_t' 'time.h' '' '' ' return x[0];' then add_def HAVE_LONG_TIME_T 1 + + if [ "x$ntp_era_split" != "x" ]; then + split_seconds=$ntp_era_split + split_days=0 + else + split_seconds=`date '+%s'` + if [ "x$split_seconds" = "" ]; then + echo "Could not get current time, --with-ntp-era option is needed" + exit 1 + fi + split_days=$((50 * 365)) + fi + + add_def NTP_ERA_SPLIT "(${split_seconds}LL - $split_days * 24 * 3600)" + + date_format='+%Y-%m-%dT%H:%M:%SZ' + + # Print the full NTP interval if a suitable date is found + if [ "x`date -u -d '1970-01-01 UTC 9 days ago 5 seconds 3 seconds' \ + $date_format 2> /dev/null`" = "x1969-12-23T00:00:08Z" ] + then + time1="`date -u -d "1970-01-01 UTC $split_days days ago $split_seconds seconds" \ + $date_format`" + time2="`date -u -d "1970-01-01 UTC $split_days days ago $split_seconds seconds 4294967296 seconds" \ + $date_format`" + echo "NTP time mapped to $time1/$time2" + fi fi MATHCODE='return (int) pow(2.0, log(sqrt((double)argc)));' diff --git a/ntp_core.c b/ntp_core.c index c83f1e8..278b804 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -258,10 +258,35 @@ do_size_checks(void) /* ================================================== */ +static void +do_time_checks(void) +{ +#ifdef HAVE_LONG_TIME_T + /* Check that time before NTP_ERA_SPLIT underflows correctly */ + + struct timeval tv1 = {NTP_ERA_SPLIT, 1}, tv2 = {NTP_ERA_SPLIT - 1, 1}; + NTP_int64 ntv1, ntv2; + int r; + + UTI_TimevalToInt64(&tv1, &ntv1, 0); + UTI_TimevalToInt64(&tv2, &ntv2, 0); + UTI_Int64ToTimeval(&ntv1, &tv1); + UTI_Int64ToTimeval(&ntv2, &tv2); + + r = tv1.tv_sec == NTP_ERA_SPLIT && + tv1.tv_sec + (1ULL << 32) - 1 == tv2.tv_sec; + + assert(r); +#endif +} + +/* ================================================== */ + void NCR_Initialise(void) { do_size_checks(); + do_time_checks(); logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements", " Date (UTC) Time IP Address L St 1234 abc 5678 LP RP Score Offset Peer del. Peer disp. Root del. Root disp.") diff --git a/util.c b/util.c index 35bc12b..e1d314e 100644 --- a/util.c +++ b/util.c @@ -498,16 +498,17 @@ void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, uint32_t fuzz) { - unsigned long usec = src->tv_usec; - unsigned long sec = src->tv_sec; - uint32_t lo; + uint32_t lo, sec, usec; + + sec = (uint32_t)src->tv_sec; + usec = (uint32_t)src->tv_usec; /* Recognize zero as a special case - it always signifies an 'unknown' value */ if (!usec && !sec) { dest->hi = dest->lo = 0; } else { - dest->hi = htonl(src->tv_sec + JAN_1970); + dest->hi = htonl(sec + JAN_1970); /* This formula gives an error of about 0.1us worst case */ lo = 4295 * usec - (usec>>5) - (usec>>9); @@ -525,13 +526,23 @@ void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest) { + uint32_t ntp_sec, ntp_frac; + /* As yet, there is no need to check for zero - all processing that has to detect that case is in the NTP layer */ - dest->tv_sec = ntohl(src->hi) - JAN_1970; + ntp_sec = ntohl(src->hi); + ntp_frac = ntohl(src->lo); + +#ifdef HAVE_LONG_TIME_T + dest->tv_sec = ntp_sec - (uint32_t)(NTP_ERA_SPLIT + JAN_1970) + + (time_t)NTP_ERA_SPLIT; +#else + dest->tv_sec = ntp_sec - JAN_1970; +#endif /* Until I invent a slick way to do this, just do it the obvious way */ - dest->tv_usec = (int)(0.5 + (double)(ntohl(src->lo)) / 4294.967296); + dest->tv_usec = (int)(0.5 + (double)(ntp_frac) / 4294.967296); } /* ================================================== */