/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <getopt.h>
#include <locale.h>
#include <net/if.h>
#include "af-list.h"
#include "alloc-util.h"
+#include "ansi-color.h"
#include "argv-util.h"
#include "build.h"
#include "bus-common-errors.h"
#include "escape.h"
#include "format-ifname.h"
#include "format-table.h"
+#include "glyph-util.h"
+#include "help-util.h"
#include "hostname-util.h"
#include "json-util.h"
#include "main-func.h"
#include "missing-network.h"
#include "netlink-util.h"
+#include "options.h"
#include "ordered-set.h"
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "polkit-agent.h"
-#include "pretty-print.h"
#include "resolvconf-compat.h"
#include "resolve-util.h"
#include "resolvectl.h"
"Invalid DNS URI: %s", name);
}
+VERB(verb_query, "query", "HOSTNAME|ADDRESS…", 2, VERB_ANY, 0,
+ "Resolve domain names, IPv4 and IPv6 addresses");
static int verb_query(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int ret = 0, r;
return 0;
}
+VERB(verb_service, "service", "[[NAME] TYPE] DOMAIN", 2, 4, 0,
+ "Resolve service (SRV)");
static int verb_service(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
}
#endif
+VERB(verb_openpgp, "openpgp", "EMAIL@DOMAIN…", 2, VERB_ANY, 0,
+ "Query OpenPGP public key");
static int verb_openpgp(int argc, char *argv[], uintptr_t _data, void *userdata) {
#if HAVE_OPENSSL
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
return STR_IN_SET(s, "tcp", "udp", "sctp");
}
+VERB(verb_tlsa, "tlsa", "DOMAIN[:PORT]…", 2, VERB_ANY, 0,
+ "Query TLS public key");
static int verb_tlsa(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *family = "tcp";
return status_full(mode, STRV_MAKE(ifname));
}
+VERB(verb_status, "status", "[LINK…]", VERB_ANY, VERB_ANY, VERB_DEFAULT,
+ "Show link and server status");
static int verb_status(int argc, char *argv[], uintptr_t _data, void *userdata) {
return status_full(STATUS_ALL, strv_skip(argv, 1));
}
+VERB(verb_show_statistics, "statistics", NULL, VERB_ANY, 1, 0,
+ "Show resolver statistics");
static int verb_show_statistics(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(table_unrefp) Table *table = NULL;
sd_json_variant *reply = NULL;
return table_print_or_warn(table);
}
+VERB(verb_reset_statistics, "reset-statistics", NULL, VERB_ANY, 1, 0,
+ "Reset resolver statistics");
static int verb_reset_statistics(int argc, char *argv[], uintptr_t _data, void *userdata) {
sd_json_variant *reply = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
return 0;
}
+VERB(verb_flush_caches, "flush-caches", NULL, VERB_ANY, 1, 0,
+ "Flush all local DNS caches");
static int verb_flush_caches(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_reset_server_features, "reset-server-features", NULL, VERB_ANY, 1, 0,
+ "Forget learnt DNS server feature levels");
static int verb_reset_server_features(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_monitor, "monitor", NULL, VERB_ANY, 1, 0,
+ "Monitor DNS queries");
static int verb_monitor(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
return 0;
}
+VERB(verb_show_cache, "show-cache", NULL, VERB_ANY, 1, 0,
+ "Show cache contents");
static int verb_show_cache(int argc, char *argv[], uintptr_t _data, void *userdata) {
sd_json_variant *reply = NULL, *d = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
return table_print_or_warn(table);
}
+VERB(verb_show_server_state, "show-server-state", NULL, VERB_ANY, 1, 0,
+ "Show servers state");
static int verb_show_server_state(int argc, char *argv[], uintptr_t _data, void *userdata) {
sd_json_variant *reply = NULL, *d = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
return sd_json_variant_dump(d, arg_json_format_flags, NULL, NULL);
}
+VERB(verb_dns, "dns", "[LINK [SERVER…]]", VERB_ANY, VERB_ANY, 0,
+ "Get/set per-interface DNS server address");
static int verb_dns(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return sd_bus_call(bus, req, 0, error, NULL);
}
+VERB(verb_domain, "domain", "[LINK [DOMAIN…]]", VERB_ANY, VERB_ANY, 0,
+ "Get/set per-interface search domain");
static int verb_domain(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_default_route, "default-route", "[LINK [BOOL]]", VERB_ANY, 3, 0,
+ "Get/set per-interface default route flag");
static int verb_default_route(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_llmnr, "llmnr", "[LINK [MODE]]", VERB_ANY, 3, 0,
+ "Get/set per-interface LLMNR mode");
static int verb_llmnr(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_mdns, "mdns", "[LINK [MODE]]", VERB_ANY, 3, 0,
+ "Get/set per-interface MulticastDNS mode");
static int verb_mdns(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_dns_over_tls, "dnsovertls", "[LINK [MODE]]", VERB_ANY, 3, 0,
+ "Get/set per-interface DNS-over-TLS mode");
static int verb_dns_over_tls(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_dnssec, "dnssec", "[LINK [MODE]]", VERB_ANY, 3, 0,
+ "Get/set per-interface DNSSEC mode");
static int verb_dnssec(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return sd_bus_call(bus, req, 0, error, NULL);
}
+VERB(verb_nta, "nta", "[LINK [DOMAIN…]]", VERB_ANY, VERB_ANY, 0,
+ "Get/set per-interface DNSSEC NTA");
static int verb_nta(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_revert_link, "revert", "LINK", VERB_ANY, 2, 0,
+ "Revert per-interface configuration");
static int verb_revert_link(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
return 0;
}
+VERB(verb_log_level, "log-level", "[LEVEL]", VERB_ANY, 2, 0,
+ "Get/set logging threshold for systemd-resolved");
static int verb_log_level(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
}
static int compat_help(void) {
- _cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL;
int r;
- r = terminal_urlify_man("resolvectl", "1", &link);
+ r = option_parser_get_help_table_ns("systemd-resolve", &options);
if (r < 0)
- return log_oom();
+ return r;
pager_open(arg_pager_flags);
- printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
- "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
- "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
- "%1$s [OPTIONS...] --statistics\n"
- "%1$s [OPTIONS...] --reset-statistics\n"
- "\n"
- "%2$sResolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%3$s\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -4 Resolve IPv4 addresses\n"
- " -6 Resolve IPv6 addresses\n"
- " -i --interface=INTERFACE Look on interface\n"
- " -p --protocol=PROTO|help Look via protocol\n"
- " -t --type=TYPE|help Query RR with DNS type\n"
- " -c --class=CLASS|help Query RR with DNS class\n"
- " --service Resolve service (SRV)\n"
- " --service-address=BOOL Resolve address for services (default: yes)\n"
- " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
- " --openpgp Query OpenPGP public key\n"
- " --tlsa Query TLS public key\n"
- " --cname=BOOL Follow CNAME redirects (default: yes)\n"
- " --search=BOOL Use search domains for single-label names\n"
- " (default: yes)\n"
- " --statistics Show resolver statistics\n"
- " --reset-statistics Reset resolver statistics\n"
- " --status Show link and server status\n"
- " --flush-caches Flush all local DNS caches\n"
- " --reset-server-features\n"
- " Forget learnt DNS server feature levels\n"
- " --set-dns=SERVER Set per-interface DNS server address\n"
- " --set-domain=DOMAIN Set per-interface search domain\n"
- " --set-llmnr=MODE Set per-interface LLMNR mode\n"
- " --set-mdns=MODE Set per-interface MulticastDNS mode\n"
- " --set-dnsovertls=MODE Set per-interface DNS-over-TLS mode\n"
- " --set-dnssec=MODE Set per-interface DNSSEC mode\n"
- " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n"
- " --revert Revert per-interface configuration\n"
- " --raw[=payload|packet] Dump the answer as binary data\n"
- " --no-pager Do not pipe output into a pager\n"
- " --legend=BOOL Print headers and additional info (default: yes)\n"
- "\nSee the %4$s for details.\n",
- program_invocation_short_name,
- ansi_highlight(),
- ansi_normal(),
- link);
+ help_cmdline("[OPTIONS…] HOSTNAME|ADDRESS…");
+ help_cmdline("[OPTIONS…] --service [[NAME] TYPE] DOMAIN");
+ help_cmdline("[OPTIONS…] --openpgp EMAIL@DOMAIN…");
+ help_cmdline("[OPTIONS…] --statistics");
+ help_cmdline("[OPTIONS…] --reset-statistics");
+ help_abstract("Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.");
+
+ help_section("Options");
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+ help_man_page_reference("resolvectl", "1");
return 0;
}
static int native_help(void) {
- _cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *verbs = NULL, *options = NULL;
int r;
- r = terminal_urlify_man("resolvectl", "1", &link);
+ r = verbs_get_help_table(&verbs);
if (r < 0)
- return log_oom();
+ return r;
+
+ r = option_parser_get_help_table_ns("resolvectl", &options);
+ if (r < 0)
+ return r;
+
+ (void) table_sync_column_widths(0, verbs, options);
pager_open(arg_pager_flags);
- printf("%1$s [OPTIONS...] COMMAND ...\n"
- "\n"
- "%5$sSend control commands to the network name resolution manager, or%6$s\n"
- "%5$sresolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%6$s\n"
- "\n%3$sCommands:%4$s\n"
- " query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses\n"
- " service [[NAME] TYPE] DOMAIN Resolve service (SRV)\n"
- " openpgp EMAIL@DOMAIN... Query OpenPGP public key\n"
- " tlsa DOMAIN[:PORT]... Query TLS public key\n"
- " status [LINK...] Show link and server status\n"
- " statistics Show resolver statistics\n"
- " reset-statistics Reset resolver statistics\n"
- " flush-caches Flush all local DNS caches\n"
- " reset-server-features Forget learnt DNS server feature levels\n"
- " monitor Monitor DNS queries\n"
- " show-cache Show cache contents\n"
- " show-server-state Show servers state\n"
- " dns [LINK [SERVER...]] Get/set per-interface DNS server address\n"
- " domain [LINK [DOMAIN...]] Get/set per-interface search domain\n"
- " default-route [LINK [BOOL]] Get/set per-interface default route flag\n"
- " llmnr [LINK [MODE]] Get/set per-interface LLMNR mode\n"
- " mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode\n"
- " dnsovertls [LINK [MODE]] Get/set per-interface DNS-over-TLS mode\n"
- " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n"
- " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n"
- " revert LINK Revert per-interface configuration\n"
- " log-level [LEVEL] Get/set logging threshold for systemd-resolved\n"
- "\n%3$sOptions:%4$s\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -4 Resolve IPv4 addresses\n"
- " -6 Resolve IPv6 addresses\n"
- " -i --interface=INTERFACE Look on interface\n"
- " -p --protocol=PROTO|help Look via protocol\n"
- " -t --type=TYPE|help Query RR with DNS type\n"
- " -c --class=CLASS|help Query RR with DNS class\n"
- " --service-address=BOOL Resolve address for services (default: yes)\n"
- " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
- " --cname=BOOL Follow CNAME redirects (default: yes)\n"
- " --validate=BOOL Allow DNSSEC validation (default: yes)\n"
- " --synthesize=BOOL Allow synthetic response (default: yes)\n"
- " --cache=BOOL Allow response from cache (default: yes)\n"
- " --stale-data=BOOL Allow response from cache with stale data (default: yes)\n"
- " --relax-single-label=BOOL Allow single label lookups to go upstream (default: no)\n"
- " --zone=BOOL Allow response from locally registered mDNS/LLMNR\n"
- " records (default: yes)\n"
- " --trust-anchor=BOOL Allow response from local trust anchor (default:\n"
- " yes)\n"
- " --network=BOOL Allow response from network (default: yes)\n"
- " --search=BOOL Use search domains for single-label names (default:\n"
- " yes)\n"
- " --raw[=payload|packet] Dump the answer as binary data\n"
- " --no-pager Do not pipe output into a pager\n"
- " --no-ask-password Do not prompt for password\n"
- " --legend=BOOL Print headers and additional info (default: yes)\n"
- " --json=MODE Output as JSON\n"
- " -j Same as --json=pretty on tty, --json=short\n"
- " otherwise\n"
- "\nSee the %2$s for details.\n",
- program_invocation_short_name,
- link,
- ansi_underline(),
- ansi_normal(),
- ansi_highlight(),
- ansi_normal());
+ help_cmdline("[OPTIONS…] COMMAND …");
+ help_abstract("Send control commands to the network name resolution manager, or\n"
+ "resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.");
+
+ help_section("Commands");
+ r = table_print_or_warn(verbs);
+ if (r < 0)
+ return r;
+ help_section("Options");
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ help_man_page_reference("resolvectl", "1");
return 0;
}
-static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) {
- return native_help();
-}
-
-static int compat_parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_LEGEND,
- ARG_SERVICE,
- ARG_CNAME,
- ARG_SERVICE_ADDRESS,
- ARG_SERVICE_TXT,
- ARG_OPENPGP,
- ARG_TLSA,
- ARG_RAW,
- ARG_SEARCH,
- ARG_STATISTICS,
- ARG_RESET_STATISTICS,
- ARG_STATUS,
- ARG_FLUSH_CACHES,
- ARG_RESET_SERVER_FEATURES,
- ARG_NO_PAGER,
- ARG_SET_DNS,
- ARG_SET_DOMAIN,
- ARG_SET_LLMNR,
- ARG_SET_MDNS,
- ARG_SET_DNS_OVER_TLS,
- ARG_SET_DNSSEC,
- ARG_SET_NTA,
- ARG_REVERT_LINK,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "type", required_argument, NULL, 't' },
- { "class", required_argument, NULL, 'c' },
- { "legend", required_argument, NULL, ARG_LEGEND },
- { "interface", required_argument, NULL, 'i' },
- { "protocol", required_argument, NULL, 'p' },
- { "cname", required_argument, NULL, ARG_CNAME },
- { "service", no_argument, NULL, ARG_SERVICE },
- { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
- { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
- { "openpgp", no_argument, NULL, ARG_OPENPGP },
- { "tlsa", optional_argument, NULL, ARG_TLSA },
- { "raw", optional_argument, NULL, ARG_RAW },
- { "search", required_argument, NULL, ARG_SEARCH },
- { "statistics", no_argument, NULL, ARG_STATISTICS, },
- { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
- { "status", no_argument, NULL, ARG_STATUS },
- { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES },
- { "reset-server-features", no_argument, NULL, ARG_RESET_SERVER_FEATURES },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "set-dns", required_argument, NULL, ARG_SET_DNS },
- { "set-domain", required_argument, NULL, ARG_SET_DOMAIN },
- { "set-llmnr", required_argument, NULL, ARG_SET_LLMNR },
- { "set-mdns", required_argument, NULL, ARG_SET_MDNS },
- { "set-dnsovertls", required_argument, NULL, ARG_SET_DNS_OVER_TLS },
- { "set-dnssec", required_argument, NULL, ARG_SET_DNSSEC },
- { "set-nta", required_argument, NULL, ARG_SET_NTA },
- { "revert", no_argument, NULL, ARG_REVERT_LINK },
- {}
- };
+VERB_COMMON_HELP_HIDDEN(native_help);
- int c, r;
+static int compat_parse_argv(int argc, char *argv[], char ***remaining_args) {
+ int r;
assert(argc >= 0);
assert(argv);
+ assert(remaining_args);
+
+ OptionParser opts = { argc, argv, .namespace = "systemd-resolve" };
- while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
+ FOREACH_OPTION_OR_RETURN(c, &opts)
switch (c) {
- case 'h':
+ OPTION_NAMESPACE("systemd-resolve"): {}
+
+ OPTION_COMMON_HELP:
return compat_help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case '4':
+ OPTION_SHORT('4', NULL, "Resolve IPv4 addresses"):
arg_family = AF_INET;
break;
- case '6':
+ OPTION_SHORT('6', NULL, "Resolve IPv6 addresses"):
arg_family = AF_INET6;
break;
- case 'i':
- r = ifname_mangle(optarg);
+ OPTION('i', "interface", "INTERFACE", "Look on interface"):
+ r = ifname_mangle(opts.arg);
if (r < 0)
return r;
break;
- case 'p':
- r = parse_protocol(optarg);
+ OPTION('p', "protocol", "PROTO|help", "Look via protocol"):
+ r = parse_protocol(opts.arg);
if (r <= 0)
return r;
break;
- case 't':
- if (streq(optarg, "help")) {
+ OPTION('t', "type", "TYPE|help", "Query RR with DNS type"):
+ if (streq(opts.arg, "help")) {
help_dns_types();
return 0;
}
- r = dns_type_from_string(optarg);
+ r = dns_type_from_string(opts.arg);
if (r < 0)
- return log_error_errno(r, "Failed to parse RR record type %s: %m", optarg);
+ return log_error_errno(r, "Failed to parse RR record type %s: %m", opts.arg);
arg_type = (uint16_t) r;
assert((int) arg_type == r);
arg_mode = MODE_RESOLVE_RECORD;
break;
- case 'c':
- if (streq(optarg, "help")) {
+ OPTION('c', "class", "CLASS|help", "Query RR with DNS class"):
+ if (streq(opts.arg, "help")) {
help_dns_classes();
return 0;
}
- r = dns_class_from_string(optarg);
+ r = dns_class_from_string(opts.arg);
if (r < 0)
- return log_error_errno(r, "Failed to parse RR record class %s: %m", optarg);
+ return log_error_errno(r, "Failed to parse RR record class %s: %m", opts.arg);
arg_class = (uint16_t) r;
assert((int) arg_class == r);
break;
- case ARG_SERVICE:
+ OPTION_LONG("service", NULL, "Resolve service (SRV)"):
arg_mode = MODE_RESOLVE_SERVICE;
break;
- case ARG_SERVICE_ADDRESS:
- r = parse_boolean_argument("--service-address=", optarg, NULL);
+ OPTION_LONG("service-address", "BOOL", "Resolve address for services (default: yes)"):
+ r = parse_boolean_argument("--service-address=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
break;
- case ARG_SERVICE_TXT:
- r = parse_boolean_argument("--service-txt=", optarg, NULL);
+ OPTION_LONG("service-txt", "BOOL", "Resolve TXT records for services (default: yes)"):
+ r = parse_boolean_argument("--service-txt=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
break;
- case ARG_OPENPGP:
+ OPTION_LONG("openpgp", NULL, "Query OpenPGP public key"):
arg_mode = MODE_RESOLVE_OPENPGP;
break;
- case ARG_TLSA:
+ OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "tlsa", "FAMILY", "Query TLS public key"):
arg_mode = MODE_RESOLVE_TLSA;
- if (!optarg || service_family_is_valid(optarg))
- arg_service_family = optarg;
+ if (!opts.arg || service_family_is_valid(opts.arg))
+ arg_service_family = opts.arg;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown service family \"%s\".", optarg);
+ "Unknown service family \"%s\".", opts.arg);
break;
- case ARG_CNAME:
- r = parse_boolean_argument("--cname=", optarg, NULL);
+ OPTION_LONG("cname", "BOOL", "Follow CNAME redirects (default: yes)"):
+ r = parse_boolean_argument("--cname=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
break;
-
- case ARG_SEARCH:
- r = parse_boolean_argument("--search=", optarg, NULL);
+ OPTION_LONG("search", "BOOL", "Use search domains for single-label names (default: yes)"):
+ r = parse_boolean_argument("--search=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
break;
- case ARG_STATISTICS:
+ OPTION_LONG("statistics", NULL, "Show resolver statistics"):
arg_mode = MODE_STATISTICS;
break;
- case ARG_RESET_STATISTICS:
+ OPTION_LONG("reset-statistics", NULL, "Reset resolver statistics"):
arg_mode = MODE_RESET_STATISTICS;
break;
- case ARG_STATUS:
+ OPTION_LONG("status", NULL, "Show link and server status"):
arg_mode = MODE_STATUS;
break;
- case ARG_FLUSH_CACHES:
+ OPTION_LONG("flush-caches", NULL, "Flush all local DNS caches"):
arg_mode = MODE_FLUSH_CACHES;
break;
- case ARG_RESET_SERVER_FEATURES:
+ OPTION_LONG("reset-server-features", NULL,
+ "Forget learnt DNS server feature levels"):
arg_mode = MODE_RESET_SERVER_FEATURES;
break;
- case ARG_SET_DNS:
- r = strv_extend(&arg_set_dns, optarg);
+ OPTION_LONG("set-dns", "SERVER", "Set per-interface DNS server address"):
+ r = strv_extend(&arg_set_dns, opts.arg);
if (r < 0)
return log_oom();
arg_mode = MODE_SET_LINK;
break;
- case ARG_SET_DOMAIN:
- r = strv_extend(&arg_set_domain, optarg);
+ OPTION_LONG("set-domain", "DOMAIN", "Set per-interface search domain"):
+ r = strv_extend(&arg_set_domain, opts.arg);
if (r < 0)
return log_oom();
arg_mode = MODE_SET_LINK;
break;
- case ARG_SET_LLMNR:
- arg_set_llmnr = optarg;
+ OPTION_LONG("set-llmnr", "MODE", "Set per-interface LLMNR mode"):
+ arg_set_llmnr = opts.arg;
arg_mode = MODE_SET_LINK;
break;
- case ARG_SET_MDNS:
- arg_set_mdns = optarg;
+ OPTION_LONG("set-mdns", "MODE", "Set per-interface MulticastDNS mode"):
+ arg_set_mdns = opts.arg;
arg_mode = MODE_SET_LINK;
break;
- case ARG_SET_DNS_OVER_TLS:
- arg_set_dns_over_tls = optarg;
+ OPTION_LONG("set-dnsovertls", "MODE", "Set per-interface DNS-over-TLS mode"):
+ arg_set_dns_over_tls = opts.arg;
arg_mode = MODE_SET_LINK;
break;
- case ARG_SET_DNSSEC:
- arg_set_dnssec = optarg;
+ OPTION_LONG("set-dnssec", "MODE", "Set per-interface DNSSEC mode"):
+ arg_set_dnssec = opts.arg;
arg_mode = MODE_SET_LINK;
break;
- case ARG_SET_NTA:
- r = strv_extend(&arg_set_nta, optarg);
+ OPTION_LONG("set-nta", "DOMAIN", "Set per-interface DNSSEC NTA"):
+ r = strv_extend(&arg_set_nta, opts.arg);
if (r < 0)
return log_oom();
arg_mode = MODE_SET_LINK;
break;
- case ARG_REVERT_LINK:
+ OPTION_LONG("revert", NULL, "Revert per-interface configuration"):
arg_mode = MODE_REVERT_LINK;
break;
- case ARG_RAW:
+ OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "raw", "payload|packet",
+ "Dump the answer as binary data"):
if (on_tty())
return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
"Refusing to write binary data to tty.");
- if (optarg == NULL || streq(optarg, "payload"))
+ if (opts.arg == NULL || streq(opts.arg, "payload"))
arg_raw = RAW_PAYLOAD;
- else if (streq(optarg, "packet"))
+ else if (streq(opts.arg, "packet"))
arg_raw = RAW_PACKET;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown --raw specifier \"%s\".",
- optarg);
+ opts.arg);
arg_legend = false;
break;
- case ARG_NO_PAGER:
+ OPTION_COMMON_NO_PAGER:
arg_pager_flags |= PAGER_DISABLE;
break;
- case ARG_LEGEND:
- r = parse_boolean_argument("--legend=", optarg, &arg_legend);
+ OPTION_LONG("legend", "BOOL", "Print headers and additional info (default: yes)"):
+ r = parse_boolean_argument("--legend=", opts.arg, &arg_legend);
if (r < 0)
return r;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
if (arg_type == 0 && arg_class != 0)
"--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=.");
}
+ *remaining_args = option_parser_get_args(&opts);
return 1 /* work to do */;
}
-static int native_parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_LEGEND,
- ARG_CNAME,
- ARG_VALIDATE,
- ARG_SYNTHESIZE,
- ARG_CACHE,
- ARG_ZONE,
- ARG_TRUST_ANCHOR,
- ARG_NETWORK,
- ARG_SERVICE_ADDRESS,
- ARG_SERVICE_TXT,
- ARG_RAW,
- ARG_SEARCH,
- ARG_NO_PAGER,
- ARG_NO_ASK_PASSWORD,
- ARG_JSON,
- ARG_STALE_DATA,
- ARG_RELAX_SINGLE_LABEL,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "type", required_argument, NULL, 't' },
- { "class", required_argument, NULL, 'c' },
- { "legend", required_argument, NULL, ARG_LEGEND },
- { "interface", required_argument, NULL, 'i' },
- { "protocol", required_argument, NULL, 'p' },
- { "cname", required_argument, NULL, ARG_CNAME },
- { "validate", required_argument, NULL, ARG_VALIDATE },
- { "synthesize", required_argument, NULL, ARG_SYNTHESIZE },
- { "cache", required_argument, NULL, ARG_CACHE },
- { "zone", required_argument, NULL, ARG_ZONE },
- { "trust-anchor", required_argument, NULL, ARG_TRUST_ANCHOR },
- { "network", required_argument, NULL, ARG_NETWORK },
- { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
- { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
- { "raw", optional_argument, NULL, ARG_RAW },
- { "search", required_argument, NULL, ARG_SEARCH },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
- { "json", required_argument, NULL, ARG_JSON },
- { "stale-data", required_argument, NULL, ARG_STALE_DATA },
- { "relax-single-label", required_argument, NULL, ARG_RELAX_SINGLE_LABEL },
- {}
- };
-
- int c, r;
+static int native_parse_argv(int argc, char *argv[], char ***remaining_args) {
+ int r;
assert(argc >= 0);
assert(argv);
+ assert(remaining_args);
+
+ OptionParser opts = { argc, argv, .namespace = "resolvectl" };
- while ((c = getopt_long(argc, argv, "h46i:t:c:p:j", options, NULL)) >= 0)
+ FOREACH_OPTION_OR_RETURN(c, &opts)
switch (c) {
- case 'h':
+ OPTION_NAMESPACE("resolvectl"): {}
+
+ OPTION_COMMON_HELP:
return native_help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case '4':
+ OPTION_SHORT('4', NULL, "Resolve IPv4 addresses"):
arg_family = AF_INET;
break;
- case '6':
+ OPTION_SHORT('6', NULL, "Resolve IPv6 addresses"):
arg_family = AF_INET6;
break;
- case 'i':
- r = ifname_mangle(optarg);
+ OPTION('i', "interface", "INTERFACE", "Look on interface"):
+ r = ifname_mangle(opts.arg);
if (r < 0)
return r;
break;
- case 'p':
- r = parse_protocol(optarg);
+ OPTION('p', "protocol", "PROTO|help", "Look via protocol"):
+ r = parse_protocol(opts.arg);
if (r <= 0)
return r;
break;
- case 't':
- if (streq(optarg, "help")) {
+ OPTION('t', "type", "TYPE|help", "Query RR with DNS type"):
+ if (streq(opts.arg, "help")) {
help_dns_types();
return 0;
}
- r = dns_type_from_string(optarg);
+ r = dns_type_from_string(opts.arg);
if (r < 0)
- return log_error_errno(r, "Failed to parse RR record type %s: %m", optarg);
+ return log_error_errno(r, "Failed to parse RR record type %s: %m", opts.arg);
arg_type = (uint16_t) r;
assert((int) arg_type == r);
break;
- case 'c':
- if (streq(optarg, "help")) {
+ OPTION('c', "class", "CLASS|help", "Query RR with DNS class"):
+ if (streq(opts.arg, "help")) {
help_dns_classes();
return 0;
}
- r = dns_class_from_string(optarg);
+ r = dns_class_from_string(opts.arg);
if (r < 0)
- return log_error_errno(r, "Failed to parse RR record class %s: %m", optarg);
+ return log_error_errno(r, "Failed to parse RR record class %s: %m", opts.arg);
arg_class = (uint16_t) r;
assert((int) arg_class == r);
break;
- case ARG_SERVICE_ADDRESS:
- r = parse_boolean_argument("--service-address=", optarg, NULL);
+ OPTION_LONG("service-address", "BOOL", "Resolve address for services (default: yes)"):
+ r = parse_boolean_argument("--service-address=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
break;
- case ARG_SERVICE_TXT:
- r = parse_boolean_argument("--service-txt=", optarg, NULL);
+ OPTION_LONG("service-txt", "BOOL", "Resolve TXT records for services (default: yes)"):
+ r = parse_boolean_argument("--service-txt=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
break;
- case ARG_CNAME:
- r = parse_boolean_argument("--cname=", optarg, NULL);
+ OPTION_LONG("cname", "BOOL", "Follow CNAME redirects (default: yes)"):
+ r = parse_boolean_argument("--cname=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
break;
- case ARG_VALIDATE:
- r = parse_boolean_argument("--validate=", optarg, NULL);
+ OPTION_LONG("validate", "BOOL", "Allow DNSSEC validation (default: yes)"):
+ r = parse_boolean_argument("--validate=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_VALIDATE, r == 0);
break;
- case ARG_SYNTHESIZE:
- r = parse_boolean_argument("--synthesize=", optarg, NULL);
+ OPTION_LONG("synthesize", "BOOL", "Allow synthetic response (default: yes)"):
+ r = parse_boolean_argument("--synthesize=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_SYNTHESIZE, r == 0);
break;
- case ARG_CACHE:
- r = parse_boolean_argument("--cache=", optarg, NULL);
+ OPTION_LONG("cache", "BOOL", "Allow response from cache (default: yes)"):
+ r = parse_boolean_argument("--cache=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_CACHE, r == 0);
break;
- case ARG_STALE_DATA:
- r = parse_boolean_argument("--stale-data=", optarg, NULL);
+ OPTION_LONG("stale-data", "BOOL",
+ "Allow response from cache with stale data (default: yes)"):
+ r = parse_boolean_argument("--stale-data=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_STALE, r == 0);
break;
- case ARG_RELAX_SINGLE_LABEL:
- r = parse_boolean_argument("--relax-single-label=", optarg, NULL);
+ OPTION_LONG("relax-single-label", "BOOL",
+ "Allow single label lookups to go upstream (default: no)"):
+ r = parse_boolean_argument("--relax-single-label=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_RELAX_SINGLE_LABEL, r > 0);
break;
- case ARG_ZONE:
- r = parse_boolean_argument("--zone=", optarg, NULL);
+ OPTION_LONG("zone", "BOOL",
+ "Allow response from locally registered mDNS/LLMNR records (default: yes)"):
+ r = parse_boolean_argument("--zone=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_ZONE, r == 0);
break;
- case ARG_TRUST_ANCHOR:
- r = parse_boolean_argument("--trust-anchor=", optarg, NULL);
+ OPTION_LONG("trust-anchor", "BOOL",
+ "Allow response from local trust anchor (default: yes)"):
+ r = parse_boolean_argument("--trust-anchor=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_TRUST_ANCHOR, r == 0);
break;
- case ARG_NETWORK:
- r = parse_boolean_argument("--network=", optarg, NULL);
+ OPTION_LONG("network", "BOOL", "Allow response from network (default: yes)"):
+ r = parse_boolean_argument("--network=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_NETWORK, r == 0);
break;
- case ARG_SEARCH:
- r = parse_boolean_argument("--search=", optarg, NULL);
+ OPTION_LONG("search", "BOOL", "Use search domains for single-label names (default: yes)"):
+ r = parse_boolean_argument("--search=", opts.arg, NULL);
if (r < 0)
return r;
SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
break;
- case ARG_RAW:
+ OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "raw", "payload|packet",
+ "Dump the answer as binary data"):
if (on_tty())
return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
"Refusing to write binary data to tty.");
- if (optarg == NULL || streq(optarg, "payload"))
+ if (opts.arg == NULL || streq(opts.arg, "payload"))
arg_raw = RAW_PAYLOAD;
- else if (streq(optarg, "packet"))
+ else if (streq(opts.arg, "packet"))
arg_raw = RAW_PACKET;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown --raw specifier \"%s\".",
- optarg);
+ opts.arg);
arg_legend = false;
break;
- case ARG_NO_PAGER:
+ OPTION_COMMON_NO_PAGER:
arg_pager_flags |= PAGER_DISABLE;
break;
- case ARG_NO_ASK_PASSWORD:
+ OPTION_COMMON_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
- case ARG_LEGEND:
- r = parse_boolean_argument("--legend=", optarg, &arg_legend);
+ OPTION_LONG("legend", "BOOL", "Print headers and additional info (default: yes)"):
+ r = parse_boolean_argument("--legend=", opts.arg, &arg_legend);
if (r < 0)
return r;
break;
- case ARG_JSON:
- r = parse_json_argument(optarg, &arg_json_format_flags);
+ OPTION_COMMON_JSON:
+ r = parse_json_argument(opts.arg, &arg_json_format_flags);
if (r <= 0)
return r;
-
break;
- case 'j':
+ OPTION_COMMON_LOWERCASE_J:
arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
if (arg_type == 0 && arg_class != 0)
if (arg_class != 0 && arg_type == 0)
arg_type = DNS_TYPE_A;
+ *remaining_args = option_parser_get_args(&opts);
return 1 /* work to do */;
}
-static int native_main(int argc, char *argv[]) {
-
- static const Verb verbs[] = {
- { "help", VERB_ANY, VERB_ANY, 0, verb_help },
- { "status", VERB_ANY, VERB_ANY, VERB_DEFAULT, verb_status },
- { "query", 2, VERB_ANY, 0, verb_query },
- { "service", 2, 4, 0, verb_service },
- { "openpgp", 2, VERB_ANY, 0, verb_openpgp },
- { "tlsa", 2, VERB_ANY, 0, verb_tlsa },
- { "statistics", VERB_ANY, 1, 0, verb_show_statistics },
- { "reset-statistics", VERB_ANY, 1, 0, verb_reset_statistics },
- { "flush-caches", VERB_ANY, 1, 0, verb_flush_caches },
- { "reset-server-features", VERB_ANY, 1, 0, verb_reset_server_features },
- { "dns", VERB_ANY, VERB_ANY, 0, verb_dns },
- { "domain", VERB_ANY, VERB_ANY, 0, verb_domain },
- { "default-route", VERB_ANY, 3, 0, verb_default_route },
- { "llmnr", VERB_ANY, 3, 0, verb_llmnr },
- { "mdns", VERB_ANY, 3, 0, verb_mdns },
- { "dnsovertls", VERB_ANY, 3, 0, verb_dns_over_tls },
- { "dnssec", VERB_ANY, 3, 0, verb_dnssec },
- { "nta", VERB_ANY, VERB_ANY, 0, verb_nta },
- { "revert", VERB_ANY, 2, 0, verb_revert_link },
- { "log-level", VERB_ANY, 2, 0, verb_log_level },
- { "monitor", VERB_ANY, 1, 0, verb_monitor },
- { "show-cache", VERB_ANY, 1, 0, verb_show_cache },
- { "show-server-state", VERB_ANY, 1, 0, verb_show_server_state },
- {}
- };
-
- return dispatch_verb(argc, argv, verbs, /* userdata= */ NULL);
-}
-
-static int translate(const char *verb, const char *single_arg, size_t num_args, char **args) {
+static int translate(const char *verb, const char *single_arg, char **args) {
char **fake, **p;
size_t num;
assert(verb);
- assert(num_args == 0 || args);
- num = !!single_arg + num_args + 1;
+ num = !!single_arg + strv_length(args) + 1;
p = fake = newa0(char *, num + 1);
*p++ = (char *) verb;
if (single_arg)
*p++ = (char *) single_arg;
- FOREACH_ARRAY(arg, args, num_args)
- *p++ = *arg;
+ STRV_FOREACH(a, args)
+ *p++ = *a;
- optind = 0;
- return native_main((int) num, fake);
+ return dispatch_verb_with_args(fake, /* userdata= */ NULL);
}
-static int compat_main(int argc, char *argv[]) {
+static int compat_main(char **args) {
int r = 0;
switch (arg_mode) {
case MODE_RESOLVE_HOST:
case MODE_RESOLVE_RECORD:
- return translate("query", NULL, argc - optind, argv + optind);
+ return translate("query", NULL, args);
case MODE_RESOLVE_SERVICE:
- return translate("service", NULL, argc - optind, argv + optind);
+ return translate("service", NULL, args);
case MODE_RESOLVE_OPENPGP:
- return translate("openpgp", NULL, argc - optind, argv + optind);
+ return translate("openpgp", NULL, args);
case MODE_RESOLVE_TLSA:
- return translate("tlsa", arg_service_family, argc - optind, argv + optind);
+ return translate("tlsa", arg_service_family, args);
case MODE_STATISTICS:
- return translate("statistics", NULL, 0, NULL);
+ return translate("statistics", NULL, NULL);
case MODE_RESET_STATISTICS:
- return translate("reset-statistics", NULL, 0, NULL);
+ return translate("reset-statistics", NULL, NULL);
case MODE_FLUSH_CACHES:
- return translate("flush-caches", NULL, 0, NULL);
+ return translate("flush-caches", NULL, NULL);
case MODE_RESET_SERVER_FEATURES:
- return translate("reset-server-features", NULL, 0, NULL);
+ return translate("reset-server-features", NULL, NULL);
case MODE_STATUS:
- return translate("status", NULL, argc - optind, argv + optind);
+ return translate("status", NULL, args);
case MODE_SET_LINK:
assert(arg_ifname);
if (arg_disable_default_route) {
- r = translate("default-route", arg_ifname, 1, STRV_MAKE("no"));
+ r = translate("default-route", arg_ifname, STRV_MAKE("no"));
if (r < 0)
return r;
}
if (arg_set_dns) {
- r = translate("dns", arg_ifname, strv_length(arg_set_dns), arg_set_dns);
+ r = translate("dns", arg_ifname, arg_set_dns);
if (r < 0)
return r;
}
if (arg_set_domain) {
- r = translate("domain", arg_ifname, strv_length(arg_set_domain), arg_set_domain);
+ r = translate("domain", arg_ifname, arg_set_domain);
if (r < 0)
return r;
}
if (arg_set_nta) {
- r = translate("nta", arg_ifname, strv_length(arg_set_nta), arg_set_nta);
+ r = translate("nta", arg_ifname, arg_set_nta);
if (r < 0)
return r;
}
if (arg_set_llmnr) {
- r = translate("llmnr", arg_ifname, 1, (char **) &arg_set_llmnr);
+ r = translate("llmnr", arg_ifname, STRV_MAKE(arg_set_llmnr));
if (r < 0)
return r;
}
if (arg_set_mdns) {
- r = translate("mdns", arg_ifname, 1, (char **) &arg_set_mdns);
+ r = translate("mdns", arg_ifname, STRV_MAKE(arg_set_mdns));
if (r < 0)
return r;
}
if (arg_set_dns_over_tls) {
- r = translate("dnsovertls", arg_ifname, 1, (char **) &arg_set_dns_over_tls);
+ r = translate("dnsovertls", arg_ifname, STRV_MAKE(arg_set_dns_over_tls));
if (r < 0)
return r;
}
if (arg_set_dnssec) {
- r = translate("dnssec", arg_ifname, 1, (char **) &arg_set_dnssec);
+ r = translate("dnssec", arg_ifname, STRV_MAKE(arg_set_dnssec));
if (r < 0)
return r;
}
case MODE_REVERT_LINK:
assert(arg_ifname);
- return translate("revert", arg_ifname, 0, NULL);
+ return translate("revert", arg_ifname, NULL);
case _MODE_INVALID:
assert_not_reached();
}
static int run(int argc, char **argv) {
+ char **args = NULL;
bool compat = false;
int r;
r = resolvconf_parse_argv(argc, argv);
} else if (invoked_as(argv, "systemd-resolve")) {
compat = true;
- r = compat_parse_argv(argc, argv);
+ r = compat_parse_argv(argc, argv, &args);
} else
- r = native_parse_argv(argc, argv);
+ r = native_parse_argv(argc, argv, &args);
if (r <= 0)
return r;
if (compat)
- return compat_main(argc, argv);
+ return compat_main(args);
- return native_main(argc, argv);
+ return dispatch_verb_with_args(args, /* userdata= */ NULL);
}
DEFINE_MAIN_FUNCTION(run);