From 317d1e13972fd178ad3219b7be8d0bc474bf92d2 Mon Sep 17 00:00:00 2001 From: Marius Tomaschewski Date: Thu, 15 Jun 2023 10:39:26 +0200 Subject: [PATCH] client: use interval argument range in `wicked arp` Parse `--interval ` option argument as randomization range in `wicked arp` actions. --- client/arputil.c | 115 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/client/arputil.c b/client/arputil.c index 2c7370642..ab35782c6 100644 --- a/client/arputil.c +++ b/client/arputil.c @@ -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; @@ -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) @@ -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 ); } } @@ -325,11 +363,13 @@ do_arp_verify_run(struct arp_handle *handle, const char *caller, int argc, char "\n" " --count \n" " Send duplicate address detection probes\n" - " (default: 3). Returns 4 when address is in use.\n" - " --interval \n" + " (default: %u). Returns 4 when address is in use.\n" + " --interval \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; @@ -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; @@ -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; } @@ -596,11 +635,13 @@ do_arp_notify_run(struct arp_handle *handle, const char *caller, int argc, char "\n" " --count \n" " Announce IP address use (gratuitous ARP) times\n" - " (default: 2).\n" - " --interval \n" + " (default: %u).\n" + " --interval \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; @@ -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; @@ -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; } @@ -794,9 +837,9 @@ do_arp_ping_run(struct arp_handle *handle, const char *caller, int argc, char ** " --count | inf\n" " Ping specified IP address times\n" " (default: infinite).\n" - " --interval \n" + " --interval \n" " Packet sending interval in msec\n" - " (default: 1000).\n" + " (default: %u).\n" " --replies \n" " Wait unitil specified number of ping replies\n" " --timeout \n" @@ -804,6 +847,7 @@ do_arp_ping_run(struct arp_handle *handle, const char *caller, int argc, char ** " --from-ip \n" " Use specified IP address as the ping source\n" , argv[0] + , ARP_PING_INTERVAL_MIN ); goto cleanup; @@ -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; @@ -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) @@ -1165,7 +1212,7 @@ ni_do_arp(const char *caller, int argc, char **argv) " Returns 4, when duplicate IP address exists.\n" " --notify \n" " Notify about IP address use (gratuitous ARP)\n" - " --interval \n" + " --interval \n" " Packet sending interval in msec\n" "\n" "Actions:\n" @@ -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;