]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Always send timevals in cmdmon protocol in 64-bit format
authorMiroslav Lichvar <mlichvar@redhat.com>
Fri, 9 Oct 2009 13:31:59 +0000 (15:31 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 13 Oct 2009 14:15:23 +0000 (16:15 +0200)
This is to avoid incompatibility between 64/32-bit client/server.
While at it, convert all time values in the protocol to timeval
to avoid Y2K38 problem.

candm.h
client.c
cmdmon.c
manual.c
reports.h
rtc_linux.c
util.c
util.h

diff --git a/candm.h b/candm.h
index 52f58d3bda4d756e9ce1faa96f24883d3fc61c5e..0abda603abaf3cf48b22f9434ae11b62190de70f 100644 (file)
--- a/candm.h
+++ b/candm.h
    password.  (This time value has long since gone by) */
 #define SPECIAL_UTOKEN 0x10101010
 
+/* Structure used to exchange timevals independent on size of time_t */
+typedef struct {
+  uint32_t tv_sec_high;
+  uint32_t tv_sec_low;
+  uint32_t tv_usec;
+} Timeval;
+
+/* This is used in tv_sec_high for 32-bit timestamps */
+#define TV_NOHIGHSEC 0x7fffffff
+
 /* The EOR (end of record) fields are used by the offsetof operator in
    pktlength.c, to get the number of bytes that ought to be
    transmitted for each packet type. */
@@ -151,12 +161,12 @@ typedef struct {
 } REQ_Modify_Maxupdateskew;
 
 typedef struct {
-  struct timeval ts;
+  Timeval ts;
   int32_t EOR;
 } REQ_Logon;
 
 typedef struct {
-  struct timeval ts;
+  Timeval ts;
   int32_t EOR;
 } REQ_Settime;
 
@@ -311,7 +321,7 @@ typedef struct {
 
    Version 3 : NTP_Source message lengthened (auto_offline)
 
-   Version 4 : IPv6 addressing added
+   Version 4 : IPv6 addressing added, 64-bit time values
 
  */
 
@@ -463,8 +473,7 @@ typedef struct {
 typedef struct {
   uint32_t ref_id;
   uint32_t stratum;
-  uint32_t ref_time_s;
-  uint32_t ref_time_us;
+  Timeval ref_time;
   uint32_t current_correction_s;
   uint32_t current_correction_us;
   int32_t freq_ppm;
@@ -487,7 +496,7 @@ typedef struct {
 } RPY_Sourcestats;
 
 typedef struct {
-  uint32_t ref_time;
+  Timeval ref_time;
   uint16_t n_samples;
   uint16_t n_runs;
   uint32_t span_seconds;
@@ -540,7 +549,7 @@ typedef struct {
 #define MAX_MANUAL_LIST_SAMPLES 32
 
 typedef struct {
-  uint32_t when;
+  Timeval when;
   int32_t slewed_offset;
   int32_t orig_offset;
   int32_t residual;
index de074e11e5fca4b505d3c116fc3073d721eb13ed..4059fe3f7251e6c0f2f005ed8cd185b27074cdcf 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1030,6 +1030,7 @@ process_cmd_password(CMD_Request *msg, char *line)
   char *p, *q;
   char *password;
   struct timezone tz;
+  struct timeval now;
 
   p = line;
   while (*p && isspace((unsigned char)*p))
@@ -1062,13 +1063,12 @@ process_cmd_password(CMD_Request *msg, char *line)
     *p = 0;
   }
     
-  if (gettimeofday(&msg->data.logon.ts, &tz) < 0) {
+  if (gettimeofday(&now, &tz) < 0) {
     printf("500 - Could not read time of day\n");
     return 0;
   } else {
     msg->command = htons(REQ_LOGON); /* Just force a round trip so that we get tokens etc */
-    msg->data.logon.ts.tv_sec = htonl(msg->data.logon.ts.tv_sec);
-    msg->data.logon.ts.tv_usec = htonl(msg->data.logon.ts.tv_usec);
+    UTI_TimevalHostToNetwork(&now, &msg->data.logon.ts);
     return 1;
   }
 }
@@ -1713,8 +1713,7 @@ process_cmd_tracking(char *line)
            a, b, c, d, "");
            //* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */
     printf("Stratum         : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum));
-    ref_time.tv_sec = ntohl(reply.data.tracking.ref_time_s);
-    ref_time.tv_usec = ntohl(reply.data.tracking.ref_time_us);
+    UTI_TimevalNetworkToHost(&reply.data.tracking.ref_time, &ref_time);
     ref_time_tm = *gmtime((time_t *)&ref_time.tv_sec);
     printf("Ref time (UTC)  : %s", asctime(&ref_time_tm));
     correction_tv.tv_sec = (int32_t)ntohl(reply.data.tracking.current_correction_s);
@@ -1746,7 +1745,7 @@ process_cmd_rtcreport(char *line)
   int auth_ok;
   CMD_Request request;
   CMD_Reply reply;
-  time_t ref_time;
+  struct timeval ref_time;
   struct tm ref_time_tm;
   unsigned short n_samples;
   unsigned short n_runs;
@@ -1775,8 +1774,8 @@ process_cmd_rtcreport(char *line)
       default:
         break;
     }
-    ref_time = (time_t) ntohl(reply.data.rtc.ref_time);
-    ref_time_tm = *gmtime(&ref_time);
+    UTI_TimevalNetworkToHost(&reply.data.rtc.ref_time, &ref_time);
+    ref_time_tm = *gmtime(&ref_time.tv_sec);
     n_samples = ntohs(reply.data.rtc.n_samples);
     n_runs = ntohs(reply.data.rtc.n_runs);
     span_seconds = ntohl(reply.data.rtc.span_seconds);
@@ -2170,7 +2169,7 @@ process_cmd_manual_list(const char *line)
   int n_samples;
   RPY_ManualListSample *sample;
   int i;
-  time_t when;
+  struct timeval when;
   double slewed_offset, orig_offset, residual;
 
   request.command = htons(REQ_MANUAL_LIST);
@@ -2186,11 +2185,11 @@ process_cmd_manual_list(const char *line)
                  "====================================================\n");
           for (i=0; i<n_samples; i++) {
             sample = &reply.data.manual_list.samples[i];
-            when = ntohl(sample->when);
+            UTI_TimevalNetworkToHost(&sample->when, &when);
             slewed_offset = WIRE2REAL(sample->slewed_offset);
             orig_offset = WIRE2REAL(sample->orig_offset);
             residual = WIRE2REAL(sample->residual);
-            printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when), slewed_offset, orig_offset, residual);
+            printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when.tv_sec), slewed_offset, orig_offset, residual);
           }
           break;
         case STT_NOHOSTACCESS:
@@ -2251,6 +2250,7 @@ process_cmd_manual_delete(const char *line)
 static void
 process_cmd_settime(char *line)
 {
+  struct timeval ts;
   time_t now, new_time;
   CMD_Request request;
   CMD_Reply reply;
@@ -2266,8 +2266,9 @@ process_cmd_settime(char *line)
   if (new_time == -1) {
     printf("510 - Could not parse date string\n");
   } else {
-    request.data.settime.ts.tv_sec = htonl(new_time);
-    request.data.settime.ts.tv_usec = htonl(0);
+    ts.tv_sec = new_time;
+    ts.tv_usec = 0;
+    UTI_TimevalHostToNetwork(&ts, &request.data.settime.ts);
     request.command = htons(REQ_SETTIME);
     submit_ok = submit_request(&request, &reply, &reply_auth_ok);
     if (submit_ok) {
index 04087551bf7bda2f7be502fd855505258b74f621..ca8025546aed3c7b717f4dbaae076e92f0556abd 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -535,22 +535,17 @@ check_unique_ts(struct timeval *ts, struct timeval *now)
 static int
 ts_is_unique_and_not_stale(struct timeval *ts, struct timeval *now)
 {
-  long tv_sec;
-  struct timeval host_order_ts;
   int within_margin=0;
   int is_unique=0;
   long diff;
 
-  host_order_ts.tv_sec = tv_sec = ntohl(ts->tv_sec);
-  host_order_ts.tv_usec = ntohl(ts->tv_usec);
-
-  diff = now->tv_sec - tv_sec;
+  diff = now->tv_sec - ts->tv_sec;
   if ((diff < TS_MARGIN) && (diff > -TS_MARGIN)) {
     within_margin = 1;
   } else {
     within_margin = 0;
   }
-  is_unique = check_unique_ts(&host_order_ts, now);
+  is_unique = check_unique_ts(ts, now);
     
   return within_margin && is_unique;
 }
@@ -919,8 +914,7 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
   struct timeval ts;
   long offset_cs;
   double dfreq_ppm, new_afreq_ppm;
-  ts.tv_sec = ntohl(rx_message->data.settime.ts.tv_sec);
-  ts.tv_usec = ntohl(rx_message->data.settime.ts.tv_usec);
+  UTI_TimevalNetworkToHost(&rx_message->data.settime.ts, &ts);
   if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) {
     tx_message->status = htons(STT_SUCCESS);
     tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
@@ -1377,8 +1371,7 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
   tx_message->reply  = htons(RPY_TRACKING);
   tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
   tx_message->data.tracking.stratum = htonl(rpt.stratum);
-  tx_message->data.tracking.ref_time_s = htonl(rpt.ref_time.tv_sec);
-  tx_message->data.tracking.ref_time_us = htonl(rpt.ref_time.tv_usec);
+  UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
   tx_message->data.tracking.current_correction_s = htonl(rpt.current_correction.tv_sec);
   tx_message->data.tracking.current_correction_us = htonl(rpt.current_correction.tv_usec);
   tx_message->data.tracking.freq_ppm = REAL2WIRE(rpt.freq_ppm);
@@ -1424,7 +1417,7 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
     tx_message->reply  = htons(RPY_RTC);
-    tx_message->data.rtc.ref_time = htonl(report.ref_time);
+    UTI_TimevalHostToNetwork(&report.ref_time, &tx_message->data.rtc.ref_time);
     tx_message->data.rtc.n_samples = htons(report.n_samples);
     tx_message->data.rtc.n_runs = htons(report.n_runs);
     tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
@@ -1641,7 +1634,7 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
   tx_message->data.manual_list.n_samples = htonl(n_samples);
   for (i=0; i<n_samples; i++) {
     sample = &tx_message->data.manual_list.samples[i];
-    sample->when = htonl(report[i].when);
+    UTI_TimevalHostToNetwork(&report[i].when, &sample->when);
     sample->slewed_offset = REAL2WIRE(report[i].slewed_offset);
     sample->orig_offset = REAL2WIRE(report[i].orig_offset);
     sample->residual = REAL2WIRE(report[i].residual);
@@ -1936,11 +1929,17 @@ read_from_cmd_socket(void *anything)
 
   valid_ts = 0;
 
-  if (md5_ok && ((utoken_ok && token_ok) ||
-                 ((ntohl(rx_message.utoken) == SPECIAL_UTOKEN) &&
-                  (rx_command == REQ_LOGON) &&
-                  (valid_ts = ts_is_unique_and_not_stale(&rx_message.data.logon.ts, &now))))) {
-    issue_token = 1;
+  if (md5_ok) {
+    struct timeval ts;
+
+    UTI_TimevalNetworkToHost(&rx_message.data.logon.ts, &ts);
+    if ((utoken_ok && token_ok) ||
+        ((ntohl(rx_message.utoken) == SPECIAL_UTOKEN) &&
+         (rx_command == REQ_LOGON) &&
+         (valid_ts = ts_is_unique_and_not_stale(&ts, &now))))
+      issue_token = 1;
+    else 
+      issue_token = 0;
   } else {
     issue_token = 0;
   }
index 2664f0550987f355c187789740e919a45c69ca8e..0290df85f9542546645af86ccf38d171afa0be24 100644 (file)
--- a/manual.c
+++ b/manual.c
@@ -287,7 +287,7 @@ MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n)
   }
 
   for (i=0; i<n_samples && i<max; i++) {
-    report[i].when = samples[i].when.tv_sec;
+    report[i].when = samples[i].when;
     report[i].slewed_offset = samples[i].offset;
     report[i].orig_offset = samples[i].orig_offset;
     report[i].residual = samples[i].residual;
index 06a0b424c27bd95863c8430d77f2e1abf03e7f27..763b80dd0feec1ce04a5261066cbbaa2fc5c82dd 100644 (file)
--- a/reports.h
+++ b/reports.h
@@ -76,7 +76,7 @@ typedef struct {
 } RPT_SourcestatsReport;
 
 typedef struct {
-  unsigned long ref_time;
+  struct timeval ref_time;
   unsigned short n_samples;
   unsigned short n_runs;
   unsigned long span_seconds;
@@ -106,7 +106,7 @@ typedef struct {
 } RPT_ClientAccessByIndex_Report;
 
 typedef struct {
-  time_t when;
+  struct timeval when;
   double slewed_offset;
   double orig_offset;
   double residual;
index dc5a15df0467b2e4ea34137a2a4ad7a9441a1b0d..8a60b1439e97bed382b009331d8713e5558ec297 100644 (file)
@@ -1104,7 +1104,8 @@ RTC_Linux_TimePreInit(void)
 int
 RTC_Linux_GetReport(RPT_RTC_Report *report)
 {
-  report->ref_time = (unsigned long) coef_ref_time;
+  report->ref_time.tv_sec = coef_ref_time;
+  report->ref_time.tv_usec = 0;
   report->n_samples = n_samples;
   report->n_runs = n_runs;
   if (n_samples > 1) {
diff --git a/util.c b/util.c
index 5717d547eb78a7bb9dc4522416db9fdf821bbf4c..2346f813bf071e8281f3d45e6d95ec59445b056d 100644 (file)
--- a/util.c
+++ b/util.c
@@ -501,4 +501,41 @@ UTI_Int64ToTimeval(NTP_int64 *src,
   dest->tv_usec = (int)(0.5 + (double)(ntohl(src->lo)) / 4294.967296);
 }
 
+/* ================================================== */
+
+void
+UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest)
+{
+  uint32_t sec_low, sec_high;
+
+  dest->tv_usec = ntohl(src->tv_usec);
+  sec_high = ntohl(src->tv_sec_high);
+  sec_low = ntohl(src->tv_sec_low);
+
+  /* get the missing bits from current time when received timestamp
+     is only 32-bit */
+  if (sizeof (time_t) > 4 && sec_high == TV_NOHIGHSEC) {
+    struct timeval now;
+    struct timezone tz;
+
+    gettimeofday(&now, &tz);
+    sec_high = now.tv_sec >> 32;
+  }
+  dest->tv_sec = (time_t)sec_high << 16 << 16 | sec_low;
+}
+
+/* ================================================== */
+
+void
+UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest)
+{
+  dest->tv_usec = htonl(src->tv_usec);
+  if (sizeof (time_t) > 4)
+    dest->tv_sec_high = htonl(src->tv_sec >> 32);
+  else
+    dest->tv_sec_high = htonl(TV_NOHIGHSEC);
+  dest->tv_sec_low = htonl(src->tv_sec);
+}
+
+
 /* ================================================== */
diff --git a/util.h b/util.h
index 1ec21842e308a769020f68f589f5dfedc69cc960..cddbc5c8cf169867b5a3a43e2bea5379e998a427 100644 (file)
--- a/util.h
+++ b/util.h
@@ -35,6 +35,7 @@
 
 #include "addressing.h"
 #include "ntp.h"
+#include "candm.h"
 
 /* Convert a timeval into a floating point number of seconds */
 extern void UTI_TimevalToDouble(struct timeval *a, double *b);
@@ -96,6 +97,9 @@ extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest);
 
 extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
 
+extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
+extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
+
 #if defined (INLINE_UTILITIES)
 #define INLINE_STATIC inline static
 #include "util.c"