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) */
#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;

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View 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) {

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);
}
/* ================================================== */
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 "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"