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.
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. */
} 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;
Version 3 : NTP_Source message lengthened (auto_offline)
- Version 4 : IPv6 addressing added
+ Version 4 : IPv6 addressing added, 64-bit time values
*/
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;
} RPY_Sourcestats;
typedef struct {
- uint32_t ref_time;
+ Timeval ref_time;
uint16_t n_samples;
uint16_t n_runs;
uint32_t span_seconds;
#define MAX_MANUAL_LIST_SAMPLES 32
typedef struct {
- uint32_t when;
+ Timeval when;
int32_t slewed_offset;
int32_t orig_offset;
int32_t residual;
char *p, *q;
char *password;
struct timezone tz;
+ struct timeval now;
p = line;
while (*p && isspace((unsigned char)*p))
*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;
}
}
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);
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;
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);
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);
"====================================================\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:
static void
process_cmd_settime(char *line)
{
+ struct timeval ts;
time_t now, new_time;
CMD_Request request;
CMD_Reply reply;
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) {
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;
}
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);
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);
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);
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);
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;
}
}
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;
} RPT_SourcestatsReport;
typedef struct {
- unsigned long ref_time;
+ struct timeval ref_time;
unsigned short n_samples;
unsigned short n_runs;
unsigned long span_seconds;
} RPT_ClientAccessByIndex_Report;
typedef struct {
- time_t when;
+ struct timeval when;
double slewed_offset;
double orig_offset;
double residual;
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) {
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);
+}
+
+
/* ================================================== */
#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);
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"