Compare commits

..

2 commits

Author SHA1 Message Date
lohhiiccc
606069df82 chore: update LICENSE 2026-04-23 13:00:45 +02:00
lohhiiccc
4b4750cb59 feat: --preload option 2026-04-23 12:59:08 +02:00
11 changed files with 87 additions and 21 deletions

View file

@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode: notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author> net-tools Copyright (C) 2026 lohhiiccc
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.

View file

@ -109,6 +109,14 @@ enum {
OPT_ARG_NONE, \ OPT_ARG_NONE, \
"Set the Don't Fragment bit" \ "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( \ X( \
'p', \ 'p', \
"pattern", \ "pattern", \

View file

@ -6,6 +6,7 @@
extern const struct option_descriptor g_options[]; extern const struct option_descriptor g_options[];
int cli_handle_count(const char *arg, void *config); 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_pattern(const char *arg, void *config);
int cli_handle_dont_fragment(const char *arg, void *config); int cli_handle_dont_fragment(const char *arg, void *config);
int cli_handle_deadline(const char *arg, void *config); int cli_handle_deadline(const char *arg, void *config);

View file

@ -3,6 +3,7 @@
/* Default configuration values */ /* Default configuration values */
#define DEFAULT_COUNT 0 #define DEFAULT_COUNT 0
#define DEFAULT_PRELOAD 1
#define DEFAULT_INTERVAL 1.0 #define DEFAULT_INTERVAL 1.0
#define DEFAULT_TTL 64 #define DEFAULT_TTL 64
#define DEFAULT_PACKET_SIZE 56 #define DEFAULT_PACKET_SIZE 56

View file

@ -16,6 +16,7 @@ struct ping_config
/* Options */ /* Options */
uint64_t count; uint64_t count;
uint64_t preload;
double interval; double interval;
uint8_t ttl; uint8_t ttl;
size_t packet_size; size_t packet_size;

2
libcli

@ -1 +1 @@
Subproject commit ad6a542969dda29afe5431d0e674eca8d8794141 Subproject commit d39210fe74135e806adba7a6ea18696a901ba2d0

@ -1 +1 @@
Subproject commit a9bdaf33f22b60b8643871b2522721cd041ac885 Subproject commit e6693c97cc22b82adc3be85c72a5d5f655c69eb1

View file

@ -44,6 +44,7 @@ FORCE:
libping_core_la_SOURCES = \ libping_core_la_SOURCES = \
cli/parse.c \ cli/parse.c \
cli/handlers/handle_count.c \ cli/handlers/handle_count.c \
cli/handlers/handle_preload.c \
cli/handlers/handle_pattern.c \ cli/handlers/handle_pattern.c \
cli/handlers/handle_dont_fragment.c \ cli/handlers/handle_dont_fragment.c \
cli/handlers/handle_deadline.c \ cli/handlers/handle_deadline.c \

View file

@ -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;
}

View file

@ -31,6 +31,7 @@ init_config(struct ping_config *config)
{ {
memset(config, 0, sizeof(struct ping_config)); memset(config, 0, sizeof(struct ping_config));
config->count = DEFAULT_COUNT; config->count = DEFAULT_COUNT;
config->preload = DEFAULT_PRELOAD;
config->interval = DEFAULT_INTERVAL; config->interval = DEFAULT_INTERVAL;
config->ttl = DEFAULT_TTL; config->ttl = DEFAULT_TTL;
config->packet_size = DEFAULT_PACKET_SIZE; config->packet_size = DEFAULT_PACKET_SIZE;

View file

@ -1,3 +1,4 @@
#include <errno.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -9,11 +10,13 @@
#include "internal/ping/loop.h" #include "internal/ping/loop.h"
/* Forward declarations */ /* Forward declarations */
static int ping_one(const struct ping_config *config, static icmp_handle_t *ping_create_handle(const struct ping_config *config);
struct destinations *dest, icmp_handle_t *handle); 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, static void ping_init_state(struct ping_state *state, struct ping_stats *stats,
struct ping_tracker *tracker, const struct ping_config *config, struct ping_tracker *tracker, const struct ping_config *config,
struct in_addr dest, icmp_handle_t *handle); struct in_addr dest, icmp_handle_t *handle);
static int ping_preload(struct ping_state *state, size_t payload_len);
/* -------------------- */ /* -------------------- */
int int
@ -25,31 +28,41 @@ ping_run(const struct ping_config *config)
if (0 == config->nb_destinations) if (0 == config->nb_destinations)
return 1; return 1;
handle = icmp_create(); handle = ping_create_handle(config);
if (NULL == handle) if (NULL == handle)
{
dprintf(STDERR_FILENO, "%s: requires CAP_NET_RAW or root privileges\n",
g_prog_name);
return 1; 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) while (i < config->nb_destinations)
{ {
if (0 != ping_one(config, &config->destinations[i], handle)) if (0 != ping_one(config, &config->destinations[i], handle))
ret = 1; ret = 1;
i++; i++;
} }
cleanup:
icmp_destroy(handle); icmp_destroy(handle);
return ret; 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 static int
ping_one(const struct ping_config *config, struct destinations *dest, ping_one(const struct ping_config *config, struct destinations *dest,
icmp_handle_t *handle) 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); ping_init_state(&state, &stats, &tracker, config, dest->ip, handle);
payload_len = config->packet_size; payload_len = config->packet_size;
if (0 != ping_scheduler_init(&state)) if (0 != ping_scheduler_init(&state))
{
dprintf(STDERR_FILENO, "%s: sigaction: %s\n",
g_prog_name, strerror(errno));
return 1; return 1;
}
ping_output_start(config, dest, payload_len); 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_loop(&state, payload_len);
ping_output_summary(&state, dest); ping_output_summary(&state, dest);
return tracker.nb_recv <= state.nb_errors; 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; state->handle = handle;
icmp_get_time(&state->start_time); 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;
}