mirror of
https://github.com/systemd/systemd.git
synced 2025-01-12 13:18:14 +03:00
resolvconf-compat: first parse provided interface name as is
Then, try to drop multiple protocol specifiers at the end. Strictly speaking, this breaks backward compatibility: if eth0 and eth0.42 exists, then previously, echo 'nameserver 192.168.0.1' | resolvconf -a eth0.42 adds the DNS server to eth0 instead of eth0.42, as we unconditionally dropped the specifier after the last dot, and echo 'nameserver 192.168.0.1' | resolvconf -a eth0.42.dhcp adds the DNS server to eth0.42. However, with this commit, now the both commands add the DNS server to eth0.42. But, hopefully, this should be preferable behavior. Fixes #25032.
This commit is contained in:
parent
427eeb44f2
commit
7d4e850323
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user