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})
* 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
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

View File

@ -145,6 +145,9 @@ node /org/freedesktop/resolve1 {
readonly as DNSSECNegativeTrustAnchors = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
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.Introspectable { ... };
@ -406,10 +409,10 @@ node /org/freedesktop/resolve1 {
<refsect2>
<title>Properties</title>
<varname>LLMNRHostname</varname> contains the hostname currently exposed on the network via LLMNR. It
usually follows the system hostname as may be queried via
<para><varname>LLMNRHostname</varname> contains the hostname currently exposed on the network via
LLMNR. It usually follows the system hostname as may be queried via
<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
<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
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>
</refsect2>
</refsect1>

View File

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

View File

@ -1067,7 +1067,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</listitem>
</varlistentry>
<varlistentry>
<varlistentry id='log-level'>
<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

View File

@ -2516,6 +2516,48 @@ static int verb_revert_link(int argc, char **argv, void *userdata) {
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) {
if (arg_legend)
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 },
{ "nta", VERB_ANY, VERB_ANY, 0, verb_nta },
{ "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 "stdio-util.h"
#include "strv.h"
#include "syslog-util.h"
#include "user-util.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);
}
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[] = {
SD_BUS_VTABLE_START(0),
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("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",
"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)) {
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;
}

View File

@ -9,6 +9,7 @@
#include "dns-domain.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "ordered-set.h"
#include "resolved-conf.h"
#include "resolved-dns-server.h"
@ -27,41 +28,30 @@
#define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf"
int manager_check_resolv_conf(const Manager *m) {
const char *path;
struct stat st;
int r;
struct stat st, own;
assert(m);
/* 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)
return 0;
r = stat("/etc/resolv.conf", &st);
if (r < 0) {
if (stat("/etc/resolv.conf", &st) < 0) {
if (errno == ENOENT)
return 0;
return log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
}
FOREACH_STRING(path,
PRIVATE_STUB_RESOLV_CONF,
PRIVATE_STATIC_RESOLV_CONF) {
struct stat own;
/* Is it symlinked to our own uplink file? */
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;
}
}
/* Is it symlinked to our own uplink file? */
if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
st.st_dev == own.st_dev &&
st.st_ino == own.st_ino)
return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
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);
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);
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);
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;
}
if (rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF) < 0) {
r = log_error_errno(errno, "Failed to move private resolv.conf file into place: %m");
goto fail;
if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO) {
r = fopen_temporary_label(PRIVATE_STUB_RESOLV_CONF, PRIVATE_STUB_RESOLV_CONF, &f_stub, &temp_path_stub);
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) {
log_error_errno(r, "Failed to write private stub-resolv.conf contents: %m");
goto fail;
/* Something went wrong, perform cleanup... */
(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;
}