New upstream version 246.5

This commit is contained in:
Michael Biebl 2020-09-13 21:00:26 +02:00
parent 129ef395a7
commit 7de6915edf
73 changed files with 1134 additions and 415 deletions

View File

@ -80,7 +80,7 @@
<parameter>m</parameter> itself if there is no parent container.</para>
<para><function>sd_bus_message_enter_container()</function> enters the next container of the message
<parameter>m</parameter>. It behaves mostly the same as
<parameter>m</parameter> for reading. It behaves mostly the same as
<function>sd_bus_message_open_container()</function>. Entering a container allows reading its contents
with
<citerefentry><refentrytitle>sd_bus_message_read</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@ -89,7 +89,12 @@
<para><function>sd_bus_message_exit_container()</function> exits the scope of the last container entered
with <function>sd_bus_message_enter_container()</function>. It behaves mostly the same as
<function>sd_bus_message_close_container()</function>.</para>
<function>sd_bus_message_close_container()</function>. Note that
<function>sd_bus_message_exit_container()</function> may only be called after iterating through all
members of the container, i.e. reading or skipping them. Use
<citerefentry><refentrytitle>sd_bus_message_skip</refentrytitle><manvolnum>3</manvolnum></citerefentry>
to skip over felds of a container in order to be able to exit the container with
<function>sd_bus_message_exit_container()</function> without reading all members.</para>
</refsect1>
<refsect1>
@ -128,6 +133,13 @@
<listitem><para>Memory allocation failed.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-EBUSY</constant></term>
<listitem><para><function>sd_bus_message_exit_container()</function> was called but there are
unread members left in the container.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
@ -158,6 +170,7 @@
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_read</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_skip</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<ulink url="https://dbus.freedesktop.org/doc/dbus-specification.html">The D-Bus specification</ulink>
</para>
</refsect1>

View File

@ -297,9 +297,10 @@
<listitem><para>Takes a boolean argument. If true, the time when the service unit was last triggered
is stored on disk. When the timer is activated, the service unit is triggered immediately if it
would have been triggered at least once during the time when the timer was inactive. This is useful
to catch up on missed runs of the service when the system was powered down. Note that this setting
only has an effect on timers configured with <varname>OnCalendar=</varname>. Defaults to
would have been triggered at least once during the time when the timer was inactive. Such triggering
is nonetheless subject to the delay imposed by <varname>RandomizedDelaySec=</varname>.
This is useful to catch up on missed runs of the service when the system was powered down. Note that
this setting only has an effect on timers configured with <varname>OnCalendar=</varname>. Defaults to
<varname>false</varname>.</para>
<para>Use <command>systemctl clean --what=state …</command> on the timer unit to remove the timestamp

View File

@ -28,11 +28,11 @@
<programlisting>
#Type Name ID GECOS Home directory Shell
u user_name uid "User Description" /path/to/shell
u user_name uid:gid - -
u user_name /file/owned/by/user - -
g group_name gid "Group Description"
g group_name /file/owned/by/group -
u user_name uid "User Description" /home/dir /path/to/shell
u user_name uid:gid "User Description" /home/dir /path/to/shell
u user_name /file/owned/by/user "User Description" /home/dir /path/to/shell
g group_name gid
g group_name /file/owned/by/group
m user_name group_name
r - lowest-highest</programlisting>
</refsynopsisdiv>

View File

@ -227,6 +227,7 @@ conf.set_quoted('SYSTEMCTL_BINARY_PATH', join_paths(rootbin
conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent'))
conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge'))
conf.set_quoted('ROOTPREFIX', rootprefixdir)
conf.set_quoted('ROOTPREFIX_NOSLASH', rootprefixdir_noslash)
conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup'))

View File

@ -48,6 +48,7 @@ _resolvectl() {
[DNSSEC]='dnssec'
[DNSOVERTLS]='dnsovertls'
[STANDALONE]='statistics reset-statistics flush-caches reset-server-features'
[LOG_LEVEL]='log-level'
)
local -A ARGS=(
[FAMILY]='tcp udp sctp'
@ -95,6 +96,9 @@ _resolvectl() {
elif __contains_word "$verb" ${VERBS[STATUS]}; then
comps="$interfaces"
elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then
comps='debug info notice warning err crit alert emerg'
elif __contains_word "$verb" ${VERBS[FAMILY]}; then
for ((i++; i < COMP_CWORD; i++)); do
if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} &&

View File

@ -284,6 +284,7 @@ static bool shall_clamp(sd_device *d) {
r = sd_device_get_property_value(d, "ID_BACKLIGHT_CLAMP", &s);
if (r < 0) {
if (r != -ENOENT)
log_device_debug_errno(d, r, "Failed to get ID_BACKLIGHT_CLAMP property, ignoring: %m");
return true;
}

View File

@ -315,6 +315,15 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
return -errno;
}
/* For the root fs — when no initrd is involved — btrfs returns /dev/root on any kernels from
* the past few years. That sucks, as we have no API to determine the actual root then. let's
* return an recognizable error for this case, so that the caller can maybe print a nice
* message about this.
*
* https://bugzilla.kernel.org/show_bug.cgi?id=89721 */
if (path_equal((char*) di.path, "/dev/root"))
return -EUCLEAN;
if (stat((char*) di.path, &st) < 0)
return -errno;

View File

@ -121,3 +121,9 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret);
int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota);
int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota);
static inline int btrfs_log_dev_root(int level, int ret, const char *p) {
return log_full_errno(level, ret,
"File system behind %s is reported by btrfs to be backed by pseudo-device /dev/root, which is not a valid userspace accessible device node. "
"Cannot determine correct backing block device.", p);
}

View File

@ -161,28 +161,21 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
return 0;
}
int capability_bounding_set_drop(uint64_t keep, bool right_now) {
_cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL;
int capability_gain_cap_setpcap(cap_t *ret_before_caps) {
_cleanup_cap_free_ cap_t caps = NULL;
cap_flag_value_t fv;
int r;
/* If we are run as PID 1 we will lack CAP_SETPCAP by default
* in the effective set (yes, the kernel drops that when
* executing init!), so get it back temporarily so that we can
* call PR_CAPBSET_DROP. */
before_cap = cap_get_proc();
if (!before_cap)
caps = cap_get_proc();
if (!caps)
return -errno;
if (cap_get_flag(before_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0)
if (cap_get_flag(caps, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0)
return -errno;
if (fv != CAP_SET) {
_cleanup_cap_free_ cap_t temp_cap = NULL;
static const cap_value_t v = CAP_SETPCAP;
temp_cap = cap_dup(before_cap);
temp_cap = cap_dup(caps);
if (!temp_cap)
return -errno;
@ -193,8 +186,27 @@ int capability_bounding_set_drop(uint64_t keep, bool right_now) {
log_debug_errno(errno, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m");
/* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this just means
* we'll fail later, when we actually intend to drop some capabilities. */
* we'll fail later, when we actually intend to drop some capabilities or try to set securebits. */
}
if (ret_before_caps)
/* Return the capabilities as they have been before setting CAP_SETPCAP */
*ret_before_caps = TAKE_PTR(caps);
return 0;
}
int capability_bounding_set_drop(uint64_t keep, bool right_now) {
_cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL;
int r;
/* If we are run as PID 1 we will lack CAP_SETPCAP by default
* in the effective set (yes, the kernel drops that when
* executing init!), so get it back temporarily so that we can
* call PR_CAPBSET_DROP. */
r = capability_gain_cap_setpcap(&before_cap);
if (r < 0)
return r;
after_cap = cap_dup(before_cap);
if (!after_cap)

View File

@ -14,6 +14,7 @@
unsigned cap_last_cap(void);
int have_effective_cap(int value);
int capability_gain_cap_setpcap(cap_t *return_caps);
int capability_bounding_set_drop(uint64_t keep, bool right_now);
int capability_bounding_set_drop_usermode(uint64_t keep);

View File

@ -229,6 +229,7 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
bool do_chown, do_chmod;
struct stat st;
int r;
/* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no
* point in time the access mode is above the old access mode under the old ownership or the new
@ -259,18 +260,22 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
if (do_chown && do_chmod) {
mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */
if (((minimal ^ st.st_mode) & 07777) != 0)
if (fchmod_opath(fd, minimal & 07777) < 0)
return -errno;
if (((minimal ^ st.st_mode) & 07777) != 0) {
r = fchmod_opath(fd, minimal & 07777);
if (r < 0)
return r;
}
}
if (do_chown)
if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0)
return -errno;
if (do_chmod)
if (fchmod_opath(fd, mode & 07777) < 0)
return -errno;
if (do_chmod) {
r = fchmod_opath(fd, mode & 07777);
if (r < 0)
return r;
}
return do_chown || do_chmod;
}

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
@ -19,7 +20,6 @@
#include "strv.h"
#if ENABLE_DEBUG_HASHMAP
#include <pthread.h>
#include "list.h"
#endif
@ -189,7 +189,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
* a handful of directly stored entries in a hashmap. When a hashmap
* outgrows direct storage, it gets its own key for indirect storage. */
static uint8_t shared_hash_key[HASH_KEY_SIZE];
static bool shared_hash_key_initialized;
/* Fields that all hashmap/set types must have */
struct HashmapBase {
@ -768,6 +767,10 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
static void shared_hash_key_initialize(void) {
random_bytes(shared_hash_key, sizeof(shared_hash_key));
}
static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type];
@ -790,10 +793,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
reset_direct_storage(h);
if (!shared_hash_key_initialized) {
random_bytes(shared_hash_key, sizeof(shared_hash_key));
shared_hash_key_initialized= true;
}
static pthread_once_t once = PTHREAD_ONCE_INIT;
assert_se(pthread_once(&once, shared_hash_key_initialize) == 0);
#if ENABLE_DEBUG_HASHMAP
h->debug.func = func;

View File

@ -795,13 +795,13 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
assert(addr);
siphash24_compress(addr, sizeof(*addr), state);
}
static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
return memcmp(a, b, sizeof(*a));
}

View File

@ -74,5 +74,8 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
* See also oss-fuzz#11344. */
#define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} })
void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state);
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b);
extern const struct hash_ops in_addr_data_hash_ops;
extern const struct hash_ops in6_addr_hash_ops;

View File

@ -234,12 +234,12 @@ void log_assert_failed_return_realm(
#define log_full_errno(level, error, ...) \
log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__)
#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__)
#define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__)
int log_emergency_level(void);
/* Normal logging */
#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__)
#define log_debug(...) log_full_errno(LOG_DEBUG, 0, __VA_ARGS__)
#define log_info(...) log_full(LOG_INFO, __VA_ARGS__)
#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__)
#define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__)

View File

@ -34,7 +34,7 @@ int quotactl_path(int cmd, const char *path, int id, void *addr) {
r = get_block_device(path, &devno);
if (r < 0)
return r;
if (devno == 0)
if (devno == 0) /* Doesn't have a block device */
return -ENODEV;
return quotactl_devno(cmd, devno, id, addr);

View File

@ -617,40 +617,62 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
return false;
}
int fd_inc_sndbuf(int fd, size_t n) {
int fd_set_sndbuf(int fd, size_t n, bool increase) {
int r, value;
socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 0;
/* If we have the privileges we will ignore the kernel limit. */
/* First, try to set the buffer size with SO_SNDBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
if (r < 0)
return r;
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 1;
/* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (r < 0)
return r;
}
return 1;
}
int fd_inc_rcvbuf(int fd, size_t n) {
int fd_set_rcvbuf(int fd, size_t n, bool increase) {
int r, value;
socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 0;
/* If we have the privileges we will ignore the kernel limit. */
/* First, try to set the buffer size with SO_RCVBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
return 1;
/* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (r < 0)
return r;
}
return 1;
}

View File

@ -118,8 +118,14 @@ int netlink_family_from_string(const char *s) _pure_;
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
int fd_inc_sndbuf(int fd, size_t n);
int fd_inc_rcvbuf(int fd, size_t n);
int fd_set_sndbuf(int fd, size_t n, bool increase);
static inline int fd_inc_sndbuf(int fd, size_t n) {
return fd_set_sndbuf(fd, n, true);
}
int fd_set_rcvbuf(int fd, size_t n, bool increase);
static inline int fd_inc_rcvbuf(int fd, size_t n) {
return fd_set_rcvbuf(fd, n, true);
}
int ip_tos_to_string_alloc(int i, char **s);
int ip_tos_from_string(const char *s);

View File

@ -1249,15 +1249,15 @@ static int verb_status(int argc, char *argv[], void *userdata) {
printf(" Secure Boot: %sd\n", enable_disable(is_efi_secure_boot()));
printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
r = efi_get_reboot_to_firmware();
if (r > 0)
k = efi_get_reboot_to_firmware();
if (k > 0)
printf(" Boot into FW: %sactive%s\n", ansi_highlight_yellow(), ansi_normal());
else if (r == 0)
else if (k == 0)
printf(" Boot into FW: supported\n");
else if (r == -EOPNOTSUPP)
else if (k == -EOPNOTSUPP)
printf(" Boot into FW: not supported\n");
else {
errno = -r;
errno = -k;
printf(" Boot into FW: %sfailed%s (%m)\n", ansi_highlight_red(), ansi_normal());
}
printf("\n");

View File

@ -900,7 +900,7 @@ void emit_bpf_firewall_warning(Unit *u) {
if (!warned) {
bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container();
log_unit_full(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
"unit configures an IP firewall, but %s.\n"
"(This warning is only shown for the first unit using IP firewalling.)",
getuid() != 0 ? "not running as root" :

View File

@ -78,7 +78,7 @@ static int set_attribute_and_warn(Unit *u, const char *controller, const char *a
r = cg_set_attribute(controller, u->cgroup_path, attribute, value);
if (r < 0)
log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value);
return r;
@ -724,7 +724,7 @@ static usec_t cgroup_cpu_adjust_period_and_log(Unit *u, usec_t period, usec_t qu
if (new_period != period) {
char v[FORMAT_TIMESPAN_MAX];
log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, 0,
log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING,
"Clamping CPU interval for cpu.max: period is now %s",
format_timespan(v, sizeof(v), new_period, 1));
u->warned_clamping_cpu_quota_period = true;
@ -986,7 +986,7 @@ static int cgroup_apply_devices(Unit *u) {
else
r = cg_set_attribute("devices", path, "devices.allow", "a");
if (r < 0)
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
log_unit_full_errno(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to reset devices.allow/devices.deny: %m");
}
@ -1351,7 +1351,7 @@ static void cgroup_context_apply(
else
r = 0;
if (r < 0)
log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r,
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r,
"Failed to write to tasks limit sysctls: %m");
}
@ -2436,7 +2436,7 @@ void unit_prune_cgroup(Unit *u) {
* the containing slice is stopped. So even if we failed now, this unit shouldn't assume
* that the cgroup is still realized the next time it is started. Do not return early
* on error, continue cleanup. */
log_unit_full(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
log_unit_full_errno(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
if (is_root_slice)
return;

View File

@ -1072,26 +1072,42 @@ static int enforce_groups(gid_t gid, const gid_t *supplementary_gids, int ngids)
return 0;
}
static int set_securebits(int bits, int mask) {
int current, applied;
current = prctl(PR_GET_SECUREBITS);
if (current < 0)
return -errno;
/* Clear all securebits defined in mask and set bits */
applied = (current & ~mask) | bits;
if (current == applied)
return 0;
if (prctl(PR_SET_SECUREBITS, applied) < 0)
return -errno;
return 1;
}
static int enforce_user(const ExecContext *context, uid_t uid) {
assert(context);
int r;
if (!uid_is_valid(uid))
return 0;
/* Sets (but doesn't look up) the uid and make sure we keep the
* capabilities while doing so. */
* capabilities while doing so. For setting secure bits the capability CAP_SETPCAP is
* required, so we also need keep-caps in this case.
*/
if (context->capability_ambient_set != 0) {
if (context->capability_ambient_set != 0 || context->secure_bits != 0) {
/* First step: If we need to keep capabilities but
* drop privileges we need to make sure we keep our
* caps, while we drop privileges. */
if (uid != 0) {
int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
if (prctl(PR_GET_SECUREBITS) != sb)
if (prctl(PR_SET_SECUREBITS, sb) < 0)
return -errno;
/* Add KEEP_CAPS to the securebits */
r = set_securebits(1<<SECURE_KEEP_CAPS, 0);
if (r < 0)
return r;
}
}
@ -3779,8 +3795,16 @@ static int exec_child(
}
}
/* This is done before enforce_user, but ambient set
* does not survive over setresuid() if keep_caps is not set. */
/* Ambient capabilities are cleared during setresuid() (in enforce_user()) even with
* keep-caps set.
* To be able to raise the ambient capabilities after setresuid() they have to be
* added to the inherited set and keep caps has to be set (done in enforce_user()).
* After setresuid() the ambient capabilities can be raised as they are present in
* the permitted and inhertiable set. However it is possible that someone wants to
* set ambient capabilities without changing the user, so we also set the ambient
* capabilities here.
* The requested ambient capabilities are raised in the inheritable set if the
* second argument is true. */
if (!needs_ambient_hack) {
r = capability_ambient_set_apply(context->capability_ambient_set, true);
if (r < 0) {
@ -3806,21 +3830,12 @@ static int exec_child(
if (!needs_ambient_hack &&
context->capability_ambient_set != 0) {
/* Fix the ambient capabilities after user change. */
/* Raise the ambient capabilities after user change. */
r = capability_ambient_set_apply(context->capability_ambient_set, false);
if (r < 0) {
*exit_status = EXIT_CAPABILITIES;
return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m");
}
/* If we were asked to change user and ambient capabilities
* were requested, we had to add keep-caps to the securebits
* so that we would maintain the inherited capability set
* through the setresuid(). Make sure that the bit is added
* also to the context secure_bits so that we don't try to
* drop the bit away next. */
secure_bits |= 1<<SECURE_KEEP_CAPS;
}
}
}
@ -3862,12 +3877,27 @@ static int exec_child(
#endif
/* PR_GET_SECUREBITS is not privileged, while PR_SET_SECUREBITS is. So to suppress potential EPERMs
* we'll try not to call PR_SET_SECUREBITS unless necessary. */
if (prctl(PR_GET_SECUREBITS) != secure_bits)
* we'll try not to call PR_SET_SECUREBITS unless necessary. Setting securebits requires
* CAP_SETPCAP. */
if (prctl(PR_GET_SECUREBITS) != secure_bits) {
/* CAP_SETPCAP is required to set securebits. This capabilitiy is raised into the
* effective set here.
* The effective set is overwritten during execve with the following values:
* - ambient set (for non-root processes)
* - (inheritable | bounding) set for root processes)
*
* Hence there is no security impact to raise it in the effective set before execve
*/
r = capability_gain_cap_setpcap(NULL);
if (r < 0) {
*exit_status = EXIT_CAPABILITIES;
return log_unit_error_errno(unit, r, "Failed to gain CAP_SETPCAP for setting secure bits");
}
if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) {
*exit_status = EXIT_SECUREBITS;
return log_unit_error_errno(unit, errno, "Failed to set process secure bits: %m");
}
}
if (context_has_no_new_privileges(context))
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
@ -5715,8 +5745,13 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
n = strcspn(v, " ");
buf = strndupa(v, n);
if (safe_atoi(buf, &fdpair[0]) < 0 || !fdset_contains(fds, fdpair[0]))
return log_debug("Unable to process exec-runtime netns fd specification.");
r = safe_atoi(buf, &fdpair[0]);
if (r < 0)
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-0=%s: %m", buf);
if (!fdset_contains(fds, fdpair[0]))
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
"exec-runtime specification netns-socket-0= refers to unknown fd %d: %m", fdpair[0]);
fdpair[0] = fdset_remove(fds, fdpair[0]);
if (v[n] != ' ')
goto finalize;
@ -5729,8 +5764,12 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
n = strcspn(v, " ");
buf = strndupa(v, n);
if (safe_atoi(buf, &fdpair[1]) < 0 || !fdset_contains(fds, fdpair[1]))
return log_debug("Unable to process exec-runtime netns fd specification.");
r = safe_atoi(buf, &fdpair[1]);
if (r < 0)
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-1=%s: %m", buf);
if (!fdset_contains(fds, fdpair[0]))
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
"exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", fdpair[1]);
fdpair[1] = fdset_remove(fds, fdpair[1]);
}

View File

@ -918,17 +918,17 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) {
* good */
if (pid == getpid_cached() || pid == 1) {
log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the manager, refusing.", pid);
log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the manager, refusing.", pid);
return -EPERM;
}
if (pid == s->control_pid) {
log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the control process, refusing.", pid);
log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the control process, refusing.", pid);
return -EPERM;
}
if (!pid_is_alive(pid)) {
log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid);
log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" does not exist or is a zombie.", pid);
return -ESRCH;
}
@ -958,7 +958,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd);
if (r == -ENOLINK) {
log_unit_full(UNIT(s), LOG_DEBUG, r,
log_unit_debug_errno(UNIT(s), r,
"Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
questionable_pid_file = true;
@ -966,7 +966,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd);
}
if (r < 0)
return log_unit_full(UNIT(s), prio, fd,
return log_unit_full_errno(UNIT(s), prio, fd,
"Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
/* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd
@ -980,7 +980,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = parse_pid(k, &pid);
if (r < 0)
return log_unit_full(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file);
return log_unit_full_errno(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file);
if (s->main_pid_known && pid == s->main_pid)
return 0;

View File

@ -383,8 +383,10 @@ static int slice_freezer_action(Unit *s, FreezerAction action) {
assert(s);
assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW));
if (!slice_freezer_action_supported_by_children(s))
return log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice");
if (!slice_freezer_action_supported_by_children(s)) {
log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice");
return 0;
}
HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE], i) {
if (UNIT_DEREF(member->slice) != s)

View File

@ -18,6 +18,7 @@
#include "dbus-socket.h"
#include "dbus-unit.h"
#include "def.h"
#include "errno-list.h"
#include "exit-status.h"
#include "fd-util.h"
#include "format-util.h"
@ -1072,20 +1073,17 @@ static void socket_apply_socket_options(Socket *s, int fd) {
}
if (s->receive_buffer > 0) {
/* We first try with SO_RCVBUFFORCE, in case we have the perms for that */
if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) {
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer);
r = fd_set_rcvbuf(fd, s->receive_buffer, false);
if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m");
}
log_unit_full_errno(UNIT(s), ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r,
"SO_RCVBUF/SO_RCVBUFFORCE failed: %m");
}
if (s->send_buffer > 0) {
if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) {
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer);
r = fd_set_sndbuf(fd, s->send_buffer, false);
if (r < 0)
log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m");
}
log_unit_full_errno(UNIT(s), ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r,
"SO_SNDBUF/SO_SNDBUFFORCE failed: %m");
}
if (s->mark >= 0) {
@ -1418,11 +1416,12 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {
if (cfd >= 0) {
r = instance_from_socket(cfd, s->n_accepted, &instance);
if (r == -ENOTCONN)
/* ENOTCONN is legitimate if TCP RST was received.
* This connection is over, but the socket unit lives on. */
if (ERRNO_IS_DISCONNECT(r))
/* ENOTCONN is legitimate if TCP RST was received. Other socket families might return
* different errors. This connection is over, but the socket unit lives on. */
return log_unit_debug_errno(UNIT(s), r,
"Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring.");
"Got %s on incoming socket, assuming aborted connection attempt, ignoring.",
errno_to_name(r));
if (r < 0)
return r;
}
@ -2359,8 +2358,8 @@ static void socket_enter_running(Socket *s, int cfd) {
if (!pending) {
if (!UNIT_ISSET(s->service)) {
log_unit_error(UNIT(s), "Service to activate vanished, refusing activation.");
r = -ENOENT;
r = log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT),
"Service to activate vanished, refusing activation.");
goto fail;
}
@ -2382,8 +2381,10 @@ static void socket_enter_running(Socket *s, int cfd) {
if (s->max_connections_per_source > 0) {
r = socket_acquire_peer(s, cfd, &p);
if (r < 0)
goto refuse;
if (ERRNO_IS_DISCONNECT(r))
goto notconn;
if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */
goto fail;
if (r > 0 && p->n_ref > s->max_connections_per_source) {
_cleanup_free_ char *t = NULL;
@ -2397,6 +2398,8 @@ static void socket_enter_running(Socket *s, int cfd) {
}
r = socket_instantiate_service(s, cfd);
if (ERRNO_IS_DISCONNECT(r))
goto notconn;
if (r < 0)
goto fail;
@ -2406,6 +2409,8 @@ static void socket_enter_running(Socket *s, int cfd) {
s->n_accepted++;
r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net);
if (ERRNO_IS_DISCONNECT(r))
goto notconn;
if (r < 0)
goto fail;
@ -2430,10 +2435,15 @@ static void socket_enter_running(Socket *s, int cfd) {
refuse:
s->n_refused++;
notconn:
safe_close(cfd);
return;
fail:
if (ERRNO_IS_RESOURCE(r))
log_unit_warning(UNIT(s), "Failed to queue service startup job: %s",
bus_error_message(&error, r));
else
log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",
cfd >= 0 ? "template" : "non-template",
bus_error_message(&error, r));

View File

@ -284,7 +284,7 @@ static int swap_load_devnode(Swap *s) {
r = device_new_from_stat_rdev(&d, &st);
if (r < 0) {
log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
log_unit_full_errno(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to allocate device for swap %s: %m", s->what);
return 0;
}

View File

@ -1009,9 +1009,8 @@ int transaction_add_job_and_dependencies(
SET_FOREACH(dep, following, i) {
r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e);
if (r < 0) {
log_unit_full(dep,
r == -ERFKILL ? LOG_INFO : LOG_WARNING,
r, "Cannot add dependency job, ignoring: %s",
log_unit_full_errno(dep, r == -ERFKILL ? LOG_INFO : LOG_WARNING, r,
"Cannot add dependency job, ignoring: %s",
bus_error_message(e, r));
sd_bus_error_free(e);
}
@ -1046,7 +1045,7 @@ int transaction_add_job_and_dependencies(
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e);
if (r < 0) {
/* unit masked, job type not applicable and unit not found are not considered as errors. */
log_unit_full(dep,
log_unit_full_errno(dep,
IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING,
r, "Cannot add dependency job, ignoring: %s",
bus_error_message(e, r));

View File

@ -896,7 +896,7 @@ int unit_thaw_vtable_common(Unit *u);
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full(unit, level, error, ...) \
#define log_unit_full_errno(unit, level, error, ...) \
({ \
const Unit *_u = (unit); \
(log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \
@ -904,17 +904,19 @@ int unit_thaw_vtable_common(Unit *u);
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
})
#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__)
#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__)
#define log_unit_full(unit, level, ...) (void) log_unit_full_errno(unit, level, 0, __VA_ARGS__)
#define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__)
#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__)
#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__)
#define log_unit_debug(unit, ...) log_unit_full_errno(unit, LOG_DEBUG, 0, __VA_ARGS__)
#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, __VA_ARGS__)
#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, __VA_ARGS__)
#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__)
#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, __VA_ARGS__)
#define log_unit_debug_errno(unit, error, ...) log_unit_full_errno(unit, LOG_DEBUG, error, __VA_ARGS__)
#define log_unit_info_errno(unit, error, ...) log_unit_full_errno(unit, LOG_INFO, error, __VA_ARGS__)
#define log_unit_notice_errno(unit, error, ...) log_unit_full_errno(unit, LOG_NOTICE, error, __VA_ARGS__)
#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, __VA_ARGS__)
#define log_unit_error_errno(unit, error, ...) log_unit_full_errno(unit, LOG_ERR, error, __VA_ARGS__)
#define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__
#define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id

View File

@ -211,13 +211,15 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to extract instance: %m");
if (isempty(name))
return log_error("Unit %s is missing the instance name.", *i);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unit %s is missing the instance name.", *i);
r = unit_name_template(*i, &template);
if (r < 0)
return log_error_errno(r, "Failed to extract template: %m");
if (arg_template && !streq(arg_template, template))
return log_error("Unit %s template %s does not match specified template %s.",
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unit %s template %s does not match specified template %s.",
*i, template, arg_template);
} else {
name = strdup(*i);

View File

@ -729,10 +729,14 @@ static int add_mounts(void) {
int r;
r = get_block_device_harder("/", &devno);
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, "root file system");
if (r < 0)
return log_error_errno(r, "Failed to determine block device of root file system: %m");
if (r == 0) {
if (r == 0) { /* Not backed by block device */
r = get_block_device_harder("/usr", &devno);
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, "/usr");
if (r < 0)
return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
if (r == 0) {

View File

@ -1112,7 +1112,7 @@ static int home_fixate_internal(
if (r < 0)
return r;
if (for_state == HOME_FIXATING_FOR_ACTIVATION) {
if (IN_SET(for_state, HOME_FIXATING_FOR_ACTIVATION, HOME_FIXATING_FOR_ACQUIRE)) {
/* Remember the secret data, since we need it for the activation again, later on. */
user_record_unref(h->secret);
h->secret = user_record_ref(secret);

View File

@ -91,18 +91,9 @@ int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor
}
_public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) {
int r, n = (int) size;
assert_return(m, -EINVAL);
assert_return((size_t) n == size, -EINVAL);
if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) {
r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;
}
return 0;
return fd_set_rcvbuf(m->sock, size, false);
}
int device_monitor_disconnect(sd_device_monitor *m) {

View File

@ -31,7 +31,7 @@
device; \
device = sd_device_enumerator_get_subsystem_next(enumerator))
#define log_device_full(device, level, error, ...) \
#define log_device_full_errno(device, level, error, ...) \
({ \
const char *_sysname = NULL; \
sd_device *_d = (device); \
@ -41,17 +41,19 @@
(void) sd_device_get_sysname(_d, &_sysname); \
log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \
_sysname ? "DEVICE=" : NULL, _sysname, \
NULL, NULL, ##__VA_ARGS__); \
NULL, NULL, __VA_ARGS__); \
})
#define log_device_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_device_info(device, ...) log_device_full(device, LOG_INFO, 0, ##__VA_ARGS__)
#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_device_error(device, ...) log_device_full(device, LOG_ERR, 0, ##__VA_ARGS__)
#define log_device_full(device, level, ...) (void) log_device_full_errno(device, level, 0, __VA_ARGS__)
#define log_device_debug_errno(device, error, ...) log_device_full(device, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_device_info_errno(device, error, ...) log_device_full(device, LOG_INFO, error, ##__VA_ARGS__)
#define log_device_notice_errno(device, error, ...) log_device_full(device, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_device_warning_errno(device, error, ...) log_device_full(device, LOG_WARNING, error, ##__VA_ARGS__)
#define log_device_error_errno(device, error, ...) log_device_full(device, LOG_ERR, error, ##__VA_ARGS__)
#define log_device_debug(device, ...) log_device_full_errno(device, LOG_DEBUG, 0, __VA_ARGS__)
#define log_device_info(device, ...) log_device_full(device, LOG_INFO, __VA_ARGS__)
#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, __VA_ARGS__)
#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, __VA_ARGS__)
#define log_device_error(device, ...) log_device_full(device, LOG_ERR, __VA_ARGS__)
#define log_device_debug_errno(device, error, ...) log_device_full_errno(device, LOG_DEBUG, error, __VA_ARGS__)
#define log_device_info_errno(device, error, ...) log_device_full_errno(device, LOG_INFO, error, __VA_ARGS__)
#define log_device_notice_errno(device, error, ...) log_device_full_errno(device, LOG_NOTICE, error, __VA_ARGS__)
#define log_device_warning_errno(device, error, ...) log_device_full_errno(device, LOG_WARNING, error, __VA_ARGS__)
#define log_device_error_errno(device, error, ...) log_device_full_errno(device, LOG_ERR, error, __VA_ARGS__)

View File

@ -321,7 +321,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
return from_user_dir("XDG_DESKTOP_DIR", buffer, ret);
case SD_PATH_SYSTEMD_UTIL:
*ret = ROOTPREFIX "/lib/systemd";
*ret = ROOTPREFIX_NOSLASH "/lib/systemd";
return 0;
case SD_PATH_SYSTEMD_SYSTEM_UNIT:
@ -329,7 +329,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
return 0;
case SD_PATH_SYSTEMD_SYSTEM_PRESET:
*ret = ROOTPREFIX "/lib/systemd/system-preset";
*ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-preset";
return 0;
case SD_PATH_SYSTEMD_USER_UNIT:
@ -337,7 +337,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
return 0;
case SD_PATH_SYSTEMD_USER_PRESET:
*ret = ROOTPREFIX "/lib/systemd/user-preset";
*ret = ROOTPREFIX_NOSLASH "/lib/systemd/user-preset";
return 0;
case SD_PATH_SYSTEMD_SYSTEM_CONF:
@ -357,11 +357,11 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
return 0;
case SD_PATH_SYSTEMD_SLEEP:
*ret = ROOTPREFIX "/lib/systemd/system-sleep";
*ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-sleep";
return 0;
case SD_PATH_SYSTEMD_SHUTDOWN:
*ret = ROOTPREFIX "/lib/systemd/system-shutdown";
*ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-shutdown";
return 0;
/* FIXME: systemd.pc uses ${prefix}, but CONF_PATHS_NULSTR doesn't.
@ -371,19 +371,19 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
return 0;
case SD_PATH_SYSUSERS:
*ret = ROOTPREFIX "/lib/sysusers.d";
*ret = ROOTPREFIX_NOSLASH "/lib/sysusers.d";
return 0;
case SD_PATH_SYSCTL:
*ret = ROOTPREFIX "/lib/sysctl.d";
*ret = ROOTPREFIX_NOSLASH "/lib/sysctl.d";
return 0;
case SD_PATH_BINFMT:
*ret = ROOTPREFIX "/lib/binfmt.d";
*ret = ROOTPREFIX_NOSLASH "/lib/binfmt.d";
return 0;
case SD_PATH_MODULES_LOAD:
*ret = ROOTPREFIX "/lib/modules-load.d";
*ret = ROOTPREFIX_NOSLASH "/lib/modules-load.d";
return 0;
case SD_PATH_CATALOG:

View File

@ -852,10 +852,12 @@ int config_parse_macsec_key_id(
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse KeyId \"%s\": %m", rvalue);
return 0;
}
if (l > MACSEC_KEYID_LEN)
return log_syntax(unit, LOG_WARNING, filename, line, 0,
if (l > MACSEC_KEYID_LEN) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified KeyId is larger then the allowed maximum (%zu > %u), ignoring: %s",
l, MACSEC_KEYID_LEN, rvalue);
return 0;
}
dest = a ? a->sa.key_id : b->sa.key_id;
memcpy_safe(dest, p, l);

View File

@ -493,13 +493,17 @@ static int wireguard_decode_key_and_warn(
(void) warn_file_is_world_accessible(filename, NULL, unit, line);
r = unbase64mem_full(rvalue, strlen(rvalue), true, &key, &len);
if (r < 0)
return log_syntax(unit, LOG_WARNING, filename, line, r,
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue);
if (len != WG_KEY_LEN)
return log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL),
return 0;
}
if (len != WG_KEY_LEN) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.",
lvalue, len);
return 0;
}
memcpy(ret, key, WG_KEY_LEN);
return 0;

View File

@ -10,6 +10,7 @@
#include "netlink-util.h"
#include "networkd-address.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
#include "parse-util.h"
#include "set.h"
#include "socket-util.h"
@ -123,6 +124,9 @@ void address_free(Address *address) {
}
if (address->link && !address->acd) {
NDiscAddress *n;
Iterator i;
set_remove(address->link->addresses, address);
set_remove(address->link->addresses_foreign, address);
set_remove(address->link->static_addresses, address);
@ -134,8 +138,9 @@ void address_free(Address *address) {
set_remove(address->link->dhcp6_addresses_old, address);
set_remove(address->link->dhcp6_pd_addresses, address);
set_remove(address->link->dhcp6_pd_addresses_old, address);
set_remove(address->link->ndisc_addresses, address);
set_remove(address->link->ndisc_addresses_old, address);
SET_FOREACH(n, address->link->ndisc_addresses, i)
if (n->address == address)
free(set_remove(address->link->ndisc_addresses, n));
if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address))
memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
@ -162,7 +167,7 @@ static uint32_t address_prefix(const Address *a) {
return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
}
static void address_hash_func(const Address *a, struct siphash *state) {
void address_hash_func(const Address *a, struct siphash *state) {
assert(a);
siphash24_compress(&a->family, sizeof(a->family), state);
@ -187,7 +192,7 @@ static void address_hash_func(const Address *a, struct siphash *state) {
}
}
static int address_compare_func(const Address *a1, const Address *a2) {
int address_compare_func(const Address *a1, const Address *a2) {
int r;
r = CMP(a1->family, a2->family);

View File

@ -75,6 +75,8 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret);
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
void address_hash_func(const Address *a, struct siphash *state);
int address_compare_func(const Address *a1, const Address *a2);
extern const struct hash_ops address_hash_ops;
CONFIG_PARSER_PROTOTYPE(config_parse_address);

View File

@ -251,11 +251,10 @@ static int dhcp_prefix_route_from_lease(
static int link_set_dhcp_routes(Link *link) {
_cleanup_free_ sd_dhcp_route **static_routes = NULL;
bool classless_route = false, static_route = false;
const struct in_addr *router;
struct in_addr address;
int r, n, i;
uint32_t table;
Route *rt;
int r, n;
assert(link);
@ -298,9 +297,9 @@ static int link_set_dhcp_routes(Link *link) {
if (n == -ENODATA)
log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
else if (n < 0)
log_link_debug_errno(link, n, "DHCP: could not get routes: %m");
return log_link_error_errno(link, n, "DHCP: could not get routes: %m");
for (i = 0; i < n; i++) {
for (int i = 0; i < n; i++) {
switch (sd_dhcp_route_get_option(static_routes[i])) {
case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
classless_route = true;
@ -312,11 +311,14 @@ static int link_set_dhcp_routes(Link *link) {
}
if (link->network->dhcp_use_routes) {
for (i = 0; i < n; i++) {
/* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
* the DHCP client MUST ignore the Static Routes option. */
if (classless_route && static_route)
log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option");
for (int i = 0; i < n; i++) {
_cleanup_(route_freep) Route *route = NULL;
/* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
the DHCP client MUST ignore the Static Routes option. */
if (classless_route &&
sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
continue;
@ -347,20 +349,20 @@ static int link_set_dhcp_routes(Link *link) {
}
if (link->network->dhcp_use_gateway) {
const struct in_addr *router;
r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
if (IN_SET(r, 0, -ENODATA))
log_link_info(link, "DHCP: No gateway received from DHCP server.");
else if (r < 0)
log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
else if (in4_addr_is_null(&router[0]))
log_link_info(link, "DHCP: Received gateway is null.");
else if (classless_route)
/* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
a Router option, the DHCP client MUST ignore the Router option. */
if (classless_route && static_route)
log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) {
* a Router option, the DHCP client MUST ignore the Router option. */
log_link_warning(link, "Classless static routes received from DHCP server: ignoring router option");
else {
_cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
r = route_new(&route_gw);
@ -399,7 +401,6 @@ static int link_set_dhcp_routes(Link *link) {
r = dhcp_route_configure(route, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not set router: %m");
}
LIST_FOREACH(routes, rt, link->network->static_routes) {
if (!rt->gateway_from_dhcp)
@ -415,6 +416,7 @@ static int link_set_dhcp_routes(Link *link) {
return log_link_error_errno(link, r, "Could not set gateway: %m");
}
}
}
return link_set_dns_routes(link, &address);
}

View File

@ -160,6 +160,7 @@ static int dhcp6_pd_remove_old(Link *link, bool force) {
if (k < 0)
r = k;
if (link->radv)
(void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64);
dhcp6_pd_free(hashmap_get(link->manager->dhcp6_prefixes, &route->dst.in6));
}
@ -201,6 +202,7 @@ int dhcp6_pd_remove(Link *link) {
if (k < 0)
r = k;
if (link->radv)
(void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64);
dhcp6_pd_free(hashmap_get(link->manager->dhcp6_prefixes, &route->dst.in6));
}
@ -992,7 +994,7 @@ static int dhcp6_update_address(
addr->cinfo.ifa_valid = lifetime_valid;
(void) in_addr_to_string(addr->family, &addr->in_addr, &buffer);
log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, 0,
log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO,
"DHCPv6 address %s/%u timeout preferred %d valid %d",
strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid);

View File

@ -292,10 +292,12 @@ int config_parse_fdb_destination(
return log_oom();
r = in_addr_from_string_auto(rvalue, &fdb_entry->family, &fdb_entry->destination_addr);
if (r < 0)
return log_syntax(unit, LOG_WARNING, filename, line, r,
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"FDB destination IP address is invalid, ignoring assignment: %s",
rvalue);
return 0;
}
fdb_entry = NULL;

View File

@ -720,7 +720,6 @@ static Link *link_free(Link *link) {
link->dhcp6_pd_routes = set_free(link->dhcp6_pd_routes);
link->dhcp6_pd_routes_old = set_free(link->dhcp6_pd_routes_old);
link->ndisc_routes = set_free(link->ndisc_routes);
link->ndisc_routes_old = set_free(link->ndisc_routes_old);
link->nexthops = set_free(link->nexthops);
link->nexthops_foreign = set_free(link->nexthops_foreign);
@ -736,7 +735,6 @@ static Link *link_free(Link *link) {
link->dhcp6_pd_addresses = set_free(link->dhcp6_pd_addresses);
link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old);
link->ndisc_addresses = set_free(link->ndisc_addresses);
link->ndisc_addresses_old = set_free(link->ndisc_addresses_old);
while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address);
@ -1163,6 +1161,8 @@ void link_check_ready(Link *link) {
}
if (link_has_carrier(link) || !link->network->configure_without_carrier) {
bool has_ndisc_address = false;
NDiscAddress *n;
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) {
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
@ -1175,8 +1175,14 @@ void link_check_ready(Link *link) {
return;
}
SET_FOREACH(n, link->ndisc_addresses, i)
if (!n->marked) {
has_ndisc_address = true;
break;
}
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && set_isempty(link->ndisc_addresses) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) {
log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no dynamic address is assigned yet.", __func__);
return;
@ -4674,7 +4680,7 @@ int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, in
const char *err_msg = NULL;
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_link_full(link, level, err,
return log_link_full_errno(link, level, err,
"%s: %s%s%s%m",
msg,
strempty(err_msg),

View File

@ -132,8 +132,8 @@ typedef struct Link {
sd_ndisc *ndisc;
Set *ndisc_rdnss;
Set *ndisc_dnssl;
Set *ndisc_addresses, *ndisc_addresses_old;
Set *ndisc_routes, *ndisc_routes_old;
Set *ndisc_addresses;
Set *ndisc_routes;
unsigned ndisc_addresses_messages;
unsigned ndisc_routes_messages;
bool ndisc_addresses_configured:1;

View File

@ -36,11 +36,11 @@
#include "path-util.h"
#include "set.h"
#include "signal-util.h"
#include "stat-util.h"
#include "strv.h"
#include "sysctl-util.h"
#include "tmpfile-util.h"
#include "udev-util.h"
#include "virt.h"
/* use 128 MB for receive socket kernel queue. */
#define RCVBUF_SIZE (128*1024*1024)
@ -260,16 +260,19 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
static int manager_connect_udev(Manager *m) {
int r;
/* udev does not initialize devices inside containers,
* so we rely on them being already initialized before
* entering the container */
if (detect_container() > 0)
/* udev does not initialize devices inside containers, so we rely on them being already
* initialized before entering the container. */
if (path_is_read_only_fs("/sys") > 0)
return 0;
r = sd_device_monitor_new(&m->device_monitor);
if (r < 0)
return log_error_errno(r, "Failed to initialize device monitor: %m");
r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
if (r < 0)
log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
if (r < 0)
return log_error_errno(r, "Could not add device monitor filter: %m");
@ -1346,7 +1349,7 @@ static int manager_connect_genl(Manager *m) {
r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE);
if (r < 0)
return r;
log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m");
r = sd_netlink_attach_event(m->genl, m->event, 0);
if (r < 0)
@ -1368,9 +1371,14 @@ static int manager_connect_rtnl(Manager *m) {
if (r < 0)
return r;
/* Bump receiver buffer, but only if we are not called via socket activation, as in that
* case systemd sets the receive buffer size for us, and the value in the .socket unit
* should take full effect. */
if (fd < 0) {
r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
if (r < 0)
return r;
log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m");
}
r = sd_netlink_attach_event(m->rtnl, m->event, 0);
if (r < 0)

View File

@ -35,79 +35,218 @@
#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
static int ndisc_remove_old(Link *link, bool force);
static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force);
static int ndisc_address_callback(Address *address) {
Address *a;
struct in6_addr router = {};
NDiscAddress *n;
Iterator i;
assert(address);
assert(address->link);
/* Make this called only once */
SET_FOREACH(a, address->link->ndisc_addresses, i)
a->callback = NULL;
SET_FOREACH(n, address->link->ndisc_addresses, i)
if (n->address == address) {
router = n->router;
break;
}
return ndisc_remove_old(address->link, true);
if (IN6_IS_ADDR_UNSPECIFIED(&router)) {
_cleanup_free_ char *buf = NULL;
(void) in_addr_to_string(address->family, &address->in_addr, &buf);
log_link_debug(address->link, "%s is called for %s/%u, but it is already removed, ignoring.",
__func__, strna(buf), address->prefixlen);
return 0;
}
/* Make this called only once */
SET_FOREACH(n, address->link->ndisc_addresses, i)
if (IN6_ARE_ADDR_EQUAL(&n->router, &router))
n->address->callback = NULL;
return ndisc_remove_old_one(address->link, &router, true);
}
static int ndisc_remove_old(Link *link, bool force) {
Address *address;
Route *route;
static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force) {
NDiscAddress *na;
NDiscRoute *nr;
NDiscDNSSL *dnssl;
NDiscRDNSS *rdnss;
Iterator i;
int k, r = 0;
assert(link);
assert(router);
if (!force) {
bool set_callback = !set_isempty(link->ndisc_addresses);
bool set_callback = false;
if (!link->ndisc_addresses_configured || !link->ndisc_routes_configured)
return 0;
SET_FOREACH(address, link->ndisc_addresses, i)
if (address_is_ready(address)) {
SET_FOREACH(na, link->ndisc_addresses, i)
if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) {
set_callback = true;
break;
}
if (set_callback)
SET_FOREACH(na, link->ndisc_addresses, i)
if (!na->marked && address_is_ready(na->address)) {
set_callback = false;
break;
}
if (set_callback) {
SET_FOREACH(address, link->ndisc_addresses, i)
address->callback = ndisc_address_callback;
SET_FOREACH(na, link->ndisc_addresses, i)
if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router))
na->address->callback = ndisc_address_callback;
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) router, &buf);
log_link_debug(link, "No SLAAC address obtained from %s is ready. "
"The old NDisc information will be removed later.",
strna(buf));
}
return 0;
}
}
if (!set_isempty(link->ndisc_addresses_old) || !set_isempty(link->ndisc_routes_old))
log_link_debug(link, "Removing old NDisc addresses and routes.");
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) router, &buf);
log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf));
}
link_dirty(link);
SET_FOREACH(address, link->ndisc_addresses_old, i) {
k = address_remove(address, link, NULL);
SET_FOREACH(na, link->ndisc_addresses, i)
if (na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) {
k = address_remove(na->address, link, NULL);
if (k < 0)
r = k;
}
SET_FOREACH(route, link->ndisc_routes_old, i) {
k = route_remove(route, link, NULL);
SET_FOREACH(nr, link->ndisc_routes, i)
if (nr->marked && IN6_ARE_ADDR_EQUAL(&nr->router, router)) {
k = route_remove(nr->route, link, NULL);
if (k < 0)
r = k;
}
SET_FOREACH(rdnss, link->ndisc_rdnss, i)
if (rdnss->marked)
if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router))
free(set_remove(link->ndisc_rdnss, rdnss));
SET_FOREACH(dnssl, link->ndisc_dnssl, i)
if (dnssl->marked)
if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router))
free(set_remove(link->ndisc_dnssl, dnssl));
return r;
}
static int ndisc_remove_old(Link *link) {
_cleanup_set_free_free_ Set *routers = NULL;
_cleanup_free_ struct in6_addr *router = NULL;
struct in6_addr *a;
NDiscAddress *na;
NDiscRoute *nr;
NDiscDNSSL *dnssl;
NDiscRDNSS *rdnss;
Iterator i;
int k, r;
assert(link);
routers = set_new(&in6_addr_hash_ops);
if (!routers)
return -ENOMEM;
SET_FOREACH(na, link->ndisc_addresses, i)
if (!set_contains(routers, &na->router)) {
router = newdup(struct in6_addr, &na->router, 1);
if (!router)
return -ENOMEM;
r = set_put(routers, router);
if (r < 0)
return r;
assert(r > 0);
TAKE_PTR(router);
}
SET_FOREACH(nr, link->ndisc_routes, i)
if (!set_contains(routers, &nr->router)) {
router = newdup(struct in6_addr, &nr->router, 1);
if (!router)
return -ENOMEM;
r = set_put(routers, router);
if (r < 0)
return r;
assert(r > 0);
TAKE_PTR(router);
}
SET_FOREACH(rdnss, link->ndisc_rdnss, i)
if (!set_contains(routers, &rdnss->router)) {
router = newdup(struct in6_addr, &rdnss->router, 1);
if (!router)
return -ENOMEM;
r = set_put(routers, router);
if (r < 0)
return r;
assert(r > 0);
TAKE_PTR(router);
}
SET_FOREACH(dnssl, link->ndisc_dnssl, i)
if (!set_contains(routers, &dnssl->router)) {
router = newdup(struct in6_addr, &dnssl->router, 1);
if (!router)
return -ENOMEM;
r = set_put(routers, router);
if (r < 0)
return r;
assert(r > 0);
TAKE_PTR(router);
}
r = 0;
SET_FOREACH(a, routers, i) {
k = ndisc_remove_old_one(link, a, false);
if (k < 0)
r = k;
}
return r;
}
static void ndisc_route_hash_func(const NDiscRoute *x, struct siphash *state) {
route_hash_func(x->route, state);
}
static int ndisc_route_compare_func(const NDiscRoute *a, const NDiscRoute *b) {
return route_compare_func(a->route, b->route);
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ndisc_route_hash_ops,
NDiscRoute,
ndisc_route_hash_func,
ndisc_route_compare_func,
free);
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
@ -130,7 +269,7 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
log_link_debug(link, "NDisc routes set.");
link->ndisc_routes_configured = true;
r = ndisc_remove_old(link, false);
r = ndisc_remove_old(link);
if (r < 0) {
link_enter_failed(link);
return 1;
@ -142,6 +281,67 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
return 1;
}
static int ndisc_route_configure(Route *route, Link *link, sd_ndisc_router *rt) {
_cleanup_free_ NDiscRoute *nr = NULL;
NDiscRoute *nr_exist;
struct in6_addr router;
Route *ret;
int r;
assert(route);
assert(link);
assert(rt);
r = route_configure(route, link, ndisc_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
link->ndisc_routes_messages++;
r = sd_ndisc_router_get_address(rt, &router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
nr = new(NDiscRoute, 1);
if (!nr)
return log_oom();
*nr = (NDiscRoute) {
.router = router,
.route = ret,
};
nr_exist = set_get(link->ndisc_routes, nr);
if (nr_exist) {
nr_exist->marked = false;
nr_exist->router = router;
return 0;
}
r = set_ensure_put(&link->ndisc_routes, &ndisc_route_hash_ops, nr);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store NDisc SLAAC route: %m");
assert(r > 0);
TAKE_PTR(nr);
return 0;
}
static void ndisc_address_hash_func(const NDiscAddress *x, struct siphash *state) {
address_hash_func(x->address, state);
}
static int ndisc_address_compare_func(const NDiscAddress *a, const NDiscAddress *b) {
return address_compare_func(a->address, b->address);
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
ndisc_address_hash_ops,
NDiscAddress,
ndisc_address_hash_func,
ndisc_address_compare_func,
free);
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
@ -165,7 +365,7 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
log_link_debug(link, "NDisc SLAAC addresses set.");
link->ndisc_addresses_configured = true;
r = ndisc_remove_old(link, false);
r = ndisc_remove_old(link);
if (r < 0) {
link_enter_failed(link);
return 1;
@ -181,34 +381,16 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 1;
}
static int ndisc_route_configure(Route *route, Link *link) {
Route *ret;
int r;
assert(route);
assert(link);
r = route_configure(route, link, ndisc_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
link->ndisc_routes_messages++;
r = set_ensure_put(&link->ndisc_routes, &route_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store NDisc route: %m");
(void) set_remove(link->ndisc_routes_old, ret);
return 0;
}
static int ndisc_address_configure(Address *address, Link *link) {
static int ndisc_address_configure(Address *address, Link *link, sd_ndisc_router *rt) {
_cleanup_free_ NDiscAddress *na = NULL;
NDiscAddress *na_exist;
struct in6_addr router;
Address *ret;
int r;
assert(address);
assert(link);
assert(rt);
r = address_configure(address, link, ndisc_address_handler, true, &ret);
if (r < 0)
@ -216,11 +398,31 @@ static int ndisc_address_configure(Address *address, Link *link) {
link->ndisc_addresses_messages++;
r = set_ensure_put(&link->ndisc_addresses, &address_hash_ops, ret);
r = sd_ndisc_router_get_address(rt, &router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
na = new(NDiscAddress, 1);
if (!na)
return log_oom();
*na = (NDiscAddress) {
.router = router,
.address = ret,
};
na_exist = set_get(link->ndisc_addresses, na);
if (na_exist) {
na_exist->marked = false;
na_exist->router = router;
return 0;
}
r = set_ensure_put(&link->ndisc_addresses, &ndisc_address_hash_ops, na);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store NDisc SLAAC address: %m");
(void) set_remove(link->ndisc_addresses_old, ret);
assert(r > 0);
TAKE_PTR(na);
return 0;
}
@ -286,7 +488,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route->lifetime = time_now + lifetime * USEC_PER_SEC;
route->mtu = mtu;
r = ndisc_route_configure(route, link);
r = ndisc_route_configure(route, link, rt);
if (r < 0)
return log_link_error_errno(link, r, "Could not set default route: %m");
@ -300,7 +502,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route_gw->gw = gateway;
r = ndisc_route_configure(route_gw, link);
r = ndisc_route_configure(route_gw, link, rt);
if (r < 0)
return log_link_error_errno(link, r, "Could not set gateway: %m");
}
@ -514,7 +716,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
address->in_addr.in6 = *a;
r = ndisc_address_configure(address, link);
r = ndisc_address_configure(address, link, rt);
if (r < 0)
return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
}
@ -560,7 +762,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m");
r = ndisc_route_configure(route, link);
r = ndisc_route_configure(route, link, rt);
if (r < 0)
return log_link_error_errno(link, r, "Could not set prefix route: %m");;
@ -617,7 +819,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get route address: %m");
r = ndisc_route_configure(route, link);
r = ndisc_route_configure(route, link, rt);
if (r < 0)
return log_link_error_errno(link, r, "Could not set additional route: %m");
@ -642,6 +844,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
uint32_t lifetime;
const struct in6_addr *a;
struct in6_addr router;
NDiscRDNSS *rdnss;
usec_t time_now;
Iterator i;
@ -650,6 +853,10 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
assert(link);
assert(rt);
r = sd_ndisc_router_get_address(rt, &router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
@ -663,6 +870,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
SET_FOREACH(rdnss, link->ndisc_rdnss, i)
if (IN6_ARE_ADDR_EQUAL(&rdnss->router, &router))
rdnss->marked = true;
if (lifetime == 0)
@ -682,6 +890,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
rdnss = set_get(link->ndisc_rdnss, &d);
if (rdnss) {
rdnss->marked = false;
rdnss->router = router;
rdnss->valid_until = time_now + lifetime * USEC_PER_SEC;
continue;
}
@ -692,6 +901,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
*x = (NDiscRDNSS) {
.address = a[j],
.router = router,
.valid_until = time_now + lifetime * USEC_PER_SEC,
};
@ -721,6 +931,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
_cleanup_strv_free_ char **l = NULL;
struct in6_addr router;
uint32_t lifetime;
usec_t time_now;
NDiscDNSSL *dnssl;
@ -731,6 +942,10 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
assert(link);
assert(rt);
r = sd_ndisc_router_get_address(rt, &router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
@ -744,6 +959,7 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
SET_FOREACH(dnssl, link->ndisc_dnssl, i)
if (IN6_ARE_ADDR_EQUAL(&dnssl->router, &router))
dnssl->marked = true;
if (lifetime == 0)
@ -767,10 +983,12 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
dnssl = set_get(link->ndisc_dnssl, s);
if (dnssl) {
dnssl->marked = false;
dnssl->router = router;
dnssl->valid_until = time_now + lifetime * USEC_PER_SEC;
continue;
}
s->router = router;
s->valid_until = time_now + lifetime * USEC_PER_SEC;
r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s));
@ -865,9 +1083,11 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
}
static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
Address *address;
Route *route;
struct in6_addr router;
uint64_t flags;
NDiscAddress *na;
NDiscRoute *nr;
Iterator i;
int r;
assert(link);
@ -880,17 +1100,17 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
link_dirty(link);
while ((address = set_steal_first(link->ndisc_addresses))) {
r = set_ensure_put(&link->ndisc_addresses_old, &address_hash_ops, address);
r = sd_ndisc_router_get_address(rt, &router);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store old NDisc SLAAC address: %m");
}
return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
while ((route = set_steal_first(link->ndisc_routes))) {
r = set_ensure_put(&link->ndisc_routes_old, &route_hash_ops, route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store old NDisc route: %m");
}
SET_FOREACH(na, link->ndisc_addresses, i)
if (IN6_ARE_ADDR_EQUAL(&na->router, &router))
na->marked = true;
SET_FOREACH(nr, link->ndisc_routes, i)
if (IN6_ARE_ADDR_EQUAL(&nr->router, &router))
nr->marked = true;
r = sd_ndisc_router_get_flags(rt, &flags);
if (r < 0)
@ -933,7 +1153,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
else
log_link_debug(link, "Setting NDisc routes.");
r = ndisc_remove_old(link, false);
r = ndisc_remove_old(link);
if (r < 0)
return r;

View File

@ -2,7 +2,9 @@
#pragma once
#include "conf-parser.h"
#include "networkd-address.h"
#include "networkd-link.h"
#include "networkd-route.h"
#include "time-util.h"
typedef struct IPv6Token IPv6Token;
@ -23,9 +25,24 @@ typedef enum IPv6AcceptRAStartDHCP6Client {
_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -1,
} IPv6AcceptRAStartDHCP6Client;
typedef struct NDiscAddress {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
struct in6_addr router;
Address *address;
} NDiscAddress;
typedef struct NDiscRoute {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
struct in6_addr router;
Route *route;
} NDiscRoute;
typedef struct NDiscRDNSS {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
struct in6_addr router;
usec_t valid_until;
struct in6_addr address;
} NDiscRDNSS;
@ -33,6 +50,7 @@ typedef struct NDiscRDNSS {
typedef struct NDiscDNSSL {
/* Used when GC'ing old domains when configuration changes. */
bool marked;
struct in6_addr router;
usec_t valid_until;
/* The domain name follows immediately. */
} NDiscDNSSL;

View File

@ -681,7 +681,9 @@ int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_le
int r;
assert(link);
assert(link->radv);
if (!link->radv)
return 0;
r = sd_radv_prefix_new(&p);
if (r < 0)

View File

@ -9,6 +9,7 @@
#include "netlink-util.h"
#include "networkd-ipv4ll.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
#include "networkd-route.h"
#include "parse-util.h"
#include "set.h"
@ -142,6 +143,9 @@ void route_free(Route *route) {
network_config_section_free(route->section);
if (route->link) {
NDiscRoute *n;
Iterator i;
set_remove(route->link->routes, route);
set_remove(route->link->routes_foreign, route);
set_remove(route->link->dhcp_routes, route);
@ -150,8 +154,9 @@ void route_free(Route *route) {
set_remove(route->link->dhcp6_routes_old, route);
set_remove(route->link->dhcp6_pd_routes, route);
set_remove(route->link->dhcp6_pd_routes_old, route);
set_remove(route->link->ndisc_routes, route);
set_remove(route->link->ndisc_routes_old, route);
SET_FOREACH(n, route->link->ndisc_routes, i)
if (n->route == route)
free(set_remove(route->link->ndisc_routes, n));
}
ordered_set_free_free(route->multipath_routes);
@ -161,7 +166,7 @@ void route_free(Route *route) {
free(route);
}
static void route_hash_func(const Route *route, struct siphash *state) {
void route_hash_func(const Route *route, struct siphash *state) {
assert(route);
siphash24_compress(&route->family, sizeof(route->family), state);
@ -196,7 +201,7 @@ static void route_hash_func(const Route *route, struct siphash *state) {
}
}
static int route_compare_func(const Route *a, const Route *b) {
int route_compare_func(const Route *a, const Route *b) {
int r;
r = CMP(a->family, b->family);

View File

@ -62,6 +62,8 @@ struct Route {
LIST_FIELDS(Route, routes);
};
void route_hash_func(const Route *route, struct siphash *state);
int route_compare_func(const Route *a, const Route *b);
extern const struct hash_ops route_hash_ops;
int route_new(Route **ret);

View File

@ -11,6 +11,7 @@
#include <sys/vfs.h>
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "crypt-util.h"
#include "device-nodes.h"
#include "dissect-image.h"
@ -94,6 +95,8 @@ static int maybe_resize_underlying_device(const char *mountpath, dev_t main_devn
if (r < 0)
return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m",
mountpath);
if (devno == 0)
return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target);
log_debug("Underlying device %d:%d, main dev %d:%d, %s",
major(devno), minor(devno),
@ -210,8 +213,12 @@ static int run(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "\"%s\" is not a mount point: %m", arg_target);
r = get_block_device(arg_target, &devno);
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, arg_target);
if (r < 0)
return log_error_errno(r, "Failed to determine block device of \"%s\": %m", arg_target);
if (devno == 0)
return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target);
r = maybe_resize_underlying_device(arg_target, devno);
if (r < 0)

View File

@ -2734,6 +2734,8 @@ static int context_open_copy_block_paths(Context *context) {
/* Special support for btrfs */
r = btrfs_get_block_device_fd(source_fd, &devt);
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, p->copy_blocks_path);
if (r < 0)
return log_error_errno(r, "Unable to determine backing block device of '%s': %m", p->copy_blocks_path);
@ -3150,6 +3152,8 @@ static int find_root(char **ret, int *ret_fd) {
}
r = acquire_root_devno(arg_node, O_RDONLY|O_CLOEXEC, ret, ret_fd);
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, arg_node);
if (r < 0)
return log_error_errno(r, "Failed to determine backing device of %s: %m", arg_node);
@ -3177,6 +3181,8 @@ static int find_root(char **ret, int *ret_fd) {
r = acquire_root_devno(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
if (r < 0) {
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, p);
if (r != -ENODEV)
return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
} else

View File

@ -2545,6 +2545,7 @@ static int native_help(void) {
" dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n"
" nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n"
" revert LINK Revert per-interface configuration\n"
" log-level [LEVEL] Get/set logging threshold for systemd-resolved\n"
"\nOptions:\n"
" -h --help Show this help\n"
" --version Show package version\n"

View File

@ -349,7 +349,8 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
#if HAVE_LIBIDN2
r = idn2_to_unicode_8z8z(label, &utf8, 0);
if (r != IDN2_OK)
return log_error("Failed to undo IDNA: %s", idn2_strerror(r));
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Failed to undo IDNA: %s", idn2_strerror(r));
assert(utf8_is_valid(utf8));
r = strlen(utf8);

View File

@ -943,7 +943,7 @@ int config_parse_channel(const char *unit,
}
if (k < 1) {
log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue);
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid %s value, ignoring: %s", lvalue, rvalue);
return 0;
}

View File

@ -14,24 +14,26 @@
* See, network/networkd-link.h for example.
*/
#define log_link_full(link, level, error, ...) \
#define log_link_full_errno(link, level, error, ...) \
({ \
const Link *_l = (link); \
(_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
}) \
#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__)
#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__)
#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 0, __VA_ARGS__)
#define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__)
#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__)
#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__)
#define log_link_debug(link, ...) log_link_full_errno(link, LOG_DEBUG, 0, __VA_ARGS__)
#define log_link_info(link, ...) log_link_full(link, LOG_INFO, __VA_ARGS__)
#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, __VA_ARGS__)
#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, __VA_ARGS__)
#define log_link_error(link, ...) log_link_full(link, LOG_ERR, __VA_ARGS__)
#define log_link_debug_errno(link, error, ...) log_link_full_errno(link, LOG_DEBUG, error, __VA_ARGS__)
#define log_link_info_errno(link, error, ...) log_link_full_errno(link, LOG_INFO, error, __VA_ARGS__)
#define log_link_notice_errno(link, error, ...) log_link_full_errno(link, LOG_NOTICE, error, __VA_ARGS__)
#define log_link_warning_errno(link, error, ...) log_link_full_errno(link, LOG_WARNING, error, __VA_ARGS__)
#define log_link_error_errno(link, error, ...) log_link_full_errno(link, LOG_ERR, error, __VA_ARGS__)
#define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__
#define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname

View File

@ -212,12 +212,14 @@ int pkcs11_token_login(
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
if (ret_used_pin)
*ret_used_pin = NULL;
return 0;
}
if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
log_info("No login into security token '%s' required.", token_label);
if (ret_used_pin)
*ret_used_pin = NULL;
return 0;
}

View File

@ -403,6 +403,8 @@ int find_hibernate_location(HibernateLocation **ret_hibernate_location) {
r = swap_device_to_device_id(swap, &swap_device);
if (r < 0)
return log_debug_errno(r, "%s: failed to query device number: %m", swap->device);
if (swap_device == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "%s: not backed by block device.", swap->device);
hibernate_location = hibernate_location_free(hibernate_location);
hibernate_location = new(HibernateLocation, 1);

View File

@ -2085,8 +2085,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (streq(key, "systemd.unit")) {
if (proc_cmdline_value_missing(key, value))
return 0;
if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
return log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
return 0;
}
return free_and_strdup_warn(ret, key);

View File

@ -773,6 +773,7 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
struct stat stbuf;
mode_t new_mode;
bool do_chown;
int r;
assert(i);
assert(fd);
@ -818,8 +819,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
log_debug("\"%s\" matches temporary mode %o already.", path, m);
else {
log_debug("Temporarily changing \"%s\" to mode %o.", path, m);
if (fchmod_opath(fd, m) < 0)
return log_error_errno(errno, "fchmod() of %s failed: %m", path);
r = fchmod_opath(fd, m);
if (r < 0)
return log_error_errno(r, "fchmod() of %s failed: %m", path);
}
}
}
@ -850,8 +852,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
log_debug("\"%s\" matches mode %o already.", path, new_mode);
else {
log_debug("Changing \"%s\" to mode %o.", path, new_mode);
if (fchmod_opath(fd, new_mode) < 0)
return log_error_errno(errno, "fchmod() of %s failed: %m", path);
r = fchmod_opath(fd, new_mode);
if (r < 0)
return log_error_errno(r, "fchmod() of %s failed: %m", path);
}
}
}

View File

@ -320,7 +320,8 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
case NET_ADDR_PERM:
break;
default:
return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type);
log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type);
return 0;
}
if (want_random == (addr_type == NET_ADDR_RANDOM))

View File

@ -87,7 +87,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
return 0;
}
static char* parse_token(const char *current, int32_t *val_out) {
static const char* parse_token(const char *current, int32_t *val_out) {
char *next;
int32_t val;
@ -109,7 +109,7 @@ static char* parse_token(const char *current, int32_t *val_out) {
static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) {
struct input_absinfo absinfo;
char *next;
const char *next;
int r;
r = ioctl(fd, EVIOCGABS(evcode), &absinfo);
@ -122,7 +122,7 @@ static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *val
next = parse_token(next, &absinfo.fuzz);
next = parse_token(next, &absinfo.flat);
if (!next)
return log_device_error(dev, "Failed to parse EV_ABS override '%s'", value);
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse EV_ABS override '%s'", value);
log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32,
evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat);

View File

@ -50,7 +50,7 @@ static int builtin_uaccess(sd_device *dev, int argc, char *argv[], bool test) {
r = devnode_acl(path, true, false, 0, true, uid);
if (r < 0) {
log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m");
log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m");
goto finish;
}
@ -64,7 +64,7 @@ finish:
/* Better be safe than sorry and reset ACL */
k = devnode_acl(path, true, false, 0, false, 0);
if (k < 0) {
log_device_full(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m");
log_device_full_errno(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m");
if (r >= 0)
r = k;
}

View File

@ -633,7 +633,7 @@ static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userd
if (si->si_status == 0)
log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd);
else
log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0,
log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
"Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
ret = si->si_status;
break;

View File

@ -325,7 +325,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
r = chmod_and_chown(devnode, mode, uid, gid);
if (r < 0)
log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r,
log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r,
"Failed to set owner/mode of %s to uid=" UID_FMT
", gid=" GID_FMT ", mode=%#o: %m",
devnode,
@ -348,7 +348,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
q = mac_selinux_apply(devnode, label);
if (q < 0)
log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
"SECLABEL: failed to set SELinux label '%s': %m", label);
else
log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label);
@ -358,7 +358,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label);
if (q < 0)
log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q,
"SECLABEL: failed to set SMACK label '%s': %m", label);
else
log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label);

View File

@ -182,43 +182,46 @@ struct UdevRules {
/*** Logging helpers ***/
#define log_rule_full(device, rules, level, error, fmt, ...) \
#define log_rule_full_errno(device, rules, level, error, fmt, ...) \
({ \
UdevRules *_r = (rules); \
UdevRuleFile *_f = _r ? _r->current_file : NULL; \
UdevRuleLine *_l = _f ? _f->current_line : NULL; \
const char *_n = _f ? _f->filename : NULL; \
\
log_device_full(device, level, error, "%s:%u " fmt, \
log_device_full_errno(device, level, error, "%s:%u " fmt, \
strna(_n), _l ? _l->line_number : 0, \
##__VA_ARGS__); \
})
#define log_rule_debug(device, rules, ...) log_rule_full(device, rules, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, 0, ##__VA_ARGS__)
#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, 0, ##__VA_ARGS__)
#define log_rule_full(device, rules, level, ...) (void) log_rule_full_errno(device, rules, level, 0, __VA_ARGS__)
#define log_rule_debug_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_rule_info_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_INFO, error, ##__VA_ARGS__)
#define log_rule_notice_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_rule_warning_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_WARNING, error, ##__VA_ARGS__)
#define log_rule_error_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_ERR, error, ##__VA_ARGS__)
#define log_rule_debug(device, rules, ...) log_rule_full_errno(device, rules, LOG_DEBUG, 0, __VA_ARGS__)
#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, __VA_ARGS__)
#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, __VA_ARGS__)
#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, __VA_ARGS__)
#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, __VA_ARGS__)
#define log_token_full(rules, ...) log_rule_full(NULL, rules, ##__VA_ARGS__)
#define log_rule_debug_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_DEBUG, error, __VA_ARGS__)
#define log_rule_info_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_INFO, error, __VA_ARGS__)
#define log_rule_notice_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_NOTICE, error, __VA_ARGS__)
#define log_rule_warning_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_WARNING, error, __VA_ARGS__)
#define log_rule_error_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_ERR, error, __VA_ARGS__)
#define log_token_debug(rules, ...) log_token_full(rules, LOG_DEBUG, 0, ##__VA_ARGS__)
#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, 0, ##__VA_ARGS__)
#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, 0, ##__VA_ARGS__)
#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, 0, ##__VA_ARGS__)
#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, 0, ##__VA_ARGS__)
#define log_token_full_errno(rules, level, error, ...) log_rule_full_errno(NULL, rules, level, error, __VA_ARGS__)
#define log_token_full(rules, level, ...) (void) log_token_full_errno(rules, level, 0, __VA_ARGS__)
#define log_token_debug_errno(rules, error, ...) log_token_full(rules, LOG_DEBUG, error, ##__VA_ARGS__)
#define log_token_info_errno(rules, error, ...) log_token_full(rules, LOG_INFO, error, ##__VA_ARGS__)
#define log_token_notice_errno(rules, error, ...) log_token_full(rules, LOG_NOTICE, error, ##__VA_ARGS__)
#define log_token_warning_errno(rules, error, ...) log_token_full(rules, LOG_WARNING, error, ##__VA_ARGS__)
#define log_token_error_errno(rules, error, ...) log_token_full(rules, LOG_ERR, error, ##__VA_ARGS__)
#define log_token_debug(rules, ...) log_token_full_errno(rules, LOG_DEBUG, 0, __VA_ARGS__)
#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, __VA_ARGS__)
#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, __VA_ARGS__)
#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, __VA_ARGS__)
#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, __VA_ARGS__)
#define log_token_debug_errno(rules, error, ...) log_token_full_errno(rules, LOG_DEBUG, error, __VA_ARGS__)
#define log_token_info_errno(rules, error, ...) log_token_full_errno(rules, LOG_INFO, error, __VA_ARGS__)
#define log_token_notice_errno(rules, error, ...) log_token_full_errno(rules, LOG_NOTICE, error, __VA_ARGS__)
#define log_token_warning_errno(rules, error, ...) log_token_full_errno(rules, LOG_WARNING, error, __VA_ARGS__)
#define log_token_error_errno(rules, error, ...) log_token_full_errno(rules, LOG_ERR, error, __VA_ARGS__)
#define _log_token_invalid(rules, key, type) \
log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \

View File

@ -97,9 +97,7 @@ int udev_watch_begin(sd_device *dev) {
log_device_debug(dev, "Adding watch on '%s'", devnode);
wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
if (wd < 0)
return log_device_full(dev,
errno == ENOENT ? LOG_DEBUG : LOG_ERR,
errno,
return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
"Failed to add device '%s' to watch: %m", devnode);
device_set_watch_handle(dev, wd);

View File

@ -1685,8 +1685,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
/* Bump receiver buffer, but only if we are not called via socket activation, as in that
* case systemd sets the receive buffer size for us, and the value in the .socket unit
* should take full effect. */
if (fd_uevent < 0)
(void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
if (fd_uevent < 0) {
r = sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
if (r < 0)
log_warning_errno(r, "Failed to set receive buffer size for device monitor, ignoring: %m");
}
r = device_monitor_enable_receiving(manager->monitor);
if (r < 0)

View File

@ -31,7 +31,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
r = write_string_file_atomic_label_ts(path, message, ts);
if (r == -EROFS)
return log_debug("Cannot create \"%s\", file system is read-only.", path);
return log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
if (r < 0)
return log_error_errno(r, "Failed to write \"%s\": %m", path);
return 0;

View File

@ -187,8 +187,10 @@ static int on_runlevel(Context *c) {
runlevel = get_current_runlevel(c);
if (runlevel < 0)
return runlevel;
if (runlevel == 0)
return log_warning("Failed to get new runlevel, utmp update skipped.");
if (runlevel == 0) {
log_warning("Failed to get new runlevel, utmp update skipped.");
return 0;
}
if (previous == runlevel)
return 0;

View File

@ -175,7 +175,7 @@ static int run(int argc, char *argv[]) {
r = get_block_device_harder(path, &devt);
if (r < 0)
return log_error_errno(r, "Failed to determine device major/minor of %s: %m", path);
else if (r > 0) {
else if (r > 0) { /* backed by block device */
_cleanup_free_ char *dn = NULL;
r = device_path_make_major_minor(S_IFBLK, devt, &dn);

View File

@ -10,10 +10,10 @@ ExecStart=test -f /var/lib/waldo/yay
ExecStart=test -f /var/lib/quux/pief/yayyay
ExecStart=test -f /var/lib/private/waldo/yay
ExecStart=test -f /var/lib/private/quux/pief/yayyay
ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"'
ExecStart=sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"'
# Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates
ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo'
ExecStart=sh -x -c 'test $$(find / \\( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \\) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d "\\\\n") = /var/lib/private/quux/pief/var/lib/private/waldo'
Type=oneshot
DynamicUser=yes

View File

@ -51,3 +51,261 @@ Peer=2001:db8:0:f103::10/128
[Address]
Address=::/64
# test for ENOBUFS issue #17012
[Network]
Address=10.3.3.1/16
Address=10.3.3.2/16
Address=10.3.3.3/16
Address=10.3.3.4/16
Address=10.3.3.5/16
Address=10.3.3.6/16
Address=10.3.3.7/16
Address=10.3.3.8/16
Address=10.3.3.9/16
Address=10.3.3.10/16
Address=10.3.3.11/16
Address=10.3.3.12/16
Address=10.3.3.13/16
Address=10.3.3.14/16
Address=10.3.3.15/16
Address=10.3.3.16/16
Address=10.3.3.17/16
Address=10.3.3.18/16
Address=10.3.3.19/16
Address=10.3.3.20/16
Address=10.3.3.21/16
Address=10.3.3.22/16
Address=10.3.3.23/16
Address=10.3.3.24/16
Address=10.3.3.25/16
Address=10.3.3.26/16
Address=10.3.3.27/16
Address=10.3.3.28/16
Address=10.3.3.29/16
Address=10.3.3.30/16
Address=10.3.3.31/16
Address=10.3.3.32/16
Address=10.3.3.33/16
Address=10.3.3.34/16
Address=10.3.3.35/16
Address=10.3.3.36/16
Address=10.3.3.37/16
Address=10.3.3.38/16
Address=10.3.3.39/16
Address=10.3.3.40/16
Address=10.3.3.41/16
Address=10.3.3.42/16
Address=10.3.3.43/16
Address=10.3.3.44/16
Address=10.3.3.45/16
Address=10.3.3.46/16
Address=10.3.3.47/16
Address=10.3.3.48/16
Address=10.3.3.49/16
Address=10.3.3.50/16
Address=10.3.3.51/16
Address=10.3.3.52/16
Address=10.3.3.53/16
Address=10.3.3.54/16
Address=10.3.3.55/16
Address=10.3.3.56/16
Address=10.3.3.57/16
Address=10.3.3.58/16
Address=10.3.3.59/16
Address=10.3.3.60/16
Address=10.3.3.61/16
Address=10.3.3.62/16
Address=10.3.3.63/16
Address=10.3.3.64/16
Address=10.3.3.65/16
Address=10.3.3.66/16
Address=10.3.3.67/16
Address=10.3.3.68/16
Address=10.3.3.69/16
Address=10.3.3.70/16
Address=10.3.3.71/16
Address=10.3.3.72/16
Address=10.3.3.73/16
Address=10.3.3.74/16
Address=10.3.3.75/16
Address=10.3.3.76/16
Address=10.3.3.77/16
Address=10.3.3.78/16
Address=10.3.3.79/16
Address=10.3.3.80/16
Address=10.3.3.81/16
Address=10.3.3.82/16
Address=10.3.3.83/16
Address=10.3.3.84/16
Address=10.3.3.85/16
Address=10.3.3.86/16
Address=10.3.3.87/16
Address=10.3.3.88/16
Address=10.3.3.89/16
Address=10.3.3.90/16
Address=10.3.3.91/16
Address=10.3.3.92/16
Address=10.3.3.93/16
Address=10.3.3.94/16
Address=10.3.3.95/16
Address=10.3.3.96/16
Address=10.3.3.97/16
Address=10.3.3.98/16
Address=10.3.3.99/16
Address=10.3.3.100/16
Address=10.3.3.101/16
Address=10.3.3.101/16
Address=10.3.3.102/16
Address=10.3.3.103/16
Address=10.3.3.104/16
Address=10.3.3.105/16
Address=10.3.3.106/16
Address=10.3.3.107/16
Address=10.3.3.108/16
Address=10.3.3.109/16
Address=10.3.3.110/16
Address=10.3.3.111/16
Address=10.3.3.112/16
Address=10.3.3.113/16
Address=10.3.3.114/16
Address=10.3.3.115/16
Address=10.3.3.116/16
Address=10.3.3.117/16
Address=10.3.3.118/16
Address=10.3.3.119/16
Address=10.3.3.120/16
Address=10.3.3.121/16
Address=10.3.3.122/16
Address=10.3.3.123/16
Address=10.3.3.124/16
Address=10.3.3.125/16
Address=10.3.3.126/16
Address=10.3.3.127/16
Address=10.3.3.128/16
Address=10.3.3.129/16
Address=10.3.3.130/16
Address=10.3.3.131/16
Address=10.3.3.132/16
Address=10.3.3.133/16
Address=10.3.3.134/16
Address=10.3.3.135/16
Address=10.3.3.136/16
Address=10.3.3.137/16
Address=10.3.3.138/16
Address=10.3.3.139/16
Address=10.3.3.140/16
Address=10.3.3.141/16
Address=10.3.3.142/16
Address=10.3.3.143/16
Address=10.3.3.144/16
Address=10.3.3.145/16
Address=10.3.3.146/16
Address=10.3.3.147/16
Address=10.3.3.148/16
Address=10.3.3.149/16
Address=10.3.3.150/16
Address=10.3.3.151/16
Address=10.3.3.152/16
Address=10.3.3.153/16
Address=10.3.3.154/16
Address=10.3.3.155/16
Address=10.3.3.156/16
Address=10.3.3.157/16
Address=10.3.3.158/16
Address=10.3.3.159/16
Address=10.3.3.160/16
Address=10.3.3.161/16
Address=10.3.3.162/16
Address=10.3.3.163/16
Address=10.3.3.164/16
Address=10.3.3.165/16
Address=10.3.3.166/16
Address=10.3.3.167/16
Address=10.3.3.168/16
Address=10.3.3.169/16
Address=10.3.3.170/16
Address=10.3.3.171/16
Address=10.3.3.172/16
Address=10.3.3.173/16
Address=10.3.3.174/16
Address=10.3.3.175/16
Address=10.3.3.176/16
Address=10.3.3.177/16
Address=10.3.3.178/16
Address=10.3.3.179/16
Address=10.3.3.180/16
Address=10.3.3.181/16
Address=10.3.3.182/16
Address=10.3.3.183/16
Address=10.3.3.184/16
Address=10.3.3.185/16
Address=10.3.3.186/16
Address=10.3.3.187/16
Address=10.3.3.188/16
Address=10.3.3.189/16
Address=10.3.3.190/16
Address=10.3.3.191/16
Address=10.3.3.192/16
Address=10.3.3.193/16
Address=10.3.3.194/16
Address=10.3.3.195/16
Address=10.3.3.196/16
Address=10.3.3.197/16
Address=10.3.3.198/16
Address=10.3.3.199/16
Address=10.3.3.200/16
Address=10.3.3.201/16
Address=10.3.3.202/16
Address=10.3.3.203/16
Address=10.3.3.204/16
Address=10.3.3.205/16
Address=10.3.3.206/16
Address=10.3.3.207/16
Address=10.3.3.208/16
Address=10.3.3.209/16
Address=10.3.3.210/16
Address=10.3.3.211/16
Address=10.3.3.212/16
Address=10.3.3.213/16
Address=10.3.3.214/16
Address=10.3.3.215/16
Address=10.3.3.216/16
Address=10.3.3.217/16
Address=10.3.3.218/16
Address=10.3.3.219/16
Address=10.3.3.220/16
Address=10.3.3.221/16
Address=10.3.3.222/16
Address=10.3.3.223/16
Address=10.3.3.224/16
Address=10.3.3.225/16
Address=10.3.3.226/16
Address=10.3.3.227/16
Address=10.3.3.228/16
Address=10.3.3.229/16
Address=10.3.3.230/16
Address=10.3.3.231/16
Address=10.3.3.232/16
Address=10.3.3.233/16
Address=10.3.3.234/16
Address=10.3.3.235/16
Address=10.3.3.236/16
Address=10.3.3.237/16
Address=10.3.3.238/16
Address=10.3.3.239/16
Address=10.3.3.240/16
Address=10.3.3.241/16
Address=10.3.3.242/16
Address=10.3.3.243/16
Address=10.3.3.244/16
Address=10.3.3.245/16
Address=10.3.3.246/16
Address=10.3.3.247/16
Address=10.3.3.248/16
Address=10.3.3.249/16
Address=10.3.3.250/16
Address=10.3.3.251/16
Address=10.3.3.252/16
Address=10.3.3.253/16
Address=10.3.3.254/16

View File

@ -1764,6 +1764,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
# test for ENOBUFS issue #17012
for i in range(1,254):
self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255')
# invalid sections
self.assertNotRegex(output, '10.10.0.1/16')
self.assertNotRegex(output, '10.10.0.2/16')
@ -1789,6 +1793,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
restart_networkd()
self.wait_online(['dummy98:routable'])
# test for ENOBUFS issue #17012
output = check_output('ip -4 address show dev dummy98')
for i in range(1,254):
self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255')
def test_address_preferred_lifetime_zero_ipv6(self):
copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
start_networkd(5)