diff --git a/ntp_core.c b/ntp_core.c index 18e6684..6d5b857 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -899,8 +899,10 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ NTP_Local_Timestamp *local_rx, /* The RX time of the received packet */ NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet RESULT : TX time of this packet */ - NTP_int64 *local_ntp_rx, /* RESULT : receive timestamp from this packet */ - NTP_int64 *local_ntp_tx, /* RESULT : transmit timestamp from this packet */ + NTP_int64 *local_ntp_rx, /* The receive timestamp from the previous packet + RESULT : receive timestamp from this packet */ + NTP_int64 *local_ntp_tx, /* The transmit timestamp from the previous packet + RESULT : transmit timestamp from this packet */ NTP_Remote_Address *where_to, /* Where to address the reponse to */ NTP_Local_Address *from /* From what address to send it */ ) @@ -998,14 +1000,21 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ /* Originate - this comes from the last packet the source sent us */ message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx; - /* Prepare random bits which will be added to the receive timestamp */ - UTI_GetNtp64Fuzz(&ts_fuzz, precision); + do { + /* Prepare random bits which will be added to the receive timestamp */ + UTI_GetNtp64Fuzz(&ts_fuzz, precision); - /* Receive - this is when we received the last packet from the source. - This timestamp will have been adjusted so that it will now look to - the source like we have been running on our latest estimate of - frequency all along */ - UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz); + /* Receive - this is when we received the last packet from the source. + This timestamp will have been adjusted so that it will now look to + the source like we have been running on our latest estimate of + frequency all along */ + UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz); + + /* Do not send a packet with a non-zero receive timestamp equal to the + originate timestamp or previous receive timestamp */ + } while (!UTI_IsZeroNtp64(&message.receive_ts) && + UTI_IsEqualAnyNtp64(&message.receive_ts, &message.originate_ts, + local_ntp_rx, NULL)); } else { UTI_ZeroNtp64(&message.originate_ts); UTI_ZeroNtp64(&message.receive_ts); @@ -1064,10 +1073,16 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ &message.transmit_ts, &ts_fuzz); } - /* Avoid sending messages with non-zero transmit timestamp equal to the - receive timestamp to allow reliable detection of the interleaved mode */ - } while (!UTI_CompareNtp64(&message.transmit_ts, &message.receive_ts) && - !UTI_IsZeroNtp64(&message.transmit_ts)); + /* Do not send a packet with a non-zero transmit timestamp which is + equal to any of the following timestamps: + - receive (to allow reliable detection of the interleaved mode) + - originate (to prevent the packet from being its own valid response + in the symmetric mode) + - previous transmit (to invalidate responses to the previous packet) + (the precision must be at least -30 to prevent an infinite loop!) */ + } while (!UTI_IsZeroNtp64(&message.transmit_ts) && + UTI_IsEqualAnyNtp64(&message.transmit_ts, &message.receive_ts, + &message.originate_ts, local_ntp_tx)); ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL); diff --git a/util.c b/util.c index 586dcbd..95c27c0 100644 --- a/util.c +++ b/util.c @@ -726,6 +726,23 @@ UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b) /* ================================================== */ +int +UTI_IsEqualAnyNtp64(NTP_int64 *a, NTP_int64 *b1, NTP_int64 *b2, NTP_int64 *b3) +{ + if (b1 && a->lo == b1->lo && a->hi == b1->hi) + return 1; + + if (b2 && a->lo == b2->lo && a->hi == b2->hi) + return 1; + + if (b3 && a->lo == b3->lo && a->hi == b3->hi) + return 1; + + return 0; +} + +/* ================================================== */ + /* 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 02d598b..40ff729 100644 --- a/util.h +++ b/util.h @@ -136,6 +136,10 @@ extern int UTI_IsZeroNtp64(NTP_int64 *ts); b, and 1 if a is after b. */ extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b); +/* Compare an NTP timestamp with up to three other timestamps. Returns 0 + if a is not equal to any of b1, b2, and b3, 1 otherwise. */ +extern int UTI_IsEqualAnyNtp64(NTP_int64 *a, NTP_int64 *b1, NTP_int64 *b2, NTP_int64 *b3); + /* Convert a timespec into an NTP timestamp */ extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);