On Fri, Jan 10, 2020 at 03:14:42PM +0100, Otto Moerbeek wrote:

> 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?

ping...

        -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