Bump NTP era if the offset we receive is small, in a similar manner
authorotto <otto@openbsd.org>
Sun, 12 Nov 2023 18:53:22 +0000 (18:53 +0000)
committerotto <otto@openbsd.org>
Sun, 12 Nov 2023 18:53:22 +0000 (18:53 +0000)
as ntpd.  ok deraadt@

usr.sbin/rdate/ntp.c
usr.sbin/rdate/rdate.8

index 2d3cba4..4aed956 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ntp.c,v 1.36 2020/01/09 19:37:56 tb Exp $     */
+/*     $OpenBSD: ntp.c,v 1.37 2023/11/12 18:53:22 otto Exp $   */
 
 /*
  * Copyright (c) 1996, 1997 by N.M. Maclaren. All rights reserved.
@@ -42,6 +42,7 @@
 #include <limits.h>
 #include <math.h>
 #include <netdb.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #define MILLION_L    1000000l          /* For conversion to/from timeval */
 #define MILLION_D       1.0e6          /* Must be equal to MILLION_L */
 
+/* 
+ * The era we're in if we have no reason to assume otherwise.
+ * If unpack_ntp() sees a small offset 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 (disable) the increments in unpack_ntp().
+ * Once more than half of era 1 has elapsed (after 2104), re-inroduce the test
+ * to move to era 2 if offset is small, repeat for each half era.
+ */
+#define NTP_ERA         0
+
+#define SECS_IN_ERA     (UINT32_MAX + 1ULL)
+
+
 struct ntp_data {
        u_char          status;
        u_char          version;
@@ -392,7 +407,7 @@ retry:
 void
 unpack_ntp(struct ntp_data *data, u_char *packet)
 {
-       int i;
+       int i, era;
        double d;
 
        data->current = current_time(JAN_1970);
@@ -403,14 +418,22 @@ unpack_ntp(struct ntp_data *data, u_char *packet)
        data->stratum = packet[1];
 
        for (i = 0, d = 0.0; i < 8; ++i)
-           d = 256.0*d+packet[NTP_RECEIVE+i];
+               d = 256.0*d+packet[NTP_RECEIVE+i];
 
+       era = NTP_ERA;
+       if (packet[NTP_RECEIVE] <= 127)
+               era++;
        data->receive = d / NTP_SCALE;
+       data->receive += era * SECS_IN_ERA;
 
        for (i = 0, d = 0.0; i < 8; ++i)
-           d = 256.0*d+packet[NTP_TRANSMIT+i];
+               d = 256.0*d+packet[NTP_TRANSMIT+i];
 
+       era = NTP_ERA;
+       if (packet[NTP_TRANSMIT] <= 127)
+               era++;
        data->transmit = d / NTP_SCALE;
+       data->transmit += era * SECS_IN_ERA;
 
        /* See write_packet for why this isn't an endian problem. */
        bcopy((packet + NTP_ORIGINATE), &data->recvck, sizeof(data->recvck));
@@ -449,11 +472,11 @@ void
 create_timeval(double difference, struct timeval *new, struct timeval *adjust)
 {
        struct timeval old;
-       long n;
+       long long n;
 
        /* Start by converting to timeval format. Note that we have to
         * cater for negative, unsigned values. */
-       if ((n = (long) difference) > difference)
+       if ((n = (long long) difference) > difference)
                --n;
        adjust->tv_sec = n;
        adjust->tv_usec = (long) (MILLION_D * (difference-n));
index edd2b2e..5efe6e0 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: rdate.8,v 1.39 2023/01/04 13:00:11 jsg Exp $
+.\"    $OpenBSD: rdate.8,v 1.40 2023/11/12 18:53:22 otto Exp $
 .\"    $NetBSD: rdate.8,v 1.4 1996/04/08 20:55:17 jtc Exp $
 .\"
 .\" Copyright (c) 1994 Christos Zoulas
@@ -24,7 +24,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: January 4 2023 $
+.Dd $Mdocdate: November 12 2023 $
 .Dt RDATE 8
 .Os
 .Sh NAME
@@ -69,7 +69,7 @@ which does not correctly account for leap seconds.
 Use SNTP (RFC 5905) instead of the RFC 868 time protocol.
 This is the default.
 This protocol counts 32 bits of seconds from January 1, 1900
-and will rollover in March 2036.
+and will handle rollover to a new NTP era in February 2036.
 .It Fl o
 Use an RFC 868 TCP protocol server instead of SNTP.
 This protocol is obsolete as it is not capable of representing