resolvectl: support networkd managed interfaces

Closes #9808.
This commit is contained in:
Yu Watanabe 2019-05-27 10:50:52 +09:00
parent 1576154957
commit 65856bf208
2 changed files with 253 additions and 150 deletions

View file

@ -247,11 +247,8 @@
<listitem>
<para>Get/set per-interface DNS configuration. These commands may be used to configure various DNS settings
for network interfaces that aren't managed by
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. (These
commands will fail when used on interfaces that are managed by <command>systemd-networkd</command>, please
configure their DNS settings directly inside the <filename>.network</filename> files instead.) These commands
may be used to inform <command>systemd-resolved</command> about per-interface DNS configuration determined
for network interfaces. These commands may be used to inform <command>systemd-resolved</command> or
<command>systemd-networkd</command> about per-interface DNS configuration determined
through external means. The <option>dns</option> command expects IPv4 or IPv6 address specifications of DNS
servers to use. The <option>domain</option> command expects valid DNS domains, possibly prefixed with
<literal>~</literal>, and configures a per-interface search or route-only domain. The

View file

@ -1844,42 +1844,17 @@ static int verb_status(int argc, char **argv, void *userdata) {
return r;
}
static int log_interface_is_managed(int r, int ifindex) {
char ifname[IF_NAMESIZE + 1];
return log_error_errno(r,
"The specified interface %s is managed by systemd-networkd. Operation refused.\n"
"Please configure DNS settings for systemd-networkd managed interfaces directly in their .network files.",
strna(format_ifname(ifindex, ifname)));
}
static int verb_dns(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
static int call_dns(sd_bus *bus, char **dns, const char *destination, const char *path, const char *interface, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
sd_bus *bus = userdata;
char **p;
int r;
assert(bus);
if (argc >= 2) {
r = ifname_mangle(argv[1]);
if (r < 0)
return r;
}
if (arg_ifindex <= 0)
return status_all(bus, STATUS_DNS);
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL);
r = sd_bus_message_new_method_call(
bus,
&req,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
destination,
path,
interface,
"SetLinkDNS");
if (r < 0)
return bus_log_create_error(r);
@ -1894,8 +1869,8 @@ static int verb_dns(int argc, char **argv, void *userdata) {
/* If only argument is the empty string, then call SetLinkDNS() with an
* empty list, which will clear the list of domains for an interface. */
if (!strv_equal(argv + 2, STRV_MAKE(""))) {
STRV_FOREACH(p, argv + 2) {
if (!strv_equal(dns, STRV_MAKE("")))
STRV_FOREACH(p, dns) {
struct in_addr_data data;
r = in_addr_from_string_auto(*p, &data.family, &data.address);
@ -1918,32 +1893,17 @@ static int verb_dns(int argc, char **argv, void *userdata) {
if (r < 0)
return bus_log_create_error(r);
}
}
r = sd_bus_message_close_container(req);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, req, 0, &error, NULL);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
return log_error_errno(r, "Failed to set DNS configuration: %s", bus_error_message(&error, r));
}
return 0;
return sd_bus_call(bus, req, 0, error, NULL);
}
static int verb_domain(int argc, char **argv, void *userdata) {
static int verb_dns(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
sd_bus *bus = userdata;
char **p;
int r;
assert(bus);
@ -1955,17 +1915,47 @@ static int verb_domain(int argc, char **argv, void *userdata) {
}
if (arg_ifindex <= 0)
return status_all(bus, STATUS_DOMAIN);
return status_all(bus, STATUS_DNS);
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL);
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL);
r = call_dns(bus, argv + 2,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
&error);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = call_dns(bus, argv + 2,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
&error);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
return log_error_errno(r, "Failed to set DNS configuration: %s", bus_error_message(&error, r));
}
return 0;
}
static int call_domain(sd_bus *bus, char **domain, const char *destination, const char *path, const char *interface, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
char **p;
int r;
r = sd_bus_message_new_method_call(
bus,
&req,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
destination,
path,
interface,
"SetLinkDomains");
if (r < 0)
return bus_log_create_error(r);
@ -1980,8 +1970,8 @@ static int verb_domain(int argc, char **argv, void *userdata) {
/* If only argument is the empty string, then call SetLinkDomains() with an
* empty list, which will clear the list of domains for an interface. */
if (!strv_equal(argv + 2, STRV_MAKE(""))) {
STRV_FOREACH(p, argv + 2) {
if (!strv_equal(domain, STRV_MAKE("")))
STRV_FOREACH(p, domain) {
const char *n;
n = **p == '~' ? *p + 1 : *p;
@ -1998,17 +1988,48 @@ static int verb_domain(int argc, char **argv, void *userdata) {
if (r < 0)
return bus_log_create_error(r);
}
}
r = sd_bus_message_close_container(req);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, req, 0, &error, NULL);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
return sd_bus_call(bus, req, 0, error, NULL);
}
static int verb_domain(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2) {
r = ifname_mangle(argv[1]);
if (r < 0)
return r;
}
if (arg_ifindex <= 0)
return status_all(bus, STATUS_DOMAIN);
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL);
r = call_domain(bus, argv + 2,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
&error);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = call_domain(bus, argv + 2,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
&error);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2042,18 +2063,29 @@ static int verb_default_route(int argc, char **argv, void *userdata) {
if (b < 0)
return log_error_errno(b, "Failed to parse boolean argument: %s", argv[2]);
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDefaultRoute",
&error,
NULL,
"ib", arg_ifindex, b);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDefaultRoute",
&error,
NULL,
"ib", arg_ifindex, b);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"SetLinkDefaultRoute",
&error,
NULL,
"ib", arg_ifindex, b);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2083,18 +2115,29 @@ static int verb_llmnr(int argc, char **argv, void *userdata) {
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL);
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkLLMNR",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkLLMNR",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"SetLinkLLMNR",
&error,
NULL,
"is", arg_ifindex, argv[2]);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2124,18 +2167,29 @@ static int verb_mdns(int argc, char **argv, void *userdata) {
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL);
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkMulticastDNS",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkMulticastDNS",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"SetLinkMulticastDNS",
&error,
NULL,
"is", arg_ifindex, argv[2]);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2165,18 +2219,29 @@ static int verb_dns_over_tls(int argc, char **argv, void *userdata) {
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_PRIVATE, NULL);
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDNSOverTLS",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDNSOverTLS",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"SetLinkDNSOverTLS",
&error,
NULL,
"is", arg_ifindex, argv[2]);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2206,18 +2271,29 @@ static int verb_dnssec(int argc, char **argv, void *userdata) {
if (argc < 3)
return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNSSEC, NULL);
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDNSSEC",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDNSSEC",
&error,
NULL,
"is", arg_ifindex, argv[2]);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"SetLinkDNSSEC",
&error,
NULL,
"is", arg_ifindex, argv[2]);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2228,9 +2304,33 @@ static int verb_dnssec(int argc, char **argv, void *userdata) {
return 0;
}
static int call_nta(sd_bus *bus, char **nta, const char *destination, const char *path, const char *interface, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
int r;
r = sd_bus_message_new_method_call(
bus,
&req,
destination,
path,
interface,
"SetLinkDNSSECNegativeTrustAnchors");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(req, "i", arg_ifindex);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append_strv(req, nta);
if (r < 0)
return bus_log_create_error(r);
return sd_bus_call(bus, req, 0, error, NULL);
}
static int verb_nta(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
sd_bus *bus = userdata;
char **p;
int r;
@ -2265,29 +2365,21 @@ static int verb_nta(int argc, char **argv, void *userdata) {
}
}
r = sd_bus_message_new_method_call(
bus,
&req,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"SetLinkDNSSECNegativeTrustAnchors");
if (r < 0)
return bus_log_create_error(r);
r = call_nta(bus, clear ? NULL : argv + 2,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
&error);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_message_append(req, "i", arg_ifindex);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append_strv(req, clear ? NULL : argv + 2);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, req, 0, &error, NULL);
r = call_nta(bus, clear ? NULL : argv + 2,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
&error);
}
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
return log_interface_is_managed(r, arg_ifindex);
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
return 0;
@ -2314,14 +2406,28 @@ static int verb_revert_link(int argc, char **argv, void *userdata) {
if (arg_ifindex <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface argument required.");
r = sd_bus_call_method(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"RevertLink",
&error,
NULL,
"i", arg_ifindex);
r = sd_bus_call_method(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"RevertLink",
&error,
NULL,
"i", arg_ifindex);
if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) {
sd_bus_error_free(&error);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"RevertLinkDNS",
&error,
NULL,
"i", arg_ifindex);
}
if (r < 0) {
if (arg_ifindex_permissive &&
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))