[Git][NTPsec/ntpsec][master] 4 commits: Supress warnings on FreeBSD with --disable-droproot

Hal Murray (@hal.murray) gitlab at mg.gitlab.com
Sun Jan 23 03:26:57 UTC 2022



Hal Murray pushed to branch master at NTPsec / ntpsec


Commits:
69d5c379 by Hal Murray at 2022-01-21T03:32:30-08:00
Supress warnings on FreeBSD with --disable-droproot

- - - - -
75a4072f by Hal Murray at 2022-01-21T03:32:30-08:00
Fix tests/option-tester.sh to work without pkg-config

- - - - -
f21e7aa4 by Hal Murray at 2022-01-22T02:24:51-08:00
Fix for #723, Loop in derive_nonce

- - - - -
003a1148 by Hal Murray at 2022-01-22T02:30:04-08:00
Fix #724, NMEA driver doesn't handle GPS WNRO with 2 digit years

- - - - -


7 changed files:

- ntpd/ntp_control.c
- ntpd/ntp_sandbox.c
- − ntpd/ntp_wrapdate.c
- ntpd/refclock_nmea.c
- ntpd/wscript
- tests/option-tester.sh
- wscript


Changes:

=====================================
ntpd/ntp_control.c
=====================================
@@ -2848,7 +2848,7 @@ static uint32_t derive_nonce(
 	)
 {
 	static uint8_t	salt[16];
-	static unsigned long	last_salt_update = 0;
+	static unsigned long	next_salt_update = 0;
 	union d_tag {
 		uint8_t	digest[EVP_MAX_MD_SIZE];
 		uint32_t extract;
@@ -2856,9 +2856,11 @@ static uint32_t derive_nonce(
 	EVP_MD_CTX	*ctx;
 	unsigned int	len;
 
-	while (!last_salt_update || current_time - last_salt_update >= SECSPERHR) {
+	if (current_time >= next_salt_update) {
 		ntp_RAND_bytes(&salt[0], sizeof(salt));
-		last_salt_update = current_time;
+		next_salt_update = current_time+SECSPERHR;
+		if (0) msyslog(LOG_INFO, "derive_nonce: update salt, %lld", \
+			(long long)next_salt_update);
 	}
 
 	ctx = EVP_MD_CTX_create();


=====================================
ntpd/ntp_sandbox.c
=====================================
@@ -35,7 +35,7 @@ static priv_set_t *lowprivs = NULL;
 static priv_set_t *highprivs = NULL;
 #endif /* HAVE_SOLARIS_PRIVS */
 
-#ifdef HAVE_PRIV_NTP_ADJTIME
+#if defined(HAVE_PRIV_NTP_ADJTIME) && defined(ENABLE_DROPROOT)
 #include <sys/types.h>
 #include <sys/sysctl.h>
 static void CheckFreeBSDdroproot(uid_t uid);
@@ -492,7 +492,7 @@ int scmp_sc[] = {
 	return nonroot;
 }
 
-#ifdef HAVE_PRIV_NTP_ADJTIME
+#if defined(HAVE_PRIV_NTP_ADJTIME) && defined(ENABLE_DROPROOT)
 void CheckFreeBSDdroproot(uid_t uid) {
 	/* This checks that mac_ntpd.ko is loaded.
 	 * It defaults to 123 and enabled, aka what we want.


=====================================
ntpd/ntp_wrapdate.c deleted
=====================================
@@ -1,320 +0,0 @@
-/*
- * Calendar-oriented stuff -- perhaps a bit hard to grok.
- *
- * Used for interpreting GPS sentences and resolving wrap issues
- * around 2-digit years.  Formerly part of refclock_nmea.c,
- * dissected out so it can be used by other drivers.
- */
-
-#include "config.h"
-#include "ntp_types.h"
-
-#include "ntp.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_stdlib.h"
-#include "ntp_calendar.h"
-#include "ntp_wrapdate.h"
-#include "timespecops.h"
-
-static int32_t g_gpsMinBase;
-static int32_t g_gpsMinYear;
-
-/*
- * The GPS week time scale starts on Sunday, 1980-01-06. We need the
- * rata die number of this day.
- */
-#ifndef DAY_GPS_STARTS
-#define DAY_GPS_STARTS 722820
-#endif
-
-/*
- * -------------------------------------------------------------------
- * nmea_init - initialise data
- *
- * calculates a few runtime constants that cannot be made compile time
- * constants.
- * -------------------------------------------------------------------
- */
-void
-wrapdate_init(void)
-{
-	struct calendar date;
-
-	/* - calculate min. base value for GPS epoch & century unfolding
-	 * This assumes that the build system was roughly in sync with
-	 * the world, and that really synchronising to a time before the
-	 * program was created would be unsafe or insane. If the build
-	 * date cannot be established, at least use the start of GPS
-	 * (1980-01-06) as minimum, because GPS can surely NOT
-	 * synchronise beyond it's own big bang. We add a little safety
-	 * margin for the fuzziness of the build date, which is in an
-	 * undefined time zone. */
-	if (ntpcal_get_build_date(&date))
-		g_gpsMinBase = ntpcal_date_to_rd(&date) - 2;
-	else
-		g_gpsMinBase = 0;
-
-	if (g_gpsMinBase < DAY_GPS_STARTS)
-		g_gpsMinBase = DAY_GPS_STARTS;
-
-	ntpcal_rd_to_date(&date, g_gpsMinBase);
-	g_gpsMinYear  = date.year;
-	g_gpsMinBase -= DAY_NTP_STARTS;
-}
-
-/*
- * -------------------------------------------------------------------
- *
- * Unfold a time-of-day (seconds since midnight) around the current
- * system time in a manner that guarantees an absolute difference of
- * less than 12hrs.
- *
- * This function is used for NMEA sentences that contain no date
- * information. This requires the system clock to be in +/-12hrs
- * around the true time, or the clock will synchronize the system 1day
- * off if not augmented with a time sources that also provide the
- * necessary date information.
- *
- * The function updates the calendar structure it also uses as
- * input to fetch the time from.
- *
- * returns true on success, false on failure
- * -------------------------------------------------------------------
- */
-bool
-unfold_day(
-	struct calendar * jd,
-	uint32_t		  rec_ui
-	)
-{
-	time64_t	     rec_qw;
-	ntpcal_split rec_ds;
-
-	/*
-	 * basically this is the periodic extension of the receive
-	 * time - 12hrs to the time-of-day with a period of 1 day.
-	 * But we would have to execute this in 64bit arithmetic, and we
-	 * cannot assume we can do this; therefore this is done
-	 * in split representation.
-	 */
-	rec_qw = ntpcal_ntp_to_ntp(rec_ui - SECSPERDAY/2, time(NULL));
-	rec_ds = ntpcal_daysplit(rec_qw);
-	rec_ds.lo = ntpcal_periodic_extend(rec_ds.lo,
-					   ntpcal_date_to_daysec(jd),
-					   SECSPERDAY);
-	rec_ds.hi += ntpcal_daysec_to_date(jd, rec_ds.lo);
-	/* -1 return means calculation overflowed */
-	return (ntpcal_rd_to_date(jd, rec_ds.hi + DAY_NTP_STARTS) >= 0);
-}
-
-/*
- * -------------------------------------------------------------------
- * A 2-digit year is expanded into full year spec around the year found
- * in 'jd->year'. This should be in +79/-19 years around the system time,
- * or the result will be off by 100 years.  The asymmetric behaviour was
- * chosen to enable initial sync for systems that do not have a
- * battery-backup clock and start with a date that is typically years in
- * the past.
- *
- * Since the GPS epoch starts at 1980-01-06, the resulting year will be
- * not be before 1980 in any case.
- *
- * returns true on success, false on failure
- * -------------------------------------------------------------------
- */
-bool
-unfold_century(
-	struct calendar * jd,
-	uint32_t		  rec_ui
-	)
-{
-	struct calendar rec;
-	int32_t		baseyear;
-
-	ntpcal_ntp_to_date(&rec, rec_ui, time(NULL));
-	baseyear = rec.year - 20;
-	if (baseyear < g_gpsMinYear)
-		baseyear = g_gpsMinYear;
-	jd->year = (unsigned short)ntpcal_periodic_extend(baseyear, jd->year,
-						   100);
-
-	return ((baseyear <= jd->year) && (baseyear + 100 > jd->year));
-}
-
-/*
- * -------------------------------------------------------------------
- * A 2-digit year is expanded into a full year spec by correlation with
- * a GPS week number and the current leap second count.
- *
- * The GPS week time scale counts weeks since Sunday, 1980-01-06, modulo
- * 1024 and seconds since start of the week. The GPS time scale is based
- * on international atomic time (TAI), so the leap second difference to
- * UTC is also needed for a proper conversion.
- *
- * A brute-force analysis (that is, test for every date) shows that a
- * wrong assignment of the century can not happen between the years 1900
- * to 2399 when comparing the week signatures for different
- * centuries. (I *think* that will not happen for 400*1024 years, but I
- * have no valid proof. -*-perlinger at ntp.org-*-)
- *
- * This function is bound to work between years 1980 and 2399
- * (inclusive), which should suffice for now ;-)
- *
- * Note: This function needs a full date&time spec on input due to the
- * necessary leap second corrections!
- *
- * returns true on success, false on failure
- * -------------------------------------------------------------------
- */
-bool
-gpsfix_century(
-	struct calendar  * jd,
-	const gps_weektm * wd,
-	unsigned short   * century
-	)
-{
-	int32_t	days;
-	int32_t	doff;
-	unsigned short week;
-	unsigned short year;
-	int     loop;
-
-	/* Get day offset. Assumes that the input time is in range and
-	 * that the leap seconds do not shift more than +/-1 day.
-	 */
-	doff = ntpcal_date_to_daysec(jd) + wd->wt_leap;
-	doff = (doff >= SECSPERDAY) - (doff < 0);
-
-	/*
-	 * Loop over centuries to get a match, starting with the last
-	 * successful one. (Or with the 19th century if the cached value
-	 * is out of range...)
-	 */
-	year = jd->year % 100;
-	for (loop = 5; loop > 0; loop--,(*century)++) {
-		if (*century < 19 || *century >= 24) {
-			*century = 19;
-		}
-		/* Get days and week in GPS epoch */
-		jd->year = year + *century * 100;
-		days = ntpcal_date_to_rd(jd) - DAY_GPS_STARTS + doff;
-		week = (days / 7) % 1024;
-		if (days >= 0 && wd->wt_week == week)
-			return true; /* matched... */
-	}
-
-	jd->year = year;
-	return false; /* match failed... */
-}
-
-/*
- * -------------------------------------------------------------------
- * And now the final exercise: Considering the fact that many (most?)
- * GPS receivers cannot handle a GPS epoch wrap well, we try to
- * compensate for that problem by unwrapping a GPS epoch around the
- * receive stamp. Another exercise in periodic unfolding, of course,
- * but with enough points to take care of.
- *
- * Note: The integral part of 'tofs' is intended to handle small(!)
- * systematic offsets, as -1 for handling $GPZDG, which gives the
- * following second. (sigh...) The absolute value shall be less than a
- * day (86400 seconds).
- * -------------------------------------------------------------------
- */
-l_fp
-eval_gps_time(
-	const char            * clockname,      /* for logging */
-	const struct calendar * gpst,           /* GPS time stamp  */
-	const struct timespec * tofs,           /* GPS frac second & offset */
-	const bool            trusted,          /* do we fully trust dates from this GPS? */
-	short                 *epoch_warp,      /* for logging */
-	const l_fp            * xrecv           /* receive time stamp */
-	)
-{
-
-	l_fp    retv;
-
-	/* components of calculation */
-	int32_t rcv_sec, rcv_day; /* receive ToD and day */
-	int32_t gps_sec, gps_day; /* GPS ToD and day in NTP epoch */
-	int32_t adj_day, weeks;   /* adjusted GPS day and week shift */
-
-	/* some temporaries to shuffle data */
-	time64_t       vi64;
-	ntpcal_split rs64;
-
-	/* evaluate time stamp from receiver. */
-	gps_sec = ntpcal_date_to_daysec(gpst);
-	gps_day = ntpcal_date_to_rd(gpst) - DAY_NTP_STARTS;
-
-	/* merge in fractional offset */
-	retv = tspec_intv_to_lfp(*tofs);
-	gps_sec += lfpsint(retv);
-
-	/* If we fully trust the GPS receiver, just combine days and
-	 * seconds and be done. */
-	if (trusted) {
-		setlfpuint(retv, time64lo(ntpcal_dayjoin(gps_day, gps_sec)));
-		return retv;
-	}
-
-	/* So we do not trust the GPS receiver to deliver a correct date
-	 * due to the GPS epoch changes. We map the date from the
-	 * receiver into the +/-512 week interval around the receive
-	 * time in that case. This would be a tad easier with 64bit
-	 * calculations, but again, we restrict the code to 32bit ops
-	 * when possible. */
-
-	/* - make sure the GPS fractional day is normalised
-	 * Applying the offset value might have put us slightly over the
-	 * edge of the allowed range for seconds-of-day. Doing a full
-	 * division with floor correction is overkill here; a simple
-	 * addition or subtraction step is sufficient. Using WHILE loops
-	 * gives the right result even if the offset exceeds one day,
-	 * which is NOT what it's intended for! */
-	while (gps_sec >= SECSPERDAY) {
-		gps_sec -= SECSPERDAY;
-		gps_day += 1;
-	}
-	while (gps_sec < 0) {
-		gps_sec += SECSPERDAY;
-		gps_day -= 1;
-	}
-
-	/* - get unfold base: day of full recv time - 512 weeks */
-	vi64 = ntpcal_ntp_to_ntp(lfpuint(*xrecv), time(NULL));
-	rs64 = ntpcal_daysplit(vi64);
-	rcv_sec = rs64.lo;
-	rcv_day = rs64.hi - 512 * 7;
-
-	/* - take the fractional days into account
-	 * If the fractional day of the GPS time is smaller than the
-	 * fractional day of the receive time, we shift the base day for
-	 * the unfold by 1. */
-	if (   gps_sec  < rcv_sec
-	       || (gps_sec == rcv_sec && lfpfrac(retv) < lfpfrac(*xrecv)))
-		rcv_day += 1;
-
-	/* - don't warp ahead of GPS invention! */
-	if (rcv_day < g_gpsMinBase)
-		rcv_day = g_gpsMinBase;
-
-	/* - let the magic happen: */
-	adj_day = ntpcal_periodic_extend(rcv_day, gps_day, 1024*7);
-
-	/* - check if we should log a GPS epoch warp */
-	weeks = (adj_day - gps_day) / 7;
-	if (weeks != *epoch_warp) {
-		*epoch_warp = (short)weeks;
-		LOGIF(CLOCKINFO, (LOG_INFO,
-				  "%s Changed GPS epoch warp to %d weeks",
-				  clockname, weeks));
-	}
-
-	/* - build result and be done */
-	setlfpuint(retv, time64lo(ntpcal_dayjoin(adj_day, gps_sec)));
-	return retv;
-}
-
-// end


=====================================
ntpd/refclock_nmea.c
=====================================
@@ -30,8 +30,6 @@
 #include "ntp_io.h"
 #include "ntp_refclock.h"
 #include "ntp_stdlib.h"
-#include "ntp_calendar.h"
-#include "ntp_wrapdate.h"
 #include "timespecops.h"
 
 #ifdef HAVE_PPSAPI
@@ -220,9 +218,8 @@ typedef struct {
 	bool	ppsapi_gate;	/* system is on PPS */
 #endif /* HAVE_PPSAPI */
 	bool	gps_time;	/* use GPS time, not UTC */
-	unsigned short century_cache;	/* cached current century */
 	l_fp	last_reftime;	/* last processed reference stamp */
-	short 	epoch_warp;	/* last epoch warp, for logging */
+	int 	wnro;		/* last epoch warp, for logging */
 	/* tally stats, reset each poll cycle */
 	struct
 	{
@@ -248,18 +245,10 @@ typedef struct {
 	int    cidx;	/* current field index	*/
 } nmea_data;
 
-/*
- * The GPS week time scale starts on Sunday, 1980-01-06. We need the
- * rata die number of this day.
- */
-#ifndef DAY_GPS_STARTS
-#define DAY_GPS_STARTS 722820
-#endif
 
 /*
  * Function prototypes
  */
-static	void	nmea_init	(void);
 static	bool	nmea_start	(int, struct peer *);
 static	void	nmea_shutdown	(struct refclockproc *);
 static	void	nmea_receive	(struct recvbuf *);
@@ -279,12 +268,12 @@ static char *	field_parse	(nmea_data * data, int fn);
 static void	field_wipe	(nmea_data * data, ...);
 static uint8_t	parse_qual	(nmea_data * data, int idx,
 				 char tag, int inv);
-static bool	parse_time	(struct calendar * jd, long * nsec,
-				 nmea_data *, int idx);
-static bool	parse_date	(struct calendar *jd, nmea_data*,
-				 int idx, enum date_fmt fmt);
-static bool	parse_weekdata	(gps_weektm *, nmea_data *,
-				 int weekidx, int timeidx, int leapidx);
+static bool	parse_time	(struct timespec *dt, nmea_data *, int idx);
+static bool	parse_date	(struct timespec *dt, nmea_data*,
+					int idx, enum date_fmt fmt);
+static bool	kludge_day	(struct timespec *dt);
+static bool	fix_WNRO	(struct timespec *dt, int *wnro, \
+					const struct peer *peer);
 
 static void     save_ltc        (struct refclockproc * const, const char * const,
 				 size_t);
@@ -308,24 +297,10 @@ struct refclock refclock_nmea = {
 	nmea_shutdown,		/* shut down driver */
 	nmea_poll,		/* transmit poll message */
 	NMEA_CONTROL,		/* fudge control */
-	nmea_init,		/* initialize driver */
+	NULL,			/* initialize driver */
 	nmea_timer		/* called once per second */
 };
 
-/*
- * -------------------------------------------------------------------
- * nmea_init - initialise data
- *
- * calculates a few runtime constants that cannot be made compile time
- * constants.
- * -------------------------------------------------------------------
- */
-static void
-nmea_init(void)
-{
-    wrapdate_init();
-}
-
 /*
  * -------------------------------------------------------------------
  * nmea_start - open the GPS devices and initialize data for processing
@@ -849,9 +824,7 @@ nmea_receive(
 	double	  rd_fudge;
 
 	/* working stuff */
-	struct calendar date;	/* to keep & convert the time stamp */
-	struct timespec tofs;	/* offset to full-second reftime */
-	gps_weektm      gpsw;	/* week time storage */
+	struct timespec date;	/* to keep & convert the time stamp */
 	/* results of sentence/date/time parsing */
 	uint8_t		sentence;	/* sentence tag */
 	int		checkres;
@@ -860,9 +833,7 @@ nmea_receive(
 	bool		rc_time;
 
 	/* make sure data has defined pristine state */
-	ZERO(tofs);
 	ZERO(date);
-	ZERO(gpsw);
 	sentence = 0;
 	rc_date = false;
 	rc_time = false;
@@ -983,28 +954,27 @@ nmea_receive(
 
 	case NMEA_GPRMC:
 		/* Check quality byte, fetch data & time */
-		rc_time	 = parse_time(&date, &tofs.tv_nsec, &rdata, 1);
+		rc_time	 = parse_time(&date, &rdata, 1);
 		pp->leap = parse_qual(&rdata, 2, 'A', 0);
-		rc_date	 = parse_date(&date, &rdata, 9, DATE_1_DDMMYY)
-			&& unfold_century(&date, lfpuint(rd_timestamp));
+		rc_date	 = parse_date(&date, &rdata, 9, DATE_1_DDMMYY);
 		if (CLK_FLAG4 & pp->sloppyclockflag)
 			field_wipe(&rdata, 3, 4, 5, 6, -1);
 		break;
 
 	case NMEA_GPGGA:
 		/* Check quality byte, fetch time only */
-		rc_time	 = parse_time(&date, &tofs.tv_nsec, &rdata, 1);
+		rc_time	 = parse_time(&date, &rdata, 1);
 		pp->leap = parse_qual(&rdata, 6, '0', 1);
-		rc_date	 = unfold_day(&date, lfpuint(rd_timestamp));
+		rc_date	 = kludge_day(&date);
 		if (CLK_FLAG4 & pp->sloppyclockflag)
 			field_wipe(&rdata, 2, 4, -1);
 		break;
 
 	case NMEA_GPGLL:
 		/* Check quality byte, fetch time only */
-		rc_time	 = parse_time(&date, &tofs.tv_nsec, &rdata, 5);
+		rc_time	 = parse_time(&date, &rdata, 5);
 		pp->leap = parse_qual(&rdata, 6, 'A', 0);
-		rc_date	 = unfold_day(&date, lfpuint(rd_timestamp));
+		rc_date	 = kludge_day(&date);
 		if (CLK_FLAG4 & pp->sloppyclockflag)
 			field_wipe(&rdata, 1, 3, -1);
 		break;
@@ -1012,29 +982,25 @@ nmea_receive(
 	case NMEA_GPZDA:
 		/* No quality.	Assume best, fetch time & full date */
 		pp->leap = LEAP_NOWARNING;
-		rc_time	 = parse_time(&date, &tofs.tv_nsec, &rdata, 1);
+		rc_time	 = parse_time(&date, &rdata, 1);
 		rc_date	 = parse_date(&date, &rdata, 2, DATE_3_DDMMYYYY);
 		break;
 
 	case NMEA_GPZDG:
 		/* Check quality byte, fetch time & full date */
-		rc_time	 = parse_time(&date, &tofs.tv_nsec, &rdata, 1);
+		rc_time	 = parse_time(&date, &rdata, 1);
 		rc_date	 = parse_date(&date, &rdata, 2, DATE_3_DDMMYYYY);
 		pp->leap = parse_qual(&rdata, 4, '0', 1);
-		tofs.tv_sec = -1; /* GPZDG is following second */
+/* May be wrong sign: HGM, 2022-Jan-17 */
+		date.tv_sec = -1; /* GPZDG is following second */
 		break;
 
 	case NMEA_PGRMF:
-		/* get date, time, qualifier and GPS weektime. We need
-		 * date and time-of-day for the century fix, so we read
-		 * them first.
+		/* Ignore week stuff.  Use date and time fields. 
 		 */
-		rc_date  = parse_weekdata(&gpsw, &rdata, 1, 2, 5)
-		        && parse_date(&date, &rdata, 3, DATE_1_DDMMYY);
-		rc_time  = parse_time(&date, &tofs.tv_nsec, &rdata, 4);
+		rc_time  = parse_time(&date, &rdata, 4);
+		rc_date  = parse_date(&date, &rdata, 3, DATE_1_DDMMYY);
 		pp->leap = parse_qual(&rdata, 11, '0', 1);
-		rc_date  = rc_date
-		        && gpsfix_century(&date, &gpsw, &up->century_cache);
 		if (CLK_FLAG4 & pp->sloppyclockflag)
 			field_wipe(&rdata, 6, 8, -1);
 		break;
@@ -1068,10 +1034,9 @@ nmea_receive(
 		return;
 	}
 
-	DPRINT(1, ("%s effective timecode: %04u-%02u-%02u %02d:%02d:%02d\n",
-		   refclock_name(peer),
-		   date.year, date.month, date.monthday,
-		   date.hour, date.minute, date.second));
+	/* FIXME: should use ctime_r */
+	DPRINT(1, ("%s effective timecode: %s",
+		   refclock_name(peer), ctime(&date.tv_sec)));
 
 	/* Check if we must enter GPS time mode; log so if we do */
 	if (!up->gps_time && (sentence == NMEA_GPZDG)) {
@@ -1081,14 +1046,16 @@ nmea_receive(
 		up->gps_time = true;
 	}
 
+	/* Check/fix WNRO */
+	fix_WNRO(&date, &up->wnro, peer);
+	rd_reftime = tspec_stamp_to_lfp(date);
+
 	/*
 	 * Get the reference time stamp from the calendar buffer.
 	 * Process the new sample in the median filter and determine the
 	 * timecode timestamp, but only if the PPS is not in control.
 	 * Discard sentence if reference time did not change.
 	 */
-	rd_reftime = eval_gps_time(refclock_name(peer), &date, &tofs,
-				   (peer->cfg.mode & NMEA_DATETRUST_MASK), &up->epoch_warp, &rd_timestamp);
 	if (up->last_reftime == rd_reftime) {
 		/* Do not touch pp->a_lastcode on purpose! */
 		up->tally.filtered++;
@@ -1552,13 +1519,14 @@ parse_qual(
  * -------------------------------------------------------------------
  * Parse a time stamp in HHMMSS[.sss] format with error checking.
  *
+ * Add result to arg
+ *
  * returns true on success, false on failure
  * -------------------------------------------------------------------
  */
 static bool
 parse_time(
-	struct calendar * jd,	/* result calendar pointer */
-	long		* ns,	/* storage for nsec fraction */
+	struct timespec * dt,	/* result date+time */
 	nmea_data       * rd,
 	int		  idx
 	)
@@ -1590,14 +1558,10 @@ parse_time(
 		return false;
 	}
 
-	jd->hour   = (uint8_t)h;
-	jd->minute = (uint8_t)m;
-	jd->second = (uint8_t)s;
+	dt->tv_sec += h*3600 + m*60 + s;
 	/* if we have a fraction, scale it up to nanoseconds. */
 	if (rc == 4) {
-		*ns = (long)(f * weight[p2 - p1 - 1]);
-	} else {
-		*ns = 0;
+		dt->tv_nsec += (f * weight[p2 - p1 - 1]);
 }
 
 	return true;
@@ -1610,12 +1574,14 @@ parse_time(
  * spec spanning three fields. This function does some extensive error
  * checking to make sure the date string was consistent.
  *
+ * Add result to arg
+ *
  * returns true on success, false on failure
  * -------------------------------------------------------------------
  */
 static bool
 parse_date(
-	struct calendar * jd,	/* result pointer */
+	struct timespec * dt,	/* result pointer */
 	nmea_data       * rd,
 	int		  idx,
 	enum date_fmt	  fmt
@@ -1627,6 +1593,7 @@ parse_date(
 	unsigned int	d;
 	int		p;
 	char  	      * dp;
+	struct tm	tm;
 
 	dp = field_parse(rd, idx);
 	switch (fmt) {
@@ -1638,6 +1605,19 @@ parse_date(
 				   dp));
 			return false;
 		}
+		if (y > 80) {
+			/* We know the time is now > 2000 but
+			 * GPS might be off by n*1024 weeks.
+			 * WNRO: Week Number Roll Over, ~20 years
+			 * Don't break that correction.
+			 *
+			 * GPS time started in 1980
+			 *   anything < 80 is from the next century.
+			 */
+			y += 1900;
+		} else {
+			y += 2000;
+		}
 		break;
 
 	case DATE_3_DDMMYYYY:
@@ -1661,46 +1641,77 @@ parse_date(
 		return false;
 	}
 
-	/* store results */
-	jd->monthday = (uint8_t)d;
-	jd->month    = (uint8_t)m;
-	jd->year     = (unsigned short)y;
+	/* timegm is non-Posix. */
+	ZERO(tm);
+	tm.tm_year = y-1900;
+	tm.tm_mon = m-1;
+	tm.tm_mday = d;
+	dt->tv_sec += timegm(&tm);	/* No error checking */
 
 	return true;
 }
 
-/*
- * -------------------------------------------------------------------
- * Parse GPS week time info from an NMEA sentence. This info contains
- * the GPS week number, the GPS time-of-week and the leap seconds GPS
- * to UTC.
+/* Use system time for missing date field.
+ * Time from GPS is in dt.  We add a day offset.
+ * This assumes the system time is within 12 hours.
+ * Note the 2 interesting cases:
+ *   If GPS time is late in the day and we are early in the day
+ *   we are actually early in the following day.
+ *   If GPS time is early in the day and we are late in the day
+ *   we are actually late in the previous day.
+ *
+ * This code hasn't been tested yet.
  *
- * returns true on success, false on failure
- * -------------------------------------------------------------------
  */
-static bool
-parse_weekdata(
-	gps_weektm * wd,
-	nmea_data  * rd,
-	int          weekidx,
-	int          timeidx,
-	int          leapidx
-	)
-{
-	unsigned long secs;
-	int    fcnt;
-
-	/* parse fields and count success */
-	fcnt  = sscanf(field_parse(rd, weekidx), "%hu", &wd->wt_week);
-	fcnt += sscanf(field_parse(rd, timeidx), "%lu", &secs);
-	fcnt += sscanf(field_parse(rd, leapidx), "%hd", &wd->wt_leap);
-	if (fcnt != 3 || wd->wt_week >= 1024 || secs >= 7*SECSPERDAY) {
-		DPRINT(1, ("nmea: parse_weekdata: invalid weektime spec\n"));
-		return false;
-	}
-	wd->wt_time = (uint32_t)secs;
-
-	return true;
+static bool kludge_day (struct timespec *dt) {
+  struct timespec now;
+
+/* FIXME: check if clock is valid. */
+
+  clock_gettime(CLOCK_REALTIME, &now);
+  int nowday = now.tv_sec / 86400;
+  int nowsec = now.tv_sec % 86400;
+  int gpssec = (int)dt->tv_sec;
+  if ((gpssec-nowsec) > 12*3600) nowday -= 1;
+  if ((nowsec-gpssec) > 12*3600) nowday += 1;
+  dt->tv_sec += nowday*86400;
+  return true;
 }
 
+/* FIXME move this to a better place */
+/* Get this from date +%s */
+#define GPS_PIVOT 1642417438
+
+/* Early GPS has a 10 bit week number field.
+ * That's a bit less than 20 years.
+ * GPS started in 1980.  We have now wrapped twice: Aug 1999 and Apr 2019.
+ * https://en.wikipedia.org/wiki/GPS_week_number_rollover
+ *
+ * Some firmware fixes the date to be at least the firmware build date.
+ * That gives valid time for 20 years from the build date.
+ * It also means that old GPS units can break at any time,
+ *   not just on 1024 week boundaries.
+ *
+ * This code wraps based on our build date.
+ * But using a build date would break repeatable builds.
+ * So we use a pivot date that gets updated at release time.
+ * So our code should work for 1024 weeks from the release date.
+ *
+ * Modern GPS satellites have added 3 more bits.
+ * Old firmware doesn't know about them.
+ */
+
+static bool fix_WNRO (struct timespec *dt, int *wnro, const struct peer *peer) {
+  int i;
+  for (i=0; dt->tv_sec < GPS_PIVOT; i++) {
+    dt->tv_sec += 1024*7*86400;
+  }
+  if (*wnro != i) {
+    *wnro = i;
+    msyslog(LOG_INFO, "REFCLOCK: %s date advanced by %d weeks, WNRO", \
+      refclock_name(peer), *wnro*1024);
+  }
+  return true;
+};
+
 // end


=====================================
ntpd/wscript
=====================================
@@ -81,7 +81,6 @@ def build(ctx):
     if ctx.env.REFCLOCK_ENABLE:
 
         refclock_source = ["ntp_refclock.c",
-			   "ntp_wrapdate.c",
                            "refclock_conf.c"
                            ]
 


=====================================
tests/option-tester.sh
=====================================
@@ -16,8 +16,13 @@ then
 fi
 
 PURGE=""
-SECCOMP="$(pkg-config libseccomp --variable=includedir)"
-SECCOMP="$SECCOMP/seccomp.h"
+if which pkg-config
+then
+  SECCOMP="$(pkg-config libseccomp --variable=includedir)"
+  SECCOMP="$SECCOMP/seccomp.h"
+else
+  SECCOMP=""
+fi
 LINUX=""
 if [ `uname -s` = "Linux" -a -n "$SECCOMP" -a -f "$SECCOMPH" ]
 then
@@ -38,7 +43,7 @@ then
     DISABLE_NTS="--disable-nts"
   fi
 else
-  if ! $PYTHON ../wafhelpers/tlscheck.py
+  if ! $PYTHON ./wafhelpers/tlscheck.py
   then
     DISABLE_NTS="--disable-nts"
   fi


=====================================
wscript
=====================================
@@ -641,6 +641,7 @@ int main(int argc, char **argv) {
         ('res_init', ["netinet/in.h", "arpa/nameser.h", "resolv.h"]),
         ('strlcpy', ["string.h"]),
         ('strlcat', ["string.h"]),
+        ('timegm', ["time.h"]),
         # Hack.  It's not a function, but this works.
         ('PRIV_NTP_ADJTIME', ["sys/priv.h"])            # FreeBSD
     )
@@ -755,6 +756,12 @@ int main(int argc, char **argv) {
     if ctx.options.refclocks:
         from wafhelpers.refclock import refclock_config
         refclock_config(ctx)
+        # timegm needed by refclock_nmea, it's not in POSIX
+        # It's in Linux, FreeBSD, and NetBSD
+        if not ctx.get_define("HAVE_TIMEGM") and ctx.get_define("CLOCK_NMEA"):
+            ctx.fatal("Refclock NMEA needs timegm")
+            # We should provide an implementation.
+            # Like we do for BSD string functions.
 
     # NetBSD (used to) need to recreate sockets on changed routing.
     # Perhaps it still does. If so, this should be set.  The autoconf



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/ab11c6446b724f3dd71138c688ccc7e14bb21662...003a1148ede6a4ac5deaf2507ecfd3b40b07731a

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/ab11c6446b724f3dd71138c688ccc7e14bb21662...003a1148ede6a4ac5deaf2507ecfd3b40b07731a
You're receiving this email because of your account on gitlab.com.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20220123/57925145/attachment-0001.htm>


More information about the vc mailing list