如何将Unix Epoch时间转换为Linux ping ICMP报文的8字节TOD时间戳格式
自定义ping程序ICMP时间戳转换及问题排查方案
8字节TOD时间戳转换方法
Linux原生ping在ICMP头部后追加的8字节TOD时间戳为32位Unix Epoch秒数 + 32位微秒数的组合,无需特殊编码转换,直接按主机字节序填充即可。注意不要用仅能获取秒级时间的time()函数,需使用gettimeofday()同时获取秒和微秒值,实现代码参考:
#include <sys/time.h> #include <stdint.h> #include <linux/ip.h> #include <linux/icmp.h> // 入参为ICMP报文数据段的起始地址 void fill_icmp_tod(uint8_t *icmp_data_start) { struct timeval tv; gettimeofday(&tv, NULL); // 前4字节存32位秒数,后4字节存32位微秒数,总长度8字节 *(uint32_t *)icmp_data_start = (uint32_t)tv.tv_sec; *(uint32_t *)(icmp_data_start + 4) = (uint32_t)tv.tv_usec; }
无响应问题其他排查要点
如果时间戳填充正确仍收不到响应,优先排查以下常见问题:
- 检查ICMP校验和计算是否正确:校验和需要覆盖完整的ICMP头部+数据段,校验和错误的报文会被目标主机直接丢弃,不会返回响应
- 检查
icmp_id字段是否填充为当前进程PID:内核通过icmp_id匹配ICMP响应对应的进程,id填写错误时响应会被内核丢弃,应用层无法收到 - 确认程序运行权限:原始套接字收发ICMP报文需要root权限,或者为程序设置
CAP_NET_RAW权限:sudo setcap cap_net_raw+ep ./你的ping程序名 - 确认
icmp_seq字段按请求递增:虽然IBM文档提到用id+时间戳匹配请求响应,但部分网络设备会校验seq字段合法性,异常值可能导致报文被拦截
内容的提问来源于stack exchange,提问作者jakeprog123
相关产品推荐
相关产品推荐

