From 6e9c04896b06850c846fc20a3f4ced3c820027f4 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 24 Oct 2016 16:46:29 +0200 Subject: [PATCH] util: add functions for zeroing and comparing NTP timestamps --- clientlog.c | 4 ++-- ntp_core.c | 45 +++++++++++++++++---------------------------- util.c | 36 ++++++++++++++++++++++++++++++++++++ util.h | 12 ++++++++++++ 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/clientlog.c b/clientlog.c index a9f2634..9dca9f1 100644 --- a/clientlog.c +++ b/clientlog.c @@ -209,8 +209,8 @@ get_record(IPAddr *ip) record->ntp_rate = record->cmd_rate = INVALID_RATE; record->ntp_timeout_rate = INVALID_RATE; record->flags = 0; - record->ntp_rx_ts.hi = record->ntp_rx_ts.lo = 0; - record->ntp_tx_ts.hi = record->ntp_tx_ts.lo = 0; + UTI_ZeroNtp64(&record->ntp_rx_ts); + UTI_ZeroNtp64(&record->ntp_tx_ts); return record; } diff --git a/ntp_core.c b/ntp_core.c index 2829ebb..066077a 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -599,14 +599,10 @@ NCR_ResetInstance(NCR_Instance instance) instance->valid_rx = 0; instance->valid_timestamps = 0; - instance->remote_ntp_rx.hi = 0; - instance->remote_ntp_rx.lo = 0; - instance->remote_ntp_tx.hi = 0; - instance->remote_ntp_tx.lo = 0; - instance->local_ntp_rx.hi = 0; - instance->local_ntp_rx.lo = 0; - instance->local_ntp_tx.hi = 0; - instance->local_ntp_tx.lo = 0; + UTI_ZeroNtp64(&instance->remote_ntp_rx); + UTI_ZeroNtp64(&instance->remote_ntp_tx); + UTI_ZeroNtp64(&instance->local_ntp_rx); + UTI_ZeroNtp64(&instance->local_ntp_tx); UTI_ZeroTimespec(&instance->local_rx.ts); instance->local_rx.err = 0.0; instance->local_rx.source = NTP_TS_DAEMON; @@ -1286,24 +1282,21 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr, The test values are 1 when passed and 0 when failed. */ /* Test 1 checks for duplicate packet */ - test1 = message->transmit_ts.hi != inst->remote_ntp_tx.hi || - message->transmit_ts.lo != inst->remote_ntp_tx.lo; + test1 = !!UTI_CompareNtp64(&message->transmit_ts, &inst->remote_ntp_tx); /* Test 2 checks for bogus packet in the basic and interleaved modes. This ensures the source is responding to the latest packet we sent to it. */ - test2n = message->originate_ts.hi == inst->local_ntp_tx.hi && - message->originate_ts.lo == inst->local_ntp_tx.lo; + test2n = !UTI_CompareNtp64(&message->originate_ts, &inst->local_ntp_tx); test2i = inst->interleaved && - message->originate_ts.hi == inst->local_ntp_rx.hi && - message->originate_ts.lo == inst->local_ntp_rx.lo; + !UTI_CompareNtp64(&message->originate_ts, &inst->local_ntp_rx); test2 = test2n || test2i; interleaved_packet = !test2n && test2i; /* Test 3 checks for invalid timestamps. This can happen when the association if not properly 'up'. */ - test3 = (message->originate_ts.hi || message->originate_ts.lo) && - (message->receive_ts.hi || message->receive_ts.lo) && - (message->transmit_ts.hi || message->transmit_ts.lo); + test3 = !UTI_IsZeroNtp64(&message->originate_ts) && + !UTI_IsZeroNtp64(&message->receive_ts) && + !UTI_IsZeroNtp64(&message->transmit_ts); /* Test 4 would check for denied access. It would always pass as this function is called only for known sources. */ @@ -1817,18 +1810,17 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a on clients that are not using the interleaved mode. */ if (log_index >= 0) { CLG_GetNtpTimestamps(log_index, &local_ntp_rx, &local_ntp_tx); - interleaved = (local_ntp_rx->hi || local_ntp_rx->lo) && - message->originate_ts.hi == local_ntp_rx->hi && - message->originate_ts.lo == local_ntp_rx->lo; + interleaved = !UTI_IsZeroNtp64(local_ntp_rx) && + !UTI_CompareNtp64(&message->originate_ts, local_ntp_rx); if (interleaved) { - if (local_ntp_tx->hi || local_ntp_tx->lo) + if (!UTI_IsZeroNtp64(local_ntp_tx)) UTI_Ntp64ToTimespec(local_ntp_tx, &local_tx.ts); else interleaved = 0; tx_ts = &local_tx; } else { - local_ntp_tx->hi = local_ntp_tx->lo = 0; + UTI_ZeroNtp64(local_ntp_tx); local_ntp_tx = NULL; } } @@ -1857,10 +1849,8 @@ update_tx_timestamp(NTP_Local_Timestamp *tx_ts, NTP_Local_Timestamp *new_tx_ts, } /* Check if this is the last packet that was sent */ - if ((local_ntp_rx && (message->receive_ts.hi != local_ntp_rx->hi || - message->receive_ts.lo != local_ntp_rx->lo)) || - (local_ntp_tx && (message->transmit_ts.hi != local_ntp_tx->hi || - message->transmit_ts.lo != local_ntp_tx->lo))) { + if ((local_ntp_rx && UTI_CompareNtp64(&message->receive_ts, local_ntp_rx)) || + (local_ntp_tx && UTI_CompareNtp64(&message->transmit_ts, local_ntp_tx))) { DEBUG_LOG(LOGF_NtpCore, "RX/TX timestamp mismatch"); return; } @@ -2236,8 +2226,7 @@ broadcast_timeout(void *arg) destination = ARR_GetElement(broadcasts, (long)arg); - orig_ts.hi = 0; - orig_ts.lo = 0; + UTI_ZeroNtp64(&orig_ts); UTI_ZeroTimespec(&recv_ts.ts); recv_ts.source = NTP_TS_DAEMON; recv_ts.err = 0.0; diff --git a/util.c b/util.c index a054b79..7626a5c 100644 --- a/util.c +++ b/util.c @@ -679,6 +679,42 @@ UTI_DoubleToNtp32(double x) /* ================================================== */ +void +UTI_ZeroNtp64(NTP_int64 *ts) +{ + ts->hi = ts->lo = htonl(0); +} + +/* ================================================== */ + +int +UTI_IsZeroNtp64(NTP_int64 *ts) +{ + return !ts->hi && !ts->lo; +} + +/* ================================================== */ + +int +UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b) +{ + int32_t diff; + + if (a->hi == b->hi && a->lo == b->lo) + return 0; + + diff = ntohl(a->hi) - ntohl(b->hi); + + if (diff < 0) + return -1; + if (diff > 0) + return 1; + + return ntohl(a->lo) < ntohl(b->lo) ? -1 : 1; +} + +/* ================================================== */ + /* Seconds part of NTP timestamp correponding to the origin of the time_t format */ #define JAN_1970 0x83aa7e80UL diff --git a/util.h b/util.h index 2f2332a..8ab1400 100644 --- a/util.h +++ b/util.h @@ -126,8 +126,20 @@ extern void UTI_GetNtp64Fuzz(NTP_int64 *ts, int precision); extern double UTI_Ntp32ToDouble(NTP_int32 x); extern NTP_int32 UTI_DoubleToNtp32(double x); +/* Zero an NTP timestamp */ +extern void UTI_ZeroNtp64(NTP_int64 *ts); + +/* Check if an NTP timestamp is zero */ +extern int UTI_IsZeroNtp64(NTP_int64 *ts); + +/* Compare two NTP timestamps. Returns -1 if a is before b, 0 if a is equal to + b, and 1 if a is after b. */ +extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b); + +/* Convert a timespec into an NTP timestamp */ extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz); +/* Convert an NTP timestamp into a timespec */ extern void UTI_Ntp64ToTimespec(NTP_int64 *src, struct timespec *dest); /* Check if time + offset is sane */