Hi,

THe ntp protocol uses 32-bit unsigned timestamps counting seconds
since 1900. That means that in 2036 the timestamp field will wrap.
This difff makes sure ntpd handles that correctly by assuming we are
in era 0 unless we see "small" timestamps.

tested in the future (incuding wrapping form era 0 to 1) on a couple
of machines including one running xntpd for interoperability.

ok?

        -Otto

Index: client.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/client.c,v
retrieving revision 1.112
diff -u -p -r1.112 client.c
--- client.c    10 Nov 2019 19:24:47 -0000      1.112
+++ client.c    10 Jan 2020 14:06:14 -0000
@@ -324,12 +324,6 @@ client_dispatch(struct ntp_peer *p, u_in
                }
        }
 
-       if (T4 < JAN_1970) {
-               client_log_error(p, "recvmsg control format", EBADF);
-               set_next(p, error_interval());
-               return (0);
-       }
-
        ntp_getmsg((struct sockaddr *)&p->addr->ss, buf, size, &msg);
 
        if (msg.orgtime.int_partl != p->query->msg.xmttime.int_partl ||
@@ -374,16 +368,6 @@ client_dispatch(struct ntp_peer *p, u_in
        T1 = p->query->xmttime;
        T2 = lfp_to_d(msg.rectime);
        T3 = lfp_to_d(msg.xmttime);
-
-       /*
-        * XXX workaround: time_t / tv_sec must never wrap.
-        * around 2020 we will need a solution (64bit time_t / tv_sec).
-        * consider every answer with a timestamp beyond january 2030 bogus.
-        */
-       if (T2 > JAN_2030 || T3 > JAN_2030) {
-               set_next(p, error_interval());
-               return (0);
-       }
 
        /* Detect liars */
        if (!p->trusted && conf->constraint_median != 0 &&
Index: ntp.h
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/ntp.h,v
retrieving revision 1.13
diff -u -p -r1.13 ntp.h
--- ntp.h       22 Apr 2009 07:42:17 -0000      1.13
+++ ntp.h       10 Jan 2020 14:06:14 -0000
@@ -141,7 +141,19 @@ struct ntp_query {
 #define        MODE_RES2       7       /* reserved for private use */
 
 #define        JAN_1970        2208988800UL    /* 1970 - 1900 in seconds */
-#define        JAN_2030        1893456000UL + JAN_1970 /* 1. 1. 2030 00:00:00 
*/
+
+/*
+ * The era we're in if we have no reason to assume otherwise.
+ * If lfp_to_d() sees an offset <= INT32_MAX the era is is assumed to be
+ * NTP_ERA + 1.
+ * Once the actual year is well into era 1, (after 2036) define NTP_ERA to 1
+ * and adapt (remove) the test in lfp_to_d().
+ * Once more than half of era 1 has elapsed (after 2104), re-inroduce the test
+ * to move to era 2 if offset <= INT32_MAX, repeat for each half era.
+ */
+#define NTP_ERA                0
+
+#define SECS_IN_ERA    (UINT32_MAX + 1ULL)
 
 #define        NTP_VERSION     4
 #define        NTP_MAXSTRATUM  15
Index: util.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/util.c,v
retrieving revision 1.24
diff -u -p -r1.24 util.c
--- util.c      1 Mar 2017 00:56:30 -0000       1.24
+++ util.c      10 Jan 2020 14:06:14 -0000
@@ -86,12 +86,17 @@ d_to_tv(double d, struct timeval *tv)
 double
 lfp_to_d(struct l_fixedpt lfp)
 {
-       double  ret;
+       double  base, ret;
 
        lfp.int_partl = ntohl(lfp.int_partl);
        lfp.fractionl = ntohl(lfp.fractionl);
 
-       ret = (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
+       /* see comment in ntp.h */
+       base = NTP_ERA;
+       if (lfp.int_partl <= INT32_MAX)
+               base++; 
+       ret = base * SECS_IN_ERA;
+       ret += (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
 
        return (ret);
 }
@@ -101,6 +106,8 @@ d_to_lfp(double d)
 {
        struct l_fixedpt        lfp;
 
+       while (d > SECS_IN_ERA)
+               d -= SECS_IN_ERA;
        lfp.int_partl = htonl((u_int32_t)d);
        lfp.fractionl = htonl((u_int32_t)((d - (u_int32_t)d) * UINT_MAX));
 


Reply via email to