summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-10-25 04:08:41 +0900
committerGitHub <noreply@github.com>2022-10-25 04:08:41 +0900
commit8cf144c3f62224c45b61ce166ee7444a5efcdeae (patch)
tree4d5f8cc2e2a6ae157d5af1188260ea7767997073 /src
parentf5dfbdd01427c49ec66110ac5f33e317bcea7a78 (diff)
parent72ca42c1b48111bd38f094033bac09bf286833a8 (diff)
downloadsystemd-8cf144c3f62224c45b61ce166ee7444a5efcdeae.tar.gz
Merge pull request #25052 from yuwata/resolvconf-compat
resolvconf-compat: first try to use the specified interface name as is
Diffstat (limited to 'src')
-rw-r--r--src/basic/string-util.h7
-rw-r--r--src/resolve/resolvectl.c98
-rw-r--r--src/resolve/resolvectl.h9
-rw-r--r--src/systemctl/systemctl-set-default.c16
4 files changed, 81 insertions, 49 deletions
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index 0703c848f0..46681ced99 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -171,9 +171,12 @@ int split_pair(const char *s, const char *sep, char **l, char **r);
int free_and_strdup(char **p, const char *s);
static inline int free_and_strdup_warn(char **p, const char *s) {
- if (free_and_strdup(p, s) < 0)
+ int r;
+
+ r = free_and_strdup(p, s);
+ if (r < 0)
return log_oom();
- return 0;
+ return r;
}
int free_and_strndup(char **p, const char *s, size_t l);
diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c
index 9341fb0435..b07761a495 100644
--- a/src/resolve/resolvectl.c
+++ b/src/resolve/resolvectl.c
@@ -108,51 +108,74 @@ static int interface_info_compare(const InterfaceInfo *a, const InterfaceInfo *b
return strcmp_ptr(a->name, b->name);
}
-int ifname_mangle(const char *s) {
- _cleanup_free_ char *iface = NULL;
- int ifi;
+int ifname_mangle_full(const char *s, bool drop_protocol_specifier) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_strv_free_ char **found = NULL;
+ int r;
assert(s);
- iface = strdup(s);
- if (!iface)
- return log_oom();
+ if (drop_protocol_specifier) {
+ _cleanup_free_ char *buf = NULL;
+ int ifindex_longest_name = -ENODEV;
- ifi = rtnl_resolve_interface(NULL, iface);
- if (ifi < 0) {
- if (ifi == -ENODEV && arg_ifindex_permissive) {
- log_debug("Interface '%s' not found, but -f specified, ignoring.", iface);
- return 0; /* done */
- }
+ /* When invoked as resolvconf, drop the protocol specifier(s) at the end. */
- return log_error_errno(ifi, "Failed to resolve interface \"%s\": %m", iface);
- }
+ buf = strdup(s);
+ if (!buf)
+ return log_oom();
- if (arg_ifindex > 0 && arg_ifindex != ifi)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing.");
+ for (;;) {
+ r = rtnl_resolve_interface(&rtnl, buf);
+ if (r > 0) {
+ if (ifindex_longest_name <= 0)
+ ifindex_longest_name = r;
- arg_ifindex = ifi;
- free_and_replace(arg_ifname, iface);
+ r = strv_extend(&found, buf);
+ if (r < 0)
+ return log_oom();
+ }
- return 1;
-}
+ char *dot = strrchr(buf, '.');
+ if (!dot)
+ break;
-int ifname_resolvconf_mangle(const char *s) {
- const char *dot;
+ *dot = '\0';
+ }
- assert(s);
+ unsigned n = strv_length(found);
+ if (n > 1) {
+ _cleanup_free_ char *joined = NULL;
- dot = strrchr(s, '.');
- if (dot) {
- _cleanup_free_ char *iface = NULL;
+ joined = strv_join(found, ", ");
+ log_warning("Found multiple interfaces (%s) matching with '%s'. Using '%s' (ifindex=%i).",
+ strna(joined), s, found[0], ifindex_longest_name);
- log_debug("Ignoring protocol specifier '%s'.", dot + 1);
- iface = strndup(s, dot - s);
- if (!iface)
- return log_oom();
- return ifname_mangle(iface);
+ } else if (n == 1) {
+ const char *proto;
+
+ proto = ASSERT_PTR(startswith(s, found[0]));
+ if (!isempty(proto))
+ log_info("Dropped protocol specifier '%s' from '%s'. Using '%s' (ifindex=%i).",
+ proto, s, found[0], ifindex_longest_name);
+ }
+
+ r = ifindex_longest_name;
} else
- return ifname_mangle(s);
+ r = rtnl_resolve_interface(&rtnl, s);
+ if (r < 0) {
+ if (ERRNO_IS_DEVICE_ABSENT(r) && arg_ifindex_permissive) {
+ log_debug_errno(r, "Interface '%s' not found, but -f specified, ignoring: %m", s);
+ return 0; /* done */
+ }
+ return log_error_errno(r, "Failed to resolve interface \"%s\": %m", s);
+ }
+
+ if (arg_ifindex > 0 && arg_ifindex != r)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing.");
+
+ arg_ifindex = r;
+ return free_and_strdup_warn(&arg_ifname, found ? found[0] : s); /* found */
}
static void print_source(uint64_t flags, usec_t rtt) {
@@ -3599,16 +3622,19 @@ static int compat_main(int argc, char *argv[], sd_bus *bus) {
static int run(int argc, char **argv) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ bool compat = false;
int r;
setlocale(LC_ALL, "");
log_setup();
- if (invoked_as(argv, "resolvconf"))
+ if (invoked_as(argv, "resolvconf")) {
+ compat = true;
r = resolvconf_parse_argv(argc, argv);
- else if (invoked_as(argv, "systemd-resolve"))
+ } else if (invoked_as(argv, "systemd-resolve")) {
+ compat = true;
r = compat_parse_argv(argc, argv);
- else
+ } else
r = native_parse_argv(argc, argv);
if (r <= 0)
return r;
@@ -3617,7 +3643,7 @@ static int run(int argc, char **argv) {
if (r < 0)
return log_error_errno(r, "sd_bus_open_system: %m");
- if (STR_IN_SET(program_invocation_short_name, "systemd-resolve", "resolvconf"))
+ if (compat)
return compat_main(argc, argv, bus);
return native_main(argc, argv, bus);
diff --git a/src/resolve/resolvectl.h b/src/resolve/resolvectl.h
index 1d0f147348..3e404dad10 100644
--- a/src/resolve/resolvectl.h
+++ b/src/resolve/resolvectl.h
@@ -26,5 +26,10 @@ extern char **arg_set_dns;
extern char **arg_set_domain;
extern bool arg_ifindex_permissive;
-int ifname_mangle(const char *s);
-int ifname_resolvconf_mangle(const char *s);
+int ifname_mangle_full(const char *s, bool drop_protocol_specifier);
+static inline int ifname_mangle(const char *s) {
+ return ifname_mangle_full(s, false);
+}
+static inline int ifname_resolvconf_mangle(const char *s) {
+ return ifname_mangle_full(s, true);
+}
diff --git a/src/systemctl/systemctl-set-default.c b/src/systemctl/systemctl-set-default.c
index 06845be401..c2dbf97649 100644
--- a/src/systemctl/systemctl-set-default.c
+++ b/src/systemctl/systemctl-set-default.c
@@ -109,9 +109,8 @@ int verb_set_default(int argc, char *argv[], void *userdata) {
if (install_client_side()) {
r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
install_changes_dump(r, "set default", changes, n_changes, arg_quiet);
-
- if (r > 0)
- r = 0;
+ if (r < 0)
+ goto finish;
} else {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -134,10 +133,9 @@ int verb_set_default(int argc, char *argv[], void *userdata) {
/* Try to reload if enabled */
if (!arg_no_reload) {
r = daemon_reload(ACTION_RELOAD, /* graceful= */ false);
- if (r > 0)
- r = 0;
- } else
- r = 0;
+ if (r < 0)
+ goto finish;
+ }
}
emit_cmdline_warning();
@@ -147,7 +145,7 @@ int verb_set_default(int argc, char *argv[], void *userdata) {
r = determine_default(&final);
if (r < 0)
- return r;
+ goto finish;
if (!streq(final, unit))
log_notice("Note: \"%s\" is the default unit (possibly a runtime override).", final);
@@ -156,5 +154,5 @@ int verb_set_default(int argc, char *argv[], void *userdata) {
finish:
install_changes_free(changes, n_changes);
- return r;
+ return r < 0 ? r : 0;
}