test-ndisc-send: convert to the new option parser
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include "sd-ndisc-protocol.h"
|
||||
@@ -17,6 +16,7 @@
|
||||
#include "ndisc-option.h"
|
||||
#include "netlink-util.h"
|
||||
#include "network-common.h"
|
||||
#include "options.h"
|
||||
#include "parse-util.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
@@ -72,197 +72,158 @@ static int parse_preference(const char *str) {
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_RA_HOP_LIMIT,
|
||||
ARG_RA_MANAGED,
|
||||
ARG_RA_OTHER,
|
||||
ARG_RA_HOME_AGENT,
|
||||
ARG_RA_PREFERENCE,
|
||||
ARG_RA_LIFETIME,
|
||||
ARG_RA_REACHABLE,
|
||||
ARG_RA_RETRANSMIT,
|
||||
ARG_NA_ROUTER,
|
||||
ARG_NA_SOLICITED,
|
||||
ARG_NA_OVERRIDE,
|
||||
ARG_TARGET_ADDRESS,
|
||||
ARG_REDIRECT_DESTINATION,
|
||||
ARG_OPTION_SOURCE_LL,
|
||||
ARG_OPTION_TARGET_LL,
|
||||
ARG_OPTION_REDIRECTED_HEADER,
|
||||
ARG_OPTION_MTU,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "type", required_argument, NULL, 't' },
|
||||
{ "dest", required_argument, NULL, 'd' },
|
||||
/* For Router Advertisement */
|
||||
{ "hop-limit", required_argument, NULL, ARG_RA_HOP_LIMIT },
|
||||
{ "managed", required_argument, NULL, ARG_RA_MANAGED },
|
||||
{ "other", required_argument, NULL, ARG_RA_OTHER },
|
||||
{ "home-agent", required_argument, NULL, ARG_RA_HOME_AGENT },
|
||||
{ "preference", required_argument, NULL, ARG_RA_PREFERENCE },
|
||||
{ "lifetime", required_argument, NULL, ARG_RA_LIFETIME },
|
||||
{ "reachable-time", required_argument, NULL, ARG_RA_REACHABLE },
|
||||
{ "retransmit-timer", required_argument, NULL, ARG_RA_RETRANSMIT },
|
||||
/* For Neighbor Advertisement */
|
||||
{ "is-router", required_argument, NULL, ARG_NA_ROUTER },
|
||||
{ "is-solicited", required_argument, NULL, ARG_NA_SOLICITED },
|
||||
{ "is-override", required_argument, NULL, ARG_NA_OVERRIDE },
|
||||
/* For Neighbor Solicit, Neighbor Advertisement, and Redirect */
|
||||
{ "target-address", required_argument, NULL, ARG_TARGET_ADDRESS },
|
||||
/* For Redirect */
|
||||
{ "redirect-destination", required_argument, NULL, ARG_REDIRECT_DESTINATION },
|
||||
/* Options */
|
||||
{ "source-ll-address", required_argument, NULL, ARG_OPTION_SOURCE_LL },
|
||||
{ "target-ll-address", required_argument, NULL, ARG_OPTION_TARGET_LL },
|
||||
{ "redirected-header", required_argument, NULL, ARG_OPTION_REDIRECTED_HEADER },
|
||||
{ "mtu", required_argument, NULL, ARG_OPTION_MTU },
|
||||
{}
|
||||
};
|
||||
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
int c, r;
|
||||
int r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "i:t:d:", options, NULL)) >= 0) {
|
||||
OptionParser state = { argc, argv };
|
||||
const char *arg;
|
||||
|
||||
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
|
||||
switch (c) {
|
||||
|
||||
case ARG_VERSION:
|
||||
OPTION_COMMON_VERSION:
|
||||
return version();
|
||||
|
||||
case 'i':
|
||||
r = rtnl_resolve_interface_or_warn(&rtnl, optarg);
|
||||
OPTION('i', "interface", "INTERFACE", "Network interface"):
|
||||
r = rtnl_resolve_interface_or_warn(&rtnl, arg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
arg_ifindex = r;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
r = parse_icmp6_type(optarg);
|
||||
OPTION('t', "type", "TYPE", "ICMPv6 message type"):
|
||||
r = parse_icmp6_type(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse message type: %m");
|
||||
arg_icmp6_type = r;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
r = in_addr_from_string(AF_INET6, optarg, &arg_dest);
|
||||
OPTION('d', "dest", "ADDRESS", "Destination address"):
|
||||
r = in_addr_from_string(AF_INET6, arg, &arg_dest);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse destination address: %m");
|
||||
if (!in6_addr_is_link_local(&arg_dest.in6))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The destination address %s is not a link-local address.", optarg);
|
||||
"The destination address %s is not a link-local address.", arg);
|
||||
break;
|
||||
|
||||
case ARG_RA_HOP_LIMIT:
|
||||
r = safe_atou8(optarg, &arg_hop_limit);
|
||||
OPTION_GROUP("Router Advertisement"): {}
|
||||
|
||||
OPTION_LONG("hop-limit", "LIMIT", "Hop limit"):
|
||||
r = safe_atou8(arg, &arg_hop_limit);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse hop limit: %m");
|
||||
break;
|
||||
|
||||
case ARG_RA_MANAGED:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_LONG("managed", "BOOL", "Managed flag"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse managed flag: %m");
|
||||
SET_FLAG(arg_ra_flags, ND_RA_FLAG_MANAGED, r);
|
||||
break;
|
||||
|
||||
case ARG_RA_OTHER:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_LONG("other", "BOOL", "Other flag"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse other flag: %m");
|
||||
SET_FLAG(arg_ra_flags, ND_RA_FLAG_OTHER, r);
|
||||
break;
|
||||
|
||||
case ARG_RA_HOME_AGENT:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_LONG("home-agent", "BOOL", "Home-agent flag"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse home-agent flag: %m");
|
||||
SET_FLAG(arg_ra_flags, ND_RA_FLAG_HOME_AGENT, r);
|
||||
break;
|
||||
|
||||
case ARG_RA_PREFERENCE:
|
||||
r = parse_preference(optarg);
|
||||
OPTION_LONG("preference", "PREF", "Preference"):
|
||||
r = parse_preference(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse preference: %m");
|
||||
arg_preference = r;
|
||||
break;
|
||||
|
||||
case ARG_RA_LIFETIME:
|
||||
r = parse_sec(optarg, &arg_lifetime);
|
||||
OPTION_LONG("lifetime", "SECS", "Lifetime"):
|
||||
r = parse_sec(arg, &arg_lifetime);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse lifetime: %m");
|
||||
break;
|
||||
|
||||
case ARG_RA_REACHABLE:
|
||||
r = parse_sec(optarg, &arg_reachable);
|
||||
OPTION_LONG("reachable-time", "SECS", "Reachable time"):
|
||||
r = parse_sec(arg, &arg_reachable);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse reachable time: %m");
|
||||
break;
|
||||
|
||||
case ARG_RA_RETRANSMIT:
|
||||
r = parse_sec(optarg, &arg_retransmit);
|
||||
OPTION_LONG("retransmit-timer", "SECS", "Retransmit timer"):
|
||||
r = parse_sec(arg, &arg_retransmit);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse retransmit timer: %m");
|
||||
break;
|
||||
|
||||
case ARG_NA_ROUTER:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_GROUP("Neighbor Advertisement"): {}
|
||||
|
||||
OPTION_LONG("is-router", "BOOL", "Router flag"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse is-router flag: %m");
|
||||
SET_FLAG(arg_na_flags, ND_NA_FLAG_ROUTER, r);
|
||||
break;
|
||||
|
||||
case ARG_NA_SOLICITED:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_LONG("is-solicited", "BOOL", "Solicited flag"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse is-solicited flag: %m");
|
||||
SET_FLAG(arg_na_flags, ND_NA_FLAG_SOLICITED, r);
|
||||
break;
|
||||
|
||||
case ARG_NA_OVERRIDE:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_LONG("is-override", "BOOL", "Override flag"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse is-override flag: %m");
|
||||
SET_FLAG(arg_na_flags, ND_NA_FLAG_OVERRIDE, r);
|
||||
break;
|
||||
|
||||
case ARG_TARGET_ADDRESS:
|
||||
r = in_addr_from_string(AF_INET6, optarg, &arg_target_address);
|
||||
OPTION_GROUP("Neighbor Solicit/Advertisement and Redirect"): {}
|
||||
|
||||
OPTION_LONG("target-address", "ADDRESS", "Target address"):
|
||||
r = in_addr_from_string(AF_INET6, arg, &arg_target_address);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse target address: %m");
|
||||
break;
|
||||
|
||||
case ARG_REDIRECT_DESTINATION:
|
||||
r = in_addr_from_string(AF_INET6, optarg, &arg_redirect_destination);
|
||||
OPTION_GROUP("Redirect"): {}
|
||||
|
||||
OPTION_LONG("redirect-destination", "ADDRESS", "Redirect destination address"):
|
||||
r = in_addr_from_string(AF_INET6, arg, &arg_redirect_destination);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse destination address: %m");
|
||||
break;
|
||||
|
||||
case ARG_OPTION_SOURCE_LL:
|
||||
r = parse_boolean(optarg);
|
||||
OPTION_GROUP("NDisc Options"): {}
|
||||
|
||||
OPTION_LONG("source-ll-address", "BOOL", "Include source link-layer address"):
|
||||
r = parse_boolean(arg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse source LL address option: %m");
|
||||
arg_set_source_mac = r;
|
||||
break;
|
||||
|
||||
case ARG_OPTION_TARGET_LL:
|
||||
r = parse_ether_addr(optarg, &arg_target_mac);
|
||||
OPTION_LONG("target-ll-address", "ADDRESS", "Target link-layer address"):
|
||||
r = parse_ether_addr(arg, &arg_target_mac);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse target LL address option: %m");
|
||||
arg_set_target_mac = true;
|
||||
break;
|
||||
|
||||
case ARG_OPTION_REDIRECTED_HEADER: {
|
||||
OPTION_LONG("redirected-header", "BASE64", "Redirected header (base64)"): {
|
||||
_cleanup_free_ void *p = NULL;
|
||||
size_t len;
|
||||
|
||||
r = unbase64mem(optarg, &p, &len);
|
||||
r = unbase64mem(arg, &p, &len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse redirected header: %m");
|
||||
|
||||
@@ -272,20 +233,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_redirected_header = TAKE_PTR(p);
|
||||
break;
|
||||
}
|
||||
case ARG_OPTION_MTU:
|
||||
r = safe_atou32(optarg, &arg_mtu);
|
||||
|
||||
OPTION_LONG("mtu", "MTU", "MTU"):
|
||||
r = safe_atou32(arg, &arg_mtu);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse MTU: %m");
|
||||
arg_set_mtu = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_ifindex <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--interface/-i option is mandatory.");
|
||||
|
||||
Reference in New Issue
Block a user