1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-02-04 17:47:03 +03:00

Merge pull request #25052 from yuwata/resolvconf-compat

resolvconf-compat: first try to use the specified interface name as is
This commit is contained in:
Yu Watanabe 2022-10-25 04:08:41 +09:00 committed by GitHub
commit 8cf144c3f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 120 additions and 54 deletions

View File

@ -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);

View File

@ -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. */
buf = strdup(s);
if (!buf)
return log_oom();
for (;;) {
r = rtnl_resolve_interface(&rtnl, buf);
if (r > 0) {
if (ifindex_longest_name <= 0)
ifindex_longest_name = r;
r = strv_extend(&found, buf);
if (r < 0)
return log_oom();
}
char *dot = strrchr(buf, '.');
if (!dot)
break;
*dot = '\0';
}
return log_error_errno(ifi, "Failed to resolve interface \"%s\": %m", iface);
unsigned n = strv_length(found);
if (n > 1) {
_cleanup_free_ char *joined = 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);
} 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
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 != ifi)
if (arg_ifindex > 0 && arg_ifindex != r)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing.");
arg_ifindex = ifi;
free_and_replace(arg_ifname, iface);
return 1;
}
int ifname_resolvconf_mangle(const char *s) {
const char *dot;
assert(s);
dot = strrchr(s, '.');
if (dot) {
_cleanup_free_ char *iface = NULL;
log_debug("Ignoring protocol specifier '%s'.", dot + 1);
iface = strndup(s, dot - s);
if (!iface)
return log_oom();
return ifname_mangle(iface);
} else
return ifname_mangle(s);
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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -5,6 +5,9 @@
set -eux
set -o pipefail
# shellcheck source=test/units/assert.sh
. "$(dirname "$0")"/assert.sh
: >/failed
RUN_OUT="$(mktemp)"
@ -25,6 +28,36 @@ monitor_check_rr() {
set -o pipefail
}
# Test for resolvectl, resolvconf
systemctl unmask systemd-resolved.service
systemctl start systemd-resolved.service
systemctl service-log-level systemd-resolved.service debug
ip link add hoge type dummy
ip link add hoge.foo type dummy
resolvectl dns hoge 10.0.0.1 10.0.0.2
resolvectl dns hoge.foo 10.0.0.3 10.0.0.4
assert_in '10.0.0.1 10.0.0.2' "$(resolvectl dns hoge)"
assert_in '10.0.0.3 10.0.0.4' "$(resolvectl dns hoge.foo)"
resolvectl dns hoge 10.0.1.1 10.0.1.2
resolvectl dns hoge.foo 10.0.1.3 10.0.1.4
assert_in '10.0.1.1 10.0.1.2' "$(resolvectl dns hoge)"
assert_in '10.0.1.3 10.0.1.4' "$(resolvectl dns hoge.foo)"
if ! RESOLVCONF=$(command -v resolvconf 2>/dev/null); then
TMPDIR=$(mktemp -d -p /tmp resolvconf-tests.XXXXXX)
RESOLVCONF="$TMPDIR"/resolvconf
ln -s "$(command -v resolvectl 2>/dev/null)" "$RESOLVCONF"
fi
echo nameserver 10.0.2.1 10.0.2.2 | "$RESOLVCONF" -a hoge
echo nameserver 10.0.2.3 10.0.2.4 | "$RESOLVCONF" -a hoge.foo
assert_in '10.0.2.1 10.0.2.2' "$(resolvectl dns hoge)"
assert_in '10.0.2.3 10.0.2.4' "$(resolvectl dns hoge.foo)"
echo nameserver 10.0.3.1 10.0.3.2 | "$RESOLVCONF" -a hoge.inet.ipsec.192.168.35
echo nameserver 10.0.3.3 10.0.3.4 | "$RESOLVCONF" -a hoge.foo.dhcp
assert_in '10.0.3.1 10.0.3.2' "$(resolvectl dns hoge)"
assert_in '10.0.3.3 10.0.3.4' "$(resolvectl dns hoge.foo)"
ip link del hoge
ip link del hoge.foo
### SETUP ###
# Configure network
hostnamectl hostname ns1.unsigned.test
@ -74,8 +107,9 @@ mkdir -p /etc/bind
ln -svf /etc/bind.keys /etc/bind/bind.keys
# Start the services
systemctl unmask systemd-networkd systemd-resolved
systemctl start systemd-networkd systemd-resolved
systemctl unmask systemd-networkd
systemctl start systemd-networkd
systemctl restart systemd-resolved
# Create knot's runtime dir, since from certain version it's provided only by
# the package and not created by tmpfiles/systemd
if [[ ! -d /run/knot ]]; then