]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: expose a new bus property that informs about the /etc/resolv.conf mode
authorLennart Poettering <lennart@poettering.net>
Tue, 29 Sep 2020 15:25:15 +0000 (17:25 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 30 Sep 2020 08:27:50 +0000 (10:27 +0200)
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
man/org.freedesktop.resolve1.xml
src/resolve/resolved-bus.c
src/resolve/resolved-resolv-conf.c
src/resolve/resolved-resolv-conf.h

index 5b8acbbd9ff78349d00e5d31a99e7929f9c271a9..6a6d9de6b98cd6a2b0c43e7ce1875db92424ce87 100644 (file)
@@ -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>
 
index afe67d9e6cc789c98faeb55bfc4cde6f2a3887b6..724c3d4a6a10dbe25d7da09a613bfb94024ebc6e 100644 (file)
@@ -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),
index 0de504636770e44eadecee35fbbe242bc867b61f..05d98e518dc2fe322a5790bc0749259402a9d911 100644 (file)
@@ -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);
index f69cf2a441bab5fc7543aa43e7a01425c6a98b59..584d25c0f7cf729cfe3d9ec40f31ab0a17e51c77 100644 (file)
@@ -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_;