#!/usr/bin/perl -w
-use Test::Command tests => 75;
+use Test::Command tests => 78;
use Test::More;
# -c n count of pings to send to each target (default 1)
ff02::1 : xmt/rcv/%loss = 1/1/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+\n});
}
+# fping --icmp-timestamp -c n 127.0.0.1
+SKIP: {
+if($^O eq 'darwin') {
+ skip 'On macOS, this test is unreliable', 3;
+}
+my $cmd = Test::Command->new(cmd => "fping -4 --icmp-timestamp -c 2 127.0.0.1");
+$cmd->exit_is_num(0);
+$cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+ICMP timestamp: Originate=\d+ Receive=\d+ Transmit=\d+
+ICMP timestamp RTT tsrtt=\d+
+127\.0\.0\.1 : \[1\], 20 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0% loss\)
+ICMP timestamp: Originate=\d+ Receive=\d+ Transmit=\d+
+ICMP timestamp RTT tsrtt=\d+
+});
+
+$cmd->stderr_like(qr{127\.0\.0\.1 : xmt/rcv/%loss = 2/2/0%, min/avg/max = \d\.\d+/\d\.\d+/\d\.\d+
+});
+}
+
# fping -C n
{
my $cmd = Test::Command->new(cmd => "fping -4 -C 2 -p 100 localhost 127.0.0.1");
int random_data_flag = 0;
int cumulative_stats_flag = 0;
int check_source_flag = 0;
+int icmp_request_typ = 0;
int print_tos_flag = 0;
int print_ttl_flag = 0;
#if defined(DEBUG) || defined(_DEBUG)
{ "ttl", 'H', OPTPARSE_REQUIRED },
{ "interval", 'i', OPTPARSE_REQUIRED },
{ "iface", 'I', OPTPARSE_REQUIRED },
+ { "icmp-timestamp", '0', OPTPARSE_NONE },
#ifdef SO_MARK
{ "fwmark", 'k', OPTPARSE_REQUIRED },
#endif
}
} else if (strstr(optparse_state.optlongname, "check-source") != NULL) {
check_source_flag = 1;
+ } else if (strstr(optparse_state.optlongname, "icmp-timestamp") != NULL) {
+ icmp_request_typ = 13;
} else if (strstr(optparse_state.optlongname, "print-tos") != NULL) {
print_tos_flag = 1;
} else if (strstr(optparse_state.optlongname, "print-ttl") != NULL) {
int n;
int myseq;
int ret = 1;
+ uint8_t proto = ICMP_ECHO;
update_current_time();
h->last_send_time = current_time_ns;
dbg_printf("%s [%d]: send ping\n", h->host, index);
if (h->saddr.ss_family == AF_INET && socket4 >= 0) {
- n = socket_sendto_ping_ipv4(socket4, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident4);
+ if(icmp_request_typ == 13)
+ proto = 13;
+ n = socket_sendto_ping_ipv4(socket4, (struct sockaddr *)&h->saddr, h->saddr_len, myseq, ident4, proto);
}
#ifdef IPV6
else if (h->saddr.ss_family == AF_INET6 && socket6 >= 0) {
unsigned short *id,
unsigned short *seq,
int *ip_header_tos,
- int *ip_header_ttl)
+ int *ip_header_ttl,
+ long *ip_header_otime_ms,
+ long *ip_header_rtime_ms,
+ long *ip_header_ttime_ms)
{
struct icmp *icp;
int hlen = 0;
icp = (struct icmp *)(reply_buf + hlen);
- if (icp->icmp_type != ICMP_ECHOREPLY) {
+ if (icp->icmp_type != ICMP_ECHOREPLY && icp->icmp_type != 14) {
/* Handle other ICMP packets */
struct icmp *sent_icmp;
SEQMAP_VALUE *seqmap_value;
sent_icmp = (struct icmp *)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip));
- if (sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != ident4) {
+ if ((sent_icmp->icmp_type != ICMP_ECHO && sent_icmp->icmp_type != 13) || sent_icmp->icmp_id != ident4) {
/* not caused by us */
return -1;
}
*id = icp->icmp_id;
*seq = ntohs(icp->icmp_seq);
+ if(icp->icmp_type == 14) {
+ *ip_header_otime_ms = ntohl(icp->icmp_dun.id_ts.its_otime);
+ *ip_header_rtime_ms = ntohl(icp->icmp_dun.id_ts.its_rtime);
+ *ip_header_ttime_ms = ntohl(icp->icmp_dun.id_ts.its_ttime);
+ //tsdiff_ms = tsrecv_ms - tsorig_ms;
+ }
return hlen;
}
unsigned short seq;
int ip_header_tos = -1;
int ip_header_ttl = -1;
+ // ICMP Timestamp
+ long ip_header_otime_ms = -1;
+ long ip_header_rtime_ms = -1;
+ long ip_header_ttime_ms = -1;
+ int tsrtt;
/* Receive packet */
result = receive_packet(wait_time, /* max. wait time, in ns */
&id,
&seq,
&ip_header_tos,
- &ip_header_ttl);
+ &ip_header_ttl,
+ &ip_header_otime_ms,
+ &ip_header_rtime_ms,
+ &ip_header_ttime_ms);
if (ip_hlen < 0) {
return 1;
}
}
}
+ if (icmp_request_typ == 13) {
+ if(ip_header_otime_ms != -1 && ip_header_rtime_ms != -1 && ip_header_ttime_ms != -1) {
+ printf(" (Timestamp Originate=%lu Receive=%lu Transmit=%lu)", ip_header_otime_ms, ip_header_rtime_ms, ip_header_ttime_ms);
+ }
+ else {
+ printf(" (Timestamp unknown)");
+ }
+ }
+
if (elapsed_flag)
printf(" (%s ms)", sprint_tm(this_reply));
}
printf("\n");
+
+ if (icmp_request_typ == 13) {
+ if(ip_header_otime_ms != -1 && ip_header_rtime_ms != -1 && ip_header_ttime_ms != -1) {
+ printf("ICMP timestamp: Originate=%lu Receive=%lu Transmit=%lu\n", ip_header_otime_ms, ip_header_rtime_ms, ip_header_ttime_ms);
+ tsrtt = (ip_header_ttime_ms - ip_header_otime_ms) + (this_reply - (ip_header_rtime_ms - ip_header_otime_ms));
+ printf("ICMP timestamp RTT tsrtt=%d\n", tsrtt);
+ }
+ else {
+ printf("ICMP timestamp: unknown\n");
+ }
+ }
}
return 1;
fprintf(out, " -t, --timeout=MSEC individual target initial timeout (default: %.0f ms,\n", timeout / 1e6);
fprintf(out, " except with -l/-c/-C, where it's the -p period up to 2000 ms)\n");
fprintf(out, " --check-source discard replies not from target address\n");
+ fprintf(out, " --icmp-timestamp send ping type Timestamp Request\n");
fprintf(out, "\n");
fprintf(out, "Output options:\n");
fprintf(out, " -a, --alive show targets that are alive\n");
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
+#include <time.h>
char* ping_buffer_ipv4 = 0;
size_t ping_pkt_size_ipv4;
return ~sum;
}
-int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
+int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr, uint8_t icmp_proto)
{
struct icmp* icp;
+ struct timespec tsorig;
+ long tsorig_ms;
int n;
icp = (struct icmp*)ping_buffer_ipv4;
- icp->icmp_type = ICMP_ECHO;
+ icp->icmp_type = icmp_proto;
+ if(icmp_proto == 13) {
+ clock_gettime(CLOCK_REALTIME, &tsorig);
+ tsorig_ms = (tsorig.tv_sec % (24*60*60)) * 1000 + tsorig.tv_nsec / 1000000;
+ icp->icmp_otime = htonl(tsorig_ms);
+ icp->icmp_rtime = 0;
+ icp->icmp_ttime = 0;
+ }
icp->icmp_code = 0;
icp->icmp_cksum = 0;
icp->icmp_seq = htons(icmp_seq_nr);