summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/boot/efi/measure.c23
-rw-r--r--src/core/main.c21
-rw-r--r--src/core/manager.c40
-rw-r--r--src/login/systemd-user.m44
-rw-r--r--src/machine/machinectl.c1
-rw-r--r--src/network/networkd-address.c59
-rw-r--r--src/network/networkd-address.h6
-rw-r--r--src/network/networkd-network-gperf.gperf5
-rw-r--r--src/nspawn/nspawn.c112
-rw-r--r--src/resolve/resolve-tool.c40
-rw-r--r--src/resolve/resolved-conf.c11
-rw-r--r--src/resolve/resolved-conf.h17
-rw-r--r--src/resolve/resolved-dns-scope.h3
-rw-r--r--src/resolve/resolved-dns-stream.h1
-rw-r--r--src/resolve/resolved-dns-stub.c160
-rw-r--r--src/resolve/resolved-dns-stub.h3
-rw-r--r--src/resolve/resolved-dns-transaction.h2
-rw-r--r--src/resolve/resolved-gperf.gperf13
-rw-r--r--src/resolve/resolved-link.h1
-rw-r--r--src/resolve/resolved-manager.c1
-rw-r--r--src/resolve/resolved-manager.h2
-rw-r--r--src/resolve/resolved.conf.in1
-rw-r--r--src/shared/gcrypt-util.h8
-rw-r--r--src/udev/udevd.c4
25 files changed, 338 insertions, 204 deletions
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 13ff51cd35..4a78269e33 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -1052,6 +1052,10 @@ typedef int32_t key_serial_t;
#define ETHERTYPE_LLDP 0x88cc
#endif
+#ifndef IFA_F_MCAUTOJOIN
+#define IFA_F_MCAUTOJOIN 0x400
+#endif
+
#endif
#include "missing_syscall.h"
diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c
index 7c016387c1..4ac11a9bb0 100644
--- a/src/boot/efi/measure.c
+++ b/src/boot/efi/measure.c
@@ -209,12 +209,35 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p
return EFI_SUCCESS;
}
+/*
+ * According to TCG EFI Protocol Specification for TPM 2.0 family,
+ * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG
+ * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka
+ * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the
+ * internal switch through calling get_event_log() in order to allow
+ * to retrieve the logs from OS runtime.
+ */
+static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg)
+{
+ return uefi_call_wrapper(tcg->GetEventLog, 5, tcg,
+ EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL,
+ NULL, NULL);
+}
static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer,
UINT64 buffer_size, const CHAR16 *description) {
EFI_STATUS status;
EFI_TCG2_EVENT *tcg_event;
UINTN desc_len;
+ static BOOLEAN triggered = FALSE;
+
+ if (triggered == FALSE) {
+ status = trigger_tcg2_final_events_table(tcg);
+ if (EFI_ERROR(status))
+ return status;
+
+ triggered = TRUE;
+ }
desc_len = StrLen(description) * sizeof(CHAR16);
diff --git a/src/core/main.c b/src/core/main.c
index 6fe440277e..0fad393323 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1532,15 +1532,8 @@ int main(int argc, char *argv[]) {
* need to do that for user instances since they never log
* into the console. */
log_show_color(colors_enabled());
- make_null_stdio();
- }
-
- /* Initialize default unit */
- r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
- if (r < 0) {
- log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
- error_message = "Failed to set default unit";
- goto finish;
+ if (make_null_stdio() < 0)
+ log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m");
}
r = initialize_join_controllers();
@@ -1590,6 +1583,16 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ /* Initialize default unit */
+ if (!arg_default_unit) {
+ r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
+ if (r < 0) {
+ log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
+ error_message = "Failed to set default unit";
+ goto finish;
+ }
+ }
+
if (arg_action == ACTION_TEST &&
geteuid() == 0) {
log_error("Don't run test mode as root.");
diff --git a/src/core/manager.c b/src/core/manager.c
index 5253cb3712..c1dce62a18 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1720,16 +1720,15 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
return 0;
}
- n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
if (n < 0) {
- if (!IN_SET(errno, EAGAIN, EINTR))
- log_error("Failed to receive notification message: %m");
+ if (IN_SET(errno, EAGAIN, EINTR))
+ return 0; /* Spurious wakeup, try again */
- /* It's not an option to return an error here since it
- * would disable the notification handler entirely. Services
- * wouldn't be able to send the WATCHDOG message for
- * example... */
- return 0;
+ /* If this is any other, real error, then let's stop processing this socket. This of course means we
+ * won't take notification messages anymore, but that's still better than busy looping around this:
+ * being woken up over and over again but being unable to actually read the message off the socket. */
+ return log_error_errno(errno, "Failed to receive notification message: %m");
}
CMSG_FOREACH(cmsg, &msghdr) {
@@ -1762,13 +1761,19 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
return 0;
}
- if ((size_t) n >= sizeof(buf)) {
+ if ((size_t) n >= sizeof(buf) || (msghdr.msg_flags & MSG_TRUNC)) {
log_warning("Received notify message exceeded maximum size. Ignoring.");
return 0;
}
- /* The message should be a string. Here we make sure it's NUL-terminated,
- * but only the part until first NUL will be used anyway. */
+ /* As extra safety check, let's make sure the string we get doesn't contain embedded NUL bytes. We permit one
+ * trailing NUL byte in the message, but don't expect it. */
+ if (n > 1 && memchr(buf, 0, n-1)) {
+ log_warning("Received notify message with embedded NUL bytes. Ignoring.");
+ return 0;
+ }
+
+ /* Make sure it's NUL-terminated. */
buf[n] = 0;
/* Notify every unit that might be interested, but try
@@ -1941,14 +1946,17 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
for (;;) {
n = read(m->signal_fd, &sfsi, sizeof(sfsi));
if (n != sizeof(sfsi)) {
+ if (n >= 0) {
+ log_warning("Truncated read from signal fd (%zu bytes)!", n);
+ return 0;
+ }
- if (n >= 0)
- return -EIO;
-
- if (errno == EINTR || errno == EAGAIN)
+ if (IN_SET(errno, EINTR, EAGAIN))
break;
- return -errno;
+ /* We return an error here, which will kill this handler,
+ * to avoid a busy loop on read error. */
+ return log_error_errno(errno, "Reading from signal fd failed: %m");
}
log_received_signal(sfsi.ssi_signo == SIGCHLD ||
diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4
index f188a8e548..fe38b24fef 100644
--- a/src/login/systemd-user.m4
+++ b/src/login/systemd-user.m4
@@ -2,11 +2,9 @@
#
# Used by systemd --user instances.
-account include system-auth
-
m4_ifdef(`HAVE_SELINUX',
session required pam_selinux.so close
session required pam_selinux.so nottys open
)m4_dnl
session required pam_loginuid.so
-session include system-auth
+session optional pam_systemd.so
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index e9de31e184..7b9be3b425 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -2629,6 +2629,7 @@ static int clean_images(int argc, char *argv[], void *userdata) {
}
static int help(int argc, char *argv[], void *userdata) {
+ pager_open(arg_no_pager, false);
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the virtual machine and container\n"
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 5498e352d8..ed52d5e42d 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -571,6 +571,21 @@ int address_configure(
address->flags |= IFA_F_PERMANENT;
+ if (address->home_address)
+ address->flags |= IFA_F_HOMEADDRESS;
+
+ if (address->duplicate_address_detection)
+ address->flags |= IFA_F_NODAD;
+
+ if (address->manage_temporary_address)
+ address->flags |= IFA_F_MANAGETEMPADDR;
+
+ if (address->prefix_route)
+ address->flags |= IFA_F_NOPREFIXROUTE;
+
+ if (address->autojoin)
+ address->flags |= IFA_F_MCAUTOJOIN;
+
r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
if (r < 0)
return log_error_errno(r, "Could not set flags: %m");
@@ -856,6 +871,50 @@ int config_parse_lifetime(const char *unit,
return 0;
}
+int config_parse_address_flags(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = userdata;
+ _cleanup_address_free_ Address *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = address_new_static(network, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (streq(lvalue, "HomeAddress"))
+ n->home_address = r;
+ else if (streq(lvalue, "DuplicateAddressDetection"))
+ n->duplicate_address_detection = r;
+ else if (streq(lvalue, "ManageTemporaryAddress"))
+ n->manage_temporary_address = r;
+ else if (streq(lvalue, "PrefixRoute"))
+ n->prefix_route = r;
+ else if (streq(lvalue, "AutoJoin"))
+ n->autojoin = r;
+
+ return 0;
+}
+
bool address_is_ready(const Address *a) {
assert(a);
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 03c4bea7c6..bc3b4fc7f3 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -53,6 +53,11 @@ struct Address {
union in_addr_union in_addr_peer;
bool ip_masquerade_done:1;
+ bool duplicate_address_detection;
+ bool manage_temporary_address;
+ bool home_address;
+ bool prefix_route;
+ bool autojoin;
LIST_FIELDS(Address, addresses);
};
@@ -77,3 +82,4 @@ int config_parse_address(const char *unit, const char *filename, unsigned line,
int config_parse_broadcast(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_address_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 62779c7c48..5587961b9f 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -70,6 +70,11 @@ Address.Peer, config_parse_address,
Address.Broadcast, config_parse_broadcast, 0, 0
Address.Label, config_parse_label, 0, 0
Address.PreferredLifetime, config_parse_lifetime, 0, 0
+Address.HomeAddress, config_parse_address_flags, 0, 0
+Address.DuplicateAddressDetection, config_parse_address_flags, 0, 0
+Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0
+Address.PrefixRoute, config_parse_address_flags, 0, 0
+Address.AutoJoin, config_parse_address_flags, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index dbf94b48c3..e066c55dae 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -415,52 +415,52 @@ static int parse_argv(int argc, char *argv[]) {
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "directory", required_argument, NULL, 'D' },
- { "template", required_argument, NULL, ARG_TEMPLATE },
- { "ephemeral", no_argument, NULL, 'x' },
- { "user", required_argument, NULL, 'u' },
- { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
- { "as-pid2", no_argument, NULL, 'a' },
- { "boot", no_argument, NULL, 'b' },
- { "uuid", required_argument, NULL, ARG_UUID },
- { "read-only", no_argument, NULL, ARG_READ_ONLY },
- { "capability", required_argument, NULL, ARG_CAPABILITY },
- { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY },
- { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
- { "bind", required_argument, NULL, ARG_BIND },
- { "bind-ro", required_argument, NULL, ARG_BIND_RO },
- { "tmpfs", required_argument, NULL, ARG_TMPFS },
- { "overlay", required_argument, NULL, ARG_OVERLAY },
- { "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO },
- { "machine", required_argument, NULL, 'M' },
- { "slice", required_argument, NULL, 'S' },
- { "setenv", required_argument, NULL, 'E' },
- { "selinux-context", required_argument, NULL, 'Z' },
- { "selinux-apifs-context", required_argument, NULL, 'L' },
- { "quiet", no_argument, NULL, 'q' },
- { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, /* not documented */
- { "register", required_argument, NULL, ARG_REGISTER },
- { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
- { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
- { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
- { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN },
- { "network-veth", no_argument, NULL, 'n' },
- { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA},
- { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE },
- { "network-zone", required_argument, NULL, ARG_NETWORK_ZONE },
- { "personality", required_argument, NULL, ARG_PERSONALITY },
- { "image", required_argument, NULL, 'i' },
- { "volatile", optional_argument, NULL, ARG_VOLATILE },
- { "port", required_argument, NULL, 'p' },
- { "property", required_argument, NULL, ARG_PROPERTY },
- { "private-users", optional_argument, NULL, ARG_PRIVATE_USERS },
- { "private-users-chown", optional_argument, NULL, ARG_PRIVATE_USERS_CHOWN},
- { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL },
- { "settings", required_argument, NULL, ARG_SETTINGS },
- { "chdir", required_argument, NULL, ARG_CHDIR },
- { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "directory", required_argument, NULL, 'D' },
+ { "template", required_argument, NULL, ARG_TEMPLATE },
+ { "ephemeral", no_argument, NULL, 'x' },
+ { "user", required_argument, NULL, 'u' },
+ { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
+ { "as-pid2", no_argument, NULL, 'a' },
+ { "boot", no_argument, NULL, 'b' },
+ { "uuid", required_argument, NULL, ARG_UUID },
+ { "read-only", no_argument, NULL, ARG_READ_ONLY },
+ { "capability", required_argument, NULL, ARG_CAPABILITY },
+ { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY },
+ { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
+ { "bind", required_argument, NULL, ARG_BIND },
+ { "bind-ro", required_argument, NULL, ARG_BIND_RO },
+ { "tmpfs", required_argument, NULL, ARG_TMPFS },
+ { "overlay", required_argument, NULL, ARG_OVERLAY },
+ { "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO },
+ { "machine", required_argument, NULL, 'M' },
+ { "slice", required_argument, NULL, 'S' },
+ { "setenv", required_argument, NULL, 'E' },
+ { "selinux-context", required_argument, NULL, 'Z' },
+ { "selinux-apifs-context", required_argument, NULL, 'L' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, /* not documented */
+ { "register", required_argument, NULL, ARG_REGISTER },
+ { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
+ { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
+ { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
+ { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN },
+ { "network-veth", no_argument, NULL, 'n' },
+ { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA },
+ { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE },
+ { "network-zone", required_argument, NULL, ARG_NETWORK_ZONE },
+ { "personality", required_argument, NULL, ARG_PERSONALITY },
+ { "image", required_argument, NULL, 'i' },
+ { "volatile", optional_argument, NULL, ARG_VOLATILE },
+ { "port", required_argument, NULL, 'p' },
+ { "property", required_argument, NULL, ARG_PROPERTY },
+ { "private-users", optional_argument, NULL, ARG_PRIVATE_USERS },
+ { "private-users-chown", optional_argument, NULL, ARG_PRIVATE_USERS_CHOWN },
+ { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL },
+ { "settings", required_argument, NULL, ARG_SETTINGS },
+ { "chdir", required_argument, NULL, ARG_CHDIR },
+ { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY },
{}
};
@@ -915,13 +915,12 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_PRIVATE_USERS:
- r = optarg ? parse_boolean(optarg) : 1;
- if (r == 0) {
+ if (streq_ptr(optarg, "no")) {
/* no: User namespacing off */
arg_userns_mode = USER_NAMESPACE_NO;
arg_uid_shift = UID_INVALID;
arg_uid_range = UINT32_C(0x10000);
- } else if (r > 0) {
+ } else if (!optarg || streq(optarg, "yes")) {
/* yes: User namespacing on, UID range is read from root dir */
arg_userns_mode = USER_NAMESPACE_FIXED;
arg_uid_shift = UID_INVALID;
@@ -932,23 +931,20 @@ static int parse_argv(int argc, char *argv[]) {
arg_uid_shift = UID_INVALID;
arg_uid_range = UINT32_C(0x10000);
} else {
- _cleanup_free_ char *buffer = NULL;
const char *range, *shift;
/* anything else: User namespacing on, UID range is explicitly configured */
range = strchr(optarg, ':');
if (range) {
- buffer = strndup(optarg, range - optarg);
- if (!buffer)
- return log_oom();
- shift = buffer;
+ shift = strndupa(optarg, range - optarg);
range++;
- if (safe_atou32(range, &arg_uid_range) < 0 || arg_uid_range <= 0) {
- log_error("Failed to parse UID range: %s", range);
- return -EINVAL;
- }
+ r = safe_atou32(range, &arg_uid_range);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse UID range '%s': %m", range);
+ if (arg_uid_range == 0)
+ return log_error_errno(EINVAL, "UID range cannot be 0.");
} else
shift = optarg;
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index 07e4cd7d1d..8aa79049b6 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -395,7 +395,7 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) {
return 0;
}
-static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) {
+static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char ifname[IF_NAMESIZE] = "";
@@ -430,7 +430,8 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_
r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
if (r < 0) {
- log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
+ if (warn_missing || r != -ENXIO)
+ log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
return r;
}
@@ -488,7 +489,8 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_
return bus_log_parse_error(r);
if (n == 0) {
- log_error("%s: no records found", name);
+ if (warn_missing)
+ log_error("%s: no records found", name);
return -ESRCH;
}
@@ -618,7 +620,7 @@ static int resolve_rfc4501(sd_bus *bus, const char *name) {
if (type == 0)
type = arg_type ?: DNS_TYPE_A;
- return resolve_record(bus, n, class, type);
+ return resolve_record(bus, n, class, type, true);
invalid:
log_error("Invalid DNS URI: %s", name);
@@ -840,16 +842,34 @@ static int resolve_openpgp(sd_bus *bus, const char *address) {
}
domain++;
- r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
+ r = string_hashsum_sha256(address, domain - 1 - address, &hashed);
if (r < 0)
return log_error_errno(r, "Hashing failed: %m");
+ strshorten(hashed, 56);
+
full = strjoina(hashed, "._openpgpkey.", domain);
log_debug("Looking up \"%s\".", full);
- return resolve_record(bus, full,
- arg_class ?: DNS_CLASS_IN,
- arg_type ?: DNS_TYPE_OPENPGPKEY);
+ r = resolve_record(bus, full,
+ arg_class ?: DNS_CLASS_IN,
+ arg_type ?: DNS_TYPE_OPENPGPKEY, false);
+
+ if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */
+ hashed = NULL;
+ r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
+ if (r < 0)
+ return log_error_errno(r, "Hashing failed: %m");
+
+ full = strjoina(hashed, "._openpgpkey.", domain);
+ log_debug("Looking up \"%s\".", full);
+
+ return resolve_record(bus, full,
+ arg_class ?: DNS_CLASS_IN,
+ arg_type ?: DNS_TYPE_OPENPGPKEY, true);
+ }
+
+ return r;
}
static int resolve_tlsa(sd_bus *bus, const char *address) {
@@ -881,7 +901,7 @@ static int resolve_tlsa(sd_bus *bus, const char *address) {
return resolve_record(bus, full,
arg_class ?: DNS_CLASS_IN,
- arg_type ?: DNS_TYPE_TLSA);
+ arg_type ?: DNS_TYPE_TLSA, true);
}
static int show_statistics(sd_bus *bus) {
@@ -1877,7 +1897,7 @@ int main(int argc, char **argv) {
while (argv[optind]) {
int k;
- k = resolve_record(bus, argv[optind], arg_class, arg_type);
+ k = resolve_record(bus, argv[optind], arg_class, arg_type, true);
if (r == 0)
r = k;
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index 83f7596ac8..abf3263178 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -23,8 +23,19 @@
#include "extract-word.h"
#include "parse-util.h"
#include "resolved-conf.h"
+#include "string-table.h"
#include "string-util.h"
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting");
+
+static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = {
+ [DNS_STUB_LISTENER_NO] = "no",
+ [DNS_STUB_LISTENER_UDP] = "udp",
+ [DNS_STUB_LISTENER_TCP] = "tcp",
+ [DNS_STUB_LISTENER_YES] = "yes",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES);
+
int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
union in_addr_union address;
int family, r, ifindex = 0;
diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h
index e1fd2cceec..fc425a36b2 100644
--- a/src/resolve/resolved-conf.h
+++ b/src/resolve/resolved-conf.h
@@ -19,7 +19,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+typedef enum DnsStubListenerMode DnsStubListenerMode;
+
+enum DnsStubListenerMode {
+ DNS_STUB_LISTENER_NO,
+ DNS_STUB_LISTENER_UDP,
+ DNS_STUB_LISTENER_TCP,
+ DNS_STUB_LISTENER_YES,
+ _DNS_STUB_LISTENER_MODE_MAX,
+ _DNS_STUB_LISTENER_MODE_INVALID = -1
+};
+
#include "resolved-manager.h"
+#include "resolved-dns-server.h"
int manager_parse_config_file(Manager *m);
@@ -33,4 +45,7 @@ const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned len
int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_dns_stub_listener_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_;
+DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_;
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 538bc61f81..01a83a76b2 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -26,7 +26,10 @@ typedef struct DnsScope DnsScope;
#include "resolved-dns-cache.h"
#include "resolved-dns-dnssec.h"
#include "resolved-dns-packet.h"
+#include "resolved-dns-query.h"
+#include "resolved-dns-search-domain.h"
#include "resolved-dns-server.h"
+#include "resolved-dns-stream.h"
#include "resolved-dns-zone.h"
#include "resolved-link.h"
diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h
index e6569678fa..4cdb4f6806 100644
--- a/src/resolve/resolved-dns-stream.h
+++ b/src/resolve/resolved-dns-stream.h
@@ -25,6 +25,7 @@ typedef struct DnsStream DnsStream;
#include "resolved-dns-packet.h"
#include "resolved-dns-transaction.h"
+#include "resolved-manager.h"
/* Streams are used by three subsystems:
*
diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c
index d263cedcd9..b1c570cee6 100644
--- a/src/resolve/resolved-dns-stub.c
+++ b/src/resolve/resolved-dns-stub.c
@@ -25,6 +25,9 @@
* IP and UDP header sizes */
#define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U)
+static int manager_dns_stub_udp_fd(Manager *m);
+static int manager_dns_stub_tcp_fd(Manager *m);
+
static int dns_stub_make_reply_packet(
uint16_t id,
int rcode,
@@ -354,66 +357,48 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void
return 0;
}
-int manager_dns_stub_udp_fd(Manager *m) {
+static int manager_dns_stub_udp_fd(Manager *m) {
static const int one = 1;
-
union sockaddr_union sa = {
.in.sin_family = AF_INET,
.in.sin_port = htobe16(53),
.in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB),
};
-
+ _cleanup_close_ int fd = -1;
int r;
if (m->dns_stub_udp_fd >= 0)
return m->dns_stub_udp_fd;
- m->dns_stub_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->dns_stub_udp_fd < 0)
+ fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (fd < 0)
return -errno;
- r = setsockopt(m->dns_stub_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0)
+ return -errno;
- r = setsockopt(m->dns_stub_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof one) < 0)
+ return -errno;
- r = setsockopt(m->dns_stub_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof one) < 0)
+ return -errno;
/* Make sure no traffic from outside the local host can leak to onto this socket */
- r = setsockopt(m->dns_stub_udp_fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3) < 0)
+ return -errno;
- r = bind(m->dns_stub_udp_fd, &sa.sa, sizeof(sa.in));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (bind(fd, &sa.sa, sizeof(sa.in)) < 0)
+ return -errno;
- r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, m->dns_stub_udp_fd, EPOLLIN, on_dns_stub_packet, m);
+ r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
if (r < 0)
- goto fail;
+ return r;
(void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp");
+ m->dns_stub_udp_fd = fd;
+ fd = -1;
return m->dns_stub_udp_fd;
-
-fail:
- m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd);
- return r;
}
static int on_dns_stub_stream_packet(DnsStream *s) {
@@ -461,102 +446,83 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void
return 0;
}
-int manager_dns_stub_tcp_fd(Manager *m) {
+static int manager_dns_stub_tcp_fd(Manager *m) {
static const int one = 1;
-
union sockaddr_union sa = {
.in.sin_family = AF_INET,
.in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB),
.in.sin_port = htobe16(53),
};
-
+ _cleanup_close_ int fd = -1;
int r;
if (m->dns_stub_tcp_fd >= 0)
return m->dns_stub_tcp_fd;
- m->dns_stub_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->dns_stub_tcp_fd < 0)
+ fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (fd < 0)
return -errno;
- r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof one) < 0)
+ return -errno;
- r = setsockopt(m->dns_stub_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0)
+ return -errno;
- r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof one) < 0)
+ return -errno;
- r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof one) < 0)
+ return -errno;
/* Make sure no traffic from outside the local host can leak to onto this socket */
- r = setsockopt(m->dns_stub_tcp_fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3) < 0)
+ return -errno;
- r = bind(m->dns_stub_tcp_fd, &sa.sa, sizeof(sa.in));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (bind(fd, &sa.sa, sizeof(sa.in)) < 0)
+ return -errno;
- r = listen(m->dns_stub_tcp_fd, SOMAXCONN);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (listen(fd, SOMAXCONN) < 0)
+ return -errno;
- r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, m->dns_stub_tcp_fd, EPOLLIN, on_dns_stub_stream, m);
+ r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m);
if (r < 0)
- goto fail;
+ return r;
(void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp");
+ m->dns_stub_tcp_fd = fd;
+ fd = -1;
return m->dns_stub_tcp_fd;
-
-fail:
- m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd);
- return r;
}
int manager_dns_stub_start(Manager *m) {
+ const char *t = "UDP";
int r;
assert(m);
- r = manager_dns_stub_udp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- r = manager_dns_stub_tcp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
+ if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP))
+ r = manager_dns_stub_udp_fd(m);
- return 0;
+ if (r >= 0 &&
+ IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) {
+ t = "TCP";
+ r = manager_dns_stub_tcp_fd(m);
+ }
-eaddrinuse:
- log_warning("Another process is already listening on 127.0.0.53:53. Turning off local DNS stub support.");
- manager_dns_stub_stop(m);
+ if (IN_SET(r, -EADDRINUSE, -EPERM)) {
+ if (r == -EADDRINUSE)
+ log_warning_errno(r,
+ "Another process is already listening on %s socket 127.0.0.53:53.\n"
+ "Turning off local DNS stub support.", t);
+ else
+ log_warning_errno(r,
+ "Failed to listen on %s socket 127.0.0.53:53: %m.\n"
+ "Turning off local DNS stub support.", t);
+ manager_dns_stub_stop(m);
+ } else if (r < 0)
+ return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t);
return 0;
}
diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h
index fce4d25ede..12b86f6753 100644
--- a/src/resolve/resolved-dns-stub.h
+++ b/src/resolve/resolved-dns-stub.h
@@ -24,8 +24,5 @@
/* 127.0.0.53 in native endian */
#define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U)
-int manager_dns_stub_udp_fd(Manager *m);
-int manager_dns_stub_tcp_fd(Manager *m);
-
void manager_dns_stub_stop(Manager *m);
int manager_dns_stub_start(Manager *m);
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
index 96b066845d..5a1df70422 100644
--- a/src/resolve/resolved-dns-transaction.h
+++ b/src/resolve/resolved-dns-transaction.h
@@ -59,6 +59,8 @@ enum DnsTransactionSource {
#include "resolved-dns-packet.h"
#include "resolved-dns-question.h"
#include "resolved-dns-scope.h"
+#include "resolved-dns-server.h"
+#include "resolved-dns-stream.h"
struct DnsTransaction {
DnsScope *scope;
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
index 2fd56bce26..446f85cdf4 100644
--- a/src/resolve/resolved-gperf.gperf
+++ b/src/resolve/resolved-gperf.gperf
@@ -14,9 +14,10 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
-Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
-Resolve.Domains, config_parse_search_domains, 0, 0
-Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
-Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
-Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache)
+Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
+Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
+Resolve.Domains, config_parse_search_domains, 0, 0
+Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
+Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
+Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache)
+Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode)
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
index 6a2343f9f7..c9b2a58c34 100644
--- a/src/resolve/resolved-link.h
+++ b/src/resolve/resolved-link.h
@@ -29,6 +29,7 @@ typedef struct Link Link;
typedef struct LinkAddress LinkAddress;
#include "resolved-dns-rr.h"
+#include "resolved-dns-scope.h"
#include "resolved-dns-search-domain.h"
#include "resolved-dns-server.h"
#include "resolved-manager.h"
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 92ade820ac..40f08e8044 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -501,6 +501,7 @@ int manager_new(Manager **ret) {
m->mdns_support = RESOLVE_SUPPORT_NO;
m->dnssec_mode = DEFAULT_DNSSEC_MODE;
m->enable_cache = true;
+ m->dns_stub_listener_mode = DNS_STUB_LISTENER_UDP;
m->read_resolv_conf = true;
m->need_builtin_fallbacks = true;
m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY;
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index deebd8e484..6b2208ed94 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -30,6 +30,7 @@
typedef struct Manager Manager;
+#include "resolved-conf.h"
#include "resolved-dns-query.h"
#include "resolved-dns-search-domain.h"
#include "resolved-dns-server.h"
@@ -47,6 +48,7 @@ struct Manager {
ResolveSupport mdns_support;
DnssecMode dnssec_mode;
bool enable_cache;
+ DnsStubListenerMode dns_stub_listener_mode;
/* Network */
Hashmap *links;
diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
index 3bd8389c88..60afa151e3 100644
--- a/src/resolve/resolved.conf.in
+++ b/src/resolve/resolved.conf.in
@@ -18,3 +18,4 @@
#LLMNR=yes
#DNSSEC=@DEFAULT_DNSSEC_MODE@
#Cache=yes
+#DNSStubListener=udp
diff --git a/src/shared/gcrypt-util.h b/src/shared/gcrypt-util.h
index cf33b3c59c..1da12a32be 100644
--- a/src/shared/gcrypt-util.h
+++ b/src/shared/gcrypt-util.h
@@ -37,3 +37,11 @@ static inline int string_hashsum_sha224(const char *s, size_t len, char **out) {
return -EOPNOTSUPP;
#endif
}
+
+static inline int string_hashsum_sha256(const char *s, size_t len, char **out) {
+#ifdef HAVE_GCRYPT
+ return string_hashsum(s, len, GCRY_MD_SHA256, out);
+#else
+ return -EOPNOTSUPP;
+#endif
+}
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 19f1c29198..6000d9c7ec 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1739,7 +1739,9 @@ int main(int argc, char *argv[]) {
/* connect /dev/null to stdin, stdout, stderr */
if (log_get_max_level() < LOG_DEBUG)
- (void) make_null_stdio();
+ if (make_null_stdio() < 0)
+ log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m");
+
pid = fork();
switch (pid) {