Merge pull request #15495 from keszybz/resolve-debugging-and-stub-handling

Resolve debugging and stub handling
This commit is contained in:
Lennart Poettering 2020-04-21 09:34:21 +02:00 committed by GitHub
commit f9411d5d5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 164 additions and 54 deletions

4
TODO
View file

@ -821,6 +821,10 @@ Features:
* teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off})
* Add ConditionDirectoryNotEmpty= handle non-absoute paths as a search path or add
ConditionConfigSearchPathNotEmpty= or different syntax? See the discussion starting at
https://github.com/systemd/systemd/pull/15109#issuecomment-607740136.
* BootLoaderSpec: Clarify that the kernel has to be in $BOOT. Clarify * BootLoaderSpec: Clarify that the kernel has to be in $BOOT. Clarify
that the boot loader should be installed to the ESP. Define a way that the boot loader should be installed to the ESP. Define a way
how an installer can figure out whether a BLS compliant boot loader how an installer can figure out whether a BLS compliant boot loader

View file

@ -145,6 +145,9 @@ node /org/freedesktop/resolve1 {
readonly as DNSSECNegativeTrustAnchors = ['...', ...]; readonly as DNSSECNegativeTrustAnchors = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DNSStubListener = '...'; readonly s DNSStubListener = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite s LogLevel = '...';
}; };
interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... }; interface org.freedesktop.DBus.Introspectable { ... };
@ -406,10 +409,10 @@ node /org/freedesktop/resolve1 {
<refsect2> <refsect2>
<title>Properties</title> <title>Properties</title>
<varname>LLMNRHostname</varname> contains the hostname currently exposed on the network via LLMNR. It <para><varname>LLMNRHostname</varname> contains the hostname currently exposed on the network via
usually follows the system hostname as may be queried via LLMNR. It usually follows the system hostname as may be queried via
<citerefentry project="man-pages"><refentrytitle>gethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry project="man-pages"><refentrytitle>gethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
but may differ if a conflict is detected on the network. but may differ if a conflict is detected on the network.</para>
<para><varname>DNS</varname> contains an array of all DNS servers currently used by <para><varname>DNS</varname> contains an array of all DNS servers currently used by
<filename>systemd-resolved</filename>. It contains similar information as the DNS server data written to <filename>systemd-resolved</filename>. It contains similar information as the DNS server data written to
@ -460,6 +463,10 @@ node /org/freedesktop/resolve1 {
which DNS is configured and for the system-wide settings if there are any. Note that <filename>systemd-resolved</filename> assumes which DNS is configured and for the system-wide settings if there are any. Note that <filename>systemd-resolved</filename> assumes
DNSSEC is supported by DNS servers until it verifies that this is not the case. Thus, the reported 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> 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>
</refsect2> </refsect2>
</refsect1> </refsect1>

View file

@ -175,6 +175,7 @@
automatically, an explicit reverting is not necessary in that case.</para></listitem> automatically, an explicit reverting is not necessary in that case.</para></listitem>
</varlistentry> </varlistentry>
<xi:include href="systemctl.xml" xpointer="log-level" />
</variablelist> </variablelist>
</refsect1> </refsect1>

View file

@ -1067,7 +1067,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry id='log-level'>
<term><command>log-level</command> [<replaceable>LEVEL</replaceable>]</term> <term><command>log-level</command> [<replaceable>LEVEL</replaceable>]</term>
<listitem><para>If no argument is given, print the current log level of the manager. If an <listitem><para>If no argument is given, print the current log level of the manager. If an

View file

@ -2516,6 +2516,48 @@ static int verb_revert_link(int argc, char **argv, void *userdata) {
return 0; return 0;
} }
static int verb_log_level(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 == 1) {
_cleanup_free_ char *level = NULL;
r = sd_bus_get_property_string(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"LogLevel",
&error,
&level);
if (r < 0)
return log_error_errno(r, "Failed to get log level: %s", bus_error_message(&error, r));
puts(level);
} else {
assert(argc == 2);
r = sd_bus_set_property(
bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"LogLevel",
&error,
"s",
argv[1]);
if (r < 0)
return log_error_errno(r, "Failed to set log level: %s", bus_error_message(&error, r));
}
return 0;
}
static void help_protocol_types(void) { static void help_protocol_types(void) {
if (arg_legend) if (arg_legend)
puts("Known protocol types:"); puts("Known protocol types:");
@ -3190,6 +3232,7 @@ static int native_main(int argc, char *argv[], sd_bus *bus) {
{ "dnssec", VERB_ANY, 3, 0, verb_dnssec }, { "dnssec", VERB_ANY, 3, 0, verb_dnssec },
{ "nta", VERB_ANY, VERB_ANY, 0, verb_nta }, { "nta", VERB_ANY, VERB_ANY, 0, verb_nta },
{ "revert", VERB_ANY, 2, 0, verb_revert_link }, { "revert", VERB_ANY, 2, 0, verb_revert_link },
{ "log-level", VERB_ANY, 2, 0, verb_log_level },
{} {}
}; };

View file

@ -16,6 +16,7 @@
#include "socket-netlink.h" #include "socket-netlink.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "strv.h" #include "strv.h"
#include "syslog-util.h"
#include "user-util.h" #include "user-util.h"
#include "utf8.h" #include "utf8.h"
@ -1835,6 +1836,57 @@ static int bus_method_unregister_service(sd_bus_message *message, void *userdata
return call_dnssd_method(m, message, bus_dnssd_method_unregister, error); return call_dnssd_method(m, message, bus_dnssd_method_unregister, error);
} }
static int property_get_log_level(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *t = NULL;
int r;
assert(bus);
assert(reply);
r = log_level_to_string_alloc(log_get_max_level(), &t);
if (r < 0)
return r;
return sd_bus_message_append(reply, "s", t);
}
static int property_set_log_level(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *value,
void *userdata,
sd_bus_error *error) {
const char *t;
int r;
assert(bus);
assert(value);
r = sd_bus_message_read(value, "s", &t);
if (r < 0)
return r;
r = log_level_from_string(t);
if (r < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t);
log_info("Setting log level to %s.", t);
log_set_max_level(r);
return 0;
}
static const sd_bus_vtable resolve_vtable[] = { static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_VTABLE_START(0), SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@ -1853,7 +1905,7 @@ static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 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("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
SD_BUS_METHOD_WITH_NAMES("ResolveHostname", SD_BUS_METHOD_WITH_NAMES("ResolveHostname",
"isit", "isit",

View file

@ -1350,7 +1350,16 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
} }
if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) { if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED); DnsTransactionState result;
if (t->scope->protocol == DNS_PROTOCOL_LLMNR)
/* If we didn't find anything on LLMNR, it's not an error, but a failure to resolve
* the name. */
result = DNS_TRANSACTION_NOT_FOUND;
else
result = DNS_TRANSACTION_ATTEMPTS_MAX_REACHED;
dns_transaction_complete(t, result);
return 0; return 0;
} }

View file

@ -9,6 +9,7 @@
#include "dns-domain.h" #include "dns-domain.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "ordered-set.h" #include "ordered-set.h"
#include "resolved-conf.h" #include "resolved-conf.h"
#include "resolved-dns-server.h" #include "resolved-dns-server.h"
@ -27,41 +28,30 @@
#define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf" #define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf"
int manager_check_resolv_conf(const Manager *m) { int manager_check_resolv_conf(const Manager *m) {
const char *path; struct stat st, own;
struct stat st;
int r;
assert(m); assert(m);
/* This warns only when our stub listener is disabled and /etc/resolv.conf is a symlink to /* This warns only when our stub listener is disabled and /etc/resolv.conf is a symlink to
* PRIVATE_STATIC_RESOLV_CONF or PRIVATE_STUB_RESOLV_CONF. */ * PRIVATE_STATIC_RESOLV_CONF. */
if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO) if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO)
return 0; return 0;
r = stat("/etc/resolv.conf", &st); if (stat("/etc/resolv.conf", &st) < 0) {
if (r < 0) {
if (errno == ENOENT) if (errno == ENOENT)
return 0; return 0;
return log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m"); return log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
} }
FOREACH_STRING(path, /* Is it symlinked to our own uplink file? */
PRIVATE_STUB_RESOLV_CONF, if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
PRIVATE_STATIC_RESOLV_CONF) { st.st_dev == own.st_dev &&
st.st_ino == own.st_ino)
struct stat own; return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
/* Is it symlinked to our own uplink file? */ PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
if (stat(path, &own) >= 0 &&
st.st_dev == own.st_dev &&
st.st_ino == own.st_ino) {
log_warning("DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to %s "
"which expects DNSStubListener= to be enabled.", path);
return -EOPNOTSUPP;
}
}
return 0; return 0;
} }
@ -355,45 +345,49 @@ int manager_write_resolv_conf(Manager *m) {
r = fopen_temporary_label(PRIVATE_UPLINK_RESOLV_CONF, PRIVATE_UPLINK_RESOLV_CONF, &f_uplink, &temp_path_uplink); r = fopen_temporary_label(PRIVATE_UPLINK_RESOLV_CONF, PRIVATE_UPLINK_RESOLV_CONF, &f_uplink, &temp_path_uplink);
if (r < 0) if (r < 0)
return log_warning_errno(r, "Failed to open private resolv.conf file for writing: %m"); return log_warning_errno(r, "Failed to open new %s for writing: %m", PRIVATE_UPLINK_RESOLV_CONF);
(void) fchmod(fileno(f_uplink), 0644); (void) fchmod(fileno(f_uplink), 0644);
r = fopen_temporary_label(PRIVATE_STUB_RESOLV_CONF, PRIVATE_STUB_RESOLV_CONF, &f_stub, &temp_path_stub);
if (r < 0)
return log_warning_errno(r, "Failed to open private stub-resolv.conf file for writing: %m");
(void) fchmod(fileno(f_stub), 0644);
r = write_uplink_resolv_conf_contents(f_uplink, dns, domains); r = write_uplink_resolv_conf_contents(f_uplink, dns, domains);
if (r < 0) { if (r < 0) {
log_error_errno(r, "Failed to write private resolv.conf contents: %m"); log_error_errno(r, "Failed to write new %s: %m", PRIVATE_UPLINK_RESOLV_CONF);
goto fail; goto fail;
} }
if (rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF) < 0) { if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO) {
r = log_error_errno(errno, "Failed to move private resolv.conf file into place: %m"); r = fopen_temporary_label(PRIVATE_STUB_RESOLV_CONF, PRIVATE_STUB_RESOLV_CONF, &f_stub, &temp_path_stub);
goto fail; if (r < 0) {
log_warning_errno(r, "Failed to open new %s for writing: %m", PRIVATE_STUB_RESOLV_CONF);
goto fail;
}
(void) fchmod(fileno(f_stub), 0644);
r = write_stub_resolv_conf_contents(f_stub, dns, domains);
if (r < 0) {
log_error_errno(r, "Failed to write new %s: %m", PRIVATE_STUB_RESOLV_CONF);
goto fail;
}
if (rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF) < 0)
r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF);
} else {
r = symlink_atomic(basename(PRIVATE_UPLINK_RESOLV_CONF), PRIVATE_STUB_RESOLV_CONF);
if (r < 0)
log_error_errno(r, "Failed to symlink %s: %m", PRIVATE_STUB_RESOLV_CONF);
} }
r = write_stub_resolv_conf_contents(f_stub, dns, domains); if (rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF) < 0)
r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_UPLINK_RESOLV_CONF);
fail:
if (r < 0) { if (r < 0) {
log_error_errno(r, "Failed to write private stub-resolv.conf contents: %m"); /* Something went wrong, perform cleanup... */
goto fail; (void) unlink(temp_path_uplink);
(void) unlink(temp_path_stub);
} }
if (rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF) < 0) {
r = log_error_errno(errno, "Failed to move private stub-resolv.conf file into place: %m");
goto fail;
}
return 0;
fail:
(void) unlink(PRIVATE_UPLINK_RESOLV_CONF);
(void) unlink(temp_path_uplink);
(void) unlink(PRIVATE_STUB_RESOLV_CONF);
(void) unlink(temp_path_stub);
return r; return r;
} }