Always send timevals in cmdmon protocol in 64-bit format

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.
This commit is contained in:
Miroslav Lichvar 2009-10-09 15:31:59 +02:00
parent 8265ff2890
commit a7892a1a15
8 changed files with 93 additions and 42 deletions

23
candm.h
View file

@ -92,6 +92,16 @@
password. (This time value has long since gone by) */ password. (This time value has long since gone by) */
#define SPECIAL_UTOKEN 0x10101010 #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 /* 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 pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */ transmitted for each packet type. */
@ -151,12 +161,12 @@ typedef struct {
} REQ_Modify_Maxupdateskew; } REQ_Modify_Maxupdateskew;
typedef struct { typedef struct {
struct timeval ts; Timeval ts;
int32_t EOR; int32_t EOR;
} REQ_Logon; } REQ_Logon;
typedef struct { typedef struct {
struct timeval ts; Timeval ts;
int32_t EOR; int32_t EOR;
} REQ_Settime; } REQ_Settime;
@ -311,7 +321,7 @@ typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline) 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 { typedef struct {
uint32_t ref_id; uint32_t ref_id;
uint32_t stratum; uint32_t stratum;
uint32_t ref_time_s; Timeval ref_time;
uint32_t ref_time_us;
uint32_t current_correction_s; uint32_t current_correction_s;
uint32_t current_correction_us; uint32_t current_correction_us;
int32_t freq_ppm; int32_t freq_ppm;
@ -487,7 +496,7 @@ typedef struct {
} RPY_Sourcestats; } RPY_Sourcestats;
typedef struct { typedef struct {
uint32_t ref_time; Timeval ref_time;
uint16_t n_samples; uint16_t n_samples;
uint16_t n_runs; uint16_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
@ -540,7 +549,7 @@ typedef struct {
#define MAX_MANUAL_LIST_SAMPLES 32 #define MAX_MANUAL_LIST_SAMPLES 32
typedef struct { typedef struct {
uint32_t when; Timeval when;
int32_t slewed_offset; int32_t slewed_offset;
int32_t orig_offset; int32_t orig_offset;
int32_t residual; int32_t residual;

View file

@ -1030,6 +1030,7 @@ process_cmd_password(CMD_Request *msg, char *line)
char *p, *q; char *p, *q;
char *password; char *password;
struct timezone tz; struct timezone tz;
struct timeval now;
p = line; p = line;
while (*p && isspace((unsigned char)*p)) while (*p && isspace((unsigned char)*p))
@ -1062,13 +1063,12 @@ process_cmd_password(CMD_Request *msg, char *line)
*p = 0; *p = 0;
} }
if (gettimeofday(&msg->data.logon.ts, &tz) < 0) { if (gettimeofday(&now, &tz) < 0) {
printf("500 - Could not read time of day\n"); printf("500 - Could not read time of day\n");
return 0; return 0;
} else { } else {
msg->command = htons(REQ_LOGON); /* Just force a round trip so that we get tokens etc */ 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); UTI_TimevalHostToNetwork(&now, &msg->data.logon.ts);
msg->data.logon.ts.tv_usec = htonl(msg->data.logon.ts.tv_usec);
return 1; return 1;
} }
} }
@ -1713,8 +1713,7 @@ process_cmd_tracking(char *line)
a, b, c, d, ""); a, b, c, d, "");
//* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */ //* TODO (no_dns) ? UTI_IPToDottedQuad(ref_id) : DNS_IPAddress2Name(ref_id)); */
printf("Stratum : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum)); printf("Stratum : %lu\n", (unsigned long) ntohl(reply.data.tracking.stratum));
ref_time.tv_sec = ntohl(reply.data.tracking.ref_time_s); UTI_TimevalNetworkToHost(&reply.data.tracking.ref_time, &ref_time);
ref_time.tv_usec = ntohl(reply.data.tracking.ref_time_us);
ref_time_tm = *gmtime((time_t *)&ref_time.tv_sec); ref_time_tm = *gmtime((time_t *)&ref_time.tv_sec);
printf("Ref time (UTC) : %s", asctime(&ref_time_tm)); printf("Ref time (UTC) : %s", asctime(&ref_time_tm));
correction_tv.tv_sec = (int32_t)ntohl(reply.data.tracking.current_correction_s); 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; int auth_ok;
CMD_Request request; CMD_Request request;
CMD_Reply reply; CMD_Reply reply;
time_t ref_time; struct timeval ref_time;
struct tm ref_time_tm; struct tm ref_time_tm;
unsigned short n_samples; unsigned short n_samples;
unsigned short n_runs; unsigned short n_runs;
@ -1775,8 +1774,8 @@ process_cmd_rtcreport(char *line)
default: default:
break; break;
} }
ref_time = (time_t) ntohl(reply.data.rtc.ref_time); UTI_TimevalNetworkToHost(&reply.data.rtc.ref_time, &ref_time);
ref_time_tm = *gmtime(&ref_time); ref_time_tm = *gmtime(&ref_time.tv_sec);
n_samples = ntohs(reply.data.rtc.n_samples); n_samples = ntohs(reply.data.rtc.n_samples);
n_runs = ntohs(reply.data.rtc.n_runs); n_runs = ntohs(reply.data.rtc.n_runs);
span_seconds = ntohl(reply.data.rtc.span_seconds); span_seconds = ntohl(reply.data.rtc.span_seconds);
@ -2170,7 +2169,7 @@ process_cmd_manual_list(const char *line)
int n_samples; int n_samples;
RPY_ManualListSample *sample; RPY_ManualListSample *sample;
int i; int i;
time_t when; struct timeval when;
double slewed_offset, orig_offset, residual; double slewed_offset, orig_offset, residual;
request.command = htons(REQ_MANUAL_LIST); request.command = htons(REQ_MANUAL_LIST);
@ -2186,11 +2185,11 @@ process_cmd_manual_list(const char *line)
"====================================================\n"); "====================================================\n");
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
sample = &reply.data.manual_list.samples[i]; sample = &reply.data.manual_list.samples[i];
when = ntohl(sample->when); UTI_TimevalNetworkToHost(&sample->when, &when);
slewed_offset = WIRE2REAL(sample->slewed_offset); slewed_offset = WIRE2REAL(sample->slewed_offset);
orig_offset = WIRE2REAL(sample->orig_offset); orig_offset = WIRE2REAL(sample->orig_offset);
residual = WIRE2REAL(sample->residual); 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; break;
case STT_NOHOSTACCESS: case STT_NOHOSTACCESS:
@ -2251,6 +2250,7 @@ process_cmd_manual_delete(const char *line)
static void static void
process_cmd_settime(char *line) process_cmd_settime(char *line)
{ {
struct timeval ts;
time_t now, new_time; time_t now, new_time;
CMD_Request request; CMD_Request request;
CMD_Reply reply; CMD_Reply reply;
@ -2266,8 +2266,9 @@ process_cmd_settime(char *line)
if (new_time == -1) { if (new_time == -1) {
printf("510 - Could not parse date string\n"); printf("510 - Could not parse date string\n");
} else { } else {
request.data.settime.ts.tv_sec = htonl(new_time); ts.tv_sec = new_time;
request.data.settime.ts.tv_usec = htonl(0); ts.tv_usec = 0;
UTI_TimevalHostToNetwork(&ts, &request.data.settime.ts);
request.command = htons(REQ_SETTIME); request.command = htons(REQ_SETTIME);
submit_ok = submit_request(&request, &reply, &reply_auth_ok); submit_ok = submit_request(&request, &reply, &reply_auth_ok);
if (submit_ok) { if (submit_ok) {

View file

@ -535,22 +535,17 @@ check_unique_ts(struct timeval *ts, struct timeval *now)
static int static int
ts_is_unique_and_not_stale(struct timeval *ts, struct timeval *now) 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 within_margin=0;
int is_unique=0; int is_unique=0;
long diff; long diff;
host_order_ts.tv_sec = tv_sec = ntohl(ts->tv_sec); diff = now->tv_sec - ts->tv_sec;
host_order_ts.tv_usec = ntohl(ts->tv_usec);
diff = now->tv_sec - tv_sec;
if ((diff < TS_MARGIN) && (diff > -TS_MARGIN)) { if ((diff < TS_MARGIN) && (diff > -TS_MARGIN)) {
within_margin = 1; within_margin = 1;
} else { } else {
within_margin = 0; within_margin = 0;
} }
is_unique = check_unique_ts(&host_order_ts, now); is_unique = check_unique_ts(ts, now);
return within_margin && is_unique; return within_margin && is_unique;
} }
@ -919,8 +914,7 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
struct timeval ts; struct timeval ts;
long offset_cs; long offset_cs;
double dfreq_ppm, new_afreq_ppm; double dfreq_ppm, new_afreq_ppm;
ts.tv_sec = ntohl(rx_message->data.settime.ts.tv_sec); UTI_TimevalNetworkToHost(&rx_message->data.settime.ts, &ts);
ts.tv_usec = ntohl(rx_message->data.settime.ts.tv_usec);
if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) { if (MNL_AcceptTimestamp(&ts, &offset_cs, &dfreq_ppm, &new_afreq_ppm)) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_MANUAL_TIMESTAMP); 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->reply = htons(RPY_TRACKING);
tx_message->data.tracking.ref_id = htonl(rpt.ref_id); tx_message->data.tracking.ref_id = htonl(rpt.ref_id);
tx_message->data.tracking.stratum = htonl(rpt.stratum); tx_message->data.tracking.stratum = htonl(rpt.stratum);
tx_message->data.tracking.ref_time_s = htonl(rpt.ref_time.tv_sec); UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
tx_message->data.tracking.ref_time_us = htonl(rpt.ref_time.tv_usec);
tx_message->data.tracking.current_correction_s = htonl(rpt.current_correction.tv_sec); 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.current_correction_us = htonl(rpt.current_correction.tv_usec);
tx_message->data.tracking.freq_ppm = REAL2WIRE(rpt.freq_ppm); 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) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_RTC); 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_samples = htons(report.n_samples);
tx_message->data.rtc.n_runs = htons(report.n_runs); tx_message->data.rtc.n_runs = htons(report.n_runs);
tx_message->data.rtc.span_seconds = htonl(report.span_seconds); 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); tx_message->data.manual_list.n_samples = htonl(n_samples);
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
sample = &tx_message->data.manual_list.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->slewed_offset = REAL2WIRE(report[i].slewed_offset);
sample->orig_offset = REAL2WIRE(report[i].orig_offset); sample->orig_offset = REAL2WIRE(report[i].orig_offset);
sample->residual = REAL2WIRE(report[i].residual); sample->residual = REAL2WIRE(report[i].residual);
@ -1936,11 +1929,17 @@ read_from_cmd_socket(void *anything)
valid_ts = 0; valid_ts = 0;
if (md5_ok && ((utoken_ok && token_ok) || 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) && ((ntohl(rx_message.utoken) == SPECIAL_UTOKEN) &&
(rx_command == REQ_LOGON) && (rx_command == REQ_LOGON) &&
(valid_ts = ts_is_unique_and_not_stale(&rx_message.data.logon.ts, &now))))) { (valid_ts = ts_is_unique_and_not_stale(&ts, &now))))
issue_token = 1; issue_token = 1;
else
issue_token = 0;
} else { } else {
issue_token = 0; issue_token = 0;
} }

View file

@ -287,7 +287,7 @@ MNL_ReportSamples(RPT_ManualSamplesReport *report, int max, int *n)
} }
for (i=0; i<n_samples && i<max; i++) { 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].slewed_offset = samples[i].offset;
report[i].orig_offset = samples[i].orig_offset; report[i].orig_offset = samples[i].orig_offset;
report[i].residual = samples[i].residual; report[i].residual = samples[i].residual;

View file

@ -76,7 +76,7 @@ typedef struct {
} RPT_SourcestatsReport; } RPT_SourcestatsReport;
typedef struct { typedef struct {
unsigned long ref_time; struct timeval ref_time;
unsigned short n_samples; unsigned short n_samples;
unsigned short n_runs; unsigned short n_runs;
unsigned long span_seconds; unsigned long span_seconds;
@ -106,7 +106,7 @@ typedef struct {
} RPT_ClientAccessByIndex_Report; } RPT_ClientAccessByIndex_Report;
typedef struct { typedef struct {
time_t when; struct timeval when;
double slewed_offset; double slewed_offset;
double orig_offset; double orig_offset;
double residual; double residual;

View file

@ -1104,7 +1104,8 @@ RTC_Linux_TimePreInit(void)
int int
RTC_Linux_GetReport(RPT_RTC_Report *report) 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_samples = n_samples;
report->n_runs = n_runs; report->n_runs = n_runs;
if (n_samples > 1) { if (n_samples > 1) {

37
util.c
View file

@ -501,4 +501,41 @@ UTI_Int64ToTimeval(NTP_int64 *src,
dest->tv_usec = (int)(0.5 + (double)(ntohl(src->lo)) / 4294.967296); 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);
}
/* ================================================== */ /* ================================================== */

4
util.h
View file

@ -35,6 +35,7 @@
#include "addressing.h" #include "addressing.h"
#include "ntp.h" #include "ntp.h"
#include "candm.h"
/* Convert a timeval into a floating point number of seconds */ /* Convert a timeval into a floating point number of seconds */
extern void UTI_TimevalToDouble(struct timeval *a, double *b); 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_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) #if defined (INLINE_UTILITIES)
#define INLINE_STATIC inline static #define INLINE_STATIC inline static
#include "util.c" #include "util.c"