Skip to content

Commit

Permalink
Add feature: support ICMP type 13/14 timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
gsnw-sebast committed Oct 8, 2024
1 parent b32852c commit 6190def
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 10 deletions.
10 changes: 9 additions & 1 deletion ci/test-04-options-a-b.pl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/perl -w

use Test::Command tests => 41;
use Test::Command tests => 44;
use Test::More;
use Time::HiRes qw(gettimeofday tv_interval);

Expand Down Expand Up @@ -84,6 +84,14 @@
$cmd->stderr_is_eq("");
}

# fping --icmp-timestamp
{
my $cmd = Test::Command->new(cmd => "fping --icmp-timestamp 127.0.0.1");
$cmd->exit_is_num(0);
$cmd->stdout_like(qr{127\.0\.0\.1 is alive \(Timestamp Originate=\d+ Receive=\d+ Transmit=\d+\)});
$cmd->stderr_is_eq("");
}

# fping --print-ttl with IPv6
SKIP: {
if($ENV{SKIP_IPV6}) {
Expand Down
18 changes: 17 additions & 1 deletion ci/test-05-options-c-e.pl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/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)
Expand Down Expand Up @@ -77,6 +77,22 @@
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
{
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");
Expand Down
55 changes: 50 additions & 5 deletions src/fping.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ int timestamp_format_flag = 0;
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)
Expand Down Expand Up @@ -536,6 +537,7 @@ int main(int argc, char **argv)
{ "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
Expand Down Expand Up @@ -584,6 +586,8 @@ int main(int argc, char **argv)
}
} 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) {
Expand Down Expand Up @@ -1925,6 +1929,7 @@ int send_ping(HOST_ENTRY *h, int index)
int n;
int myseq;
int ret = 1;
uint8_t proto = ICMP_ECHO;

update_current_time();
h->last_send_time = current_time_ns;
Expand All @@ -1933,7 +1938,9 @@ int send_ping(HOST_ENTRY *h, int index)
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) {
Expand Down Expand Up @@ -2173,7 +2180,10 @@ int decode_icmp_ipv4(
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;
Expand Down Expand Up @@ -2206,7 +2216,7 @@ int decode_icmp_ipv4(

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;
Expand All @@ -2221,7 +2231,7 @@ int decode_icmp_ipv4(

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;
}
Expand Down Expand Up @@ -2272,6 +2282,12 @@ int decode_icmp_ipv4(

*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;
}
Expand Down Expand Up @@ -2384,6 +2400,11 @@ int wait_for_reply(int64_t wait_time)
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 */
Expand Down Expand Up @@ -2412,7 +2433,10 @@ int wait_for_reply(int64_t wait_time)
&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;
}
Expand Down Expand Up @@ -2539,6 +2563,15 @@ int wait_for_reply(int64_t wait_time)
}
}

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));

Expand Down Expand Up @@ -2578,6 +2611,17 @@ int wait_for_reply(int64_t wait_time)
}

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;
Expand Down Expand Up @@ -3088,6 +3132,7 @@ void usage(int is_error)
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");
Expand Down
2 changes: 1 addition & 1 deletion src/fping.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern int random_data_flag;
int open_ping_socket_ipv4(int *socktype);
void init_ping_buffer_ipv4(size_t ping_data_size);
void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident);
int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id);
int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id, uint8_t icmp_proto);
#ifdef IPV6
int open_ping_socket_ipv6(int *socktype);
void init_ping_buffer_ipv6(size_t ping_data_size);
Expand Down
14 changes: 12 additions & 2 deletions src/socket4.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <time.h>

char* ping_buffer_ipv4 = 0;
size_t ping_pkt_size_ipv4;
Expand Down Expand Up @@ -129,14 +130,23 @@ unsigned short calcsum(unsigned short* buffer, int length)
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);
Expand Down

0 comments on commit 6190def

Please sign in to comment.