[Git][NTPsec/ntpsec][master] Allow refclock sample processing to use 4-digit year timestamps.
Eric S. Raymond
gitlab at mg.gitlab.com
Wed Aug 30 14:02:20 UTC 2017
Eric S. Raymond pushed to branch master at NTPsec / ntpsec
Commits:
472eecff by Eric S. Raymond at 2017-08-30T10:02:08-04:00
Allow refclock sample processing to use 4-digit year timestamps.
This is actually a pretty big deal. Before this change the refclock sample
processing simply ignored the year part of timestamps passed in from, e.g.,
GPS devices. As a defensive adaptation to devices that shipped only 2 digit
timestamps this made sense - the century was, in effect, deduced from the
receive timestamp of the sample.
But this meant that interpretation of the sample was contingent on the
system clock being correct, and bad things could happen if it was
trashed or (especially) zeroed, returning it to 1970. After that you
couldn't use a refclock reliably until you'd already achieved time
sync with a network peer.
With this change, an ntpd receiving proper 4-digit timestamps (e.g. from
the NMEA driver) no longer needs the system clock to be correct, and can
run without remote peers. Recovery from a trashed system clock can happen.
A unit test verifying this capability is included in the patch.
- - - - -
5 changed files:
- include/ntp_stdlib.h
- libntp/clocktime.c
- ntpd/ntp_refclock.c
- ntpd/refclock_truetime.c
- tests/libntp/clocktime.c
Changes:
=====================================
include/ntp_stdlib.h
=====================================
--- a/include/ntp_stdlib.h
+++ b/include/ntp_stdlib.h
@@ -48,7 +48,7 @@ extern bool authreadkeys (const char *);
extern void authtrust (keyid_t, bool);
extern bool authusekey (keyid_t, int, const uint8_t *);
-extern int clocktime (int, int, int, int, int, uint32_t, uint32_t *, uint32_t *);
+extern int clocktime (int, int, int, int, int, int, uint32_t, uint32_t *, uint32_t *);
extern void init_auth (void);
extern void init_network (void);
extern void auth_prealloc_symkeys(int);
=====================================
libntp/clocktime.c
=====================================
--- a/libntp/clocktime.c
+++ b/libntp/clocktime.c
@@ -31,9 +31,13 @@ static int32_t ntp_to_year(uint32_t);
static uint32_t year_to_ntp(int32_t);
/*
- * Take a time spec given as day-of-year, hour, minute and second as
+ * Take a time spec given as year, 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
+ * '*ts_ui'. There are two cases: ether the year is > 99, in which
+ * case it is used, or it is < 99 in which case we ignore it and try
+ * to deduce a year,
+ *
+ * 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'.
*
@@ -49,13 +53,14 @@ static uint32_t year_to_ntp(int32_t);
*/
int
clocktime(
+ int year , /* year */
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 */
uint32_t rec_ui , /* pivot value */
- uint32_t *yearstart, /* cached start-of-year */
+ uint32_t *yearstart, /* cached start-of-year, secs from NTP epoch */
uint32_t *ts_ui ) /* effective time stamp */
{
uint32_t ystt[3]; /* year start */
@@ -72,6 +77,19 @@ clocktime(
MINSPERHR * ((int32_t)hour + (int32_t)tzoff +
HRSPERDAY * ((int32_t)yday - 1))));
/*
+ * Year > 1970 - from a 4-digit year stamp, must be greater
+ * than POSIX epoch. Means we're not dependent on the pivot
+ * value (derived from the packet receipt timestamp, and thus
+ * ultimately from the system clock) to be correct. These
+ * two lines thus make it possible to recover from a trashed
+ * or zeroed system clock.
+ */
+ if (year > 1970)
+ *yearstart = year_to_ntp(year);
+
+ /*
+ * Year was too small to make sense, probably from a 2-digit
+ * year stamp.
* 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
=====================================
ntpd/ntp_refclock.c
=====================================
--- a/ntpd/ntp_refclock.c
+++ b/ntpd/ntp_refclock.c
@@ -409,7 +409,7 @@ refclock_process_f(
* filesystem time for the years and does not use the years of
* the timecode.
*/
- if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
+ if (!clocktime(pp->year, pp->day, pp->hour, pp->minute, pp->second, GMT,
lfpuint(pp->lastrec), &pp->yearstart, &sec))
return false;
=====================================
ntpd/refclock_truetime.c
=====================================
--- a/ntpd/refclock_truetime.c
+++ b/ntpd/refclock_truetime.c
@@ -491,7 +491,7 @@ true_receive(
* find out what time it really is. Include
* the count from the PCL720
*/
- if (!clocktime(pp->day, pp->hour, pp->minute,
+ if (!clocktime(pp->year, pp->day, pp->hour, pp->minute,
pp->second, GMT, lfpuint(pp->lastrec),
&pp->yearstart, &sec)) {
refclock_report(peer, CEVNT_BADTIME);
=====================================
tests/libntp/clocktime.c
=====================================
--- a/tests/libntp/clocktime.c
+++ b/tests/libntp/clocktime.c
@@ -29,18 +29,35 @@ TEST_TEAR_DOWN(clocktime) {
// test cases
TEST(clocktime, CurrentYear) {
- // Timestamp: 2010-06-24 12:50:00Z
+ // Timestamp: 2010-06-24 12:50:00Z, no year passed in
const uint32_t timestamp = 3486372600UL;
const uint32_t expected = timestamp; // exactly the same.
- const int yday=175, hour=12, minute=50, second=0, tzoff=0;
+ const int year=0, yday=175, hour=12, minute=50, second=0, tzoff=0;
uint32_t yearstart=0;
uint32_t actual;
- TEST_ASSERT_TRUE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
TEST_ASSERT_EQUAL(expected, actual);
+ TEST_ASSERT_EQUAL(yearstart, 3471292800);
+}
+
+TEST(clocktime, CurrentYearExplicit) {
+ // Timestamp: 2010-06-24 12:50:00Z, explicit year passed in
+ const uint32_t timestamp = 3486372600UL;
+ const uint32_t expected = timestamp; // exactly the same.
+
+ const int year=2010, yday=175, hour=12, minute=50, second=0, tzoff=0;
+
+ uint32_t yearstart=0;
+ uint32_t actual;
+
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
+ TEST_ASSERT_EQUAL(expected, actual);
+ TEST_ASSERT_EQUAL(yearstart, 3471292800);
}
TEST(clocktime, CurrentYearFuzz) {
@@ -55,13 +72,13 @@ TEST(clocktime, CurrentYearFuzz) {
const uint32_t timestamp = 3486372600UL; // 2010-06-24 12:50:00Z
const uint32_t expected = 3486369600UL; // 2010-06-24 12:00:00Z
- const int yday=175, hour=12, minute=0, second=0, tzoff=0;
+ const int year=0, yday=175, hour=12, minute=0, second=0, tzoff=0;
uint32_t yearstart=0;
uint32_t actual;
- TEST_ASSERT_TRUE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
TEST_ASSERT_EQUAL(expected, actual);
}
@@ -75,13 +92,13 @@ TEST(clocktime, TimeZoneOffset) {
const uint32_t timestamp = 3486369600UL;
const uint32_t expected = timestamp;
- const int yday=175, hour=4, minute=0, second=0, tzoff=8;
+ const int year=0, yday=175, hour=4, minute=0, second=0, tzoff=8;
uint32_t yearstart=0;
uint32_t actual;
- TEST_ASSERT_TRUE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
TEST_ASSERT_EQUAL(expected, actual);
}
@@ -94,13 +111,13 @@ TEST(clocktime, WrongYearStart) {
const uint32_t timestamp = 3471418800UL;
const uint32_t expected = timestamp;
- const int yday=2, hour=11, minute=0, second=0, tzoff=0;
+ const int year=0, yday=2, hour=11, minute=0, second=0, tzoff=0;
uint32_t yearstart = 302024100UL; // Yearstart of 2009.
uint32_t actual;
- TEST_ASSERT_TRUE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
TEST_ASSERT_EQUAL(expected, actual);
}
@@ -113,13 +130,13 @@ TEST(clocktime, PreviousYear) {
const uint32_t timestamp = 3471296400UL;
const uint32_t expected = 3471289200UL;
- const int yday=365, hour=23, minute=0, second=0, tzoff=0;
+ const int year=0, yday=365, hour=23, minute=0, second=0, tzoff=0;
uint32_t yearstart = 0;
uint32_t actual;
- TEST_ASSERT_TRUE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
TEST_ASSERT_EQUAL(expected, actual);
}
@@ -132,12 +149,12 @@ TEST(clocktime, NextYear) {
const uint32_t timestamp = 3471289200UL;
const uint32_t expected = 3471296400UL;
- const int yday=1, hour=1, minute=0, second=0, tzoff=0;
+ const int year=0, yday=1, hour=1, minute=0, second=0, tzoff=0;
uint32_t yearstart = 0;
uint32_t actual;
- TEST_ASSERT_TRUE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_TRUE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
TEST_ASSERT_EQUAL(expected, actual);
}
@@ -145,12 +162,12 @@ TEST(clocktime, NoReasonableConversion) {
/* Timestamp is: 2010-01-02 11:00:00Z */
const uint32_t timestamp = 3471418800UL;
- const int yday=100, hour=12, minute=0, second=0, tzoff=0;
+ const int year=0, yday=100, hour=12, minute=0, second=0, tzoff=0;
uint32_t yearstart = 0;
uint32_t actual;
- TEST_ASSERT_FALSE(clocktime(yday, hour, minute, second, tzoff, timestamp,
- &yearstart, &actual));
+ TEST_ASSERT_FALSE(clocktime(year, yday, hour, minute, second,
+ tzoff, timestamp, &yearstart, &actual));
}
TEST(clocktime, AlwaysInLimit) {
@@ -175,7 +192,7 @@ TEST(clocktime, AlwaysInLimit) {
ydayinc = prime_incs[whichprime];
for (hour = -204; hour < 204; hour += 2) {
for (minute = -60; minute < 60; minute++) {
- clocktime(yday, hour, minute, 30, 0,
+ clocktime(0, yday, hour, minute, 30, 0,
timestamp, &yearstart, &actual);
diff = actual - timestamp;
if (diff >= 0x80000000UL) {
@@ -190,6 +207,7 @@ TEST(clocktime, AlwaysInLimit) {
TEST_GROUP_RUNNER(clocktime) {
RUN_TEST_CASE(clocktime, CurrentYear);
+ RUN_TEST_CASE(clocktime, CurrentYearExplicit);
RUN_TEST_CASE(clocktime, CurrentYearFuzz);
RUN_TEST_CASE(clocktime, TimeZoneOffset);
RUN_TEST_CASE(clocktime, WrongYearStart);
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/472eecff48f9d203d785667bf39995b4f4f51bf1
---
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/472eecff48f9d203d785667bf39995b4f4f51bf1
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/20170830/a70b705f/attachment.html>
More information about the vc
mailing list