summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/fileio.c2
-rw-r--r--src/basic/fileio.h1
-rw-r--r--src/basic/in-addr-util.c49
-rw-r--r--src/basic/in-addr-util.h16
-rw-r--r--src/basic/missing.h7
-rw-r--r--src/basic/random-util.c8
-rw-r--r--src/basic/smack-util.c2
-rw-r--r--src/basic/stat-util.c40
-rw-r--r--src/basic/stdio-util.h4
-rw-r--r--src/basic/time-util.c211
-rw-r--r--src/basic/util.c2
-rw-r--r--src/binfmt/binfmt.c6
-rw-r--r--src/core/main.c6
-rw-r--r--src/core/smack-setup.c8
-rw-r--r--src/coredump/meson.build6
-rw-r--r--src/cryptsetup/cryptsetup-generator.c72
-rw-r--r--src/firstboot/firstboot.c12
-rw-r--r--src/hibernate-resume/hibernate-resume.c2
-rw-r--r--src/libsystemd-network/lldp-internal.h3
-rw-r--r--src/libsystemd-network/ndisc-internal.h3
-rw-r--r--src/libsystemd-network/network-internal.c9
-rw-r--r--src/libsystemd-network/sd-lldp.c20
-rw-r--r--src/libsystemd-network/sd-ndisc.c15
-rw-r--r--src/libsystemd/libsystemd.sym3
-rw-r--r--src/libsystemd/sd-device/device-enumerator.c27
-rw-r--r--src/libsystemd/sd-device/device-monitor.c52
-rw-r--r--src/libsystemd/sd-device/device-private.c52
-rw-r--r--src/libsystemd/sd-device/device-util.h8
-rw-r--r--src/libsystemd/sd-device/sd-device.c89
-rw-r--r--src/libsystemd/sd-device/test-sd-device.c18
-rw-r--r--src/libsystemd/sd-event/sd-event.c28
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c3
-rw-r--r--src/libsystemd/sd-resolve/sd-resolve.c48
-rw-r--r--src/login/71-seat.rules.in2
-rw-r--r--src/login/logind-dbus.c2
-rw-r--r--src/network/fuzz-netdev-parser.c22
-rw-r--r--src/network/fuzz-network-parser.c22
-rw-r--r--src/network/meson.build18
-rw-r--r--src/network/netdev/bond.c134
-rw-r--r--src/network/netdev/bond.h7
-rw-r--r--src/network/netdev/bridge.c2
-rw-r--r--src/network/netdev/geneve.c2
-rw-r--r--src/network/netdev/netdev-gperf.gperf5
-rw-r--r--src/network/netdev/netdev.c18
-rw-r--r--src/network/netdev/netdev.h3
-rw-r--r--src/network/netdev/vcan.c1
-rw-r--r--src/network/netdev/vrf.c2
-rw-r--r--src/network/netdev/wireguard.c130
-rw-r--r--src/network/netdev/wireguard.h7
-rw-r--r--src/network/networkd-address.c47
-rw-r--r--src/network/networkd-fdb.c2
-rw-r--r--src/network/networkd-ipv6-proxy-ndp.c22
-rw-r--r--src/network/networkd-link.c96
-rw-r--r--src/network/networkd-manager.c24
-rw-r--r--src/network/networkd-network-gperf.gperf4
-rw-r--r--src/network/networkd-network.c7
-rw-r--r--src/network/networkd-network.h6
-rw-r--r--src/network/networkd-radv.c35
-rw-r--r--src/network/networkd-route.c10
-rw-r--r--src/network/networkd-route.h1
-rw-r--r--src/network/networkd-routing-policy-rule.c13
-rw-r--r--src/network/test-network-tables.c5
-rw-r--r--src/network/test-networkd-conf.c44
-rw-r--r--src/nspawn/nspawn-cgroup.c2
-rw-r--r--src/nspawn/nspawn.c16
-rw-r--r--src/shared/ask-password-api.c106
-rw-r--r--src/shared/ask-password-api.h2
-rw-r--r--src/shared/vlan-util.c3
-rw-r--r--src/sleep/sleep.c14
-rw-r--r--src/systemd/meson.build6
-rw-r--r--src/systemd/sd-event.h2
-rw-r--r--src/systemd/sd-lldp.h10
-rw-r--r--src/systemd/sd-ndisc.h6
-rw-r--r--src/systemd/sd-resolve.h5
-rw-r--r--src/test/test-ask-password-api.c6
-rw-r--r--src/test/test-in-addr-util.c82
-rw-r--r--src/test/test-stat-util.c15
-rw-r--r--src/test/test-time-util.c28
-rw-r--r--src/test/test-udev.c32
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c9
-rw-r--r--src/udev/udev-event.c61
-rw-r--r--src/udev/udev-node.c6
-rw-r--r--src/udev/udev-rules.c265
-rw-r--r--src/udev/udev-watch.c35
-rw-r--r--src/udev/udev.h9
-rw-r--r--src/udev/udevadm-hwdb.c2
-rw-r--r--src/udev/udevadm-test.c23
-rw-r--r--src/udev/udevadm-trigger.c11
-rw-r--r--src/udev/udevadm.c1
-rw-r--r--src/udev/udevd.c186
-rw-r--r--src/vconsole/vconsole-setup.c2
91 files changed, 1644 insertions, 826 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index f14afa5dce..fa6084e602 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -160,7 +160,7 @@ int write_string_file_ts(
/* We manually build our own version of fopen(..., "we") that
* works without O_CREAT */
- fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
+ fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | ((flags & WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (fd < 0) {
r = -errno;
goto fail;
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 102d33d75f..f809848408 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -17,6 +17,7 @@ typedef enum {
WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3,
WRITE_STRING_FILE_SYNC = 1 << 4,
WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5,
+ WRITE_STRING_FILE_NOFOLLOW = 1 << 6,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index d83658eaa7..6a00de2ef0 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -314,6 +314,7 @@ int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union
}
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
+ _cleanup_free_ char *buf = NULL;
const char *suffix;
int r, ifi = 0;
@@ -341,7 +342,11 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
}
}
- s = strndupa(s, suffix - s);
+ buf = strndup(s, suffix - s);
+ if (!buf)
+ return -ENOMEM;
+
+ s = buf;
}
r = in_addr_from_string_auto(s, family, ret);
@@ -490,12 +495,14 @@ int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
return 0;
}
-int in_addr_prefix_from_string(
+int in_addr_prefix_from_string_internal(
const char *p,
+ bool use_default_prefixlen,
int family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
+ _cleanup_free_ char *str = NULL;
union in_addr_union buffer;
const char *e, *l;
unsigned char k;
@@ -507,9 +514,13 @@ int in_addr_prefix_from_string(
return -EAFNOSUPPORT;
e = strchr(p, '/');
- if (e)
- l = strndupa(p, e - p);
- else
+ if (e) {
+ str = strndup(p, e - p);
+ if (!str)
+ return -ENOMEM;
+
+ l = str;
+ } else
l = p;
r = in_addr_from_string(family, l, &buffer);
@@ -520,6 +531,13 @@ int in_addr_prefix_from_string(
r = in_addr_parse_prefixlen(family, e+1, &k);
if (r < 0)
return r;
+ } else if (use_default_prefixlen) {
+ if (family == AF_INET) {
+ r = in4_addr_default_prefixlen(&buffer.in, &k);
+ if (r < 0)
+ return r;
+ } else
+ k = 0;
} else
k = FAMILY_ADDRESS_SIZE(family) * 8;
@@ -531,12 +549,14 @@ int in_addr_prefix_from_string(
return 0;
}
-int in_addr_prefix_from_string_auto(
+int in_addr_prefix_from_string_auto_internal(
const char *p,
+ bool use_default_prefixlen,
int *ret_family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
+ _cleanup_free_ char *str = NULL;
union in_addr_union buffer;
const char *e, *l;
unsigned char k;
@@ -545,9 +565,13 @@ int in_addr_prefix_from_string_auto(
assert(p);
e = strchr(p, '/');
- if (e)
- l = strndupa(p, e - p);
- else
+ if (e) {
+ str = strndup(p, e - p);
+ if (!str)
+ return -ENOMEM;
+
+ l = str;
+ } else
l = p;
r = in_addr_from_string_auto(l, &family, &buffer);
@@ -558,6 +582,13 @@ int in_addr_prefix_from_string_auto(
r = in_addr_parse_prefixlen(family, e+1, &k);
if (r < 0)
return r;
+ } else if (use_default_prefixlen) {
+ if (family == AF_INET) {
+ r = in4_addr_default_prefixlen(&buffer.in, &k);
+ if (r < 0)
+ return r;
+ } else
+ k = 0;
} else
k = FAMILY_ADDRESS_SIZE(family) * 8;
diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h
index e4be30dc0d..2dafa3c084 100644
--- a/src/basic/in-addr-util.h
+++ b/src/basic/in-addr-util.h
@@ -45,8 +45,20 @@ int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mas
int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen);
int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address);
int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret);
-int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
-int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
+int in_addr_prefix_from_string_internal(const char *p, bool use_default_prefixlen, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
+int in_addr_prefix_from_string_auto_internal(const char *p, bool use_default_prefixlen, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
+static inline int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
+ return in_addr_prefix_from_string_internal(p, false, family, ret_prefix, ret_prefixlen);
+}
+static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
+ return in_addr_prefix_from_string_auto_internal(p, false, ret_family, ret_prefix, ret_prefixlen);
+}
+static inline int in_addr_default_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
+ return in_addr_prefix_from_string_internal(p, true, family, ret_prefix, ret_prefixlen);
+}
+static inline int in_addr_default_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
+ return in_addr_prefix_from_string_auto_internal(p, true, ret_family, ret_prefix, ret_prefixlen);
+}
static inline size_t FAMILY_ADDRESS_SIZE(int family) {
assert(IN_SET(family, AF_INET, AF_INET6));
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 648a2b92d9..d671202551 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -752,7 +752,7 @@ struct input_mask {
#define IFLA_MAX (__IFLA_MAX - 1)
#endif
-#if !HAVE_IFLA_BOND_AD_INFO
+#if !HAVE_IFLA_BOND_AD_ACTOR_SYSTEM
#define IFLA_BOND_UNSPEC 0
#define IFLA_BOND_MODE 1
#define IFLA_BOND_ACTIVE_SLAVE 2
@@ -777,7 +777,10 @@ struct input_mask {
#define IFLA_BOND_AD_LACP_RATE 21
#define IFLA_BOND_AD_SELECT 22
#define IFLA_BOND_AD_INFO 23
-#define __IFLA_BOND_MAX 24
+#define IFLA_BOND_AD_ACTOR_SYS_PRIO 24
+#define IFLA_BOND_AD_USER_PORT_KEY 25
+#define IFLA_BOND_AD_ACTOR_SYSTEM 26
+#define __IFLA_BOND_MAX 27
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
#endif
diff --git a/src/basic/random-util.c b/src/basic/random-util.c
index aa04cc2318..071a41f186 100644
--- a/src/basic/random-util.c
+++ b/src/basic/random-util.c
@@ -142,8 +142,9 @@ void initialize_srand(void) {
static bool srand_called = false;
unsigned x;
#if HAVE_SYS_AUXV_H
- void *auxv;
+ const void *auxv;
#endif
+ uint64_t k;
if (srand_called)
return;
@@ -153,7 +154,7 @@ void initialize_srand(void) {
* try to make use of that to seed the pseudo-random generator. It's
* better than nothing... */
- auxv = (void*) getauxval(AT_RANDOM);
+ auxv = (const void*) getauxval(AT_RANDOM);
if (auxv) {
assert_cc(sizeof(x) <= 16);
memcpy(&x, auxv, sizeof(x));
@@ -164,6 +165,9 @@ void initialize_srand(void) {
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
+ if (rdrand64(&k) >= 0)
+ x ^= (unsigned) k;
+
srand(x);
srand_called = true;
}
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index e7ea78f349..123d00e13e 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -115,7 +115,7 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
return 0;
p = procfs_file_alloca(pid, "attr/current");
- r = write_string_file(p, label, 0);
+ r = write_string_file(p, label, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index 4e8651f428..3bef0dfe44 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -213,15 +213,47 @@ int fd_is_network_fs(int fd) {
}
int fd_is_network_ns(int fd) {
+ struct statfs s;
int r;
- r = fd_is_fs_type(fd, NSFS_MAGIC);
- if (r <= 0)
- return r;
+ /* Checks whether the specified file descriptor refers to a network namespace. On old kernels there's no nice
+ * way to detect that, hence on those we'll return a recognizable error (EUCLEAN), so that callers can handle
+ * this somewhat nicely.
+ *
+ * This function returns > 0 if the fd definitely refers to a network namespace, 0 if it definitely does not
+ * refer to a network namespace, -EUCLEAN if we can't determine, and other negative error codes on error. */
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ if (!is_fs_type(&s, NSFS_MAGIC)) {
+ /* On really old kernels, there was no "nsfs", and network namespace sockets belonged to procfs
+ * instead. Handle that in a somewhat smart way. */
+
+ if (is_fs_type(&s, PROC_SUPER_MAGIC)) {
+ struct statfs t;
+
+ /* OK, so it is procfs. Let's see if our own network namespace is procfs, too. If so, then the
+ * passed fd might refer to a network namespace, but we can't know for sure. In that case,
+ * return a recognizable error. */
+
+ if (statfs("/proc/self/ns/net", &t) < 0)
+ return -errno;
+
+ if (s.f_type == t.f_type)
+ return -EUCLEAN; /* It's possible, we simply don't know */
+ }
+
+ return 0; /* No! */
+ }
r = ioctl(fd, NS_GET_NSTYPE);
- if (r < 0)
+ if (r < 0) {
+ if (errno == ENOTTY) /* Old kernels didn't know this ioctl, let's also return a recognizable error in that case */
+ return -EUCLEAN;
+
return -errno;
+ }
return r == CLONE_NEWNET;
}
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
index 73c03274c7..dc67b6e761 100644
--- a/src/basic/stdio-util.h
+++ b/src/basic/stdio-util.h
@@ -7,6 +7,7 @@
#include <sys/types.h>
#include "macro.h"
+#include "util.h"
#define snprintf_ok(buf, len, fmt, ...) \
((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len))
@@ -18,6 +19,9 @@
do { \
int _argtypes[128]; \
size_t _i, _k; \
+ /* See https://github.com/google/sanitizers/issues/992 */ \
+ if (HAS_FEATURE_MEMORY_SANITIZER) \
+ zero(_argtypes); \
_k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
assert(_k < ELEMENTSOF(_argtypes)); \
for (_i = 0; _i < _k; _i++) { \
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 141b91f637..151ac954ad 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -868,7 +868,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
return tmp.return_value;
}
-static char* extract_multiplier(char *p, usec_t *multiplier) {
+static const char* extract_multiplier(const char *p, usec_t *multiplier) {
static const struct {
const char *suffix;
usec_t usec;
@@ -942,8 +942,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
for (;;) {
usec_t multiplier = default_unit, k;
- long long l, z = 0;
- unsigned n = 0;
+ long long l;
char *e;
p += strspn(p, WHITESPACE);
@@ -966,46 +965,47 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
return -ERANGE;
if (*e == '.') {
- char *b = e + 1;
-
- /* Don't allow "0.-0", "3.+1" or "3. 1" */
- if (IN_SET(*b, '-', '+') || isspace(*b))
- return -EINVAL;
-
- errno = 0;
- z = strtoll(b, &e, 10);
- if (errno > 0)
- return -errno;
- if (z < 0)
- return -ERANGE;
- if (e == b)
- return -EINVAL;
-
- n = e - b;
-
+ p = e + 1;
+ p += strspn(p, DIGITS);
} else if (e == p)
return -EINVAL;
+ else
+ p = e;
- e += strspn(e, WHITESPACE);
- p = extract_multiplier(e, &multiplier);
+ s = extract_multiplier(p + strspn(p, WHITESPACE), &multiplier);
+ if (s == p && *s != '\0')
+ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/
+ return -EINVAL;
- something = true;
+ p = s;
+ if ((usec_t) l >= USEC_INFINITY / multiplier)
+ return -ERANGE;
- k = ((usec_t) -1) / multiplier;
- if ((usec_t) l + 1 >= k || (usec_t) z >= k)
+ k = (usec_t) l * multiplier;
+ if (k >= USEC_INFINITY - r)
return -ERANGE;
- k = (usec_t) z * multiplier;
+ r += k;
- for (; n > 0; n--)
- k /= 10;
+ something = true;
- k += (usec_t) l * multiplier;
- if (k >= ((usec_t) -1) - r)
- return -ERANGE;
+ if (*e == '.') {
+ usec_t m = multiplier / 10;
+ const char *b;
- r += k;
+ for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) {
+ k = (usec_t) (*b - '0') * m;
+ if (k >= USEC_INFINITY - r)
+ return -ERANGE;
+
+ r += k;
+ }
+
+ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/
+ if (b == e + 1)
+ return -EINVAL;
+ }
}
*usec = r;
@@ -1032,44 +1032,60 @@ int parse_sec_fix_0(const char *t, usec_t *ret) {
return r;
}
-int parse_nsec(const char *t, nsec_t *nsec) {
+static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) {
static const struct {
const char *suffix;
nsec_t nsec;
} table[] = {
- { "seconds", NSEC_PER_SEC },
- { "second", NSEC_PER_SEC },
- { "sec", NSEC_PER_SEC },
- { "s", NSEC_PER_SEC },
+ { "seconds", NSEC_PER_SEC },
+ { "second", NSEC_PER_SEC },
+ { "sec", NSEC_PER_SEC },
+ { "s", NSEC_PER_SEC },
{ "minutes", NSEC_PER_MINUTE },
- { "minute", NSEC_PER_MINUTE },
- { "min", NSEC_PER_MINUTE },
- { "months", NSEC_PER_MONTH },
- { "month", NSEC_PER_MONTH },
- { "msec", NSEC_PER_MSEC },
- { "ms", NSEC_PER_MSEC },
- { "m", NSEC_PER_MINUTE },
- { "hours", NSEC_PER_HOUR },
- { "hour", NSEC_PER_HOUR },
- { "hr", NSEC_PER_HOUR },
- { "h", NSEC_PER_HOUR },
- { "days", NSEC_PER_DAY },
- { "day", NSEC_PER_DAY },
- { "d", NSEC_PER_DAY },
- { "weeks", NSEC_PER_WEEK },
- { "week", NSEC_PER_WEEK },
- { "w", NSEC_PER_WEEK },
- { "years", NSEC_PER_YEAR },
- { "year", NSEC_PER_YEAR },
- { "y", NSEC_PER_YEAR },
- { "usec", NSEC_PER_USEC },
- { "us", NSEC_PER_USEC },
- { "µs", NSEC_PER_USEC },
- { "nsec", 1ULL },
- { "ns", 1ULL },
- { "", 1ULL }, /* default is nsec */
+ { "minute", NSEC_PER_MINUTE },
+ { "min", NSEC_PER_MINUTE },
+ { "months", NSEC_PER_MONTH },
+ { "month", NSEC_PER_MONTH },
+ { "M", NSEC_PER_MONTH },
+ { "msec", NSEC_PER_MSEC },
+ { "ms", NSEC_PER_MSEC },
+ { "m", NSEC_PER_MINUTE },
+ { "hours", NSEC_PER_HOUR },
+ { "hour", NSEC_PER_HOUR },
+ { "hr", NSEC_PER_HOUR },
+ { "h", NSEC_PER_HOUR },
+ { "days", NSEC_PER_DAY },
+ { "day", NSEC_PER_DAY },
+ { "d", NSEC_PER_DAY },
+ { "weeks", NSEC_PER_WEEK },
+ { "week", NSEC_PER_WEEK },
+ { "w", NSEC_PER_WEEK },
+ { "years", NSEC_PER_YEAR },
+ { "year", NSEC_PER_YEAR },
+ { "y", NSEC_PER_YEAR },
+ { "usec", NSEC_PER_USEC },
+ { "us", NSEC_PER_USEC },
+ { "µs", NSEC_PER_USEC },
+ { "nsec", 1ULL },
+ { "ns", 1ULL },
+ { "", 1ULL }, /* default is nsec */
};
+ size_t i;
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+ char *e;
+
+ e = startswith(p, table[i].suffix);
+ if (e) {
+ *multiplier = table[i].nsec;
+ return e;
+ }
+ }
+
+ return p;
+}
+int parse_nsec(const char *t, nsec_t *nsec) {
const char *p, *s;
nsec_t r = 0;
bool something = false;
@@ -1091,8 +1107,8 @@ int parse_nsec(const char *t, nsec_t *nsec) {
}
for (;;) {
- long long l, z = 0;
- size_t n = 0, i;
+ nsec_t multiplier = 1, k;
+ long long l;
char *e;
p += strspn(p, WHITESPACE);
@@ -1104,7 +1120,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
break;
}
- if (*p == '-')
+ if (*p == '-') /* Don't allow "-0" */
return -ERANGE;
errno = 0;
@@ -1115,54 +1131,47 @@ int parse_nsec(const char *t, nsec_t *nsec) {
return -ERANGE;
if (*e == '.') {
- char *b = e + 1;
-
- if (IN_SET(*b, '-', '+') || isspace(*b))
- return -EINVAL;
-
- errno = 0;
- z = strtoll(b, &e, 10);
- if (errno > 0)
- return -errno;
- if (z < 0)
- return -ERANGE;
- if (e == b)
- return -EINVAL;
-
- n = e - b;
-
+ p = e + 1;
+ p += strspn(p, DIGITS);
} else if (e == p)
return -EINVAL;
+ else
+ p = e;
- e += strspn(e, WHITESPACE);
+ s = extract_nsec_multiplier(p + strspn(p, WHITESPACE), &multiplier);
+ if (s == p && *s != '\0')
+ /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/
+ return -EINVAL;
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- nsec_t k;
+ p = s;
- k = ((nsec_t) -1) / table[i].nsec;
- if ((nsec_t) l + 1 >= k || (nsec_t) z >= k)
- return -ERANGE;
+ if ((nsec_t) l >= NSEC_INFINITY / multiplier)
+ return -ERANGE;
+
+ k = (nsec_t) l * multiplier;
+ if (k >= NSEC_INFINITY - r)
+ return -ERANGE;
- k = (nsec_t) z * table[i].nsec;
+ r += k;
+
+ something = true;
- for (; n > 0; n--)
- k /= 10;
+ if (*e == '.') {
+ nsec_t m = multiplier / 10;
+ const char *b;
- k += (nsec_t) l * table[i].nsec;
- if (k >= ((nsec_t) -1) - r)
+ for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) {
+ k = (nsec_t) (*b - '0') * m;
+ if (k >= NSEC_INFINITY - r)
return -ERANGE;
r += k;
- p = e + strlen(table[i].suffix);
-
- something = true;
- break;
}
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
+ /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/
+ if (b == e + 1)
+ return -EINVAL;
+ }
}
*nsec = r;
diff --git a/src/basic/util.c b/src/basic/util.c
index 0da963f4af..b6e874c3b8 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -606,7 +606,7 @@ void disable_coredumps(void) {
if (detect_container() > 0)
return;
- r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
+ r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
}
diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
index fb8cf13f23..0dd202d086 100644
--- a/src/binfmt/binfmt.c
+++ b/src/binfmt/binfmt.c
@@ -47,7 +47,7 @@ static int delete_rule(const char *rule) {
if (!fn)
return log_oom();
- return write_string_file(fn, "-1", 0);
+ return write_string_file(fn, "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
}
static int apply_rule(const char *rule) {
@@ -55,7 +55,7 @@ static int apply_rule(const char *rule) {
(void) delete_rule(rule);
- r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
+ r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_error_errno(r, "Failed to add binary format: %m");
@@ -219,7 +219,7 @@ int main(int argc, char *argv[]) {
}
/* Flush out all rules */
- write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
+ write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
STRV_FOREACH(f, files) {
k = apply_file(*f, true);
diff --git a/src/core/main.c b/src/core/main.c
index 8a09ab67b5..a866160d76 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1391,7 +1391,7 @@ static int bump_unix_max_dgram_qlen(void) {
r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen);
if (r < 0)
- return log_warning_errno(r, "Failed to read AF_UNIX datagram queue length, ignoring: %m");
+ return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to read AF_UNIX datagram queue length, ignoring: %m");
r = safe_atolu(qlen, &v);
if (r < 0)
@@ -1400,7 +1400,7 @@ static int bump_unix_max_dgram_qlen(void) {
if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
return 0;
- r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", 0, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
+ r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", WRITE_STRING_FILE_DISABLE_BUFFER, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN);
if (r < 0)
return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to bump AF_UNIX datagram queue length, ignoring: %m");
@@ -1615,7 +1615,7 @@ static void initialize_core_pattern(bool skip_setup) {
if (getpid_cached() != 1)
return;
- r = write_string_file("/proc/sys/kernel/core_pattern", arg_early_core_pattern, 0);
+ r = write_string_file("/proc/sys/kernel/core_pattern", arg_early_core_pattern, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_warning_errno(r, "Failed to write '%s' to /proc/sys/kernel/core_pattern, ignoring: %m", arg_early_core_pattern);
}
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index 47138b863a..4e9506f09c 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -351,17 +351,17 @@ int mac_smack_setup(bool *loaded_policy) {
}
#ifdef SMACK_RUN_LABEL
- r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0);
+ r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_warning_errno(r, "Failed to set SMACK label \"" SMACK_RUN_LABEL "\" on self: %m");
- r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, 0);
+ r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_warning_errno(r, "Failed to set SMACK ambient label \"" SMACK_RUN_LABEL "\": %m");
r = write_string_file("/sys/fs/smackfs/netlabel",
- "0.0.0.0/0 " SMACK_RUN_LABEL, 0);
+ "0.0.0.0/0 " SMACK_RUN_LABEL, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_warning_errno(r, "Failed to set SMACK netlabel rule \"0.0.0.0/0 " SMACK_RUN_LABEL "\": %m");
- r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0);
+ r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_warning_errno(r, "Failed to set SMACK netlabel rule \"127.0.0.1 -CIPSO\": %m");
#endif
diff --git a/src/coredump/meson.build b/src/coredump/meson.build
index bfba7ef58c..7fa5942697 100644
--- a/src/coredump/meson.build
+++ b/src/coredump/meson.build
@@ -13,8 +13,10 @@ endif
coredumpctl_sources = files('coredumpctl.c')
-install_data('coredump.conf',
- install_dir : pkgsysconfdir)
+if conf.get('ENABLE_COREDUMP') == 1
+ install_data('coredump.conf',
+ install_dir : pkgsysconfdir)
+endif
tests += [
[['src/coredump/test-coredump-vacuum.c',
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index c3a4509030..45231bf527 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -6,11 +6,13 @@
#include "alloc-util.h"
#include "def.h"
#include "dropin.h"
+#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "fstab-util.h"
#include "generator.h"
#include "hashmap.h"
+#include "id128-util.h"
#include "log.h"
#include "mkdir.h"
#include "parse-util.h"
@@ -40,7 +42,7 @@ static char *arg_default_options = NULL;
static char *arg_default_keyfile = NULL;
static int generate_keydev_mount(const char *name, const char *keydev, char **unit, char **mount) {
- _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL;
+ _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *name_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -54,16 +56,20 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un
return r;
r = mkdir("/run/systemd/cryptsetup", 0700);
- if (r < 0)
- return r;
+ if (r < 0 && errno != EEXIST)
+ return -errno;
- where = strjoin("/run/systemd/cryptsetup/keydev-", name);
+ name_escaped = cescape(name);
+ if (!name_escaped)
+ return -ENOMEM;
+
+ where = strjoin("/run/systemd/cryptsetup/keydev-", name_escaped);
if (!where)
return -ENOMEM;
r = mkdir(where, 0700);
- if (r < 0)
- return r;
+ if (r < 0 && errno != EEXIST)
+ return -errno;
r = unit_name_from_path(where, ".mount", &u);
if (r < 0)
@@ -392,36 +398,52 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return log_oom();
} else if (streq(key, "luks.key")) {
+ size_t n;
+ _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
+ char *c;
+ const char *keyspec;
if (proc_cmdline_value_missing(key, value))
return 0;
- r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value);
- if (r == 2) {
- char *c;
- _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
+ n = strspn(value, LETTERS DIGITS "-");
+ if (value[n] != '=') {
+ if (free_and_strdup(&arg_default_keyfile, value) < 0)
+ return log_oom();
+ return 0;
+ }
- d = get_crypto_device(uuid);
- if (!d)
- return log_oom();
+ uuid = strndup(value, n);
+ if (!uuid)
+ return log_oom();
+
+ if (!id128_is_valid(uuid)) {
+ log_warning("Failed to parse luks.key= kernel command line switch. UUID is invalid, ignoring.");
+ return 0;
+ }
- c = strrchr(uuid_value, ':');
- if (!c)
- /* No keydev specified */
- return free_and_replace(d->keyfile, uuid_value);
+ d = get_crypto_device(uuid);
+ if (!d)
+ return log_oom();
- *c = '\0';
- keyfile = strdup(uuid_value);
- keydev = strdup(++c);
+ keyspec = value + n + 1;
+ c = strrchr(keyspec, ':');
+ if (c) {
+ *c = '\0';
+ keyfile = strdup(keyspec);
+ keydev = strdup(c + 1);
if (!keyfile || !keydev)
return log_oom();
+ } else {
+ /* No keydev specified */
+ keyfile = strdup(keyspec);
+ if (!keyfile)
+ return log_oom();
+ }
- free_and_replace(d->keyfile, keyfile);
- free_and_replace(d->keydev, keydev);
- } else if (free_and_strdup(&arg_default_keyfile, value) < 0)
- return log_oom();
-
+ free_and_replace(d->keyfile, keyfile);
+ free_and_replace(d->keydev, keydev);
} else if (streq(key, "luks.name")) {
if (proc_cmdline_value_missing(key, value))
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 6a939aec04..c5deb66edf 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -531,13 +531,17 @@ static int prompt_root_password(void) {
msg2 = strjoina(special_glyph(TRIANGULAR_BULLET), " Please enter new root password again: ");
for (;;) {
- _cleanup_string_free_erase_ char *a = NULL, *b = NULL;
+ _cleanup_strv_free_erase_ char **a = NULL, **b = NULL;
r = ask_password_tty(-1, msg1, NULL, 0, 0, NULL, &a);
if (r < 0)
return log_error_errno(r, "Failed to query root password: %m");
+ if (strv_length(a) != 1) {
+ log_warning("Received multiple passwords, where we expected one.");
+ return -EINVAL;
+ }
- if (isempty(a)) {
+ if (isempty(*a)) {
log_warning("No password entered, skipping.");
break;
}
@@ -546,12 +550,12 @@ static int prompt_root_password(void) {
if (r < 0)
return log_error_errno(r, "Failed to query root password: %m");
- if (!streq(a, b)) {
+ if (!streq(*a, *b)) {
log_error("Entered passwords did not match, please try again.");
continue;
}
- arg_root_password = TAKE_PTR(a);
+ arg_root_password = TAKE_PTR(*a);
break;
}
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 397757fa46..abbf357291 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -47,7 +47,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- r = write_string_file("/sys/power/resume", major_minor, WRITE_STRING_FILE_CREATE);
+ r = write_string_file("/sys/power/resume", major_minor, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) {
log_error_errno(r, "Failed to write '%s' to /sys/power/resume: %m", major_minor);
return EXIT_FAILURE;
diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h
index 328d51f8ea..88b54933c3 100644
--- a/src/libsystemd-network/lldp-internal.h
+++ b/src/libsystemd-network/lldp-internal.h
@@ -34,3 +34,6 @@ struct sd_lldp {
#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__)
+
+const char* lldp_event_to_string(sd_lldp_event e) _const_;
+sd_lldp_event lldp_event_from_string(const char *s) _pure_;
diff --git a/src/libsystemd-network/ndisc-internal.h b/src/libsystemd-network/ndisc-internal.h
index fdabbc1b0e..0c04fea8e5 100644
--- a/src/libsystemd-network/ndisc-internal.h
+++ b/src/libsystemd-network/ndisc-internal.h
@@ -38,3 +38,6 @@ struct sd_ndisc {
#define log_ndisc_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "NDISC: " fmt, ##__VA_ARGS__)
#define log_ndisc(fmt, ...) log_ndisc_errno(0, fmt, ##__VA_ARGS__)
+
+const char* ndisc_event_to_string(sd_ndisc_event e) _const_;
+sd_ndisc_event ndisc_event_from_string(const char *s) _pure_;
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 949798a1d3..d35e3e2ce1 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -255,11 +255,10 @@ int config_parse_ifalias(const char *unit,
return 0;
}
- free(*s);
- if (*n)
- *s = TAKE_PTR(n);
+ if (isempty(n))
+ *s = mfree(*s);
else
- *s = NULL;
+ free_and_replace(*s, n);
return 0;
}
@@ -294,7 +293,7 @@ int config_parse_hwaddr(const char *unit,
return 0;
}
- *hwaddr = TAKE_PTR(n);
+ free_and_replace(*hwaddr, n);
return 0;
}
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index f72ef204b9..993ca13727 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -6,15 +6,25 @@
#include "sd-lldp.h"
#include "alloc-util.h"
+#include "ether-addr-util.h"
#include "fd-util.h"
#include "lldp-internal.h"
#include "lldp-neighbor.h"
#include "lldp-network.h"
#include "socket-util.h"
-#include "ether-addr-util.h"
+#include "string-table.h"
#define LLDP_DEFAULT_NEIGHBORS_MAX 128U
+static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = {
+ [SD_LLDP_EVENT_ADDED] = "added",
+ [SD_LLDP_EVENT_REMOVED] = "removed",
+ [SD_LLDP_EVENT_UPDATED] = "updated",
+ [SD_LLDP_EVENT_REFRESHED] = "refreshed",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event);
+
static void lldp_flush_neighbors(sd_lldp *lldp) {
sd_lldp_neighbor *n;
@@ -26,12 +36,14 @@ static void lldp_flush_neighbors(sd_lldp *lldp) {
static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) {
assert(lldp);
+ assert(event >= 0 && event < _SD_LLDP_EVENT_MAX);
- log_lldp("Invoking callback for '%c'.", event);
-
- if (!lldp->callback)
+ if (!lldp->callback) {
+ log_lldp("Received '%s' event.", lldp_event_to_string(event));
return;
+ }
+ log_lldp("Invoking callback for '%s' event.", lldp_event_to_string(event));
lldp->callback(lldp, event, n, lldp->userdata);
}
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index d679fc8222..b2fd087987 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -16,19 +16,30 @@
#include "ndisc-router.h"
#include "random-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
#define NDISC_TIMEOUT_NO_RA_USEC (NDISC_ROUTER_SOLICITATION_INTERVAL * NDISC_MAX_ROUTER_SOLICITATIONS)
+static const char * const ndisc_event_table[_SD_NDISC_EVENT_MAX] = {
+ [SD_NDISC_EVENT_TIMEOUT] = "timeout",
+ [SD_NDISC_EVENT_ROUTER] = "router",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ndisc_event, sd_ndisc_event);
+
static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event event, sd_ndisc_router *rt) {
assert(ndisc);
+ assert(event >= 0 && event < _SD_NDISC_EVENT_MAX);
- log_ndisc("Invoking callback for '%c'.", event);
- if (!ndisc->callback)
+ if (!ndisc->callback) {
+ log_ndisc("Received '%s' event.", ndisc_event_to_string(event));
return;
+ }
+ log_ndisc("Invoking callback for '%s' event.", ndisc_event_to_string(event));
ndisc->callback(ndisc, event, rt, ndisc->userdata);
}
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 8d46081ec4..1f2238ca37 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -663,4 +663,7 @@ global:
sd_device_monitor_filter_add_match_tag;
sd_device_monitor_filter_update;
sd_device_monitor_filter_remove;
+
+ sd_event_source_get_floating;
+ sd_event_source_set_floating;
} LIBSYSTEMD_239;
diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c
index 8329a3f909..20529aafd3 100644
--- a/src/libsystemd/sd-device/device-enumerator.c
+++ b/src/libsystemd/sd-device/device-enumerator.c
@@ -554,7 +554,7 @@ static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *bas
if (!dir)
return -errno;
- log_debug(" device-enumerator: scanning %s", path);
+ log_debug("sd-device-enumerator: Scanning %s", path);
FOREACH_DIRENT_ALL(dent, dir, return -errno) {
int k;
@@ -586,10 +586,9 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c
dir = opendir(path);
if (!dir) {
- if (errno == ENOENT)
- return 0;
- else
- return log_error_errno(errno, "sd-device-enumerator: could not open tags directory %s: %m", path);
+ if (errno != ENOENT)
+ return log_debug_errno(errno, "sd-device-enumerator: Failed to open tags directory %s: %m", path);
+ return 0;
}
/* TODO: filter away subsystems? */
@@ -714,7 +713,7 @@ static int parent_crawl_children(sd_device_enumerator *enumerator, const char *p
dir = opendir(path);
if (!dir)
- return log_debug_errno(errno, "sd-device-enumerate: could not open parent directory %s: %m", path);
+ return log_debug_errno(errno, "sd-device-enumerator: Failed to open parent directory %s: %m", path);
FOREACH_DIRENT_ALL(dent, dir, return -errno) {
_cleanup_free_ char *child = NULL;
@@ -737,7 +736,7 @@ static int parent_crawl_children(sd_device_enumerator *enumerator, const char *p
if (maxdepth > 0)
parent_crawl_children(enumerator, child, maxdepth - 1);
else
- log_debug("device-enumerate: max depth reached, %s: ignoring devices", child);
+ log_debug("sd-device-enumerator: Max depth reached, %s: ignoring devices", child);
}
return r;
@@ -765,25 +764,25 @@ static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) {
static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
int r = 0;
- log_debug("device-enumerator: scan all dirs");
+ log_debug("sd-device-enumerator: Scan all dirs");
if (access("/sys/subsystem", F_OK) >= 0) {
/* we have /subsystem/, forget all the old stuff */
r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL);
if (r < 0)
- return log_debug_errno(r, "device-enumerator: failed to scan /sys/subsystem: %m");
+ return log_debug_errno(r, "sd-device-enumerator: Failed to scan /sys/subsystem: %m");
} else {
int k;
k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
if (k < 0) {
- log_debug_errno(k, "device-enumerator: failed to scan /sys/bus: %m");
+ log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/bus: %m");
r = k;
}
k = enumerator_scan_dir(enumerator, "class", NULL, NULL);
if (k < 0) {
- log_debug_errno(k, "device-enumerator: failed to scan /sys/class: %m");
+ log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/class: %m");
r = k;
}
}
@@ -904,7 +903,7 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
if (match_subsystem(enumerator, "module")) {
k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL);
if (k < 0) {
- log_debug_errno(k, "device-enumerator: failed to scan modules: %m");
+ log_debug_errno(k, "sd-device-enumerator: Failed to scan modules: %m");
r = k;
}
}
@@ -918,7 +917,7 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
if (match_subsystem(enumerator, "subsystem")) {
k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL);
if (k < 0) {
- log_debug_errno(k, "device-enumerator: failed to scan subsystems: %m");
+ log_debug_errno(k, "sd-device-enumerator: Failed to scan subsystems: %m");
r = k;
}
}
@@ -927,7 +926,7 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
if (match_subsystem(enumerator, "drivers")) {
k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers");
if (k < 0) {
- log_debug_errno(k, "device-enumerator: failed to scan drivers: %m");
+ log_debug_errno(k, "sd-device-enumerator: Failed to scan drivers: %m");
r = k;
}
}
diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c
index f79a8497ba..ea8231aa63 100644
--- a/src/libsystemd/sd-device/device-monitor.c
+++ b/src/libsystemd/sd-device/device-monitor.c
@@ -140,14 +140,14 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
* will not receive any messages.
*/
- log_debug("The udev service seems not to be active, disabling the monitor");
+ log_debug("sd-device-monitor: The udev service seems not to be active, disabling the monitor");
group = MONITOR_GROUP_NONE;
}
if (fd < 0) {
sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
if (sock < 0)
- return log_debug_errno(errno, "Failed to create socket: %m");
+ return log_debug_errno(errno, "sd-device-monitor: Failed to create socket: %m");
}
m = new(sd_device_monitor, 1);
@@ -165,7 +165,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
if (fd >= 0) {
r = monitor_set_nl_address(m);
if (r < 0)
- return log_debug_errno(r, "Failed to set netlink address: %m");
+ return log_debug_errno(r, "sd-device-monitor: Failed to set netlink address: %m");
}
*ret = TAKE_PTR(m);
@@ -280,24 +280,24 @@ int device_monitor_enable_receiving(sd_device_monitor *m) {
if (!m->filter_uptodate) {
r = sd_device_monitor_filter_update(m);
if (r < 0)
- return log_debug_errno(r, "Failed to update filter: %m");
+ return log_debug_errno(r, "sd-device-monitor: Failed to update filter: %m");
}
if (!m->bound) {
if (bind(m->sock, &m->snl.sa, sizeof(struct sockaddr_nl)) < 0)
- return log_debug_errno(errno, "Failed to bind monitoring socket to event source: %m");
+ return log_debug_errno(errno, "sd-device-monitor: Failed to bind monitoring socket to event source: %m");
m->bound = true;
}
r = monitor_set_nl_address(m);
if (r < 0)
- return log_debug_errno(r, "Failed to set address: %m");
+ return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m");
/* enable receiving of sender credentials */
r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true);
if (r < 0)
- return log_debug_errno(r, "Failed to set socket option SO_PASSCRED: %m");
+ return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m");
return 0;
}
@@ -392,40 +392,40 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
buflen = recvmsg(m->sock, &smsg, 0);
if (buflen < 0) {
if (errno != EINTR)
- log_debug_errno(errno, "Failed to receive message: %m");
+ log_debug_errno(errno, "sd-device-monitor: Failed to receive message: %m");
return -errno;
}
if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC))
- return log_debug_errno(EINVAL, "Invalid message length.");
+ return log_debug_errno(EINVAL, "sd-device-monitor: Invalid message length.");
if (snl.nl.nl_groups == MONITOR_GROUP_NONE) {
/* unicast message, check if we trust the sender */
if (m->snl_trusted_sender.nl.nl_pid == 0 ||
snl.nl.nl_pid != m->snl_trusted_sender.nl.nl_pid)
- return log_debug_errno(EAGAIN, "Unicast netlink message ignored.");
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Unicast netlink message ignored.");
} else if (snl.nl.nl_groups == MONITOR_GROUP_KERNEL) {
if (snl.nl.nl_pid > 0)
- return log_debug_errno(EAGAIN, "Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid);
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid);
}
cmsg = CMSG_FIRSTHDR(&smsg);
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
- return log_debug_errno(EAGAIN, "No sender credentials received, message ignored.");
+ return log_debug_errno(EAGAIN, "sd-device-monitor: No sender credentials received, message ignored.");
cred = (struct ucred*) CMSG_DATA(cmsg);
if (cred->uid != 0)
- return log_debug_errno(EAGAIN, "Sender uid="UID_FMT", message ignored.", cred->uid);
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Sender uid="UID_FMT", message ignored.", cred->uid);
if (streq(buf.raw, "libudev")) {
/* udev message needs proper version magic */
if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC))
- return log_debug_errno(EAGAIN, "Invalid message signature (%x != %x)",
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message signature (%x != %x)",
buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC));
if (buf.nlh.properties_off+32 > (size_t) buflen)
- return log_debug_errno(EAGAIN, "Invalid message length (%u > %zd)",
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message length (%u > %zd)",
buf.nlh.properties_off+32, buflen);
bufpos = buf.nlh.properties_off;
@@ -437,16 +437,16 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
/* kernel message with header */
bufpos = strlen(buf.raw) + 1;
if ((size_t) bufpos < sizeof("a@/d") || bufpos >= buflen)
- return log_debug_errno(EAGAIN, "Invalid message length");
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message length");
/* check message header */
if (!strstr(buf.raw, "@/"))
- return log_debug_errno(EAGAIN, "Invalid message header");
+ return log_debug_errno(EAGAIN, "sd-device-monitor: Invalid message header");
}
r = device_new_from_nulstr(&device, (uint8_t*) &buf.raw[bufpos], buflen - bufpos);
if (r < 0)
- return log_debug_errno(r, "Failed to create device: %m");
+ return log_debug_errno(r, "sd-device-monitor: Failed to create device from received message: %m");
if (is_initialized)
device_set_is_initialized(device);
@@ -454,9 +454,9 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
/* Skip device, if it does not pass the current filter */
r = passes_filter(m, device);
if (r < 0)
- return log_device_debug_errno(device, r, "Failed to check received device passing filter: %m");
+ return log_device_debug_errno(device, r, "sd-device-monitor: Failed to check received device passing filter: %m");
if (r == 0)
- log_device_debug(device, "Received device does not pass filter, ignoring");
+ log_device_debug(device, "sd-device-monitor: Received device does not pass filter, ignoring");
else
*ret = TAKE_PTR(device);
@@ -512,16 +512,16 @@ int device_monitor_send_device(
r = device_get_properties_nulstr(device, (const uint8_t **) &buf, &blen);
if (r < 0)
- return log_debug_errno(r, "Failed to get device properties: %m");
+ return log_device_debug_errno(device, r, "sd-device-monitor: Failed to get device properties: %m");
if (blen < 32) {
- log_debug("Device buffer is too small to contain a valid device");
+ log_device_debug(device, "sd-device-monitor: Length of device property nulstr is too small to contain valid device information");
return -EINVAL;
}
/* fill in versioned header */
r = sd_device_get_subsystem(device, &val);
if (r < 0)
- return log_device_debug_errno(device, r, "Failed to get device subsystem: %m");
+ return log_device_debug_errno(device, r, "sd-device-monitor: Failed to get device subsystem: %m");
nlh.filter_subsystem_hash = htobe32(string_hash32(val));
if (sd_device_get_devtype(device, &val) >= 0)
@@ -556,13 +556,13 @@ int device_monitor_send_device(
count = sendmsg(m->sock, &smsg, 0);
if (count < 0) {
if (!destination && errno == ECONNREFUSED) {
- log_device_debug(device, "Passed to netlink monitor");
+ log_device_debug(device, "sd-device-monitor: Passed to netlink monitor");
return 0;
} else
- return log_device_debug_errno(device, errno, "Failed to send device to netlink monitor: %m");
+ return log_device_debug_errno(device, errno, "sd-device-monitor: Failed to send device to netlink monitor: %m");
}
- log_device_debug(device, "Passed %zi byte to netlink monitor", count);
+ log_device_debug(device, "sd-device-monitor: Passed %zi byte to netlink monitor", count);
return count;
}
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index 0bd31216bf..fa0829885a 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -115,7 +115,7 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
break;
default:
- log_debug("device db: unknown key '%c'", key);
+ log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key);
}
return 0;
@@ -189,7 +189,7 @@ static int device_read_db(sd_device *device) {
if (r == -ENOENT)
return 0;
else
- return log_debug_errno(r, "sd-device: failed to read db '%s': %m", path);
+ return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", path);
}
/* devices with a database entry are initialized */
@@ -207,7 +207,7 @@ static int device_read_db(sd_device *device) {
break;
case KEY:
if (db[i] != ':') {
- log_debug("sd-device: ignoring invalid db entry with key '%c'", key);
+ log_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", key);
state = INVALID_LINE;
} else {
@@ -233,14 +233,14 @@ static int device_read_db(sd_device *device) {
db[i] = '\0';
r = handle_db_line(device, key, value);
if (r < 0)
- log_debug_errno(r, "sd-device: failed to handle db entry '%c:%s': %m", key, value);
+ log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key, value);
state = PRE_KEY;
}
break;
default:
- assert_not_reached("invalid state when parsing db");
+ assert_not_reached("Invalid state when parsing db");
}
}
@@ -376,43 +376,43 @@ static int device_amend(sd_device *device, const char *key, const char *value) {
/* the caller must verify or trust this data (e.g., if it comes from the kernel) */
r = device_set_syspath(device, path, false);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set syspath to '%s': %m", path);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path);
} else if (streq(key, "SUBSYSTEM")) {
r = device_set_subsystem(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set subsystem to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value);
} else if (streq(key, "DEVTYPE")) {
r = device_set_devtype(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devtype to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value);
} else if (streq(key, "DEVNAME")) {
r = device_set_devname(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devname to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value);
} else if (streq(key, "USEC_INITIALIZED")) {
r = device_set_usec_initialized(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set usec-initialized to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value);
} else if (streq(key, "DRIVER")) {
r = device_set_driver(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set driver to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value);
} else if (streq(key, "IFINDEX")) {
r = device_set_ifindex(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set ifindex to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value);
} else if (streq(key, "DEVMODE")) {
r = device_set_devmode(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devmode to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value);
} else if (streq(key, "DEVUID")) {
r = device_set_devuid(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devuid to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value);
} else if (streq(key, "DEVGID")) {
r = device_set_devgid(device, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devgid to '%s': %m", value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value);
} else if (streq(key, "DEVLINKS")) {
const char *word, *state;
size_t l;
@@ -425,7 +425,7 @@ static int device_amend(sd_device *device, const char *key, const char *value) {
r = device_add_devlink(device, devlink);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not add devlink '%s': %m", devlink);
+ return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink);
}
} else if (streq(key, "TAGS")) {
const char *word, *state;
@@ -439,12 +439,12 @@ static int device_amend(sd_device *device, const char *key, const char *value) {
r = device_add_tag(device, tag);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not add tag '%s': %m", tag);
+ return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag);
}
} else {
r = device_add_property_internal(device, key, value);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not add property '%s=%s': %m", key, value);
+ return log_device_debug_errno(device, r, "sd-device: Failed to add property '%s=%s': %m", key, value);
}
return 0;
@@ -480,7 +480,7 @@ static int device_append(sd_device *device, char *key, const char **_major, cons
value = strchr(key, '=');
if (!value) {
- log_debug("sd-device: not a key-value pair: '%s'", key);
+ log_device_debug(device, "sd-device: Not a key-value pair: '%s'", key);
return -EINVAL;
}
@@ -536,7 +536,7 @@ static int device_verify(sd_device *device, DeviceAction action, uint64_t seqnum
assert(device);
if (!device->devpath || !device->subsystem || action == _DEVICE_ACTION_INVALID || seqnum == 0) {
- log_debug("sd-device: device created from strv lacks devpath, subsystem, action or seqnum");
+ log_device_debug(device, "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
return -EINVAL;
}
@@ -569,7 +569,7 @@ int device_new_from_strv(sd_device **ret, char **strv) {
if (major) {
r = device_set_devnum(device, major, minor);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
}
r = device_verify(device, action, seqnum);
@@ -604,7 +604,7 @@ int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
key = (char*)&nulstr[i];
end = memchr(key, '\0', len - i);
if (!end) {
- log_debug("sd-device: failed to parse nulstr");
+ log_device_debug(device, "sd-device: Failed to parse nulstr");
return -EINVAL;
}
i += end - key + 1;
@@ -617,7 +617,7 @@ int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
if (major) {
r = device_set_devnum(device, major, minor);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set devnum %s:%s: %m", major, minor);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
}
r = device_verify(device, action, seqnum);
@@ -1083,8 +1083,8 @@ int device_update_db(sd_device *device) {
goto fail;
}
- log_debug("created %s file '%s' for '%s'", has_info ? "db" : "empty",
- path, device->devpath);
+ log_device_debug(device, "sd-device: Created %s file '%s' for '%s'", has_info ? "db" : "empty",
+ path, device->devpath);
return 0;
@@ -1092,7 +1092,7 @@ fail:
(void) unlink(path);
(void) unlink(path_tmp);
- return log_error_errno(r, "failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath);
+ return log_device_debug_errno(device, r, "sd-device: Failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath);
}
int device_delete_db(sd_device *device) {
diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h
index e25350edc5..94f6174bff 100644
--- a/src/libsystemd/sd-device/device-util.h
+++ b/src/libsystemd/sd-device/device-util.h
@@ -33,17 +33,15 @@
#define log_device_full(device, level, error, ...) \
({ \
- const char *_sysname = NULL, *_subsystem = NULL; \
+ const char *_sysname = NULL; \
sd_device *_d = (device); \
int _level = (level), _error = (error); \
\
- if (_d && _unlikely_(log_get_max_level() >= _level)) { \
+ if (_d && _unlikely_(log_get_max_level() >= _level)) \
(void) sd_device_get_sysname(_d, &_sysname); \
- (void) sd_device_get_subsystem(_d, &_subsystem); \
- } \
log_object_internal(_level, _error, __FILE__, __LINE__, __func__, \
_sysname ? "DEVICE=" : NULL, _sysname, \
- _subsystem ? "SUBSYSTEM=" : NULL, _subsystem, ##__VA_ARGS__); \
+ NULL, NULL, ##__VA_ARGS__); \
})
#define log_device_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__)
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index d0f5e1efcf..11115400dc 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -138,7 +138,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
/* must be a subdirectory of /sys */
if (!path_startswith(_syspath, "/sys/")) {
- log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath);
+ log_debug("sd-device: Syspath '%s' is not a subdirectory of /sys", _syspath);
return -EINVAL;
}
@@ -147,7 +147,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
if (r == -ENOENT)
return -ENODEV; /* the device does not exist (any more?) */
if (r < 0)
- return log_debug_errno(r, "sd-device: could not get target of '%s': %m", _syspath);
+ return log_debug_errno(r, "sd-device: Failed to get target of '%s': %m", _syspath);
if (!path_startswith(syspath, "/sys")) {
_cleanup_free_ char *real_sys = NULL, *new_syspath = NULL;
@@ -156,17 +156,17 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
/* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
r = chase_symlinks("/sys", NULL, 0, &real_sys);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not chase symlink /sys: %m");
+ return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");
p = path_startswith(syspath, real_sys);
if (!p) {
- log_debug("sd-device: canonicalized path '%s' does not starts with sysfs mount point '%s'", syspath, real_sys);
+ log_debug("sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'", syspath, real_sys);
return -ENODEV;
}
new_syspath = strjoin("/sys/", p);
if (!new_syspath)
- return log_oom();
+ return -ENOMEM;
free_and_replace(syspath, new_syspath);
path_simplify(syspath, false);
@@ -513,7 +513,7 @@ int device_read_uevent_file(sd_device *device) {
/* some devices may not have uevent files, see set_syspath() */
return 0;
else if (r < 0)
- return log_debug_errno(r, "sd-device: failed to read uevent file '%s': %m", path);
+ return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path);
for (i = 0; i < uevent_len; i++)
switch (state) {
@@ -532,7 +532,7 @@ int device_read_uevent_file(sd_device *device) {
state = PRE_VALUE;
} else if (strchr(NEWLINE, uevent[i])) {
uevent[i] = '\0';
- log_debug("sd-device: ignoring invalid uevent line '%s'", key);
+ log_device_debug(device, "sd-device: Invalid uevent line '%s', ignoring", key);
state = PRE_KEY;
}
@@ -549,20 +549,20 @@ int device_read_uevent_file(sd_device *device) {
r = handle_uevent_line(device, key, value, &major, &minor);
if (r < 0)
- log_debug_errno(r, "sd-device: failed to handle uevent entry '%s=%s': %m", key, value);
+ log_device_debug_errno(device, r, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key, value);
state = PRE_KEY;
}
break;
default:
- assert_not_reached("invalid state when parsing uevent file");
+ assert_not_reached("Invalid state when parsing uevent file");
}
if (major) {
r = device_set_devnum(device, major, minor);
if (r < 0)
- log_debug_errno(r, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major, minor, path);
+ log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, minor, path);
}
return 0;
@@ -798,7 +798,7 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
path_startswith(device->devpath, "/bus/")))
r = device_set_subsystem(device, "subsystem");
if (r < 0 && r != -ENOENT)
- return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for %s: %m", device->devpath);
device->subsystem_set = true;
} else if (!device->driver_subsystem_set)
@@ -821,7 +821,7 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
r = device_set_drivers_subsystem(device, subsys + 1);
}
if (r < 0 && r != -ENOENT)
- return log_debug_errno(r, "sd-device: could not set subsystem for driver %s: %m", device->devpath);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for driver %s: %m", device->devpath);
}
device->driver_subsystem_set = true;
@@ -944,11 +944,11 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
if (r >= 0) {
r = device_set_driver(device, driver);
if (r < 0)
- return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath);
} else if (r == -ENOENT)
device->driver_set = true;
else
- return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
+ return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath);
}
if (!device->driver)
@@ -1211,7 +1211,7 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
break;
default:
- log_debug("device db: unknown key '%c'", key);
+ log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key);
}
return 0;
@@ -1312,7 +1312,7 @@ int device_read_db_aux(sd_device *device, bool force) {
if (r == -ENOENT)
return 0;
else
- return log_debug_errno(r, "sd-device: failed to read db '%s': %m", path);
+ return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", path);
}
/* devices with a database entry are initialized */
@@ -1330,7 +1330,7 @@ int device_read_db_aux(sd_device *device, bool force) {
break;
case KEY:
if (db[i] != ':') {
- log_debug("sd-device: ignoring invalid db entry with key '%c'", key);
+ log_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", key);
state = INVALID_LINE;
} else {
@@ -1356,14 +1356,14 @@ int device_read_db_aux(sd_device *device, bool force) {
db[i] = '\0';
r = handle_db_line(device, key, value);
if (r < 0)
- log_debug_errno(r, "sd-device: failed to handle db entry '%c:%s': %m", key, value);
+ log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key, value);
state = PRE_KEY;
}
break;
default:
- assert_not_reached("invalid state when parsing db");
+ assert_not_reached("Invalid state when parsing db");
}
}
@@ -1827,12 +1827,9 @@ static void device_remove_sysattr_value(sd_device *device, const char *_key) {
/* set the attribute and save it in the cache. If a NULL value is passed the
* attribute is cleared from the cache */
_public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *_value) {
- _cleanup_close_ int fd = -1;
_cleanup_free_ char *value = NULL;
- const char *syspath;
- char *path;
- size_t len = 0;
- ssize_t size;
+ const char *syspath, *path;
+ size_t len;
int r;
assert_return(device, -EINVAL);
@@ -1850,25 +1847,6 @@ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr,
path = strjoina(syspath, "/", sysattr);
- fd = open(path, O_WRONLY | O_CLOEXEC | O_NOFOLLOW);
- if (fd < 0) {
- if (errno == ELOOP)
- return -EINVAL;
- if (errno == EISDIR)
- return -EISDIR;
-
- value = strdup("");
- if (!value)
- return -ENOMEM;
-
- r = device_add_sysattr_value(device, sysattr, value);
- if (r < 0)
- return r;
- value = NULL;
-
- return -ENXIO;
- }
-
len = strlen(_value);
/* drop trailing newlines */
@@ -1883,17 +1861,30 @@ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr,
if (!value)
return -ENOMEM;
- size = write(fd, value, len);
- if (size < 0)
- return -errno;
+ r = write_string_file(path, value, WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_NOFOLLOW);
+ if (r < 0) {
+ if (r == -ELOOP)
+ return -EINVAL;
+ if (r == -EISDIR)
+ return r;
- if ((size_t)size != len)
- return -EIO;
+ free(value);
+ value = strdup("");
+ if (!value)
+ return -ENOMEM;
+
+ r = device_add_sysattr_value(device, sysattr, value);
+ if (r < 0)
+ return r;
+
+ value = NULL;
+ return -ENXIO;
+ }
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
- value = NULL;
+ value = NULL;
return 0;
}
diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c
index 25ed3ecfea..1dda6625d2 100644
--- a/src/libsystemd/sd-device/test-sd-device.c
+++ b/src/libsystemd/sd-device/test-sd-device.c
@@ -12,10 +12,12 @@ static void test_sd_device_basic(void) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *d;
+ log_info("/* %s */", __func__);
+
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
FOREACH_DEVICE(e, d) {
- const char *syspath, *devpath, *subsystem, *val;
+ const char *syspath, *subsystem, *val;
dev_t devnum;
usec_t usec;
int i, r;
@@ -37,7 +39,7 @@ static void test_sd_device_basic(void) {
r = sd_device_get_driver(d, &val);
assert_se(r >= 0 || r == -ENOENT);
- assert_se(sd_device_get_devpath(d, &devpath) >= 0);
+ assert_se(sd_device_get_devpath(d, &val) >= 0);
r = sd_device_get_devname(d, &val);
assert_se(r >= 0 || r == -ENOENT);
@@ -47,11 +49,11 @@ static void test_sd_device_basic(void) {
r = sd_device_get_sysnum(d, &val);
assert_se(r >= 0 || r == -ENOENT);
- r = sd_device_get_is_initialized(d);
- assert_se(r >= 0);
- if (r > 0) {
+ i = sd_device_get_is_initialized(d);
+ assert_se(i >= 0);
+ if (i > 0) {
r = sd_device_get_usec_since_initialized(d, &usec);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se((r >= 0 && usec > 0) || r == -ENODATA);
}
r = sd_device_get_sysattr_value(d, "name_assign_type", &val);
@@ -60,7 +62,7 @@ static void test_sd_device_basic(void) {
r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
assert_se(r >= 0 || r == -ENOENT);
- log_debug("syspath:%s devpath:%s subsystem:%s", syspath, devpath, strempty(subsystem));
+ log_debug("subsystem:%s syspath:%s initialized:%s", strna(subsystem), syspath, yes_no(i));
}
}
@@ -91,6 +93,8 @@ static void test_sd_device_enumerator_filter_subsystem(void) {
Hashmap *h;
char *s;
+ log_info("/* %s */", __func__);
+
assert_se(subsystems = hashmap_new(&string_hash_ops));
assert_se(sd_device_enumerator_new(&e) >= 0);
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index f44e6b4cca..27caa8681c 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -3702,3 +3702,31 @@ _public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_d
return !!s->destroy_callback;
}
+
+_public_ int sd_event_source_get_floating(sd_event_source *s) {
+ assert_return(s, -EINVAL);
+
+ return s->floating;
+}
+
+_public_ int sd_event_source_set_floating(sd_event_source *s, int b) {
+ assert_return(s, -EINVAL);
+
+ if (s->floating == !!b)
+ return 0;
+
+ if (!s->event) /* Already disconnected */
+ return -ESTALE;
+
+ s->floating = b;
+
+ if (b) {
+ sd_event_source_ref(s);
+ sd_event_unref(s->event);
+ } else {
+ sd_event_ref(s->event);
+ sd_event_source_unref(s);
+ }
+
+ return 1;
+}
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 3365906813..4e42ab175f 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -224,6 +224,9 @@ static const NLType rtnl_link_info_data_bond_types[] = {
[IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 },
[IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 },
[IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED },
+ [IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BOND_AD_USER_PORT_KEY] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NETLINK_TYPE_ETHER_ADDR },
};
static const NLType rtnl_link_info_data_iptun_types[] = {
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index 61876781c0..1fbab9dbf9 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -94,6 +94,7 @@ struct sd_resolve_query {
};
void *userdata;
+ sd_resolve_destroy_t destroy_callback;
LIST_FIELDS(sd_resolve_query, queries);
};
@@ -1095,6 +1096,9 @@ static sd_resolve_query *resolve_query_free(sd_resolve_query *q) {
resolve_query_disconnect(q);
+ if (q->destroy_callback)
+ q->destroy_callback(q->userdata);
+
resolve_freeaddrinfo(q->addrinfo);
free(q->host);
free(q->serv);
@@ -1137,6 +1141,50 @@ _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
return q->resolve;
}
+_public_ int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback) {
+ assert_return(q, -EINVAL);
+
+ if (destroy_callback)
+ *destroy_callback = q->destroy_callback;
+
+ return !!q->destroy_callback;
+}
+
+_public_ int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback) {
+ assert_return(q, -EINVAL);
+
+ q->destroy_callback = destroy_callback;
+ return 0;
+}
+
+_public_ int sd_resolve_query_get_floating(sd_resolve_query *q) {
+ assert_return(q, -EINVAL);
+
+ return q->floating;
+}
+
+_public_ int sd_resolve_query_set_floating(sd_resolve_query *q, int b) {
+ assert_return(q, -EINVAL);
+
+ if (q->floating == !!b)
+ return 0;
+
+ if (!q->resolve) /* Already disconnected */
+ return -ESTALE;
+
+ q->floating = b;
+
+ if (b) {
+ sd_resolve_query_ref(q);
+ sd_resolve_unref(q->resolve);
+ } else {
+ sd_resolve_ref(q->resolve);
+ sd_resolve_query_unref(q);
+ }
+
+ return 1;
+}
+
static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
sd_resolve *resolve = userdata;
int r;
diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in
index 0db46adc84..1f30900392 100644
--- a/src/login/71-seat.rules.in
+++ b/src/login/71-seat.rules.in
@@ -12,7 +12,7 @@ ACTION=="remove", GOTO="seat_end"
TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat"
SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat"
-SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat", TAG+="master-of-seat"
+SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat"
SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 032504e63a..927e304a0c 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1226,7 +1226,7 @@ static int trigger_device(Manager *m, sd_device *d) {
if (!t)
return -ENOMEM;
- (void) write_string_file(t, "change", 0);
+ (void) write_string_file(t, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
}
return 0;
diff --git a/src/network/fuzz-netdev-parser.c b/src/network/fuzz-netdev-parser.c
new file mode 100644
index 0000000000..adc85549e5
--- /dev/null
+++ b/src/network/fuzz-netdev-parser.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "fuzz.h"
+#include "networkd-manager.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_(manager_freep) Manager *manager = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_(unlink_tempfilep) char netdev_config[] = "/tmp/fuzz-networkd.XXXXXX";
+
+ assert_se(fmkostemp_safe(netdev_config, "r+", &f) == 0);
+ if (size != 0)
+ assert_se(fwrite(data, size, 1, f) == 1);
+
+ rewind(f);
+ assert_se(manager_new(&manager) >= 0);
+ (void) netdev_load_one(manager, netdev_config);
+ return 0;
+}
diff --git a/src/network/fuzz-network-parser.c b/src/network/fuzz-network-parser.c
new file mode 100644
index 0000000000..bfeb46cff3
--- /dev/null
+++ b/src/network/fuzz-network-parser.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "fuzz.h"
+#include "networkd-manager.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_(manager_freep) Manager *manager = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_(unlink_tempfilep) char network_config[] = "/tmp/fuzz-networkd.XXXXXX";
+
+ assert_se(fmkostemp_safe(network_config, "r+", &f) == 0);
+ if (size != 0)
+ assert_se(fwrite(data, size, 1, f) == 1);
+
+ rewind(f);
+ assert_se(manager_new(&manager) >= 0);
+ (void) network_load_one(manager, network_config);
+ return 0;
+}
diff --git a/src/network/meson.build b/src/network/meson.build
index 175d2f822c..d4fa27a288 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -136,6 +136,24 @@ if conf.get('ENABLE_NETWORKD') == 1
install_data('networkd.conf',
install_dir : pkgsysconfdir)
+ fuzzers += [
+ [['src/network/fuzz-netdev-parser.c',
+ 'src/fuzz/fuzz.h'],
+ [libnetworkd_core,
+ libudev_static,
+ libsystemd_network,
+ libshared],
+ [threads]],
+
+ [['src/network/fuzz-network-parser.c',
+ 'src/fuzz/fuzz.h'],
+ [libnetworkd_core,
+ libudev_static,
+ libsystemd_network,
+ libshared],
+ [threads]]
+ ]
+
tests += [
[['src/network/test-networkd-conf.c'],
[libnetworkd_core,
diff --git a/src/network/netdev/bond.c b/src/network/netdev/bond.c
index 5840a966ab..70d314bc79 100644
--- a/src/network/netdev/bond.c
+++ b/src/network/netdev/bond.c
@@ -7,6 +7,7 @@
#include "alloc-util.h"
#include "conf-parser.h"
+#include "ether-addr-util.h"
#include "extract-word.h"
#include "missing.h"
#include "netdev/bond.h"
@@ -284,6 +285,24 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m");
}
+ if (b->ad_actor_sys_prio != 0) {
+ r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_ACTOR_SYS_PRIO, b->ad_actor_sys_prio);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYS_PRIO attribute: %m");
+ }
+
+ if (b->ad_user_port_key != 0) {
+ r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_USER_PORT_KEY, b->ad_user_port_key);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_USER_PORT_KEY attribute: %m");
+ }
+
+ if (b->ad_actor_system) {
+ r = sd_netlink_message_append_ether_addr(m, IFLA_BOND_AD_ACTOR_SYSTEM, b->ad_actor_system);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYSTEM attribute: %m");
+ }
+
r = sd_netlink_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m");
@@ -357,10 +376,8 @@ int config_parse_arp_ip_target_address(const char *unit,
return 0;
}
- LIST_PREPEND(arp_ip_target, b->arp_ip_targets, buffer);
+ LIST_PREPEND(arp_ip_target, b->arp_ip_targets, TAKE_PTR(buffer));
b->n_arp_ip_targets++;
-
- buffer = NULL;
}
if (b->n_arp_ip_targets > NETDEV_BOND_ARP_TARGETS_MAX)
@@ -371,6 +388,115 @@ int config_parse_arp_ip_target_address(const char *unit,
return 0;
}
+int config_parse_ad_actor_sys_prio(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Bond *b = userdata;
+ uint16_t v;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou16(rvalue, &v);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse actor system priority '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ if (v == 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse actor system priority '%s'. Range is [1,65535], ignoring.", rvalue);
+ return 0;
+ }
+
+ b->ad_actor_sys_prio = v;
+
+ return 0;
+}
+
+int config_parse_ad_user_port_key(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Bond *b = userdata;
+ uint16_t v;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou16(rvalue, &v);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse user port key '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ if (v > 1023) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse user port key '%s'. Range is [0,1023], ignoring.", rvalue);
+ return 0;
+ }
+
+ b->ad_user_port_key = v;
+
+ return 0;
+}
+
+int config_parse_ad_actor_system(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Bond *b = userdata;
+ _cleanup_free_ struct ether_addr *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ n = new0(struct ether_addr, 1);
+ if (!n)
+ return log_oom();
+
+ r = ether_addr_from_string(rvalue, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address %s. Ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ if (ether_addr_is_null(n) || (n->ether_addr_octet[0] & 0x01)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address %s, can not be null or multicast. Ignoring assignment.", rvalue);
+ return 0;
+ }
+
+ free_and_replace(b->ad_actor_system, n);
+
+ return 0;
+}
+
static void bond_done(NetDev *netdev) {
ArpIpTarget *t = NULL, *n = NULL;
Bond *b;
@@ -381,6 +507,8 @@ static void bond_done(NetDev *netdev) {
assert(b);
+ free(b->ad_actor_system);
+
LIST_FOREACH_SAFE(arp_ip_target, t, n, b->arp_ip_targets)
free(t);
diff --git a/src/network/netdev/bond.h b/src/network/netdev/bond.h
index be03d72087..ce6e8cadef 100644
--- a/src/network/netdev/bond.h
+++ b/src/network/netdev/bond.h
@@ -106,6 +106,10 @@ typedef struct Bond {
unsigned num_grat_arp;
unsigned min_links;
+ uint16_t ad_actor_sys_prio;
+ uint16_t ad_user_port_key;
+ struct ether_addr *ad_actor_system;
+
usec_t miimon;
usec_t updelay;
usec_t downdelay;
@@ -152,3 +156,6 @@ int config_parse_bond_arp_validate(const char *unit, const char *filename, unsig
int config_parse_bond_arp_all_targets(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bond_primary_reselect(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_arp_ip_target_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_ad_actor_sys_prio(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_ad_user_port_key(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_ad_actor_system(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c
index 5a462f8376..cb00780b8a 100644
--- a/src/network/netdev/bridge.c
+++ b/src/network/netdev/bridge.c
@@ -130,7 +130,7 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_call_async(netdev->manager->rtnl, NULL, req, netdev_bridge_set_handler,
- netdev_netlink_destroy_callback, netdev, 0, __func__);
+ netdev_destroy_callback, netdev, 0, __func__);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c
index e407a8fc5c..1742e399b8 100644
--- a/src/network/netdev/geneve.c
+++ b/src/network/netdev/geneve.c
@@ -137,7 +137,7 @@ static int netdev_geneve_create(NetDev *netdev) {
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler,
- netdev_netlink_destroy_callback, netdev, 0, __func__);
+ netdev_destroy_callback, netdev, 0, __func__);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index 96c8fb1832..61d73e15ff 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -108,7 +108,9 @@ GENEVE.TOS, config_parse_uint8, 0,
GENEVE.TTL, config_parse_uint8, 0, offsetof(Geneve, ttl)
GENEVE.UDPChecksum, config_parse_bool, 0, offsetof(Geneve, udpcsum)
GENEVE.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumrx)
+GENEVE.UDP6ZeroChecksumRx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumrx)
GENEVE.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumtx)
+GENEVE.UDP6ZeroChecksumTx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumtx)
GENEVE.DestinationPort, config_parse_ip_port, 0, offsetof(Geneve, dest_port)
GENEVE.FlowLabel, config_parse_geneve_flow_label, 0, 0
Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue)
@@ -141,6 +143,9 @@ Bond.UpDelaySec, config_parse_sec, 0,
Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay)
Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval)
Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval)
+Bond.AdActorSystemPriority, config_parse_ad_actor_sys_prio, 0, offsetof(Bond, ad_actor_sys_prio)
+Bond.AdUserPortKey, config_parse_ad_user_port_key, 0, offsetof(Bond, ad_user_port_key)
+Bond.AdActorSystem, config_parse_ad_actor_system, 0, offsetof(Bond, ad_actor_system)
Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time)
Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age)
Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time)
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 6eb63355a4..9ec16579e4 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -112,13 +112,19 @@ static void netdev_callbacks_clear(NetDev *netdev) {
}
}
+static void netdev_detach_from_manager(NetDev *netdev) {
+ if (netdev->ifname && netdev->manager)
+ hashmap_remove(netdev->manager->netdevs, netdev->ifname);
+
+ netdev->manager = NULL;
+}
+
static NetDev *netdev_free(NetDev *netdev) {
assert(netdev);
netdev_callbacks_clear(netdev);
- if (netdev->ifname && netdev->manager)
- hashmap_remove(netdev->manager->netdevs, netdev->ifname);
+ netdev_detach_from_manager(netdev);
free(netdev->filename);
@@ -149,7 +155,7 @@ static NetDev *netdev_free(NetDev *netdev) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free);
-void netdev_netlink_destroy_callback(void *userdata) {
+void netdev_destroy_callback(void *userdata) {
NetDev *netdev = userdata;
assert(userdata);
@@ -167,6 +173,8 @@ void netdev_drop(NetDev *netdev) {
netdev_callbacks_clear(netdev);
+ netdev_detach_from_manager(netdev);
+
netdev_unref(netdev);
return;
@@ -542,7 +550,7 @@ static int netdev_create(NetDev *netdev, Link *link,
link_ref(link);
} else {
r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, netdev_create_handler,
- netdev_netlink_destroy_callback, netdev, 0, __func__);
+ netdev_destroy_callback, netdev, 0, __func__);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
@@ -586,7 +594,7 @@ int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t callbac
return 0;
}
-static int netdev_load_one(Manager *manager, const char *filename) {
+int netdev_load_one(Manager *manager, const char *filename) {
_cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
_cleanup_fclose_ FILE *file = NULL;
const char *dropin_dirname;
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index 2c1a59f2c4..a1557bec41 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -146,11 +146,12 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
#define NETDEV(n) (&(n)->meta)
int netdev_load(Manager *manager);
+int netdev_load_one(Manager *manager, const char *filename);
void netdev_drop(NetDev *netdev);
NetDev *netdev_unref(NetDev *netdev);
NetDev *netdev_ref(NetDev *netdev);
-void netdev_netlink_destroy_callback(void *userdata);
+void netdev_destroy_callback(void *userdata);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
int netdev_get(Manager *manager, const char *name, NetDev **ret);
diff --git a/src/network/netdev/vcan.c b/src/network/netdev/vcan.c
index f06ad0fb42..574d1cad31 100644
--- a/src/network/netdev/vcan.c
+++ b/src/network/netdev/vcan.c
@@ -4,5 +4,6 @@
const NetDevVTable vcan_vtable = {
.object_size = sizeof(VCan),
+ .sections = "Match\0NetDev\0",
.create_type = NETDEV_CREATE_INDEPENDENT,
};
diff --git a/src/network/netdev/vrf.c b/src/network/netdev/vrf.c
index b18090f7a1..5efab537cc 100644
--- a/src/network/netdev/vrf.c
+++ b/src/network/netdev/vrf.c
@@ -27,7 +27,7 @@ static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink
const NetDevVTable vrf_vtable = {
.object_size = sizeof(Vrf),
- .sections = "NetDev\0VRF\0",
+ .sections = "Match\0NetDev\0VRF\0",
.fill_message_create = netdev_vrf_fill_message_create,
.create_type = NETDEV_CREATE_MASTER,
};
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index 1cab31302e..d5a0a19e9f 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -6,6 +6,8 @@
#include <sys/ioctl.h>
#include <net/if.h>
+#include "sd-resolve.h"
+
#include "alloc-util.h"
#include "parse-util.h"
#include "fd-util.h"
@@ -28,10 +30,13 @@ static WireguardPeer *wireguard_peer_new(Wireguard *w, unsigned section) {
if (w->last_peer_section == section && w->peers)
return w->peers;
- peer = new0(WireguardPeer, 1);
+ peer = new(WireguardPeer, 1);
if (!peer)
return NULL;
- peer->flags = WGPEER_F_REPLACE_ALLOWEDIPS;
+
+ *peer = (WireguardPeer) {
+ .flags = WGPEER_F_REPLACE_ALLOWEDIPS,
+ };
LIST_PREPEND(peers, w->peers, peer);
w->last_peer_section = section;
@@ -195,12 +200,21 @@ static int set_wireguard_interface(NetDev *netdev) {
static WireguardEndpoint* wireguard_endpoint_free(WireguardEndpoint *e) {
if (!e)
return NULL;
- netdev_unref(e->netdev);
e->host = mfree(e->host);
e->port = mfree(e->port);
return mfree(e);
}
+static void wireguard_endpoint_destroy_callback(void *userdata) {
+ WireguardEndpoint *e = userdata;
+
+ assert(e);
+ assert(e->netdev);
+
+ netdev_unref(e->netdev);
+ wireguard_endpoint_free(e);
+}
+
DEFINE_TRIVIAL_CLEANUP_FUNC(WireguardEndpoint*, wireguard_endpoint_free);
static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) {
@@ -211,8 +225,11 @@ static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) {
w = WIREGUARD(netdev);
assert(w);
- w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
+ if (!netdev->manager)
+ /* The netdev is detached. */
+ return 0;
+ assert(!w->unresolved_endpoints);
w->unresolved_endpoints = TAKE_PTR(w->failed_endpoints);
resolve_endpoints(netdev);
@@ -232,9 +249,10 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
int ret,
const struct addrinfo *ai,
void *userdata) {
- NetDev *netdev;
+ _cleanup_(netdev_unrefp) NetDev *netdev_will_unrefed = NULL;
+ NetDev *netdev = NULL;
+ WireguardEndpoint *e;
Wireguard *w;
- _cleanup_(wireguard_endpoint_freep) WireguardEndpoint *e;
int r;
assert(userdata);
@@ -245,14 +263,17 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
w = WIREGUARD(netdev);
assert(w);
- w->resolve_query = sd_resolve_query_unref(w->resolve_query);
+ if (!netdev->manager)
+ /* The netdev is detached. */
+ return 0;
if (ret != 0) {
log_netdev_error(netdev, "Failed to resolve host '%s:%s': %s", e->host, e->port, gai_strerror(ret));
LIST_PREPEND(endpoints, w->failed_endpoints, e);
- e = NULL;
+ (void) sd_resolve_query_set_destroy_callback(q, NULL); /* Avoid freeing endpoint by destroy callback. */
+ netdev_will_unrefed = netdev; /* But netdev needs to be unrefed. */
} else if ((ai->ai_family == AF_INET && ai->ai_addrlen == sizeof(struct sockaddr_in)) ||
- (ai->ai_family == AF_INET6 && ai->ai_addrlen == sizeof(struct sockaddr_in6)))
+ (ai->ai_family == AF_INET6 && ai->ai_addrlen == sizeof(struct sockaddr_in6)))
memcpy(&e->peer->endpoint, ai->ai_addr, ai->ai_addrlen);
else
log_netdev_error(netdev, "Neither IPv4 nor IPv6 address found for peer endpoint: %s:%s", e->host, e->port);
@@ -264,38 +285,53 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
set_wireguard_interface(netdev);
if (w->failed_endpoints) {
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+
w->n_retries++;
r = sd_event_add_time(netdev->manager->event,
- &w->resolve_retry_event_source,
+ &s,
CLOCK_MONOTONIC,
now(CLOCK_MONOTONIC) + exponential_backoff_milliseconds(w->n_retries),
0,
on_resolve_retry,
netdev);
- if (r < 0)
+ if (r < 0) {
log_netdev_warning_errno(netdev, r, "Could not arm resolve retry handler: %m");
+ return 0;
+ }
+
+ r = sd_event_source_set_destroy_callback(s, netdev_destroy_callback);
+ if (r < 0) {
+ log_netdev_warning_errno(netdev, r, "Failed to set destroy callback to event source: %m");
+ return 0;
+ }
+
+ (void) sd_event_source_set_floating(s, true);
+ netdev_ref(netdev);
}
return 0;
}
static void resolve_endpoints(NetDev *netdev) {
- int r = 0;
- Wireguard *w;
- WireguardEndpoint *endpoint;
static const struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_DGRAM,
.ai_protocol = IPPROTO_UDP
};
+ WireguardEndpoint *endpoint;
+ Wireguard *w;
+ int r = 0;
assert(netdev);
w = WIREGUARD(netdev);
assert(w);
LIST_FOREACH(endpoints, endpoint, w->unresolved_endpoints) {
+ _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
+
r = sd_resolve_getaddrinfo(netdev->manager->resolve,
- &w->resolve_query,
+ &q,
endpoint->host,
endpoint->port,
&hints,
@@ -304,11 +340,23 @@ static void resolve_endpoints(NetDev *netdev) {
if (r == -ENOBUFS)
break;
+ if (r < 0) {
+ log_netdev_error_errno(netdev, r, "Failed to create resolver: %m");
+ continue;
+ }
- LIST_REMOVE(endpoints, w->unresolved_endpoints, endpoint);
+ r = sd_resolve_query_set_destroy_callback(q, wireguard_endpoint_destroy_callback);
+ if (r < 0) {
+ log_netdev_error_errno(netdev, r, "Failed to set destroy callback to resolving query: %m");
+ continue;
+ }
- if (r < 0)
- log_netdev_error_errno(netdev, r, "Failed create resolver: %m");
+ (void) sd_resolve_query_set_floating(q, true);
+
+ /* Avoid freeing netdev. It will be unrefed by the destroy callback. */
+ netdev_ref(netdev);
+
+ LIST_REMOVE(endpoints, w->unresolved_endpoints, endpoint);
}
}
@@ -531,12 +579,15 @@ int config_parse_wireguard_allowed_ips(const char *unit,
return 0;
}
- ipmask = new0(WireguardIPmask, 1);
+ ipmask = new(WireguardIPmask, 1);
if (!ipmask)
return log_oom();
- ipmask->family = family;
- ipmask->ip.in6 = addr.in6;
- ipmask->cidr = prefixlen;
+
+ *ipmask = (WireguardIPmask) {
+ .family = family,
+ .ip.in6 = addr.in6,
+ .cidr = prefixlen,
+ };
LIST_PREPEND(ipmasks, peer->ipmasks, ipmask);
}
@@ -572,10 +623,6 @@ int config_parse_wireguard_endpoint(const char *unit,
if (!peer)
return log_oom();
- endpoint = new0(WireguardEndpoint, 1);
- if (!endpoint)
- return log_oom();
-
if (rvalue[0] == '[') {
begin = &rvalue[1];
end = strchr(rvalue, ']');
@@ -609,12 +656,17 @@ int config_parse_wireguard_endpoint(const char *unit,
if (!port)
return log_oom();
- endpoint->peer = TAKE_PTR(peer);
- endpoint->host = TAKE_PTR(host);
- endpoint->port = TAKE_PTR(port);
- endpoint->netdev = netdev_ref(data);
- LIST_PREPEND(endpoints, w->unresolved_endpoints, endpoint);
- endpoint = NULL;
+ endpoint = new(WireguardEndpoint, 1);
+ if (!endpoint)
+ return log_oom();
+
+ *endpoint = (WireguardEndpoint) {
+ .peer = TAKE_PTR(peer),
+ .host = TAKE_PTR(host),
+ .port = TAKE_PTR(port),
+ .netdev = data,
+ };
+ LIST_PREPEND(endpoints, w->unresolved_endpoints, TAKE_PTR(endpoint));
return 0;
}
@@ -673,11 +725,11 @@ static void wireguard_done(NetDev *netdev) {
Wireguard *w;
WireguardPeer *peer;
WireguardIPmask *mask;
+ WireguardEndpoint *e;
assert(netdev);
w = WIREGUARD(netdev);
- assert(!w->unresolved_endpoints);
- w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
+ assert(w);
while ((peer = w->peers)) {
LIST_REMOVE(peers, w->peers, peer);
@@ -687,6 +739,16 @@ static void wireguard_done(NetDev *netdev) {
}
free(peer);
}
+
+ while ((e = w->unresolved_endpoints)) {
+ LIST_REMOVE(endpoints, w->unresolved_endpoints, e);
+ wireguard_endpoint_free(e);
+ }
+
+ while ((e = w->failed_endpoints)) {
+ LIST_REMOVE(endpoints, w->failed_endpoints, e);
+ wireguard_endpoint_free(e);
+ }
}
const NetDevVTable wireguard_vtable = {
diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h
index 80a5bf87a0..bd97004519 100644
--- a/src/network/netdev/wireguard.h
+++ b/src/network/netdev/wireguard.h
@@ -2,11 +2,10 @@
typedef struct Wireguard Wireguard;
+#include "in-addr-util.h"
#include "netdev.h"
-#include "sd-resolve.h"
-#include "wireguard-netlink.h"
#include "socket-util.h"
-#include "in-addr-util.h"
+#include "wireguard-netlink.h"
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
@@ -58,12 +57,10 @@ struct Wireguard {
LIST_HEAD(WireguardPeer, peers);
size_t allocation_size;
- sd_event_source *resolve_retry_event_source;
LIST_HEAD(WireguardEndpoint, unresolved_endpoints);
LIST_HEAD(WireguardEndpoint, failed_endpoints);
unsigned n_retries;
- sd_resolve_query *resolve_query;
};
DEFINE_NETDEV_CAST(WIREGUARD, Wireguard);
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index cf33563bdd..1f722aca52 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -91,10 +91,8 @@ void address_free(Address *address) {
assert(address->network->n_static_addresses > 0);
address->network->n_static_addresses--;
- if (address->section) {
+ if (address->section)
hashmap_remove(address->network->addresses_by_section, address->section);
- network_config_section_free(address->section);
- }
}
if (address->link) {
@@ -105,6 +103,8 @@ void address_free(Address *address) {
memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
}
+ network_config_section_free(address->section);
+ free(address->label);
free(address);
}
@@ -428,6 +428,7 @@ int address_remove(
sd_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ _cleanup_free_ char *b = NULL;
int r;
assert(address);
@@ -437,6 +438,11 @@ int address_remove(
assert(link->manager);
assert(link->manager->rtnl);
+ if (DEBUG_LOGGING) {
+ if (in_addr_to_string(address->family, &address->in_addr, &b) >= 0)
+ log_link_debug(link, "Removing address %s", b);
+ }
+
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
link->ifindex, address->family);
if (r < 0)
@@ -706,8 +712,8 @@ int config_parse_address(const char *unit,
Network *network = userdata;
_cleanup_(address_freep) Address *n = NULL;
- const char *address, *e;
union in_addr_union buffer;
+ unsigned char prefixlen;
int r, f;
assert(filename);
@@ -727,44 +733,19 @@ int config_parse_address(const char *unit,
return r;
/* Address=address/prefixlen */
-
- /* prefixlen */
- e = strchr(rvalue, '/');
- if (e) {
- unsigned i;
-
- r = safe_atou(e + 1, &i);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is invalid, ignoring assignment: %s", e + 1);
- return 0;
- }
-
- n->prefixlen = (unsigned char) i;
-
- address = strndupa(rvalue, e - rvalue);
- } else
- address = rvalue;
-
- r = in_addr_from_string_auto(address, &f, &buffer);
+ r = in_addr_default_prefix_from_string_auto(rvalue, &f, &buffer, &prefixlen);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Address is invalid, ignoring assignment: %s", address);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue);
return 0;
}
- if (!e && f == AF_INET) {
- r = in4_addr_default_prefixlen(&buffer.in, &n->prefixlen);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length not specified, and a default one cannot be deduced for '%s', ignoring assignment", address);
- return 0;
- }
- }
-
if (n->family != AF_UNSPEC && f != n->family) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", address);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
return 0;
}
n->family = f;
+ n->prefixlen = prefixlen;
if (streq(lvalue, "Address"))
n->in_addr = buffer;
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index 694065e3d9..aa0c4c800f 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -200,7 +200,7 @@ int config_parse_fdb_hwaddr(
&fdb_entry->mac_addr->ether_addr_octet[4],
&fdb_entry->mac_addr->ether_addr_octet[5]);
- if (ETHER_ADDR_LEN != r) {
+ if (r != ETHER_ADDR_LEN) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
return 0;
}
diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c
index c4e2091142..6286b37deb 100644
--- a/src/network/networkd-ipv6-proxy-ndp.c
+++ b/src/network/networkd-ipv6-proxy-ndp.c
@@ -43,7 +43,7 @@ static int ipv6_proxy_ndp_set(Link *link) {
v = ipv6_proxy_ndp_is_needed(link);
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/proxy_ndp");
- r = write_string_file(p, one_zero(v), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, one_zero(v), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m");
@@ -88,16 +88,16 @@ void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) {
}
int config_parse_ipv6_proxy_ndp_address(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
Network *network = userdata;
_cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 08ea7b4139..1b233507e7 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -270,7 +270,7 @@ static int link_enable_ipv6(Link *link) {
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6");
- r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m",
enable_disable(!disabled), link->ifname);
@@ -503,6 +503,17 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
return 0;
}
+static void link_detach_from_manager(Link *link) {
+ if (!link || !link->manager)
+ return;
+
+ hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
+ set_remove(link->manager->links_requesting_uuid, link);
+ link_clean(link);
+
+ link->manager = NULL;
+}
+
static Link *link_free(Link *link) {
Address *address;
Link *carrier;
@@ -552,11 +563,7 @@ static Link *link_free(Link *link) {
sd_ndisc_unref(link->ndisc);
sd_radv_unref(link->radv);
- if (link->manager) {
- hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
- set_remove(link->manager->links_requesting_uuid, link);
- link_clean(link);
- }
+ link_detach_from_manager(link);
free(link->ifname);
@@ -785,7 +792,7 @@ static int link_set_routing_policy_rule(Link *link) {
LIST_FOREACH(rules, rule, link->network->rules) {
r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule);
- if (r == 1) {
+ if (r == 0) {
(void) routing_policy_rule_make_local(link->manager, rrule);
continue;
}
@@ -1256,7 +1263,7 @@ static int link_set_proxy_arp(Link *link) {
p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp");
- r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m");
@@ -2265,6 +2272,9 @@ void link_drop(Link *link) {
log_link_debug(link, "Link removed");
(void) unlink(link->state_file);
+
+ link_detach_from_manager(link);
+
link_unref(link);
return;
@@ -2463,7 +2473,7 @@ static int link_set_ipv4_forward(Link *link) {
* primarily to keep IPv4 and IPv6 packet forwarding behaviour
* somewhat in sync (see below). */
- r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
@@ -2485,7 +2495,7 @@ static int link_set_ipv6_forward(Link *link) {
* same behaviour there and also propagate the setting from
* one to all, to keep things simple (see above). */
- r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
@@ -2505,7 +2515,7 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
- r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
@@ -2529,7 +2539,7 @@ static int link_set_ipv6_accept_ra(Link *link) {
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
/* We handle router advertisements ourselves, tell the kernel to GTFO */
- r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
@@ -2557,7 +2567,7 @@ static int link_set_ipv6_dad_transmits(Link *link) {
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
- r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
@@ -2585,7 +2595,7 @@ static int link_set_ipv6_hop_limit(Link *link) {
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
xsprintf(buf, "%i", link->network->ipv6_hop_limit);
- r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
@@ -2611,13 +2621,45 @@ static int link_set_ipv6_mtu(Link *link) {
xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu);
- r = write_string_file(p, buf, 0);
+ r = write_string_file(p, buf, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");
return 0;
}
+static bool link_is_static_address_configured(Link *link, Address *address) {
+ Address *net_address;
+
+ assert(link);
+ assert(address);
+
+ if (!link->network)
+ return false;
+
+ LIST_FOREACH(addresses, net_address, link->network->static_addresses)
+ if (address_equal(net_address, address))
+ return true;
+
+ return false;
+}
+
+static bool link_is_static_route_configured(Link *link, Route *route) {
+ Route *net_route;
+
+ assert(link);
+ assert(route);
+
+ if (!link->network)
+ return false;
+
+ LIST_FOREACH(routes, net_route, link->network->static_routes)
+ if (route_equal(net_route, route))
+ return true;
+
+ return false;
+}
+
static int link_drop_foreign_config(Link *link) {
Address *address;
Route *route;
@@ -2629,9 +2671,15 @@ static int link_drop_foreign_config(Link *link) {
if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1)
continue;
- r = address_remove(address, link, link_address_remove_handler);
- if (r < 0)
- return r;
+ if (link_is_static_address_configured(link, address)) {
+ r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to add address: %m");
+ } else {
+ r = address_remove(address, link, link_address_remove_handler);
+ if (r < 0)
+ return r;
+ }
}
SET_FOREACH(route, link->routes_foreign, i) {
@@ -2639,9 +2687,15 @@ static int link_drop_foreign_config(Link *link) {
if (route->protocol == RTPROT_KERNEL)
continue;
- r = route_remove(route, link, link_route_remove_handler);
- if (r < 0)
- return r;
+ if (link_is_static_route_configured(link, route)) {
+ r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL);
+ if (r < 0)
+ return r;
+ } else {
+ r = route_remove(route, link, link_route_remove_handler);
+ if (r < 0)
+ return r;
+ }
}
return 0;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 7433be96ff..69861a680e 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -201,7 +201,7 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
}
if (!STR_IN_SET(action, "add", "change")) {
- log_device_debug(device, "Ignoring udev %s event for device: %m", action);
+ log_device_debug(device, "Ignoring udev %s event for device.", action);
return 0;
}
@@ -1407,10 +1407,9 @@ int manager_new(Manager **ret) {
}
void manager_free(Manager *m) {
+ AddressPool *pool;
Network *network;
- NetDev *netdev;
Link *link;
- AddressPool *pool;
if (!m)
return;
@@ -1419,6 +1418,7 @@ void manager_free(Manager *m) {
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
+ sd_resolve_unref(m->resolve);
while ((network = m->networks))
network_free(network);
@@ -1437,28 +1437,26 @@ void manager_free(Manager *m) {
link_unref(link);
}
- set_free_with_destructor(m->dirty_links, link_unref);
- hashmap_free(m->links);
- set_free(m->links_requesting_uuid);
+ m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
+ m->links = hashmap_free(m->links);
+ m->links_requesting_uuid = set_free(m->links_requesting_uuid);
set_free(m->duids_requesting_uuid);
hashmap_free(m->networks_by_name);
- while ((netdev = hashmap_first(m->netdevs)))
- netdev_unref(netdev);
- hashmap_free(m->netdevs);
+ m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
while ((pool = m->address_pools))
address_pool_free(pool);
- set_free_with_destructor(m->rules, routing_policy_rule_free);
- set_free_with_destructor(m->rules_foreign, routing_policy_rule_free);
+ /* routing_policy_rule_free() access m->rules and m->rules_foreign.
+ * So, it is necessary to set NULL after the sets are freed. */
+ m->rules = set_free_with_destructor(m->rules, routing_policy_rule_free);
+ m->rules_foreign = set_free_with_destructor(m->rules_foreign, routing_policy_rule_free);
set_free_with_destructor(m->rules_saved, routing_policy_rule_free);
sd_event_unref(m->event);
- sd_resolve_unref(m->resolve);
-
sd_device_monitor_unref(m->device_monitor);
sd_bus_unref(m->bus);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index ac924596f3..adbba5f480 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -38,8 +38,8 @@ Link.AllMulticast, config_parse_tristate,
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
Link.RequiredForOnline, config_parse_bool, 0, offsetof(Network, required_for_online)
Network.Description, config_parse_string, 0, offsetof(Network, description)
-Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
-Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
+Network.Bridge, config_parse_netdev, 0, 0
+Network.Bond, config_parse_netdev, 0, 0
Network.VLAN, config_parse_netdev, 0, 0
Network.MACVLAN, config_parse_netdev, 0, 0
Network.MACVTAP, config_parse_netdev, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 8d7795d72c..f257ac6698 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -102,7 +102,7 @@ void network_apply_anonymize_if_set(Network *network) {
network->dhcp_use_timezone = false;
}
-static int network_load_one(Manager *manager, const char *filename) {
+int network_load_one(Manager *manager, const char *filename) {
_cleanup_(network_freep) Network *network = NULL;
_cleanup_fclose_ FILE *file = NULL;
char *d;
@@ -181,8 +181,6 @@ static int network_load_one(Manager *manager, const char *filename) {
if (!d)
return -EINVAL;
- assert(streq(d, ".network"));
-
*d = '\0';
network->required_for_online = true;
@@ -607,14 +605,17 @@ int config_parse_netdev(const char *unit,
switch (kind) {
case NETDEV_KIND_BRIDGE:
+ network->bridge = netdev_unref(network->bridge);
network->bridge = netdev;
break;
case NETDEV_KIND_BOND:
+ network->bond = netdev_unref(network->bond);
network->bond = netdev;
break;
case NETDEV_KIND_VRF:
+ network->vrf = netdev_unref(network->vrf);
network->vrf = netdev;
break;
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 1be7d46735..919a2c4b3c 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -78,6 +78,8 @@ typedef enum RADVPrefixDelegation {
RADV_PREFIX_DELEGATION_STATIC,
RADV_PREFIX_DELEGATION_DHCP6,
RADV_PREFIX_DELEGATION_BOTH,
+ _RADV_PREFIX_DELEGATION_MAX,
+ _RADV_PREFIX_DELEGATION_INVALID = -1,
} RADVPrefixDelegation;
typedef struct NetworkConfigSection {
@@ -270,6 +272,7 @@ void network_free(Network *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
int network_load(Manager *manager);
+int network_load_one(Manager *manager, const char *filename);
int network_get_by_name(Manager *manager, const char *name, Network **ret);
int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac, Network **ret);
@@ -316,3 +319,6 @@ DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
const char* lldp_mode_to_string(LLDPMode m) _const_;
LLDPMode lldp_mode_from_string(const char *s) _pure_;
+
+const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
+RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c
index c7d6ac2558..600fb27d75 100644
--- a/src/network/networkd-radv.c
+++ b/src/network/networkd-radv.c
@@ -12,8 +12,21 @@
#include "parse-util.h"
#include "sd-radv.h"
#include "string-util.h"
+#include "string-table.h"
#include "strv.h"
+static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
+ [RADV_PREFIX_DELEGATION_NONE] = "no",
+ [RADV_PREFIX_DELEGATION_STATIC] = "static",
+ [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
+ [RADV_PREFIX_DELEGATION_BOTH] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
+ radv_prefix_delegation,
+ RADVPrefixDelegation,
+ RADV_PREFIX_DELEGATION_BOTH);
+
int config_parse_router_prefix_delegation(
const char *unit,
const char *filename,
@@ -27,7 +40,7 @@ int config_parse_router_prefix_delegation(
void *userdata) {
Network *network = userdata;
- int d;
+ RADVPrefixDelegation d;
assert(filename);
assert(section);
@@ -35,21 +48,14 @@ int config_parse_router_prefix_delegation(
assert(rvalue);
assert(data);
- if (streq(rvalue, "static"))
- network->router_prefix_delegation = RADV_PREFIX_DELEGATION_STATIC;
- else if (streq(rvalue, "dhcpv6"))
- network->router_prefix_delegation = RADV_PREFIX_DELEGATION_DHCP6;
- else {
- d = parse_boolean(rvalue);
- if (d > 0)
- network->router_prefix_delegation = RADV_PREFIX_DELEGATION_BOTH;
- else
- network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE;
-
- if (d < 0)
- log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router prefix delegation '%s' is invalid, ignoring assignment: %m", rvalue);
+ d = radv_prefix_delegation_from_string(rvalue);
+ if (d < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue);
+ return 0;
}
+ network->router_prefix_delegation = d;
+
return 0;
}
@@ -97,6 +103,7 @@ void prefix_free(Prefix *prefix) {
prefix->section);
}
+ network_config_section_free(prefix->section);
prefix->radv_prefix = sd_radv_prefix_unref(prefix->radv_prefix);
free(prefix);
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 529d942f15..e8cde66bef 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -201,6 +201,16 @@ static const struct hash_ops route_hash_ops = {
.compare = route_compare_func
};
+bool route_equal(Route *r1, Route *r2) {
+ if (r1 == r2)
+ return true;
+
+ if (!r1 || !r2)
+ return false;
+
+ return route_compare_func(r1, r2) == 0;
+}
+
int route_get(Link *link,
int family,
const union in_addr_union *dst,
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index 7283f48304..fe000d61b8 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -52,6 +52,7 @@ int route_get(Link *link, int family, const union in_addr_union *dst, unsigned c
int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
void route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type);
+bool route_equal(Route *r1, Route *r2);
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c
index 28a2a0fcbf..739f9e6a5a 100644
--- a/src/network/networkd-routing-policy-rule.c
+++ b/src/network/networkd-routing-policy-rule.c
@@ -79,10 +79,10 @@ static void routing_policy_rule_hash_func(const void *b, struct siphash *state)
siphash24_compress(&rule->table, sizeof(rule->table), state);
if (rule->iif)
- siphash24_compress(&rule->iif, strlen(rule->iif), state);
+ siphash24_compress(rule->iif, strlen(rule->iif), state);
if (rule->oif)
- siphash24_compress(&rule->oif, strlen(rule->oif), state);
+ siphash24_compress(rule->oif, strlen(rule->oif), state);
break;
default:
@@ -188,7 +188,7 @@ int routing_policy_rule_get(Manager *m,
if (existing) {
if (ret)
*ret = existing;
- return 1;
+ return 0;
}
return -ENOENT;
@@ -257,8 +257,8 @@ static int routing_policy_rule_add_internal(Manager *m,
rule->tos = tos;
rule->fwmark = fwmark;
rule->table = table;
- rule->iif = TAKE_PTR(iif);
- rule->oif = TAKE_PTR(oif);
+ rule->iif = iif;
+ rule->oif = oif;
r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
if (r < 0)
@@ -272,6 +272,7 @@ static int routing_policy_rule_add_internal(Manager *m,
*ret = rule;
rule = NULL;
+ iif = oif = NULL;
return 0;
}
@@ -549,7 +550,7 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, sd_netlin
r = routing_policy_rule_add(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, NULL);
if (r < 0)
- return log_error_errno(r, "Could not add rule : %m");
+ return log_error_errno(r, "Could not add rule: %m");
return 0;
}
diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c
index 521c5c2dc5..6b110b7110 100644
--- a/src/network/test-network-tables.c
+++ b/src/network/test-network-tables.c
@@ -1,6 +1,8 @@
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
#include "ethtool-util.h"
+#include "lldp-internal.h"
+#include "ndisc-internal.h"
#include "netdev/bond.h"
#include "netdev/ipvlan.h"
#include "netdev/macvlan.h"
@@ -33,7 +35,10 @@ int main(int argc, char **argv) {
test_table(lldp_mode, LLDP_MODE);
test_table(netdev_kind, NETDEV_KIND);
test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA);
+ test_table(radv_prefix_delegation, RADV_PREFIX_DELEGATION);
test_table(wol, WOL);
+ test_table(lldp_event, SD_LLDP_EVENT);
+ test_table(ndisc_event, SD_NDISC_EVENT);
test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE);
test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE);
diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c
index d05680d7e1..abef6e761a 100644
--- a/src/network/test-networkd-conf.c
+++ b/src/network/test-networkd-conf.c
@@ -168,6 +168,49 @@ static void test_config_parse_hwaddr(void) {
test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:fx hogehoge 01-23-45-67-89-ab aaaa aa:Bb:CC:dd:ee:ff", t, 2);
}
+static void test_config_parse_address_one(const char *rvalue, int family, unsigned n_addresses, const union in_addr_union *u, unsigned char prefixlen) {
+ _cleanup_(network_freep) Network *network = NULL;
+
+ assert_se(network = new0(Network, 1));
+ assert_se(network->addresses_by_section = hashmap_new(NULL));
+ assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
+ assert_se(network->n_static_addresses == n_addresses);
+ if (n_addresses > 0) {
+ assert_se(network->static_addresses);
+ assert_se(network->static_addresses->prefixlen == prefixlen);
+ assert_se(network->static_addresses->family == family);
+ assert_se(in_addr_equal(family, &network->static_addresses->in_addr, u));
+ /* TODO: check Address.in_addr and Address.broadcast */
+ }
+}
+
+static void test_config_parse_address(void) {
+ test_config_parse_address_one("", AF_INET, 0, NULL, 0);
+ test_config_parse_address_one("/", AF_INET, 0, NULL, 0);
+ test_config_parse_address_one("/8", AF_INET, 0, NULL, 0);
+ test_config_parse_address_one("1.2.3.4", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 8);
+ test_config_parse_address_one("1.2.3.4/0", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0);
+ test_config_parse_address_one("1.2.3.4/1", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1);
+ test_config_parse_address_one("1.2.3.4/2", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2);
+ test_config_parse_address_one("1.2.3.4/32", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32);
+ test_config_parse_address_one("1.2.3.4/33", AF_INET, 0, NULL, 0);
+ test_config_parse_address_one("1.2.3.4/-1", AF_INET, 0, NULL, 0);
+
+ test_config_parse_address_one("", AF_INET6, 0, NULL, 0);
+ test_config_parse_address_one("/", AF_INET6, 0, NULL, 0);
+ test_config_parse_address_one("/8", AF_INET6, 0, NULL, 0);
+ test_config_parse_address_one("::1", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0);
+ test_config_parse_address_one("::1/0", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0);
+ test_config_parse_address_one("::1/1", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1);
+ test_config_parse_address_one("::1/2", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2);
+ test_config_parse_address_one("::1/32", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32);
+ test_config_parse_address_one("::1/33", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33);
+ test_config_parse_address_one("::1/64", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64);
+ test_config_parse_address_one("::1/128", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128);
+ test_config_parse_address_one("::1/129", AF_INET6, 0, NULL, 0);
+ test_config_parse_address_one("::1/-1", AF_INET6, 0, NULL, 0);
+}
+
int main(int argc, char **argv) {
log_parse_environment();
log_open();
@@ -175,6 +218,7 @@ int main(int argc, char **argv) {
test_config_parse_duid_type();
test_config_parse_duid_rawdata();
test_config_parse_hwaddr();
+ test_config_parse_address();
return 0;
}
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index 8732c9e2aa..0a54d27e6a 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -122,7 +122,7 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
(void) mkdir_parents(fn, 0755);
sprintf(pid_string, PID_FMT, pid);
- r = write_string_file(fn, pid_string, 0);
+ r = write_string_file(fn, pid_string, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) {
log_error_errno(r, "Failed to move process: %m");
goto finish;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index fb6b603040..ab19d73c27 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2176,7 +2176,7 @@ static int reset_audit_loginuid(void) {
if (streq(p, "4294967295"))
return 0;
- r = write_string_file("/proc/self/loginuid", "4294967295", 0);
+ r = write_string_file("/proc/self/loginuid", "4294967295", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0) {
log_error_errno(r,
"Failed to reset audit login UID. This probably means that your kernel is too\n"
@@ -3148,7 +3148,7 @@ static int outer_child(
if (arg_network_namespace_path) {
r = namespace_enter(-1, -1, netns_fd, -1, -1);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to join network namespace: %m");
}
r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, fds);
@@ -3265,13 +3265,13 @@ static int setup_uid_map(pid_t pid) {
xsprintf(uid_map, "/proc/" PID_FMT "/uid_map", pid);
xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, arg_uid_shift, arg_uid_range);
- r = write_string_file(uid_map, line, 0);
+ r = write_string_file(uid_map, line, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_error_errno(r, "Failed to write UID map: %m");
/* We always assign the same UID and GID ranges */
xsprintf(uid_map, "/proc/" PID_FMT "/gid_map", pid);
- r = write_string_file(uid_map, line, 0);
+ r = write_string_file(uid_map, line, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_error_errno(r, "Failed to write GID map: %m");
@@ -3761,10 +3761,12 @@ static int run(int master,
return log_error_errno(errno, "Cannot open file %s: %m", arg_network_namespace_path);
r = fd_is_network_ns(netns_fd);
- if (r < 0 && r != -ENOTTY)
+ if (r == -EUCLEAN)
+ log_debug_errno(r, "Cannot determine if passed network namespace path '%s' really refers to a network namespace, assuming it does.", arg_network_namespace_path);
+ else if (r < 0)
return log_error_errno(r, "Failed to check %s fs type: %m", arg_network_namespace_path);
- if (r == 0) {
- log_error("Path %s doesn't refer to a network namespace", arg_network_namespace_path);
+ else if (r == 0) {
+ log_error("Path %s doesn't refer to a network namespace, refusing.", arg_network_namespace_path);
return -EINVAL;
}
}
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index ae3dd33b7a..0cab1759b0 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -27,6 +27,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
+#include "fs-util.h"
#include "io-util.h"
#include "log.h"
#include "macro.h"
@@ -133,6 +134,9 @@ static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **pa
(unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC), 0, 0) < 0)
log_debug_errno(errno, "Failed to adjust timeout: %m");
+ /* Tell everyone to check the keyring */
+ (void) touch("/run/systemd/ask-password");
+
log_debug("Added key to keyring as %" PRIi32 ".", serial);
return 1;
@@ -211,7 +215,7 @@ int ask_password_tty(
usec_t until,
AskPasswordFlags flags,
const char *flag_file,
- char **ret) {
+ char ***ret) {
enum {
POLL_TTY,
@@ -223,6 +227,7 @@ int ask_password_tty(
_cleanup_close_ int cttyfd = -1, notify = -1;
struct termios old_termios, new_termios;
char passphrase[LINE_MAX + 1] = {}, *x;
+ _cleanup_strv_free_erase_ char **l = NULL;
struct pollfd pollfd[_POLL_MAX];
size_t p = 0, codepoint = 0;
int r;
@@ -235,14 +240,25 @@ int ask_password_tty(
if (!message)
message = "Password:";
- if (flag_file) {
+ if (flag_file || ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname)) {
notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK);
if (notify < 0)
return -errno;
-
+ }
+ if (flag_file) {
if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0)
return -errno;
}
+ if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
+ r = ask_password_keyring(keyname, flags, ret);
+ if (r >= 0)
+ return 0;
+ else if (r != -ENOKEY)
+ return r;
+
+ if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_ATTRIB /* for mtime */) < 0)
+ return -errno;
+ }
/* If the caller didn't specify a TTY, then use the controlling tty, if we can. */
if (ttyfd < 0)
@@ -324,9 +340,17 @@ int ask_password_tty(
goto finish;
}
- if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
+ if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) {
(void) flush_fd(notify);
+ r = ask_password_keyring(keyname, flags, ret);
+ if (r >= 0) {
+ r = 0;
+ goto finish;
+ } else if (r != -ENOKEY)
+ goto finish;
+ }
+
if (pollfd[POLL_TTY].revents == 0)
continue;
@@ -436,10 +460,14 @@ int ask_password_tty(
goto finish;
}
+ r = strv_consume(&l, x);
+ if (r < 0)
+ goto finish;
+
if (keyname)
- (void) add_to_keyring_and_log(keyname, flags, STRV_MAKE(x));
+ (void) add_to_keyring_and_log(keyname, flags, l);
- *ret = x;
+ *ret = TAKE_PTR(l);
r = 0;
finish:
@@ -495,14 +523,15 @@ int ask_password_agent(
enum {
FD_SOCKET,
FD_SIGNAL,
+ FD_INOTIFY,
_FD_MAX
};
- _cleanup_close_ int socket_fd = -1, signal_fd = -1, fd = -1;
+ _cleanup_close_ int socket_fd = -1, signal_fd = -1, notify = -1, fd = -1;
char temp[] = "/run/systemd/ask-password/tmp.XXXXXX";
char final[sizeof(temp)] = "";
_cleanup_free_ char *socket_name = NULL;
- _cleanup_strv_free_ char **l = NULL;
+ _cleanup_strv_free_erase_ char **l = NULL;
_cleanup_fclose_ FILE *f = NULL;
struct pollfd pollfd[_FD_MAX];
sigset_t mask, oldmask;
@@ -519,6 +548,25 @@ int ask_password_agent(
(void) mkdir_p_label("/run/systemd/ask-password", 0755);
+ if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
+ r = ask_password_keyring(keyname, flags, ret);
+ if (r >= 0) {
+ r = 0;
+ goto finish;
+ } else if (r != -ENOKEY)
+ goto finish;
+
+ notify = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
+ if (notify < 0) {
+ r = -errno;
+ goto finish;
+ }
+ if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_ATTRIB /* for mtime */) < 0) {
+ r = -errno;
+ goto finish;
+ }
+ }
+
fd = mkostemp_safe(temp);
if (fd < 0) {
r = fd;
@@ -589,6 +637,8 @@ int ask_password_agent(
pollfd[FD_SOCKET].events = POLLIN;
pollfd[FD_SIGNAL].fd = signal_fd;
pollfd[FD_SIGNAL].events = POLLIN;
+ pollfd[FD_INOTIFY].fd = notify;
+ pollfd[FD_INOTIFY].events = POLLIN;
for (;;) {
char passphrase[LINE_MAX+1];
@@ -610,7 +660,7 @@ int ask_password_agent(
goto finish;
}
- k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1);
+ k = poll(pollfd, notify >= 0 ? _FD_MAX : _FD_MAX - 1, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1);
if (k < 0) {
if (errno == EINTR)
continue;
@@ -629,6 +679,20 @@ int ask_password_agent(
goto finish;
}
+ if (notify >= 0 && pollfd[FD_INOTIFY].revents != 0) {
+ (void) flush_fd(notify);
+
+ r = ask_password_keyring(keyname, flags, ret);
+ if (r >= 0) {
+ r = 0;
+ goto finish;
+ } else if (r != -ENOKEY)
+ goto finish;
+ }
+
+ if (pollfd[FD_SOCKET].revents == 0)
+ continue;
+
if (pollfd[FD_SOCKET].revents != POLLIN) {
r = -EIO;
goto finish;
@@ -736,29 +800,17 @@ int ask_password_auto(
assert(ret);
- if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) {
+ if ((flags & ASK_PASSWORD_ACCEPT_CACHED) &&
+ keyname &&
+ ((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) &&
+ (flags & ASK_PASSWORD_NO_AGENT)) {
r = ask_password_keyring(keyname, flags, ret);
if (r != -ENOKEY)
return r;
}
- if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO)) {
- char *s = NULL, **l = NULL;
-
- r = ask_password_tty(-1, message, keyname, until, flags, NULL, &s);
- if (r < 0)
- return r;
-
- r = strv_push(&l, s);
- if (r < 0) {
- string_erase(s);
- free(s);
- return -ENOMEM;
- }
-
- *ret = l;
- return 0;
- }
+ if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO))
+ return ask_password_tty(-1, message, keyname, until, flags, NULL, ret);
if (!(flags & ASK_PASSWORD_NO_AGENT))
return ask_password_agent(message, icon, id, keyname, until, flags, ret);
diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h
index 93ca8bff52..2d84ba6b04 100644
--- a/src/shared/ask-password-api.h
+++ b/src/shared/ask-password-api.h
@@ -15,7 +15,7 @@ typedef enum AskPasswordFlags {
ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */
} AskPasswordFlags;
-int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char **ret);
+int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret);
int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret);
int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret);
diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c
index 400994a354..2f9df7dd1b 100644
--- a/src/shared/vlan-util.c
+++ b/src/shared/vlan-util.c
@@ -9,6 +9,9 @@ int parse_vlanid(const char *p, uint16_t *ret) {
uint16_t id;
int r;
+ assert(p);
+ assert(ret);
+
r = safe_atou16(p, &id);
if (r < 0)
return r;
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index a4eba59851..198d45c902 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -42,7 +42,7 @@ static int write_hibernate_location_info(void) {
/* if it's a swap partition, we just write the disk to /sys/power/resume */
if (streq(type, "partition")) {
- r = write_string_file("/sys/power/resume", device, 0);
+ r = write_string_file("/sys/power/resume", device, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_debug_errno(r, "Faileed to write partitoin device to /sys/power/resume: %m");
@@ -80,12 +80,12 @@ static int write_hibernate_location_info(void) {
offset = fiemap->fm_extents[0].fe_physical / page_size();
xsprintf(offset_str, "%" PRIu64, offset);
- r = write_string_file("/sys/power/resume_offset", offset_str, 0);
+ r = write_string_file("/sys/power/resume_offset", offset_str, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_debug_errno(r, "Failed to write offset '%s': %m", offset_str);
xsprintf(device_str, "%lx", (unsigned long)stb.st_dev);
- r = write_string_file("/sys/power/resume", device_str, 0);
+ r = write_string_file("/sys/power/resume", device_str, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_debug_errno(r, "Failed to write device '%s': %m", device_str);
@@ -99,7 +99,7 @@ static int write_mode(char **modes) {
STRV_FOREACH(mode, modes) {
int k;
- k = write_string_file("/sys/power/disk", *mode, 0);
+ k = write_string_file("/sys/power/disk", *mode, WRITE_STRING_FILE_DISABLE_BUFFER);
if (k >= 0)
return 0;
@@ -118,7 +118,7 @@ static int write_state(FILE **f, char **states) {
STRV_FOREACH(state, states) {
int k;
- k = write_string_stream(*f, *state, 0);
+ k = write_string_stream(*f, *state, WRITE_STRING_FILE_DISABLE_BUFFER);
if (k >= 0)
return 0;
log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m", *state);
@@ -155,6 +155,8 @@ static int execute(char **modes, char **states) {
if (!f)
return log_error_errno(errno, "Failed to open /sys/power/state: %m");
+ setvbuf(f, NULL, _IONBF, 0);
+
/* Configure the hibernation mode */
if (!strv_isempty(modes)) {
r = write_hibernate_location_info();
@@ -211,7 +213,7 @@ static int rtc_write_wake_alarm(uint64_t sec) {
xsprintf(buf, "%" PRIu64, sec);
- r = write_string_file("/sys/class/rtc/rtc0/wakealarm", buf, 0);
+ r = write_string_file("/sys/class/rtc/rtc0/wakealarm", buf, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_error_errno(r, "Failed to write '%s' to /sys/class/rtc/rtc0/wakealarm: %m", buf);
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
index dde0aaf781..e0c967efc5 100644
--- a/src/systemd/meson.build
+++ b/src/systemd/meson.build
@@ -65,11 +65,11 @@ if cxx.found()
endif
endif
-foreach header : _systemd_headers + _not_installed_headers
+foreach header : _systemd_headers + _not_installed_headers + ['../libudev/libudev.h']
foreach opt : opts
- name = ''.join([header, ':'] + opt)
+ name = ''.join(['cc-', header.split('/')[-1], ':'] + opt)
if want_tests != 'false'
- test('cc-' + name,
+ test(name,
check_compilation_sh,
args : cc.cmd_array() + ['-c', '-x'] + opt +
['-Werror', '-include',
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index c38eb84beb..b15cade20a 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -143,6 +143,8 @@ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret);
int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback);
int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
+int sd_event_source_get_floating(sd_event_source *s);
+int sd_event_source_set_floating(sd_event_source *s, int b);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index d650794cc0..a3e5cd6be6 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -109,10 +109,12 @@ typedef struct sd_lldp sd_lldp;
typedef struct sd_lldp_neighbor sd_lldp_neighbor;
typedef enum sd_lldp_event {
- SD_LLDP_EVENT_ADDED = 'a',
- SD_LLDP_EVENT_REMOVED = 'r',
- SD_LLDP_EVENT_UPDATED = 'u',
- SD_LLDP_EVENT_REFRESHED = 'f',
+ SD_LLDP_EVENT_ADDED,
+ SD_LLDP_EVENT_REMOVED,
+ SD_LLDP_EVENT_UPDATED,
+ SD_LLDP_EVENT_REFRESHED,
+ _SD_LLDP_EVENT_MAX,
+ _SD_LLDP_EVENT_INVALID = -1,
} sd_lldp_event;
typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata);
diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h
index 6b6249ca03..d1bee343a2 100644
--- a/src/systemd/sd-ndisc.h
+++ b/src/systemd/sd-ndisc.h
@@ -55,8 +55,10 @@ typedef struct sd_ndisc sd_ndisc;
typedef struct sd_ndisc_router sd_ndisc_router;
typedef enum sd_ndisc_event {
- SD_NDISC_EVENT_TIMEOUT = 't',
- SD_NDISC_EVENT_ROUTER = 'r',
+ SD_NDISC_EVENT_TIMEOUT,
+ SD_NDISC_EVENT_ROUTER,
+ _SD_NDISC_EVENT_MAX,
+ _SD_NDISC_EVENT_INVALID = -1,
} sd_ndisc_event;
typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata);
diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h
index 5695119b40..089fcdee37 100644
--- a/src/systemd/sd-resolve.h
+++ b/src/systemd/sd-resolve.h
@@ -42,6 +42,7 @@ typedef struct sd_resolve_query sd_resolve_query;
/* A callback on completion */
typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata);
typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata);
+typedef void (*sd_resolve_destroy_t)(void *userdata);
enum {
SD_RESOLVE_GET_HOST = 1 << 0,
@@ -108,6 +109,10 @@ int sd_resolve_query_is_done(sd_resolve_query*q);
void *sd_resolve_query_get_userdata(sd_resolve_query *q);
void *sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata);
+int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback);
+int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback);
+int sd_resolve_query_get_floating(sd_resolve_query *q);
+int sd_resolve_query_set_floating(sd_resolve_query *q, int b);
sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q);
diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c
index ffd6da80fe..23b06be19b 100644
--- a/src/test/test-ask-password-api.c
+++ b/src/test/test-ask-password-api.c
@@ -3,15 +3,17 @@
#include "alloc-util.h"
#include "ask-password-api.h"
#include "log.h"
+#include "strv.h"
static void ask_password(void) {
int r;
- _cleanup_free_ char *ret;
+ _cleanup_strv_free_ char **ret = NULL;
r = ask_password_tty(-1, "hello?", "da key", 0, 0, NULL, &ret);
assert(r >= 0);
+ assert(strv_length(ret) == 1);
- log_info("Got %s", ret);
+ log_info("Got %s", *ret);
}
int main(int argc, char **argv) {
diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c
index 5b6e87bf5a..75c3e305c3 100644
--- a/src/test/test-in-addr-util.c
+++ b/src/test/test-in-addr-util.c
@@ -4,12 +4,12 @@
#include "in-addr-util.h"
-static void test_in_addr_prefix_from_string(const char *p, int family, int ret, const union in_addr_union *u, unsigned char prefixlen) {
+static void test_in_addr_prefix_from_string(const char *p, int family, int ret, const union in_addr_union *u, unsigned char prefixlen, bool use_default) {
union in_addr_union q;
unsigned char l;
int r;
- r = in_addr_prefix_from_string(p, family, &q, &l);
+ r = in_addr_prefix_from_string_internal(p, use_default, family, &q, &l);
assert_se(r == ret);
if (r >= 0) {
@@ -18,7 +18,7 @@ static void test_in_addr_prefix_from_string(const char *p, int family, int ret,
assert_se(in_addr_equal(family, &q, u));
assert_se(l == prefixlen);
- r = in_addr_prefix_from_string_auto(p, &f, &q, &l);
+ r = in_addr_prefix_from_string_auto_internal(p, use_default, &f, &q, &l);
assert_se(r >= 0);
assert_se(f == family);
@@ -28,31 +28,57 @@ static void test_in_addr_prefix_from_string(const char *p, int family, int ret,
}
int main(int argc, char *argv[]) {
- test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32);
- test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0);
- test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1);
- test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2);
- test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32);
- test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0);
- test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0);
- test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0);
-
- test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0);
- test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128);
- test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0);
- test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1);
- test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2);
- test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32);
- test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33);
- test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64);
- test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128);
- test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0);
- test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0);
+ test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, false);
+ test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, false);
+ test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, false);
+ test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, false);
+ test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, false);
+ test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, false);
+ test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, false);
+ test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, false);
+
+ test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, false);
+ test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, false);
+ test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, false);
+ test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, false);
+ test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, false);
+ test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, false);
+ test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, false);
+ test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, false);
+ test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, false);
+ test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, false);
+ test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, false);
+
+ test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 8, true);
+ test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, true);
+ test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, true);
+ test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, true);
+ test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, true);
+ test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, true);
+
+ test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, true);
+ test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, true);
+ test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, true);
+ test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, true);
+ test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, true);
+ test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, true);
+ test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, true);
+ test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, true);
+ test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, true);
+ test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, true);
+ test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, true);
return 0;
}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index 43f56a6c20..2b0564d8a0 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -67,11 +67,26 @@ static void test_path_is_temporary_fs(void) {
assert_se(path_is_temporary_fs("/i-dont-exist") == -ENOENT);
}
+static void test_fd_is_network_ns(void) {
+ _cleanup_close_ int fd = -1;
+ assert_se(fd_is_network_ns(STDIN_FILENO) == 0);
+ assert_se(fd_is_network_ns(STDERR_FILENO) == 0);
+ assert_se(fd_is_network_ns(STDOUT_FILENO) == 0);
+
+ assert_se((fd = open("/proc/self/ns/mnt", O_CLOEXEC|O_RDONLY)) >= 0);
+ assert_se(IN_SET(fd_is_network_ns(fd), 0, -EUCLEAN));
+ fd = safe_close(fd);
+
+ assert_se((fd = open("/proc/self/ns/net", O_CLOEXEC|O_RDONLY)) >= 0);
+ assert_se(IN_SET(fd_is_network_ns(fd), 1, -EUCLEAN));
+}
+
int main(int argc, char *argv[]) {
test_files_same();
test_is_symlink();
test_path_is_fs_type();
test_path_is_temporary_fs();
+ test_fd_is_network_ns();
return 0;
}
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
index 00051eb434..2ec2ade3f1 100644
--- a/src/test/test-time-util.c
+++ b/src/test/test-time-util.c
@@ -39,6 +39,14 @@ static void test_parse_sec(void) {
assert_se(u == USEC_INFINITY);
assert_se(parse_sec("+3.1s", &u) >= 0);
assert_se(u == 3100 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1s.2", &u) >= 0);
+ assert_se(u == 3300 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1 .2", &u) >= 0);
+ assert_se(u == 3300 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1 sec .2 sec", &u) >= 0);
+ assert_se(u == 3300 * USEC_PER_MSEC);
+ assert_se(parse_sec("3.1 sec 1.2 sec", &u) >= 0);
+ assert_se(u == 4300 * USEC_PER_MSEC);
assert_se(parse_sec(" xyz ", &u) < 0);
assert_se(parse_sec("", &u) < 0);
@@ -56,6 +64,10 @@ static void test_parse_sec(void) {
assert_se(parse_sec("3.+1s", &u) < 0);
assert_se(parse_sec("3. 1s", &u) < 0);
assert_se(parse_sec("3.s", &u) < 0);
+ assert_se(parse_sec("12.34.56", &u) < 0);
+ assert_se(parse_sec("12..34", &u) < 0);
+ assert_se(parse_sec("..1234", &u) < 0);
+ assert_se(parse_sec("1234..", &u) < 0);
}
static void test_parse_sec_fix_0(void) {
@@ -97,7 +109,7 @@ static void test_parse_time(void) {
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_time("11111111111111y", &u, 1) == -ERANGE);
- assert_se(parse_time("1.1111111111111y", &u, 1) == -ERANGE);
+ assert_se(parse_time("1.1111111111111y", &u, 1) >= 0);
}
static void test_parse_nsec(void) {
@@ -129,6 +141,14 @@ static void test_parse_nsec(void) {
assert_se(u == NSEC_INFINITY);
assert_se(parse_nsec("+3.1s", &u) >= 0);
assert_se(u == 3100 * NSEC_PER_MSEC);
+ assert_se(parse_nsec("3.1s.2", &u) >= 0);
+ assert_se(u == 3100 * NSEC_PER_MSEC);
+ assert_se(parse_nsec("3.1 .2s", &u) >= 0);
+ assert_se(u == 200 * NSEC_PER_MSEC + 3);
+ assert_se(parse_nsec("3.1 sec .2 sec", &u) >= 0);
+ assert_se(u == 3300 * NSEC_PER_MSEC);
+ assert_se(parse_nsec("3.1 sec 1.2 sec", &u) >= 0);
+ assert_se(u == 4300 * NSEC_PER_MSEC);
assert_se(parse_nsec(" xyz ", &u) < 0);
assert_se(parse_nsec("", &u) < 0);
@@ -148,8 +168,12 @@ static void test_parse_nsec(void) {
assert_se(parse_nsec("3.+1s", &u) < 0);
assert_se(parse_nsec("3. 1s", &u) < 0);
assert_se(parse_nsec("3.s", &u) < 0);
+ assert_se(parse_nsec("12.34.56", &u) < 0);
+ assert_se(parse_nsec("12..34", &u) < 0);
+ assert_se(parse_nsec("..1234", &u) < 0);
+ assert_se(parse_nsec("1234..", &u) < 0);
assert_se(parse_nsec("1111111111111y", &u) == -ERANGE);
- assert_se(parse_nsec("1.111111111111y", &u) == -ERANGE);
+ assert_se(parse_nsec("1.111111111111y", &u) >= 0);
}
static void test_format_timespan_one(usec_t x, usec_t accuracy) {
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 1285117c32..e972b56b2c 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -11,6 +11,7 @@
#include <sys/signalfd.h>
#include <unistd.h>
+#include "device-private.h"
#include "fs-util.h"
#include "log.h"
#include "missing.h"
@@ -52,10 +53,11 @@ static int fake_filesystems(void) {
}
int main(int argc, char *argv[]) {
- _cleanup_(udev_event_freep) struct udev_event *event = NULL;
- _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
_cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
- const char *devpath, *action;
+ _cleanup_(udev_event_freep) struct udev_event *event = NULL;
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ const char *devpath, *devname, *action;
+ int r;
test_setup_logging(LOG_INFO);
@@ -76,31 +78,35 @@ int main(int argc, char *argv[]) {
rules = udev_rules_new(1);
const char *syspath = strjoina("/sys", devpath);
- dev = udev_device_new_from_synthetic_event(NULL, syspath, action);
- if (!dev) {
- log_debug("unknown device '%s'", devpath);
+ r = device_new_from_synthetic_event(&dev, syspath, action);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to open device '%s'", devpath);
goto out;
}
- assert_se(event = udev_event_new(dev));
+ assert_se(event = udev_event_new(dev, 0, NULL));
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
/* do what devtmpfs usually provides us */
- if (udev_device_get_devnode(dev)) {
+ if (sd_device_get_devname(dev, &devname) >= 0) {
+ const char *subsystem;
mode_t mode = 0600;
- if (streq(udev_device_get_subsystem(dev), "block"))
+ if (sd_device_get_subsystem(dev, &subsystem) >= 0 && streq(subsystem, "block"))
mode |= S_IFBLK;
else
mode |= S_IFCHR;
if (!streq(action, "remove")) {
- (void) mkdir_parents_label(udev_device_get_devnode(dev), 0755);
- assert_se(mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev)) == 0);
+ dev_t devnum = makedev(0, 0);
+
+ (void) mkdir_parents_label(devname, 0755);
+ (void) sd_device_get_devnum(dev, &devnum);
+ assert_se(mknod(devname, mode, devnum) == 0);
} else {
- assert_se(unlink(udev_device_get_devnode(dev)) == 0);
- (void) rmdir_parents(udev_device_get_devnode(dev), "/");
+ assert_se(unlink(devname) == 0);
+ (void) rmdir_parents(devname, "/");
}
}
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 088abecb7d..ba2e1d37f0 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -350,7 +350,6 @@ static int parse_password(const char *filename, char **wall) {
if (arg_plymouth)
r = ask_password_plymouth(message, not_after, accept_cached ? ASK_PASSWORD_ACCEPT_CACHED : 0, filename, &passwords);
else {
- char *password = NULL;
int tty_fd = -1;
if (arg_console) {
@@ -368,18 +367,12 @@ static int parse_password(const char *filename, char **wall) {
r = ask_password_tty(tty_fd, message, NULL, not_after,
(echo ? ASK_PASSWORD_ECHO : 0) |
(arg_console ? ASK_PASSWORD_CONSOLE_COLOR : 0),
- filename, &password);
+ filename, &passwords);
if (arg_console) {
tty_fd = safe_close(tty_fd);
release_terminal();
}
-
- if (r >= 0)
- r = strv_push(&passwords, password);
-
- if (r < 0)
- string_free_erase(password);
}
/* If the query went away, that's OK */
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index a0f6a5daa4..c1d0b3662b 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -16,7 +16,7 @@
#include "device-util.h"
#include "fd-util.h"
#include "format-util.h"
-#include "libudev-device-internal.h"
+#include "libudev-private.h"
#include "netlink-util.h"
#include "path-util.h"
#include "process-util.h"
@@ -42,7 +42,7 @@ typedef struct Spawn {
size_t result_len;
} Spawn;
-struct udev_event *udev_event_new(struct udev_device *dev) {
+struct udev_event *udev_event_new(sd_device *dev, int exec_delay, sd_netlink *rtnl) {
struct udev_event *event;
assert(dev);
@@ -52,8 +52,10 @@ struct udev_event *udev_event_new(struct udev_device *dev) {
return NULL;
*event = (struct udev_event) {
- .dev = dev,
+ .dev = sd_device_ref(dev),
.birth_usec = now(CLOCK_MONOTONIC),
+ .exec_delay = exec_delay,
+ .rtnl = sd_netlink_ref(rtnl),
};
return event;
@@ -65,6 +67,8 @@ struct udev_event *udev_event_free(struct udev_event *event) {
if (!event)
return NULL;
+ sd_device_unref(event->dev);
+ sd_device_unref(event->dev_db_clone);
sd_netlink_unref(event->rtnl);
while ((p = hashmap_steal_first_key(event->run_list)))
free(p);
@@ -125,7 +129,7 @@ static const struct subst_map_entry map[] = {
static ssize_t subst_format_var(struct udev_event *event,
const struct subst_map_entry *entry, char *attr,
char *dest, size_t l) {
- sd_device *parent, *dev = event->dev->device;
+ sd_device *parent, *dev = event->dev;
const char *val = NULL;
char *s = dest;
dev_t devnum;
@@ -155,7 +159,7 @@ static ssize_t subst_format_var(struct udev_event *event,
case SUBST_ID:
if (!event->dev_parent)
return 0;
- r = sd_device_get_sysname(event->dev_parent->device, &val);
+ r = sd_device_get_sysname(event->dev_parent, &val);
if (r < 0)
return r;
l = strpcpy(&s, l, val);
@@ -163,7 +167,7 @@ static ssize_t subst_format_var(struct udev_event *event,
case SUBST_DRIVER:
if (!event->dev_parent)
return 0;
- r = sd_device_get_driver(event->dev_parent->device, &val);
+ r = sd_device_get_driver(event->dev_parent, &val);
if (r < 0)
return r == -ENOENT ? 0 : r;
l = strpcpy(&s, l, val);
@@ -236,8 +240,8 @@ static ssize_t subst_format_var(struct udev_event *event,
(void) sd_device_get_sysattr_value(dev, attr, &val);
/* try to read the attribute of the parent device, other matches have selected */
- if (!val && event->dev_parent && event->dev_parent->device != dev)
- (void) sd_device_get_sysattr_value(event->dev_parent->device, attr, &val);
+ if (!val && event->dev_parent && event->dev_parent != dev)
+ (void) sd_device_get_sysattr_value(event->dev_parent, attr, &val);
if (!val)
return 0;
@@ -402,9 +406,9 @@ subst:
subst_len = subst_format_var(event, entry, attr, s, l);
if (subst_len < 0) {
if (format_dollar)
- log_device_warning_errno(event->dev->device, subst_len, "Failed to substitute variable '$%s', ignoring: %m", entry->name);
+ log_device_warning_errno(event->dev, subst_len, "Failed to substitute variable '$%s', ignoring: %m", entry->name);
else
- log_device_warning_errno(event->dev->device, subst_len, "Failed to apply format '%%%c', ignoring: %m", entry->fmt);
+ log_device_warning_errno(event->dev, subst_len, "Failed to apply format '%%%c', ignoring: %m", entry->fmt);
continue;
}
@@ -636,9 +640,9 @@ int udev_event_spawn(struct udev_event *event,
free_and_replace(argv[0], program);
}
- r = device_get_properties_strv(event->dev->device, &envp);
+ r = device_get_properties_strv(event->dev, &envp);
if (r < 0)
- return log_device_error_errno(event->dev->device, r, "Failed to get device properties");
+ return log_device_error_errno(event->dev, r, "Failed to get device properties");
log_debug("Starting '%s'", cmd);
@@ -682,7 +686,7 @@ int udev_event_spawn(struct udev_event *event,
}
static int rename_netif(struct udev_event *event) {
- sd_device *dev = event->dev->device;
+ sd_device *dev = event->dev;
const char *action, *oldname;
char name[IFNAMSIZ];
int ifindex, r;
@@ -725,7 +729,7 @@ static int rename_netif(struct udev_event *event) {
}
static int update_devnode(struct udev_event *event) {
- sd_device *dev = event->dev->device;
+ sd_device *dev = event->dev;
const char *action;
bool apply;
int r;
@@ -737,8 +741,8 @@ static int update_devnode(struct udev_event *event) {
return log_device_error_errno(dev, r, "Failed to get devnum: %m");
/* remove/update possible left-over symlinks from old database entry */
- if (event->dev_db)
- (void) udev_node_update_old_links(dev, event->dev_db->device);
+ if (event->dev_db_clone)
+ (void) udev_node_update_old_links(dev, event->dev_db_clone);
if (!event->owner_set) {
r = device_get_devnode_uid(dev, &event->uid);
@@ -780,7 +784,7 @@ static void event_execute_rules_on_remove(
Hashmap *properties_list,
struct udev_rules *rules) {
- sd_device *dev = event->dev->device;
+ sd_device *dev = event->dev;
int r;
r = device_read_db_force(dev);
@@ -810,8 +814,7 @@ int udev_event_execute_rules(struct udev_event *event,
usec_t timeout_usec, usec_t timeout_warn_usec,
Hashmap *properties_list,
struct udev_rules *rules) {
- _cleanup_(sd_device_unrefp) sd_device *clone = NULL;
- sd_device *dev = event->dev->device;
+ sd_device *dev = event->dev;
const char *subsystem, *action;
int r;
@@ -831,28 +834,24 @@ int udev_event_execute_rules(struct udev_event *event,
return 0;
}
- r = device_clone_with_db(dev, &clone);
+ r = device_clone_with_db(dev, &event->dev_db_clone);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to clone sd_device object, ignoring: %m");
- if (clone) {
- event->dev_db = udev_device_new(NULL, clone);
- if (!event->dev_db)
- return -ENOMEM;
-
+ if (event->dev_db_clone) {
r = sd_device_get_devnum(dev, NULL);
if (r < 0) {
if (r != -ENOENT)
log_device_debug_errno(dev, r, "Failed to get devnum, ignoring: %m");
if (streq(action, "move")) {
- r = device_copy_properties(dev, clone);
+ r = device_copy_properties(dev, event->dev_db_clone);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to copy properties from cloned device, ignoring: %m");
}
} else
/* Disable watch during event processing. */
- (void) udev_watch_end(clone);
+ (void) udev_watch_end(event->dev_db_clone);
}
(void) udev_rules_apply_to_event(rules, event,
@@ -863,12 +862,12 @@ int udev_event_execute_rules(struct udev_event *event,
(void) update_devnode(event);
/* preserve old, or get new initialization timestamp */
- r = device_ensure_usec_initialized(dev, clone);
+ r = device_ensure_usec_initialized(dev, event->dev_db_clone);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to set initialization timestamp, ignoring: %m");
/* (re)write database file */
- r = device_tag_index(dev, clone, true);
+ r = device_tag_index(dev, event->dev_db_clone, true);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/, ignoring: %m");
@@ -878,7 +877,7 @@ int udev_event_execute_rules(struct udev_event *event,
device_set_is_initialized(dev);
- event->dev_db = udev_device_unref(event->dev_db);
+ event->dev_db_clone = sd_device_unref(event->dev_db_clone);
return 0;
}
@@ -895,7 +894,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
udev_event_apply_format(event, cmd, command, sizeof(command), false);
if (builtin_cmd >= 0 && builtin_cmd < _UDEV_BUILTIN_MAX)
- udev_builtin_run(event->dev->device, builtin_cmd, command, false);
+ udev_builtin_run(event->dev, builtin_cmd, command, false);
else {
if (event->exec_delay > 0) {
log_debug("delay execution of '%s'", command);
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 46445eda6a..94bebd69c7 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -73,6 +73,8 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
} while (r == -ENOENT);
if (r == 0)
return 0;
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink);
}
log_device_debug(dev, "Atomically replace '%s'", slink);
@@ -211,10 +213,8 @@ static int link_update(sd_device *dev, const char *slink, bool add) {
log_device_debug(dev, "No reference left, removing '%s'", slink);
if (unlink(slink) == 0)
(void) rmdir_parents(slink, "/");
- } else {
- log_device_debug(dev, "Creating link '%s' to '%s'", slink, target);
+ } else
(void) node_symlink(dev, target, slink);
- }
if (add)
do {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 7703e867f8..ad4b32abea 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -16,13 +16,15 @@
#include "alloc-util.h"
#include "conf-files.h"
#include "def.h"
+#include "device-private.h"
+#include "device-util.h"
#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "glob-util.h"
-#include "libudev-device-internal.h"
+#include "libudev-private.h"
#include "path-util.h"
#include "proc-cmdline.h"
#include "stat-util.h"
@@ -556,7 +558,7 @@ static gid_t add_gid(struct udev_rules *rules, const char *group) {
return gid;
}
-static int import_property_from_string(struct udev_device *dev, char *line) {
+static int import_property_from_string(sd_device *dev, char *line) {
char *key;
char *val;
size_t len;
@@ -568,12 +570,12 @@ static int import_property_from_string(struct udev_device *dev, char *line) {
/* comment or empty line */
if (IN_SET(key[0], '#', '\0'))
- return -1;
+ return 0;
/* split key/value */
val = strchr(key, '=');
- if (val == NULL)
- return -1;
+ if (!val)
+ return -EINVAL;
val[0] = '\0';
val++;
@@ -584,7 +586,7 @@ static int import_property_from_string(struct udev_device *dev, char *line) {
/* terminate key */
len = strlen(key);
if (len == 0)
- return -1;
+ return -EINVAL;
while (isspace(key[len-1]))
len--;
key[len] = '\0';
@@ -592,30 +594,28 @@ static int import_property_from_string(struct udev_device *dev, char *line) {
/* terminate value */
len = strlen(val);
if (len == 0)
- return -1;
+ return -EINVAL;
while (isspace(val[len-1]))
len--;
val[len] = '\0';
if (len == 0)
- return -1;
+ return -EINVAL;
/* unquote */
if (IN_SET(val[0], '"', '\'')) {
if (len == 1 || val[len-1] != val[0]) {
log_debug("inconsistent quoting: '%s', skip", line);
- return -1;
+ return -EINVAL;
}
val[len-1] = '\0';
val++;
}
- udev_device_add_property(dev, key, val);
-
- return 0;
+ return device_add_property(dev, key, val);
}
-static int import_file_into_properties(struct udev_device *dev, const char *filename) {
+static int import_file_into_properties(sd_device *dev, const char *filename) {
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -665,24 +665,21 @@ static int import_program_into_properties(struct udev_event *event,
return 0;
}
-static int import_parent_into_properties(struct udev_device *dev, const char *filter) {
- struct udev_device *dev_parent;
- struct udev_list_entry *list_entry;
+static int import_parent_into_properties(sd_device *dev, const char *filter) {
+ const char *key, *val;
+ sd_device *parent;
+ int r;
assert(dev);
assert(filter);
- dev_parent = udev_device_get_parent(dev);
- if (dev_parent == NULL)
- return -1;
-
- udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) {
- const char *key = udev_list_entry_get_name(list_entry);
- const char *val = udev_list_entry_get_value(list_entry);
+ r = sd_device_get_parent(dev, &parent);
+ if (r < 0)
+ return r;
+ FOREACH_DEVICE_PROPERTY(parent, key, val)
if (fnmatch(filter, key, 0) == 0)
- udev_device_add_property(dev, key, val);
- }
+ device_add_property(dev, key, val);
return 0;
}
@@ -1517,16 +1514,17 @@ static int parse_file(struct udev_rules *rules, const char *filename) {
struct udev_rules *udev_rules_new(int resolve_names) {
struct udev_rules *rules;
- struct udev_list file_list;
struct token end_token;
char **files, **f;
int r;
- rules = new0(struct udev_rules, 1);
- if (rules == NULL)
+ rules = new(struct udev_rules, 1);
+ if (!rules)
return NULL;
- rules->resolve_names = resolve_names;
- udev_list_init(NULL, &file_list, true);
+
+ *rules = (struct udev_rules) {
+ .resolve_names = resolve_names,
+ };
/* init token array and string buffer */
rules->tokens = malloc_multiply(PREALLOC_TOKEN, sizeof(struct token));
@@ -1672,11 +1670,9 @@ static int match_key(struct udev_rules *rules, struct token *token, const char *
return -1;
}
-static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct udev_event *event, struct token *cur) {
- const char *name;
- char nbuf[UTIL_NAME_SIZE];
- const char *value;
- char vbuf[UTIL_NAME_SIZE];
+static int match_attr(struct udev_rules *rules, sd_device *dev, struct udev_event *event, struct token *cur) {
+ char nbuf[UTIL_NAME_SIZE], vbuf[UTIL_NAME_SIZE];
+ const char *name, *value;
size_t len;
name = rules_str(rules, cur->key.attr_off);
@@ -1686,8 +1682,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct
name = nbuf;
_fallthrough_;
case SB_NONE:
- value = udev_device_get_sysattr_value(dev, name);
- if (value == NULL)
+ if (sd_device_get_sysattr_value(dev, name, &value) < 0)
return -1;
break;
case SB_SUBSYS:
@@ -1732,18 +1727,23 @@ int udev_rules_apply_to_event(
usec_t timeout_usec,
usec_t timeout_warn_usec,
Hashmap *properties_list) {
- struct token *cur;
- struct token *rule;
+ sd_device *dev = event->dev;
enum escape_type esc = ESCAPE_UNSET;
+ struct token *cur, *rule;
+ const char *action, *val;
bool can_set_name;
int r;
if (!rules->tokens)
return 0;
- can_set_name = ((!streq(udev_device_get_action(event->dev), "remove")) &&
- (major(udev_device_get_devnum(event->dev)) > 0 ||
- udev_device_get_ifindex(event->dev) > 0));
+ r = sd_device_get_property_value(dev, "ACTION", &action);
+ if (r < 0)
+ return r;
+
+ can_set_name = (!streq(action, "remove") &&
+ (sd_device_get_devnum(dev, NULL) >= 0 ||
+ sd_device_get_ifindex(dev, NULL) >= 0));
/* loop through token list, match, run actions or forward to next rule */
cur = &rules->tokens[0];
@@ -1760,30 +1760,31 @@ int udev_rules_apply_to_event(
esc = ESCAPE_UNSET;
break;
case TK_M_ACTION:
- if (match_key(rules, cur, udev_device_get_action(event->dev)) != 0)
+ if (match_key(rules, cur, action) != 0)
goto nomatch;
break;
case TK_M_DEVPATH:
- if (match_key(rules, cur, udev_device_get_devpath(event->dev)) != 0)
+ if (sd_device_get_devpath(dev, &val) < 0)
+ goto nomatch;
+ if (match_key(rules, cur, val) != 0)
goto nomatch;
break;
case TK_M_KERNEL:
- if (match_key(rules, cur, udev_device_get_sysname(event->dev)) != 0)
+ if (sd_device_get_sysname(dev, &val) < 0)
+ goto nomatch;
+ if (match_key(rules, cur, val) != 0)
goto nomatch;
break;
case TK_M_DEVLINK: {
- struct udev_list_entry *list_entry;
+ const char *devlink;
bool match = false;
- udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) {
- const char *devlink;
-
- devlink = udev_list_entry_get_name(list_entry) + STRLEN("/dev/");
- if (match_key(rules, cur, devlink) == 0) {
+ FOREACH_DEVICE_DEVLINK(dev, devlink)
+ if (match_key(rules, cur, devlink + STRLEN("/dev/")) == 0) {
match = true;
break;
}
- }
+
if (!match)
goto nomatch;
break;
@@ -1794,43 +1795,48 @@ int udev_rules_apply_to_event(
break;
case TK_M_ENV: {
const char *key_name = rules_str(rules, cur->key.attr_off);
- const char *value;
-
- value = udev_device_get_property_value(event->dev, key_name);
- /* check global properties */
- if (!value && properties_list)
- value = hashmap_get(properties_list, key_name);
+ if (sd_device_get_property_value(dev, key_name, &val) < 0) {
+ /* check global properties */
+ if (properties_list)
+ val = hashmap_get(properties_list, key_name);
+ else
+ val = NULL;
+ }
- if (match_key(rules, cur, strempty(value)))
+ if (match_key(rules, cur, strempty(val)))
goto nomatch;
break;
}
case TK_M_TAG: {
- struct udev_list_entry *list_entry;
bool match = false;
+ const char *tag;
- udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(event->dev)) {
- if (streq(rules_str(rules, cur->key.value_off), udev_list_entry_get_name(list_entry))) {
+ FOREACH_DEVICE_TAG(dev, tag)
+ if (streq(rules_str(rules, cur->key.value_off), tag)) {
match = true;
break;
}
- }
+
if ((!match && (cur->key.op != OP_NOMATCH)) ||
(match && (cur->key.op == OP_NOMATCH)))
goto nomatch;
break;
}
case TK_M_SUBSYSTEM:
- if (match_key(rules, cur, udev_device_get_subsystem(event->dev)) != 0)
+ if (sd_device_get_subsystem(dev, &val) < 0)
+ goto nomatch;
+ if (match_key(rules, cur, val) != 0)
goto nomatch;
break;
case TK_M_DRIVER:
- if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0)
+ if (sd_device_get_driver(dev, &val) < 0)
+ goto nomatch;
+ if (match_key(rules, cur, val) != 0)
goto nomatch;
break;
case TK_M_ATTR:
- if (match_attr(rules, event->dev, event, cur) != 0)
+ if (match_attr(rules, dev, event, cur) != 0)
goto nomatch;
break;
case TK_M_SYSCTL: {
@@ -1863,7 +1869,7 @@ int udev_rules_apply_to_event(
next++;
/* loop over parents */
- event->dev_parent = event->dev;
+ event->dev_parent = dev;
for (;;) {
struct token *key;
@@ -1872,15 +1878,21 @@ int udev_rules_apply_to_event(
dump_token(rules, key);
switch(key->type) {
case TK_M_KERNELS:
- if (match_key(rules, key, udev_device_get_sysname(event->dev_parent)) != 0)
+ if (sd_device_get_sysname(event->dev_parent, &val) < 0)
+ goto try_parent;
+ if (match_key(rules, key, val) != 0)
goto try_parent;
break;
case TK_M_SUBSYSTEMS:
- if (match_key(rules, key, udev_device_get_subsystem(event->dev_parent)) != 0)
+ if (sd_device_get_subsystem(event->dev_parent, &val) < 0)
+ goto try_parent;
+ if (match_key(rules, key, val) != 0)
goto try_parent;
break;
case TK_M_DRIVERS:
- if (match_key(rules, key, udev_device_get_driver(event->dev_parent)) != 0)
+ if (sd_device_get_driver(event->dev_parent, &val) < 0)
+ goto try_parent;
+ if (match_key(rules, key, val) != 0)
goto try_parent;
break;
case TK_M_ATTRS:
@@ -1888,7 +1900,7 @@ int udev_rules_apply_to_event(
goto try_parent;
break;
case TK_M_TAGS: {
- bool match = udev_device_has_tag(event->dev_parent, rules_str(rules, cur->key.value_off));
+ bool match = sd_device_has_tag(event->dev_parent, rules_str(rules, cur->key.value_off));
if (match && key->key.op == OP_NOMATCH)
goto try_parent;
@@ -1903,9 +1915,10 @@ int udev_rules_apply_to_event(
break;
try_parent:
- event->dev_parent = udev_device_get_parent(event->dev_parent);
- if (event->dev_parent == NULL)
+ if (sd_device_get_parent(event->dev_parent, &event->dev_parent) < 0) {
+ event->dev_parent = NULL;
goto nomatch;
+ }
}
/* move behind our sequence of parent match keys */
cur = next;
@@ -1921,9 +1934,11 @@ int udev_rules_apply_to_event(
if (filename[0] != '/') {
char tmp[UTIL_PATH_SIZE];
+ if (sd_device_get_syspath(dev, &val) < 0)
+ goto nomatch;
+
strscpy(tmp, sizeof(tmp), filename);
- strscpyl(filename, sizeof(filename),
- udev_device_get_syspath(event->dev), "/", tmp, NULL);
+ strscpyl(filename, sizeof(filename), val, "/", tmp, NULL);
}
}
attr_subst_subdir(filename, sizeof(filename));
@@ -1938,8 +1953,7 @@ int udev_rules_apply_to_event(
break;
}
case TK_M_PROGRAM: {
- char program[UTIL_PATH_SIZE];
- char result[UTIL_LINE_SIZE];
+ char program[UTIL_PATH_SIZE], result[UTIL_LINE_SIZE];
event->program_result = mfree(event->program_result);
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program), false);
@@ -1970,7 +1984,7 @@ int udev_rules_apply_to_event(
char import[UTIL_PATH_SIZE];
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
- if (import_file_into_properties(event->dev, import) != 0)
+ if (import_file_into_properties(dev, import) != 0)
if (cur->key.op != OP_NOMATCH)
goto nomatch;
break;
@@ -2015,7 +2029,7 @@ int udev_rules_apply_to_event(
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
- r = udev_builtin_run(event->dev->device, cur->key.builtin_cmd, command, false);
+ r = udev_builtin_run(dev, cur->key.builtin_cmd, command, false);
if (r < 0) {
/* remember failure */
log_debug_errno(r, "IMPORT builtin '%s' fails: %m",
@@ -2027,16 +2041,13 @@ int udev_rules_apply_to_event(
break;
}
case TK_M_IMPORT_DB: {
- const char *key = rules_str(rules, cur->key.value_off);
- const char *value;
+ const char *key;
- value = udev_device_get_property_value(event->dev_db, key);
- if (value != NULL)
- udev_device_add_property(event->dev, key, value);
- else {
- if (cur->key.op != OP_NOMATCH)
- goto nomatch;
- }
+ key = rules_str(rules, cur->key.value_off);
+ if (sd_device_get_property_value(event->dev_db_clone, key, &val) >= 0)
+ device_add_property(dev, key, val);
+ else if (cur->key.op != OP_NOMATCH)
+ goto nomatch;
break;
}
case TK_M_IMPORT_CMDLINE: {
@@ -2045,7 +2056,6 @@ int udev_rules_apply_to_event(
const char *key;
key = rules_str(rules, cur->key.value_off);
-
r = proc_cmdline_get_key(key, PROC_CMDLINE_VALUE_OPTIONAL, &value);
if (r < 0)
log_debug_errno(r, "Failed to read %s from /proc/cmdline, ignoring: %m", key);
@@ -2053,10 +2063,10 @@ int udev_rules_apply_to_event(
imported = true;
if (value)
- udev_device_add_property(event->dev, key, value);
+ device_add_property(dev, key, value);
else
/* we import simple flags as 'FLAG=1' */
- udev_device_add_property(event->dev, key, "1");
+ device_add_property(dev, key, "1");
}
if (!imported && cur->key.op != OP_NOMATCH)
@@ -2067,7 +2077,7 @@ int udev_rules_apply_to_event(
char import[UTIL_PATH_SIZE];
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
- if (import_parent_into_properties(event->dev, import) != 0)
+ if (import_parent_into_properties(dev, import) != 0)
if (cur->key.op != OP_NOMATCH)
goto nomatch;
break;
@@ -2083,7 +2093,7 @@ int udev_rules_apply_to_event(
esc = ESCAPE_REPLACE;
break;
case TK_A_DB_PERSIST:
- udev_device_set_db_persist(event->dev);
+ device_set_db_persist(dev);
break;
case TK_A_INOTIFY_WATCH:
if (event->inotify_watch_final)
@@ -2093,7 +2103,7 @@ int udev_rules_apply_to_event(
event->inotify_watch = cur->key.watch;
break;
case TK_A_DEVLINK_PRIO:
- udev_device_set_devlink_priority(event->dev, cur->key.devlink_prio);
+ device_set_devlink_priority(dev, cur->key.devlink_prio);
break;
case TK_A_OWNER: {
char owner[UTIL_NAME_SIZE];
@@ -2138,9 +2148,8 @@ int udev_rules_apply_to_event(
break;
}
case TK_A_MODE: {
- char mode_str[UTIL_NAME_SIZE];
+ char mode_str[UTIL_NAME_SIZE], *endptr;
mode_t mode;
- char *endptr;
if (event->mode_final)
break;
@@ -2232,30 +2241,29 @@ int udev_rules_apply_to_event(
break;
}
case TK_A_ENV: {
- const char *name = rules_str(rules, cur->key.attr_off);
- char *value = rules_str(rules, cur->key.value_off);
char value_new[UTIL_NAME_SIZE];
- const char *value_old = NULL;
+ const char *name, *value_old;
- if (value[0] == '\0') {
+ name = rules_str(rules, cur->key.attr_off);
+ val = rules_str(rules, cur->key.value_off);
+ if (val[0] == '\0') {
if (cur->key.op == OP_ADD)
break;
- udev_device_add_property(event->dev, name, NULL);
+ device_add_property(dev, name, NULL);
break;
}
- if (cur->key.op == OP_ADD)
- value_old = udev_device_get_property_value(event->dev, name);
- if (value_old) {
+ if (cur->key.op == OP_ADD &&
+ sd_device_get_property_value(dev, name, &value_old) >= 0) {
char temp[UTIL_NAME_SIZE];
/* append value separated by space */
- udev_event_apply_format(event, value, temp, sizeof(temp), false);
+ udev_event_apply_format(event, val, temp, sizeof(temp), false);
strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL);
} else
- udev_event_apply_format(event, value, value_new, sizeof(value_new), false);
+ udev_event_apply_format(event, val, value_new, sizeof(value_new), false);
- udev_device_add_property(event->dev, name, value_new);
+ device_add_property(dev, name, value_new);
break;
}
case TK_A_TAG: {
@@ -2264,7 +2272,7 @@ int udev_rules_apply_to_event(
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag), false);
if (IN_SET(cur->key.op, OP_ASSIGN, OP_ASSIGN_FINAL))
- udev_device_cleanup_tags_list(event->dev);
+ device_cleanup_tags(dev);
for (p = tag; *p != '\0'; p++) {
if ((*p >= 'a' && *p <= 'z') ||
(*p >= 'A' && *p <= 'Z') ||
@@ -2275,17 +2283,17 @@ int udev_rules_apply_to_event(
break;
}
if (cur->key.op == OP_REMOVE)
- udev_device_remove_tag(event->dev, tag);
+ device_remove_tag(dev, tag);
else
- udev_device_add_tag(event->dev, tag);
+ device_add_tag(dev, tag);
break;
}
case TK_A_NAME: {
- const char *name = rules_str(rules, cur->key.value_off);
-
char name_str[UTIL_PATH_SIZE];
+ const char *name;
int count;
+ name = rules_str(rules, cur->key.value_off);
if (event->name_final)
break;
if (cur->key.op == OP_ASSIGN_FINAL)
@@ -2296,8 +2304,9 @@ int udev_rules_apply_to_event(
if (count > 0)
log_debug("%i character(s) replaced", count);
}
- if (major(udev_device_get_devnum(event->dev)) &&
- !streq(name_str, udev_device_get_devnode(event->dev) + STRLEN("/dev/"))) {
+ if (sd_device_get_devnum(dev, NULL) >= 0 &&
+ (sd_device_get_devname(dev, &val) < 0 ||
+ !streq(name_str, val + STRLEN("/dev/")))) {
log_error("NAME=\"%s\" ignored, kernel device nodes cannot be renamed; please fix it in %s:%u\n",
name,
rules_str(rules, rule->rule.filename_off),
@@ -2314,19 +2323,17 @@ int udev_rules_apply_to_event(
break;
}
case TK_A_DEVLINK: {
- char temp[UTIL_PATH_SIZE];
- char filename[UTIL_PATH_SIZE];
- char *pos, *next;
+ char temp[UTIL_PATH_SIZE], filename[UTIL_PATH_SIZE], *pos, *next;
int count = 0;
if (event->devlink_final)
break;
- if (major(udev_device_get_devnum(event->dev)) == 0)
+ if (sd_device_get_devnum(dev, NULL) < 0)
break;
if (cur->key.op == OP_ASSIGN_FINAL)
event->devlink_final = true;
if (IN_SET(cur->key.op, OP_ASSIGN, OP_ASSIGN_FINAL))
- udev_device_cleanup_devlinks_list(event->dev);
+ device_cleanup_devlinks(dev);
/* allow multiple symlinks separated by spaces */
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp), esc != ESCAPE_NONE);
@@ -2340,12 +2347,12 @@ int udev_rules_apply_to_event(
while (isspace(pos[0]))
pos++;
next = strchr(pos, ' ');
- while (next != NULL) {
+ while (next) {
next[0] = '\0';
log_debug("LINK '%s' %s:%u", pos,
rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
- udev_device_add_devlink(event->dev, filename);
+ device_add_devlink(dev, filename);
while (isspace(next[1]))
next++;
pos = &next[1];
@@ -2355,18 +2362,19 @@ int udev_rules_apply_to_event(
log_debug("LINK '%s' %s:%u", pos,
rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
- udev_device_add_devlink(event->dev, filename);
+ device_add_devlink(dev, filename);
}
break;
}
case TK_A_ATTR: {
- const char *key_name = rules_str(rules, cur->key.attr_off);
- char attr[UTIL_PATH_SIZE];
- char value[UTIL_NAME_SIZE];
+ char attr[UTIL_PATH_SIZE], value[UTIL_NAME_SIZE];
_cleanup_fclose_ FILE *f = NULL;
+ const char *key_name;
- if (util_resolve_subsys_kernel(key_name, attr, sizeof(attr), 0) != 0)
- strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
+ key_name = rules_str(rules, cur->key.attr_off);
+ if (util_resolve_subsys_kernel(key_name, attr, sizeof(attr), 0) != 0 &&
+ sd_device_get_syspath(dev, &val) >= 0)
+ strscpyl(attr, sizeof(attr), val, "/", key_name, NULL);
attr_subst_subdir(attr, sizeof(attr));
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
@@ -2381,8 +2389,7 @@ int udev_rules_apply_to_event(
break;
}
case TK_A_SYSCTL: {
- char filename[UTIL_PATH_SIZE];
- char value[UTIL_NAME_SIZE];
+ char filename[UTIL_PATH_SIZE], value[UTIL_NAME_SIZE];
udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
sysctl_normalize(filename);
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
index 4924b75c50..cf2faa0831 100644
--- a/src/udev/udev-watch.c
+++ b/src/udev/udev-watch.c
@@ -24,7 +24,7 @@ static int inotify_fd = -1;
int udev_watch_init(void) {
inotify_fd = inotify_init1(IN_CLOEXEC);
if (inotify_fd < 0)
- return log_error_errno(errno, "Failed to create inotify descriptor: %m");
+ return -errno;
return inotify_fd;
}
@@ -36,18 +36,18 @@ int udev_watch_restore(void) {
int r;
if (inotify_fd < 0)
- return log_error_errno(EINVAL, "Invalid inotify descriptor.");
+ return log_debug_errno(EINVAL, "Invalid inotify descriptor.");
if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
if (errno != ENOENT)
- return log_error_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
+ return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
return 0;
}
dir = opendir("/run/udev/watch.old");
if (!dir)
- return log_error_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
+ return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
FOREACH_DIRENT_ALL(ent, dir, break) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
@@ -58,13 +58,13 @@ int udev_watch_restore(void) {
r = readlinkat_malloc(dirfd(dir), ent->d_name, &device);
if (r < 0) {
- log_error_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
+ log_debug_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
goto unlink;
}
r = sd_device_new_from_device_id(&dev, device);
if (r < 0) {
- log_error_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device);
+ log_debug_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device);
goto unlink;
}
@@ -86,7 +86,7 @@ int udev_watch_begin(sd_device *dev) {
int wd, r;
if (inotify_fd < 0)
- return log_error_errno(EINVAL, "Invalid inotify descriptor.");
+ return log_debug_errno(EINVAL, "Invalid inotify descriptor.");
r = sd_device_get_devname(dev, &devnode);
if (r < 0)
@@ -120,13 +120,13 @@ int udev_watch_end(sd_device *dev) {
int wd, r;
if (inotify_fd < 0)
- return log_error_errno(EINVAL, "Invalid inotify descriptor.");
+ return log_debug_errno(EINVAL, "Invalid inotify descriptor.");
r = device_get_watch_handle(dev, &wd);
if (r == -ENOENT)
return 0;
if (r < 0)
- return log_device_error_errno(dev, r, "Failed to get watch handle, ignoring: %m");
+ return log_device_debug_errno(dev, r, "Failed to get watch handle, ignoring: %m");
log_device_debug(dev, "Removing watch");
(void) inotify_rm_watch(inotify_fd, wd);
@@ -147,22 +147,23 @@ int udev_watch_lookup(int wd, sd_device **ret) {
assert(ret);
if (inotify_fd < 0)
- return log_error_errno(EINVAL, "Invalid inotify descriptor.");
+ return log_debug_errno(EINVAL, "Invalid inotify descriptor.");
if (wd < 0)
- return log_error_errno(EINVAL, "Invalid watch handle.");
+ return log_debug_errno(EINVAL, "Invalid watch handle.");
xsprintf(filename, "/run/udev/watch/%d", wd);
r = readlink_malloc(filename, &device);
- if (r < 0) {
- if (r != -ENOENT)
- return log_error_errno(errno, "Failed to read link '%s': %m", filename);
+ if (r == -ENOENT)
return 0;
- }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read link '%s': %m", filename);
r = sd_device_new_from_device_id(ret, device);
+ if (r == -ENODEV)
+ return 0;
if (r < 0)
- return log_error_errno(r, "Failed to create sd_device object for '%s': %m", device);
+ return log_debug_errno(r, "Failed to create sd_device object for '%s': %m", device);
- return 0;
+ return 1;
}
diff --git a/src/udev/udev.h b/src/udev/udev.h
index f723dd7067..162859ab40 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -9,7 +9,6 @@
#include <sys/sysmacros.h>
#include <sys/types.h>
-#include "libudev.h"
#include "sd-device.h"
#include "sd-netlink.h"
@@ -21,9 +20,9 @@
#include "util.h"
struct udev_event {
- struct udev_device *dev;
- struct udev_device *dev_parent;
- struct udev_device *dev_db;
+ sd_device *dev;
+ sd_device *dev_parent;
+ sd_device *dev_db_clone;
char *name;
char *program_result;
mode_t mode;
@@ -60,7 +59,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
/* udev-event.c */
-struct udev_event *udev_event_new(struct udev_device *dev);
+struct udev_event *udev_event_new(sd_device *dev, int exec_delay, sd_netlink *rtnl);
struct udev_event *udev_event_free(struct udev_event *event);
ssize_t udev_event_apply_format(struct udev_event *event,
const char *src, char *dest, size_t size,
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 4eb2897b21..e9a1af65fc 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -80,8 +80,6 @@ static int parse_argv(int argc, char *argv[]) {
int hwdb_main(int argc, char *argv[], void *userdata) {
int r;
- log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
-
r = parse_argv(argc, argv);
if (r <= 0)
return r;
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index 20f713d738..cfaaf03db9 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -12,6 +12,10 @@
#include <sys/signalfd.h>
#include <unistd.h>
+#include "sd-device.h"
+
+#include "device-private.h"
+#include "device-util.h"
#include "string-util.h"
#include "udev-builtin.h"
#include "udev.h"
@@ -88,11 +92,10 @@ static int parse_argv(int argc, char *argv[]) {
int test_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
- _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
_cleanup_(udev_event_freep) struct udev_event *event = NULL;
- struct udev_list_entry *entry;
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ const char *cmd, *key, *value;
sigset_t mask, sigmask_orig;
- const char *cmd;
Iterator i;
void *val;
int r;
@@ -119,16 +122,16 @@ int test_main(int argc, char *argv[], void *userdata) {
goto out;
}
- dev = udev_device_new_from_synthetic_event(NULL, arg_syspath, arg_action);
- if (dev == NULL) {
- r = log_error_errno(errno, "Failed to open device '%s': %m", arg_syspath);
+ r = device_new_from_synthetic_event(&dev, arg_syspath, arg_action);
+ if (r < 0) {
+ log_error_errno(r, "Failed to open device '%s': %m", arg_syspath);
goto out;
}
/* don't read info from the db */
- udev_device_set_info_loaded(dev);
+ device_seal(dev);
- event = udev_event_new(dev);
+ event = udev_event_new(dev, 0, NULL);
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, &sigmask_orig);
@@ -138,8 +141,8 @@ int test_main(int argc, char *argv[], void *userdata) {
NULL,
rules);
- udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev))
- printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
+ FOREACH_DEVICE_PROPERTY(dev, key, value)
+ printf("%s=%s\n", key, value);
HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
char program[UTIL_PATH_SIZE];
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
index 66ed0aee59..185fe29be0 100644
--- a/src/udev/udevadm-trigger.c
+++ b/src/udev/udevadm-trigger.c
@@ -8,6 +8,7 @@
#include "device-enumerator-private.h"
#include "fd-util.h"
+#include "fileio.h"
#include "path-util.h"
#include "set.h"
#include "string-util.h"
@@ -24,7 +25,6 @@ static int exec_list(sd_device_enumerator *e, const char *action, Set *settle_se
FOREACH_DEVICE_AND_SUBSYSTEM(e, d) {
_cleanup_free_ char *filename = NULL;
- _cleanup_close_ int fd = -1;
const char *syspath;
if (sd_device_get_syspath(d, &syspath) < 0)
@@ -39,18 +39,17 @@ static int exec_list(sd_device_enumerator *e, const char *action, Set *settle_se
if (!filename)
return log_oom();
- fd = open(filename, O_WRONLY|O_CLOEXEC);
- if (fd < 0)
+ r = write_string_file(filename, action, WRITE_STRING_FILE_DISABLE_BUFFER);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to write '%s' to '%s', ignoring: %m", action, filename);
continue;
+ }
if (settle_set) {
r = set_put_strdup(settle_set, syspath);
if (r < 0)
return log_oom();
}
-
- if (write(fd, action, strlen(action)) < 0)
- log_debug_errno(errno, "Failed to write '%s' to '%s', ignoring: %m", action, filename);
}
return 0;
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index e627c50ff9..8ed679698a 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -112,6 +112,7 @@ int main(int argc, char *argv[]) {
udev_parse_config();
log_parse_environment();
log_open();
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
mac_selinux_init();
r = parse_argv(argc, argv);
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 7ec30b92c3..0757628d0d 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -86,6 +86,7 @@ typedef struct Manager {
sd_event_source *ctrl_event;
sd_event_source *uevent_event;
sd_event_source *inotify_event;
+ sd_event_source *kill_workers_event;
usec_t last_usec;
@@ -284,6 +285,7 @@ static void manager_free(Manager *manager) {
sd_event_source_unref(manager->ctrl_event);
sd_event_source_unref(manager->uevent_event);
sd_event_source_unref(manager->inotify_event);
+ sd_event_source_unref(manager->kill_workers_event);
sd_event_unref(manager->event);
manager_workers_free(manager);
@@ -340,7 +342,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
pid = fork();
switch (pid) {
case 0: {
- struct udev_device *dev = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int fd_monitor;
_cleanup_close_ int fd_signal = -1, fd_ep = -1;
@@ -364,6 +366,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
manager->ctrl_event = sd_event_source_unref(manager->ctrl_event);
manager->uevent_event = sd_event_source_unref(manager->uevent_event);
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
manager->event = sd_event_unref(manager->event);
@@ -395,7 +398,9 @@ static void worker_spawn(Manager *manager, struct event *event) {
(void) prctl(PR_SET_PDEATHSIG, SIGTERM);
/* Reset OOM score, we only protect the main daemon. */
- write_string_file("/proc/self/oom_score_adj", "0", 0);
+ r = set_oom_score_adjust(0);
+ if (r < 0)
+ log_debug_errno(r, "Failed to reset OOM score, ignoring: %m");
for (;;) {
_cleanup_(udev_event_freep) struct udev_event *udev_event = NULL;
@@ -404,15 +409,12 @@ static void worker_spawn(Manager *manager, struct event *event) {
assert(dev);
log_debug("seq %llu running", udev_device_get_seqnum(dev));
- udev_event = udev_event_new(dev);
- if (udev_event == NULL) {
+ udev_event = udev_event_new(dev->device, arg_exec_delay, rtnl);
+ if (!udev_event) {
r = -ENOMEM;
goto out;
}
- if (arg_exec_delay > 0)
- udev_event->exec_delay = arg_exec_delay;
-
/*
* Take a shared lock on the device node; this establishes
* a concept of device "ownership" to serialize device
@@ -438,9 +440,6 @@ static void worker_spawn(Manager *manager, struct event *event) {
}
}
- /* needed for renaming netifs */
- udev_event->rtnl = rtnl;
-
/* apply rules, create node, symlinks */
udev_event_execute_rules(udev_event,
arg_event_timeout_usec, arg_event_timeout_warn_usec,
@@ -450,7 +449,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
udev_event_execute_run(udev_event,
arg_event_timeout_usec, arg_event_timeout_warn_usec);
- if (udev_event->rtnl)
+ if (!rtnl)
/* in case rtnl was initialized */
rtnl = sd_netlink_ref(udev_event->rtnl);
@@ -474,8 +473,7 @@ skip:
log_error_errno(r, "failed to send result of seq %llu to main daemon: %m",
udev_device_get_seqnum(dev));
- udev_device_unref(dev);
- dev = NULL;
+ dev = udev_device_unref(dev);
/* wait for more device messages from main udevd, or term signal */
while (dev == NULL) {
@@ -765,6 +763,73 @@ static void manager_reload(Manager *manager) {
"STATUS=Processing with %u children at max", arg_children_max);
}
+static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userdata) {
+ Manager *manager = userdata;
+
+ assert(manager);
+
+ log_debug("Cleanup idle workers");
+ manager_kill_workers(manager);
+
+ return 1;
+}
+
+static int manager_enable_kill_workers_event(Manager *manager) {
+ int enabled, r;
+
+ assert(manager);
+
+ if (!manager->kill_workers_event)
+ goto create_new;
+
+ r = sd_event_source_get_enabled(manager->kill_workers_event, &enabled);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to query whether event source for killing idle workers is enabled or not, trying to create new event source: %m");
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
+ goto create_new;
+ }
+
+ if (enabled == SD_EVENT_ONESHOT)
+ return 0;
+
+ r = sd_event_source_set_time(manager->kill_workers_event, now(CLOCK_MONOTONIC) + 3 * USEC_PER_SEC);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to set time to event source for killing idle workers, trying to create new event source: %m");
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
+ goto create_new;
+ }
+
+ r = sd_event_source_set_enabled(manager->kill_workers_event, SD_EVENT_ONESHOT);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to enable event source for killing idle workers, trying to create new event source: %m");
+ manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event);
+ goto create_new;
+ }
+
+ return 0;
+
+create_new:
+ r = sd_event_add_time(manager->event, &manager->kill_workers_event, CLOCK_MONOTONIC,
+ now(CLOCK_MONOTONIC) + 3 * USEC_PER_SEC, USEC_PER_SEC, on_kill_workers_event, manager);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to create timer event for killing idle workers: %m");
+
+ return 0;
+}
+
+static int manager_disable_kill_workers_event(Manager *manager) {
+ int r;
+
+ if (!manager->kill_workers_event)
+ return 0;
+
+ r = sd_event_source_set_enabled(manager->kill_workers_event, SD_EVENT_OFF);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m");
+
+ return 0;
+}
+
static void event_queue_start(Manager *manager) {
struct event *event;
usec_t usec;
@@ -786,6 +851,8 @@ static void event_queue_start(Manager *manager) {
manager->last_usec = usec;
}
+ (void) manager_disable_kill_workers_event(manager);
+
udev_builtin_init();
if (!manager->rules) {
@@ -1121,7 +1188,7 @@ static int synthesize_change(sd_device *dev) {
*/
log_debug("Device '%s' is closed, synthesising 'change'", devname);
strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL);
- write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
+ write_string_file(filename, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
FOREACH_DEVICE(e, d) {
const char *t, *n, *s;
@@ -1136,7 +1203,7 @@ static int synthesize_change(sd_device *dev) {
log_debug("Device '%s' is closed, synthesising partition '%s' 'change'", devname, n);
strscpyl(filename, sizeof(filename), s, "/uevent", NULL);
- write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
+ write_string_file(filename, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
}
return 0;
@@ -1144,7 +1211,7 @@ static int synthesize_change(sd_device *dev) {
log_debug("Device %s is closed, synthesising 'change'", devname);
strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL);
- write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
+ write_string_file(filename, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
return 0;
}
@@ -1157,6 +1224,8 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
assert(manager);
+ (void) manager_disable_kill_workers_event(manager);
+
l = read(fd, &buffer, sizeof(buffer));
if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR))
@@ -1169,23 +1238,16 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
const char *devnode;
- if (udev_watch_lookup(e->wd, &dev) < 0)
+ if (udev_watch_lookup(e->wd, &dev) <= 0)
continue;
if (sd_device_get_devname(dev, &devnode) < 0)
continue;
- log_debug("inotify event: %x for %s", e->mask, devnode);
- if (e->mask & IN_CLOSE_WRITE) {
+ log_device_debug(dev, "Inotify event: %x for %s", e->mask, devnode);
+ if (e->mask & IN_CLOSE_WRITE)
synthesize_change(dev);
-
- /* settle might be waiting on us to determine the queue
- * state. If we just handled an inotify event, we might have
- * generated a "change" event, but we won't have queued up
- * the resultant uevent yet. Do that.
- */
- on_uevent(NULL, -1, 0, manager);
- } else if (e->mask & IN_IGNORED)
+ else if (e->mask & IN_IGNORED)
udev_watch_end(dev);
}
@@ -1248,15 +1310,13 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi
} else
log_warning("worker ["PID_FMT"] exit with status 0x%04x", pid, status);
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- if (worker->event) {
- log_error("worker ["PID_FMT"] failed while handling '%s'", pid, worker->event->devpath);
- /* delete state from disk */
- udev_device_delete_db(worker->event->dev);
- udev_device_tag_index(worker->event->dev, NULL, false);
- /* forward kernel event without amending it */
- udev_monitor_send_device(manager->monitor, NULL, worker->event->dev_kernel);
- }
+ if ((!WIFEXITED(status) || WEXITSTATUS(status) != 0) && worker->event) {
+ log_error("worker ["PID_FMT"] failed while handling '%s'", pid, worker->event->devpath);
+ /* delete state from disk */
+ udev_device_delete_db(worker->event->dev);
+ udev_device_tag_index(worker->event->dev, NULL, false);
+ /* forward kernel event without amending it */
+ udev_monitor_send_device(manager->monitor, NULL, worker->event->dev_kernel);
}
worker_free(worker);
@@ -1265,33 +1325,38 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi
/* we can start new workers, try to schedule events */
event_queue_start(manager);
+ /* Disable unnecessary cleanup event */
+ if (hashmap_isempty(manager->workers) && manager->kill_workers_event)
+ (void) sd_event_source_set_enabled(manager->kill_workers_event, SD_EVENT_OFF);
+
return 1;
}
static int on_post(sd_event_source *s, void *userdata) {
Manager *manager = userdata;
- int r;
assert(manager);
- if (LIST_IS_EMPTY(manager->events)) {
- /* no pending events */
- if (!hashmap_isempty(manager->workers)) {
- /* there are idle workers */
- log_debug("cleanup idle workers");
- manager_kill_workers(manager);
- } else {
- /* we are idle */
- if (manager->exit) {
- r = sd_event_exit(manager->event, 0);
- if (r < 0)
- return r;
- } else if (manager->cgroup)
- /* cleanup possible left-over processes in our cgroup */
- cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, CGROUP_IGNORE_SELF, NULL, NULL, NULL);
- }
+ if (!LIST_IS_EMPTY(manager->events))
+ return 1;
+
+ /* There are no pending events. Let's cleanup idle process. */
+
+ if (!hashmap_isempty(manager->workers)) {
+ /* There are idle workers */
+ (void) manager_enable_kill_workers_event(manager);
+ return 1;
}
+ /* There are no idle workers. */
+
+ if (manager->exit)
+ return sd_event_exit(manager->event, 0);
+
+ if (manager->cgroup)
+ /* cleanup possible left-over processes in our cgroup */
+ (void) cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, CGROUP_IGNORE_SELF, NULL, NULL, NULL);
+
return 1;
}
@@ -1578,9 +1643,10 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0)
return log_error_errno(r, "could not enable SO_PASSCRED: %m");
- manager->fd_inotify = udev_watch_init();
- if (manager->fd_inotify < 0)
- return log_error_errno(ENOMEM, "error initializing inotify");
+ r = udev_watch_init();
+ if (r < 0)
+ return log_error_errno(r, "Failed to create inotify descriptor: %m");
+ manager->fd_inotify = r;
udev_watch_restore();
@@ -1702,6 +1768,8 @@ int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
}
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
+
r = must_be_root();
if (r < 0)
goto exit;
@@ -1713,7 +1781,7 @@ int main(int argc, char *argv[]) {
arg_children_max = 8;
if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0)
- arg_children_max += CPU_COUNT(&cpu_set) * 2;
+ arg_children_max += CPU_COUNT(&cpu_set) * 8;
mem_limit = physical_memory() / (128LU*1024*1024);
arg_children_max = MAX(10U, MIN(arg_children_max, mem_limit));
@@ -1790,7 +1858,9 @@ int main(int argc, char *argv[]) {
setsid();
- write_string_file("/proc/self/oom_score_adj", "-1000", 0);
+ r = set_oom_score_adjust(-1000);
+ if (r < 0)
+ log_debug_errno(r, "Failed to adjust OOM score, ignoring: %m");
}
r = run(fd_ctrl, fd_uevent, cgroup);
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index f162d29220..4c55ed7cb5 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -112,7 +112,7 @@ static int toggle_utf8(const char *name, int fd, bool utf8) {
static int toggle_utf8_sysfs(bool utf8) {
int r;
- r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), 0);
+ r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", enable_disable(utf8));