1
0
mirror of https://git.FreeBSD.org/src.git synced 2026-06-02 11:24:32 +00:00

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 1ad76f1b60, 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:			1ad76f1b60
MFC after:		1 month
Differential Revision:	https://reviews.freebsd.org/D56759
This commit is contained in:
Maxim Konovalov
2026-05-01 17:45:27 +00:00
parent c4f08d46c7
commit 069681afd5
2 changed files with 43 additions and 1 deletions
+8 -1
View File
@@ -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],
+35
View File
@@ -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()