Skip to content

Commit

Permalink
client: use interval argument range in wicked arp
Browse files Browse the repository at this point in the history
Parse `--interval <msec[..msec]>` option argument
as randomization range in `wicked arp` actions.
  • Loading branch information
mtomaschewski authored and cfconrad committed Jun 15, 2023
1 parent 9cd42dc commit 317d1e1
Showing 1 changed file with 81 additions and 34 deletions.
115 changes: 81 additions & 34 deletions client/arputil.c
Expand Up @@ -48,10 +48,20 @@ struct arp_ops;

#define NI_ARPUTIL_MAX_SEND_ERR 3

#define ARP_VERIFY_COUNT 3
#define ARP_VERIFY_INTERVAL_MIN 1000
#define ARP_VERIFY_INTERVAL_MAX 2000
#define ARP_NOTIFY_COUNT 2
#define ARP_NOTIFY_INTERVAL_MIN 2000
#define ARP_NOTIFY_INTERVAL_MAX 2000
#define ARP_PING_COUNT -1U
#define ARP_PING_INTERVAL_MIN 1000
#define ARP_PING_INTERVAL_MAX 1000

struct arp_handle {
ni_bool_t verbose;
unsigned int count;
unsigned int interval;
ni_uint_range_t interval;
unsigned int deadline;
unsigned int replies;

Expand Down Expand Up @@ -82,6 +92,31 @@ struct arp_ops {

static void do_arp_handle_close(struct arp_handle *);

static ni_bool_t
do_parse_interval(ni_uint_range_t *range, const char *arg)
{
const char *needle = "..";
ni_bool_t ret = FALSE;
char *smin = NULL;
char *smax = NULL;

if (!range || ni_string_empty(arg) || !ni_string_dup(&smin, arg))
return ret;

range->min = range->max = 0;
if ((smax = strstr(smin, needle))) {
*smax = '\0';
smax += ni_string_len(needle);
ret = !ni_parse_uint(smin, &range->min, 10) &&
!ni_parse_uint(smax, &range->max, 10) &&
range->min >= 100 && range->max >= range->min;
} else {
ret = !ni_parse_uint(smin, &range->min, 10) &&
(range->max = range->min) >= 100;
}
ni_string_free(&smin);
return ret;
}

static int
do_arp_init(struct arp_handle *handle, ni_capture_devinfo_t *dev_info)
Expand Down Expand Up @@ -261,11 +296,14 @@ do_arp_arm_deadline_timer(struct arp_handle *handle)
static void
do_arp_arm_interval_timer(struct arp_handle *handle)
{
ni_timeout_t rt;

rt = ni_timeout_random_range(handle->interval.min, handle->interval.max);
if (handle->timer.interval) {
ni_timer_rearm(handle->timer.interval, handle->interval);
ni_timer_rearm(handle->timer.interval, rt);
} else {
handle->timer.interval = ni_timer_register(
handle->interval, do_arp_interval_timeout, handle
rt, do_arp_interval_timeout, handle
);
}
}
Expand Down Expand Up @@ -325,11 +363,13 @@ do_arp_verify_run(struct arp_handle *handle, const char *caller, int argc, char
"\n"
" --count <count>\n"
" Send <count> duplicate address detection probes\n"
" (default: 3). Returns 4 when address is in use.\n"
" --interval <msec>\n"
" (default: %u). Returns 4 when address is in use.\n"
" --interval <msec[..msec]>\n"
" DAD probing packet sending interval in msec\n"
" (default: 1000..2000).\n"
" (default: %u..%u).\n"
, argv[0]
, ARP_VERIFY_COUNT
, ARP_VERIFY_INTERVAL_MIN, ARP_VERIFY_INTERVAL_MAX
);
goto cleanup;

Expand All @@ -351,8 +391,7 @@ do_arp_verify_run(struct arp_handle *handle, const char *caller, int argc, char
break;

case OPT_INTERVAL:
if (ni_parse_uint(optarg, &handle->interval, 10) ||
!handle->interval) {
if (!do_parse_interval(&handle->interval, optarg)) {
ni_error("%s: Cannot parse verify interval '%s'",
argv[0], optarg);
goto cleanup;
Expand Down Expand Up @@ -386,19 +425,19 @@ do_arp_verify_run(struct arp_handle *handle, const char *caller, int argc, char
static int
do_arp_verify_init(struct arp_handle *handle, ni_netdev_t *dev, ni_netconfig_t *nc)
{
/* a uniform random jitter of (PROBE_MAX - PROBE_MIN) */
const ni_int_range_t jitter = { .min = 0, .max = 1000 };
static const ni_uint_range_t range = {
.min = ARP_VERIFY_INTERVAL_MIN,
.max = ARP_VERIFY_INTERVAL_MAX,
};

(void)nc;
(void)dev;

/* rfc5227 PROBE_NUM */
if (!handle->count)
handle->count = 3;
handle->count = ARP_VERIFY_COUNT;

/* rfc5227 random(PROBE_MIN .. PROBE_MAX) */
if (!handle->interval)
handle->interval = ni_timeout_randomize(1000, &jitter);
if (!handle->interval.min)
handle->interval = range;

return 0;
}
Expand Down Expand Up @@ -596,11 +635,13 @@ do_arp_notify_run(struct arp_handle *handle, const char *caller, int argc, char
"\n"
" --count <count>\n"
" Announce IP address use (gratuitous ARP) <count> times\n"
" (default: 2).\n"
" --interval <msec>\n"
" (default: %u).\n"
" --interval <msec[..msec]>\n"
" Announcement packet sending interval in msec\n"
" (default: 2000).\n"
" (default: %u).\n"
, argv[0]
, ARP_NOTIFY_COUNT
, ARP_NOTIFY_INTERVAL_MIN
);
goto cleanup;

Expand All @@ -622,8 +663,7 @@ do_arp_notify_run(struct arp_handle *handle, const char *caller, int argc, char
break;

case OPT_INTERVAL:
if (ni_parse_uint(optarg, &handle->interval, 10) ||
!handle->interval) {
if (!do_parse_interval(&handle->interval, optarg)) {
ni_error("%s: Cannot parse notify interval '%s'",
argv[0], optarg);
goto cleanup;
Expand Down Expand Up @@ -657,16 +697,19 @@ do_arp_notify_run(struct arp_handle *handle, const char *caller, int argc, char
static int
do_arp_notify_init(struct arp_handle *handle, ni_netdev_t *dev, ni_netconfig_t *nc)
{
static const ni_uint_range_t range = {
.min = ARP_NOTIFY_INTERVAL_MIN,
.max = ARP_NOTIFY_INTERVAL_MAX,
};

(void)nc;
(void)dev;

/* rfc5227 ANNOUNCE_NUM */
if (!handle->count)
handle->count = 2;
handle->count = ARP_NOTIFY_COUNT;

/* rfc5227 ANNOUNCE_INTERVAL */
if (!handle->interval)
handle->interval = 2000;
if (!handle->interval.min)
handle->interval = range;

return 0;
}
Expand Down Expand Up @@ -794,16 +837,17 @@ do_arp_ping_run(struct arp_handle *handle, const char *caller, int argc, char **
" --count <count> | inf\n"
" Ping specified IP address <count> times\n"
" (default: infinite).\n"
" --interval <msec>\n"
" --interval <msec[..msec]>\n"
" Packet sending interval in msec\n"
" (default: 1000).\n"
" (default: %u).\n"
" --replies <count>\n"
" Wait unitil specified number of ping replies\n"
" --timeout <msec>\n"
" Wait for ping replies until given timeout in msec\n"
" --from-ip <source ip>\n"
" Use specified IP address as the ping source\n"
, argv[0]
, ARP_PING_INTERVAL_MIN
);
goto cleanup;

Expand All @@ -828,8 +872,7 @@ do_arp_ping_run(struct arp_handle *handle, const char *caller, int argc, char **
break;

case OPT_INTERVAL:
if (ni_parse_uint(optarg, &handle->interval, 10) ||
!handle->interval) {
if (!do_parse_interval(&handle->interval, optarg)) {
ni_error("%s: Cannot parse ping interval '%s'",
argv[0], optarg);
goto cleanup;
Expand Down Expand Up @@ -887,15 +930,19 @@ do_arp_ping_run(struct arp_handle *handle, const char *caller, int argc, char **
static int
do_arp_ping_init(struct arp_handle *handle, ni_netdev_t *dev, ni_netconfig_t *nc)
{
static const ni_uint_range_t range = {
.min = ARP_PING_INTERVAL_MIN,
.max = ARP_PING_INTERVAL_MAX,
};
ni_address_t *ap;

ni_assert(handle && nc && dev);

if (!handle->count)
handle->count = -1U;
handle->count = ARP_PING_COUNT;

if (!handle->interval)
handle->interval = 1000;
if (!handle->interval.min)
handle->interval = range;

if (handle->deadline) {
if (!handle->replies)
Expand Down Expand Up @@ -1165,7 +1212,7 @@ ni_do_arp(const char *caller, int argc, char **argv)
" Returns 4, when duplicate IP address exists.\n"
" --notify <count>\n"
" Notify about IP address use (gratuitous ARP)\n"
" --interval <msec>\n"
" --interval <msec[..msec]>\n"
" Packet sending interval in msec\n"
"\n"
"Actions:\n"
Expand Down Expand Up @@ -1207,7 +1254,7 @@ ni_do_arp(const char *caller, int argc, char **argv)
break;

case OPT_INTERVAL:
if (ni_parse_uint(optarg, &handle.interval, 10) || !handle.interval) {
if (!do_parse_interval(&handle.interval, optarg)) {
ni_error("%s: Cannot parse valid interval timeout: '%s'",
argv[0], optarg);
goto cleanup;
Expand Down

0 comments on commit 317d1e1

Please sign in to comment.