net-tools/src/ping/core/callback.c
2026-03-16 11:49:10 -05:00

90 lines
2.3 KiB
C

#include "icmp_types.h"
#include "ping/ft_ping_flags.h"
#include "internal/ping/output.h"
/* Forward declarations */
static int extract_our_echo(const icmp_reply_t *reply, uint16_t our_id,
uint16_t *seq_out);
static void handle_echo_reply(struct ping_state *state,
const icmp_reply_t *reply);
static int extract_our_error(const icmp_reply_t *reply, uint16_t our_id,
icmp_offending_packet_t *out, uint16_t *seq_out);
static void handle_icmp_error(struct ping_state *state,
const icmp_reply_t *reply);
/* -------------------- */
void
ping_callback(const icmp_reply_t *reply, void *userdata)
{
struct ping_state *state;
state = (struct ping_state *)userdata;
if (ICMP_TYPE_ECHO_REPLY == reply->type)
handle_echo_reply(state, reply);
else if (ICMP_TYPE_TIME_EXCEEDED == reply->type
|| ICMP_TYPE_DEST_UNREACHABLE == reply->type)
handle_icmp_error(state, reply);
}
static int
extract_our_echo(const icmp_reply_t *reply, uint16_t our_id,
uint16_t *seq_out)
{
uint16_t id;
uint16_t seq;
if (0 > icmp_reply_id_seq(reply, &id, &seq))
return 0;
if (our_id != id)
return 0;
*seq_out = seq;
return 1;
}
static void
handle_echo_reply(struct ping_state *state, const icmp_reply_t *reply)
{
uint16_t seq;
int64_t rtt;
if (0 == extract_our_echo(reply, state->id, &seq))
return;
rtt = ping_tracker_record_recv(state->tracker, seq, &reply->timestamp);
if (0 > rtt)
return;
ping_stats_update(state->stats, rtt);
if (HAS_FLAG(state->config->flags, FLAG_FLOOD))
ping_output_flood_erase();
else
ping_output_packet(reply, seq, rtt, state->config->packet_size,
state->config);
}
static int
extract_our_error(const icmp_reply_t *reply, uint16_t our_id,
icmp_offending_packet_t *out, uint16_t *seq_out)
{
if (0 > icmp_error_extract_offending(reply, out))
return 0;
if (ICMP_TYPE_ECHO_REQUEST != out->icmp_type)
return 0;
if (our_id != out->rest.echo.id)
return 0;
*seq_out = out->rest.echo.seq;
return 1;
}
static void
handle_icmp_error(struct ping_state *state, const icmp_reply_t *reply)
{
icmp_offending_packet_t offending;
uint16_t seq;
if (0 == extract_our_error(reply, state->id, &offending, &seq))
return;
if (0 > ping_tracker_record_recv(state->tracker, seq, &reply->timestamp))
return;
state->nb_errors++;
if (!HAS_FLAG(state->config->flags, FLAG_QUIET))
ping_output_error(reply, &offending, seq, state->config);
}