Skip to content

Commit

Permalink
resolvconf-compat: first parse provided interface name as is
Browse files Browse the repository at this point in the history
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 systemd#25032.
  • Loading branch information
yuwata committed Oct 18, 2022
1 parent 2f1fe79 commit e279a89
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 33 deletions.
69 changes: 38 additions & 31 deletions src/resolve/resolvectl.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,51 +108,58 @@ 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 ifname_mangle_full(const char *s, bool drop_protocol_specifier) {
_cleanup_free_ char *buf = NULL;
int ifi;

assert(s);

iface = strdup(s);
if (!iface)
return log_oom();
ifi = rtnl_resolve_interface(NULL, s);
if (ifi < 0 && drop_protocol_specifier) {
/* When invoked as resolvconf, drop the protocol specifier(s) at the end. */
for (;;) {
char *dot;

if (buf) {
dot = strrchr(buf, '.');
if (!dot)
break;

*dot = '\0';
} else {
dot = strrchr(s, '.');
if (!dot)
break;

buf = strndup(s, dot - s);
if (!buf)
return log_oom();
}

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 */
log_debug("Ignoring protocol specifier '%s'.", dot + 1);
ifi = rtnl_resolve_interface(NULL, buf);
if (ifi >= 0)
break;
}
}

return log_error_errno(ifi, "Failed to resolve interface \"%s\": %m", iface);
if (ifi == -ENODEV && arg_ifindex_permissive) {
log_debug("Interface '%s' not found, but -f specified, ignoring.", s);
return 0; /* done */
}

if (ifi < 0)
return log_error_errno(ifi, "Failed to resolve interface \"%s\": %m", s);

if (arg_ifindex > 0 && arg_ifindex != ifi)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing.");

arg_ifindex = ifi;
free_and_replace(arg_ifname, iface);
if (!buf)
return free_and_strdup_warn(&arg_ifname, s);

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);
free_and_replace(arg_ifname, buf);
return 1; /* found */
}

static void print_source(uint64_t flags, usec_t rtt) {
Expand Down
9 changes: 7 additions & 2 deletions src/resolve/resolvectl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit e279a89

Please sign in to comment.