From 4b4750cb59a9285eaf55de3e89cddb9dae011377 Mon Sep 17 00:00:00 2001 From: lohhiiccc <96543753+lohhiiccc@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:59:08 +0200 Subject: [PATCH] feat: --preload option --- includes/internal/cli/options.h | 8 +++ includes/internal/ping/cli_handlers.h | 1 + includes/ping/ft_ping_const.h | 1 + includes/ping/ping.h | 1 + src/ping/Makefile.am | 1 + src/ping/cli/handlers/handle_preload.c | 14 +++++ src/ping/cli/parse.c | 1 + src/ping/core/ping.c | 75 +++++++++++++++++++------- 8 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 src/ping/cli/handlers/handle_preload.c diff --git a/includes/internal/cli/options.h b/includes/internal/cli/options.h index e3e68d6..d4aa1c9 100644 --- a/includes/internal/cli/options.h +++ b/includes/internal/cli/options.h @@ -109,6 +109,14 @@ enum { OPT_ARG_NONE, \ "Set the Don't Fragment bit" \ ) \ + X( \ + 'l', \ + "preload", \ + required_argument, \ + cli_handle_preload, \ + OPT_ARG_UINT, \ + "Send N packets in burst before normal loop" \ + ) \ X( \ 'p', \ "pattern", \ diff --git a/includes/internal/ping/cli_handlers.h b/includes/internal/ping/cli_handlers.h index 0e1d9c2..45e2c89 100644 --- a/includes/internal/ping/cli_handlers.h +++ b/includes/internal/ping/cli_handlers.h @@ -6,6 +6,7 @@ extern const struct option_descriptor g_options[]; int cli_handle_count(const char *arg, void *config); +int cli_handle_preload(const char *arg, void *config); int cli_handle_pattern(const char *arg, void *config); int cli_handle_dont_fragment(const char *arg, void *config); int cli_handle_deadline(const char *arg, void *config); diff --git a/includes/ping/ft_ping_const.h b/includes/ping/ft_ping_const.h index ffedf65..76e7f25 100644 --- a/includes/ping/ft_ping_const.h +++ b/includes/ping/ft_ping_const.h @@ -3,6 +3,7 @@ /* Default configuration values */ #define DEFAULT_COUNT 0 +#define DEFAULT_PRELOAD 1 #define DEFAULT_INTERVAL 1.0 #define DEFAULT_TTL 64 #define DEFAULT_PACKET_SIZE 56 diff --git a/includes/ping/ping.h b/includes/ping/ping.h index 3c9ade6..c29f7c2 100644 --- a/includes/ping/ping.h +++ b/includes/ping/ping.h @@ -16,6 +16,7 @@ struct ping_config /* Options */ uint64_t count; + uint64_t preload; double interval; uint8_t ttl; size_t packet_size; diff --git a/src/ping/Makefile.am b/src/ping/Makefile.am index a856257..bad783a 100644 --- a/src/ping/Makefile.am +++ b/src/ping/Makefile.am @@ -44,6 +44,7 @@ FORCE: libping_core_la_SOURCES = \ cli/parse.c \ cli/handlers/handle_count.c \ + cli/handlers/handle_preload.c \ cli/handlers/handle_pattern.c \ cli/handlers/handle_dont_fragment.c \ cli/handlers/handle_deadline.c \ diff --git a/src/ping/cli/handlers/handle_preload.c b/src/ping/cli/handlers/handle_preload.c new file mode 100644 index 0000000..56e3698 --- /dev/null +++ b/src/ping/cli/handlers/handle_preload.c @@ -0,0 +1,14 @@ +#include "ping/cli.h" +#include "internal/cli/parse_utils.h" + +int +cli_handle_preload(const char *arg, void *config_void) +{ + struct ping_config *config = (struct ping_config *)config_void; + uint64_t preload; + + if (0 != cli_parse_uint64(arg, &preload)) + return CLI_ERROR; + config->preload = preload; + return CLI_SUCCESS; +} diff --git a/src/ping/cli/parse.c b/src/ping/cli/parse.c index 5248afc..82b1246 100644 --- a/src/ping/cli/parse.c +++ b/src/ping/cli/parse.c @@ -31,6 +31,7 @@ init_config(struct ping_config *config) { memset(config, 0, sizeof(struct ping_config)); config->count = DEFAULT_COUNT; + config->preload = DEFAULT_PRELOAD; config->interval = DEFAULT_INTERVAL; config->ttl = DEFAULT_TTL; config->packet_size = DEFAULT_PACKET_SIZE; diff --git a/src/ping/core/ping.c b/src/ping/core/ping.c index 741d986..7ccfe37 100644 --- a/src/ping/core/ping.c +++ b/src/ping/core/ping.c @@ -1,3 +1,4 @@ +#include #include #include @@ -9,47 +10,59 @@ #include "internal/ping/loop.h" /* Forward declarations */ -static int ping_one(const struct ping_config *config, - struct destinations *dest, icmp_handle_t *handle); +static icmp_handle_t *ping_create_handle(const struct ping_config *config); +static int ping_one(const struct ping_config *config, struct destinations + *dest, icmp_handle_t *handle); static void ping_init_state(struct ping_state *state, struct ping_stats *stats, struct ping_tracker *tracker, const struct ping_config *config, struct in_addr dest, icmp_handle_t *handle); +static int ping_preload(struct ping_state *state, size_t payload_len); /* -------------------- */ int ping_run(const struct ping_config *config) { icmp_handle_t *handle; - int ret = 0 ; - size_t i = 0 ; + int ret = 0; + size_t i = 0; if (0 == config->nb_destinations) return 1; - handle = icmp_create(); + handle = ping_create_handle(config); if (NULL == handle) - { - dprintf(STDERR_FILENO, "%s: requires CAP_NET_RAW or root privileges\n", - g_prog_name); return 1; - } - if (HAS_FLAG(config->flags, FLAG_DONT_FRAGMENT) - && 0 != icmp_set_dont_fragment(handle)) - { - ret = 1; - goto cleanup; - } - while (i < config->nb_destinations) { if (0 != ping_one(config, &config->destinations[i], handle)) ret = 1; i++; } -cleanup: icmp_destroy(handle); return ret; } +static icmp_handle_t * +ping_create_handle(const struct ping_config *config) +{ + icmp_handle_t *handle; + + handle = icmp_create(); + if (NULL == handle) + { + dprintf(STDERR_FILENO, "%s: requires CAP_NET_RAW or root privileges\n", + g_prog_name); + return NULL; + } + if (HAS_FLAG(config->flags, FLAG_DONT_FRAGMENT) + && 0 != icmp_set_dont_fragment(handle)) + { + dprintf(STDERR_FILENO, "%s: %s\n", g_prog_name, icmp_strerror(handle)); + icmp_destroy(handle); + return NULL; + } + return handle; +} + static int ping_one(const struct ping_config *config, struct destinations *dest, icmp_handle_t *handle) @@ -62,9 +75,14 @@ ping_one(const struct ping_config *config, struct destinations *dest, ping_init_state(&state, &stats, &tracker, config, dest->ip, handle); payload_len = config->packet_size; if (0 != ping_scheduler_init(&state)) + { + dprintf(STDERR_FILENO, "%s: sigaction: %s\n", + g_prog_name, strerror(errno)); return 1; + } ping_output_start(config, dest, payload_len); - do_send(&state, payload_len); + if (0 != ping_preload(&state, payload_len)) + return 1; ping_loop(&state, payload_len); ping_output_summary(&state, dest); return tracker.nb_recv <= state.nb_errors; @@ -86,3 +104,24 @@ ping_init_state(struct ping_state *state, struct ping_stats *stats, state->handle = handle; icmp_get_time(&state->start_time); } + +static int +ping_preload(struct ping_state *state, size_t payload_len) +{ + const struct ping_config *config = state->config; + uint64_t i = 0; + + while (i < config->preload && (0 == config->count || + state->tracker->nb_sent < config->count)) + { + do_send(state, payload_len); + i++; + } + if (0 == config->preload && 0 != ping_scheduler_arm(config)) + { + dprintf(STDERR_FILENO, "%s: setitimer: %s\n", + g_prog_name, strerror(errno)); + return 1; + } + return 0; +}