diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-09-29 17:25:15 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2020-09-30 10:27:50 +0200 |
commit | 4261ab654c0df009b5a37a30593d58d47fec617f (patch) | |
tree | 22d01a94616ded315f1835243d0998f0ef66105f | |
parent | loginctl: add -P as short for --value --property= (diff) | |
download | systemd-4261ab654c0df009b5a37a30593d58d47fec617f.tar.xz systemd-4261ab654c0df009b5a37a30593d58d47fec617f.zip |
resolved: expose a new bus property that informs about the /etc/resolv.conf mode
It can be one of "foreign", "missing", "stub", "static", "uplink",
depending on how /etc/resolv.conf is set up:
foreign → someone/something else manages /etc/resolv.conf,
systemd-resolved is just the consumer
missing → /etc/resolv.conf is missing altogether
stub/static/uplink → the file is managed by resolved, with the
well-known modes
Fixes: #17159
-rw-r--r-- | man/org.freedesktop.resolve1.xml | 13 | ||||
-rw-r--r-- | src/resolve/resolved-bus.c | 24 | ||||
-rw-r--r-- | src/resolve/resolved-resolv-conf.c | 47 | ||||
-rw-r--r-- | src/resolve/resolved-resolv-conf.h | 15 |
4 files changed, 96 insertions, 3 deletions
diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml index 5b8acbbd9f..6a6d9de6b9 100644 --- a/man/org.freedesktop.resolve1.xml +++ b/man/org.freedesktop.resolve1.xml @@ -147,6 +147,8 @@ node /org/freedesktop/resolve1 { readonly as DNSSECNegativeTrustAnchors = ['...', ...]; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly s DNSStubListener = '...'; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly s ResolvConfMode = '...'; }; interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Introspectable { ... }; @@ -272,6 +274,8 @@ node /org/freedesktop/resolve1 { <variablelist class="dbus-property" generated="True" extra-ref="DNSStubListener"/> + <variablelist class="dbus-property" generated="True" extra-ref="ResolvConfMode"/> + <!--End of Autogenerated section--> <refsect2> @@ -555,9 +559,12 @@ node /org/freedesktop/resolve1 { DNSSEC is supported by DNS servers until it verifies that this is not the case. Thus, the reported value may initially be true, until the first transactions are executed.</para> - <para>The <varname>LogLevel</varname> property shows the (maximum) log level of the manager, with the - same values as the <option>--log-level=</option> option described in - <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para> + <para>The <varname>ResolvConfMode</varname> property exposes how <filename>/etc/resolv.conf</filename> + is managed on the host. Currently, the values <literal>uplink</literal>, <literal>stub</literal>, + <literal>static</literal> (these three correspond to the three different files + <filename>systemd-resolved.service</filename> provides), <literal>foreign</literal> (the file is + managed by admin or another service, <filename>systemd-resolved.service</filename> just consumes it), + <literal>missing</literal> (<filename>/etc/resolv.conf</filename> is missing).</para> </refsect2> </refsect1> diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index afe67d9e6c..724c3d4a6a 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -15,6 +15,7 @@ #include "resolved-dnssd-bus.h" #include "resolved-dnssd.h" #include "resolved-link-bus.h" +#include "resolved-resolv-conf.h" #include "socket-netlink.h" #include "stdio-util.h" #include "strv.h" @@ -1620,6 +1621,28 @@ static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string); static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode, "s", Manager, manager_get_dns_over_tls_mode, dns_over_tls_mode_to_string); +static int bus_property_get_resolv_conf_mode( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + int r; + + assert(reply); + + r = resolv_conf_mode(); + if (r < 0) { + log_warning_errno(r, "Failed to test /etc/resolv.conf mode, ignoring: %m"); + return sd_bus_message_append(reply, "s", NULL); + } + + return sd_bus_message_append(reply, "s", resolv_conf_mode_to_string(r)); +} + static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; DnsScope *s; @@ -2000,6 +2023,7 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0), SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0), SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0), + SD_BUS_PROPERTY("ResolvConfMode", "s", bus_property_get_resolv_conf_mode, 0, 0), SD_BUS_METHOD_WITH_ARGS("ResolveHostname", SD_BUS_ARGS("i", ifindex, "s", name, "i", family, "t", flags), diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 0de5046367..05d98e518d 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -15,6 +15,7 @@ #include "resolved-dns-server.h" #include "resolved-resolv-conf.h" #include "stat-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "tmpfile-util-label.h" @@ -371,3 +372,49 @@ int manager_write_resolv_conf(Manager *m) { return r; } + +int resolv_conf_mode(void) { + static const char * const table[_RESOLV_CONF_MODE_MAX] = { + [RESOLV_CONF_UPLINK] = PRIVATE_UPLINK_RESOLV_CONF, + [RESOLV_CONF_STUB] = PRIVATE_STUB_RESOLV_CONF, + [RESOLV_CONF_STATIC] = PRIVATE_STATIC_RESOLV_CONF, + }; + + struct stat system_st; + + if (stat("/etc/resolv.conf", &system_st) < 0) { + if (errno == ENOENT) + return RESOLV_CONF_MISSING; + + return -errno; + } + + for (ResolvConfMode m = 0; m < _RESOLV_CONF_MODE_MAX; m++) { + struct stat our_st; + + if (!table[m]) + continue; + + if (stat(table[m], &our_st) < 0) { + if (errno != ENOENT) + log_debug_errno(errno, "Failed to stat() %s, ignoring: %m", table[m]); + + continue; + } + + if (system_st.st_dev == our_st.st_dev && + system_st.st_ino == our_st.st_ino) + return m; + } + + return RESOLV_CONF_FOREIGN; +} + +static const char* const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = { + [RESOLV_CONF_UPLINK] = "uplink", + [RESOLV_CONF_STUB] = "stub", + [RESOLV_CONF_STATIC] = "static", + [RESOLV_CONF_MISSING] = "missing", + [RESOLV_CONF_FOREIGN] = "foreign", +}; +DEFINE_STRING_TABLE_LOOKUP(resolv_conf_mode, ResolvConfMode); diff --git a/src/resolve/resolved-resolv-conf.h b/src/resolve/resolved-resolv-conf.h index f69cf2a441..584d25c0f7 100644 --- a/src/resolve/resolved-resolv-conf.h +++ b/src/resolve/resolved-resolv-conf.h @@ -6,3 +6,18 @@ int manager_check_resolv_conf(const Manager *m); int manager_read_resolv_conf(Manager *m); int manager_write_resolv_conf(Manager *m); + +typedef enum ResolvConfMode { + RESOLV_CONF_UPLINK, + RESOLV_CONF_STUB, + RESOLV_CONF_STATIC, + RESOLV_CONF_FOREIGN, + RESOLV_CONF_MISSING, + _RESOLV_CONF_MODE_MAX, + _RESOLV_CONF_MODE_INVALID = -1, +} ResolvConfMode; + +int resolv_conf_mode(void); + +const char* resolv_conf_mode_to_string(ResolvConfMode m) _const_; +ResolvConfMode resolv_conf_mode_from_string(const char *s) _pure_; |