diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-10-25 04:08:41 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-25 04:08:41 +0900 |
commit | 8cf144c3f62224c45b61ce166ee7444a5efcdeae (patch) | |
tree | 4d5f8cc2e2a6ae157d5af1188260ea7767997073 /src | |
parent | f5dfbdd01427c49ec66110ac5f33e317bcea7a78 (diff) | |
parent | 72ca42c1b48111bd38f094033bac09bf286833a8 (diff) | |
download | systemd-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.h | 7 | ||||
-rw-r--r-- | src/resolve/resolvectl.c | 98 | ||||
-rw-r--r-- | src/resolve/resolvectl.h | 9 | ||||
-rw-r--r-- | src/systemctl/systemctl-set-default.c | 16 |
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; } |