git: 069681afd58a - main - ping: use CLOCK_REALTIME for ICMP Originate Timestamp
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 02 May 2026 03:17:38 UTC
The branch main has been updated by maxim:
URL: https://cgit.FreeBSD.org/src/commit/?id=069681afd58a711eb7407be4a9c9a05f787d250f
commit 069681afd58a711eb7407be4a9c9a05f787d250f
Author: Maxim Konovalov <maxim@FreeBSD.org>
AuthorDate: 2026-05-01 17:45:27 +0000
Commit: Maxim Konovalov <maxim@FreeBSD.org>
CommitDate: 2026-05-02 03:16:55 +0000
ping: use CLOCK_REALTIME for ICMP Originate Timestamp
RFC 792 defines the ICMP Originate Timestamp field as milliseconds
since midnight UTC. However, ping(8) currently derives this value
from CLOCK_MONOTONIC, which represents time since an unspecified
starting point and is not related to UTC.
The issue was introduced by commit 1ad76f1b6047, which replaced
gettimeofday(2) with clock_gettime(CLOCK_MONOTONIC) for timekeeping
in ping(8).
Fix this by using CLOCK_REALTIME when generating the ICMP originate
timestamp.
Before:
$ ping -Mt -c1 127.0.0.1
ICMP_TSTAMP
PING 127.0.0.1 (127.0.0.1): 56 data bytes
<...> time=0.061 ms tso=16:50:31 tsr=17:38:28 tst=17:38:28
(note the tso is off)
After:
$ ping -Mt -c1 127.0.0.1
ICMP_TSTAMP
PING 127.0.0.1 (127.0.0.1): 56 data bytes
<...> time=0.038 ms tso=17:42:09 tsr=17:42:09 tst=17:42:09
Reviewed by: asomers, glebius
Fixes: 1ad76f1b6047
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D56759
---
sbin/ping/ping.c | 9 ++++++++-
sbin/ping/tests/ping_test.sh | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index d10e3c85c9bd..579ecb9151bb 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -1029,9 +1029,16 @@ pinger(void)
*/
tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec);
- if (options & F_TIME)
+ if (options & F_TIME) {
+ /*
+ * However, per RFC 792 the Originate Timestamp (otime)
+ * should be milliseconds since midnight UTC. Something,
+ * that CLOCK_MONOTONIC does not guarantee.
+ */
+ (void)clock_gettime(CLOCK_REALTIME, &now);
icp.icmp_otime = htonl((now.tv_sec % (24*60*60))
* 1000 + now.tv_nsec / 1000000);
+ }
if (timing)
bcopy((void *)&tv32,
(void *)&outpack[ICMP_MINLEN + phdr_len],
diff --git a/sbin/ping/tests/ping_test.sh b/sbin/ping/tests/ping_test.sh
index 5a12ace104d7..6e090cfd945a 100644
--- a/sbin/ping/tests/ping_test.sh
+++ b/sbin/ping/tests/ping_test.sh
@@ -253,6 +253,40 @@ inject_reply_cleanup()
ifconfig `cat tun.txt` destroy
}
+atf_test_case timestamp_origin
+timestamp_origin_head()
+{
+ atf_set "descr" "ICMP Originate Timestamp"
+}
+timestamp_origin_body()
+{
+ require_ipv4
+ # Run ping timestamp
+ out=$(ping -Mt -c1 127.0.0.1)
+
+ # Extract tso and tsr
+ tso=$(echo "$out" | sed -n 's/.*tso=\([0-9:]*\).*/\1/p')
+ tsr=$(echo "$out" | sed -n 's/.*tsr=\([0-9:]*\).*/\1/p')
+
+ atf_check test -n "$tso"
+ atf_check test -n "$tsr"
+
+ # Convert tso and tsr from HH:MM:SS to seconds
+ tso_s=`date -jf %H:%M:%S $tso`
+ tsr_s=`date -jf %H:%M:%S $tsr`
+
+ diff=$((tso_s - tsr_s))
+ # Tolerate negative time difference between the sender and receiver
+ if [ $diff -lt 0 ]; then
+ diff=$(( -diff ))
+ fi
+
+ # Tolerate 2 seconds difference
+ if [ $diff -gt 2 ]; then
+ atf_fail "tso ($tso) differs from tsr ($tsr) by $diff seconds"
+ fi
+}
+
atf_init_test_cases()
{
atf_add_test_case ping_c1_s56_t1
@@ -271,6 +305,7 @@ atf_init_test_cases()
atf_add_test_case inject_opts
atf_add_test_case inject_pip
atf_add_test_case inject_reply
+ atf_add_test_case timestamp_origin
}
check_ping_statistics()