1
0
mirror of https://github.com/systemd/systemd synced 2026-04-09 08:34:50 +02:00

Compare commits

...

28 Commits

Author SHA1 Message Date
Yu Watanabe
99f8a6d7f5
Merge pull request #21581 from keszybz/really-random-fixlets
Really random fixlets
2021-12-01 12:54:00 +09:00
Yu Watanabe
361bf5fb77
Merge pull request #21564 from yuwata/errno-eagain-eintr
tree-wide: introduce ERRNO_IS_TRANSIENT() and use it
2021-12-01 12:52:27 +09:00
Yu Watanabe
db58f6a933
Merge pull request #21536 from medhefgo/test
test: Introduce TEST_RET macro
2021-12-01 12:52:10 +09:00
Yu Watanabe
c8cbe8e0eb
Merge pull request #21288 from loongarch64/la64/main
Add support for the LoongArch architecture.
2021-12-01 12:51:48 +09:00
Luca Boccassi
c7b5d3b5e4
Merge pull request #21553 from yuwata/network-wireguard-add-routes-to-allowed-ips
network: wireguard: add routes to AllowedIPs=
2021-11-30 23:30:31 +00:00
Zbigniew Jędrzejewski-Szmek
160dadc035 tmpfiles: 'st' may have been used uninitialized 2021-11-30 22:57:31 +01:00
Zbigniew Jędrzejewski-Szmek
baf60a80b5 man: prettify line number handling in python example
This way the 'line_number' variable contains the actual line number as we think
of it, instead of adjusting it on output.
2021-11-30 22:56:51 +01:00
Zbigniew Jędrzejewski-Szmek
75c293f37d test-sizeof: show stack and heap randomization
It's useful to reassure yourself those those things actually work ;)
2021-11-30 22:55:15 +01:00
Yu Watanabe
6387cac3f3 test-network: add tests for creating routes to wireguard's AllowedIPs= 2021-12-01 04:00:16 +09:00
Yu Watanabe
e908434458 network: wireguard: automatically configure routes to addresses specified in AllowedIPs=
Closes #14176.
2021-12-01 04:00:11 +09:00
Yu Watanabe
28870a9d2e network: route: expose route_hash_ops 2021-12-01 03:56:00 +09:00
Yu Watanabe
9e11bd58fb network/wireguard: drop unnecessary .in6 specifier
This should not change any behavior, as the size of the IPv4 address is
smaller than IPv6.
2021-12-01 03:56:00 +09:00
Yu Watanabe
5e82a61375 network: route: read RTA_TABLE attribute to get route table
If the table of a route is larger than 255, then the value is stored in
RTA_TABLE attribute. But the attribute is not supported by old kernels.
So, first try to read the value from RTA_TABLE attribute, then fallback
to the value in the message header.
2021-12-01 03:53:09 +09:00
Yu Watanabe
af31670340 network: route: use typesafe function 2021-12-01 03:52:11 +09:00
Zbigniew Jędrzejewski-Szmek
5f1d6ebd2a oomd: use type suffix instead of casting
The end result is the same.
2021-11-30 18:42:47 +01:00
Xiaotian Wu
0444a6e4be gpt: update the gpt test case for LoongArch 2021-11-30 23:34:29 +08:00
Wu Xiaotian
5c0968a2d1 architecture: Add support for the LoongArch architecture 2021-11-30 23:34:20 +08:00
Yu Watanabe
b3d06b9226 libsystemd: ignore both EINTR and EAGAIN 2021-11-30 23:06:43 +09:00
Yu Watanabe
8add30a03c tree-wide: use ERRNO_IS_TRANSIENT() 2021-11-30 23:06:43 +09:00
Yu Watanabe
7aad83580f errno-util: introduce ERRNO_IS_TRANSIENT() 2021-11-30 23:06:43 +09:00
Yu Watanabe
16edfadc67 ask-password: fix error handling
ERRNO_IS_NOT_SUPPORTED() also matches positive values.
Fortunately, lookup_key() does not return positive values.
2021-11-30 23:05:24 +09:00
Yu Watanabe
97e80ee4a8 sd-dhcp6-client: fix error handling 2021-11-30 22:37:21 +09:00
Jan Janssen
5a45a6bbb6 test-parse-util: Add SI-suffix parse_size tests 2021-11-28 11:48:34 +01:00
Jan Janssen
d19bff65ee test-namespace: Convert to TEST macro 2021-11-28 11:48:34 +01:00
Jan Janssen
353b980204 test-barrier: Convert to TEST macro 2021-11-28 11:48:34 +01:00
Jan Janssen
26e555cbba test: Convert to TEST/TEST_RET macros
Note that test-cgroup-mask, test-cgroup-unit-default and test-unit-name will now
report being skipped instead of reporting success if not run under systemd.
2021-11-28 11:46:26 +01:00
Jan Janssen
0578dfe3eb test: Add sd_booted condition test to TEST macro
Note that this will only report test skips if they use TEST_RET macro.
Regular TEST macros can still be skipped, but this will not be reported
back to main();
2021-11-28 11:42:28 +01:00
Jan Janssen
4c0acc0761 test: Add TEST_RET macro
This declares a test function whose return code will be passed from
main(). The first test that does not return EXIT_SUCCESS wins.
2021-11-28 11:40:45 +01:00
61 changed files with 904 additions and 615 deletions

View File

@ -13,7 +13,7 @@ def read_os_release():
filename = '/usr/lib/os-release' filename = '/usr/lib/os-release'
f = open(filename) f = open(filename)
for line_number, line in enumerate(f): for line_number, line in enumerate(f, start=1):
line = line.rstrip() line = line.rstrip()
if not line or line.startswith('#'): if not line or line.startswith('#'):
continue continue
@ -23,7 +23,7 @@ def read_os_release():
val = ast.literal_eval(val) val = ast.literal_eval(val)
yield name, val yield name, val
else: else:
print(f'{filename}:{line_number + 1}: bad line {line!r}', print(f'{filename}:{line_number}: bad line {line!r}',
file=sys.stderr) file=sys.stderr)
os_release = dict(read_os_release()) os_release = dict(read_os_release())

View File

@ -1569,6 +1569,29 @@
<para>Sets a firewall mark on outgoing WireGuard packets from this interface. Takes a number between 1 and 4294967295.</para> <para>Sets a firewall mark on outgoing WireGuard packets from this interface. Takes a number between 1 and 4294967295.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>RouteTable=</varname></term>
<listitem>
<para>The table identifier for the routes to the addresses specified in the
<varname>AllowedIPs=</varname>. Takes the special value <literal>off</literal>, one of the
predefined names <literal>default</literal>, <literal>main</literal>, and
<literal>local</literal>, names defined in <varname>RouteTable=</varname> in
<citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
or a number in the range 1…4294967295. When <literal>off</literal> the routes to the
addresses specified in the <varname>AllowedIPs=</varname> setting will not be configured.
Defaults to <literal>main</literal>. This setting will be ignored when the same setting is
specified in the [WireGuardPeer] section.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>
<para>The priority of the routes to the addresses specified in the
<varname>AllowedIPs=</varname>. Takes an integer in the range 0…4294967295. Defaults to 0
for IPv4 addresses, and 1024 for IPv6 addresses. This setting will be ignored when the same
setting is specified in the [WireGuardPeer] section.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
@ -1653,6 +1676,27 @@
Most users will not need this.</para> Most users will not need this.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>RouteTable=</varname></term>
<listitem>
<para>The table identifier for the routes to the addresses specified in the
<varname>AllowedIPs=</varname>. Takes the special value <literal>off</literal>, one of the
predefined names <literal>default</literal>, <literal>main</literal>, and
<literal>local</literal>, names defined in <varname>RouteTable=</varname> in
<citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
or a number in the range 1…4294967295. Defaults to unset, and the value specified in the
same setting in the [WireGuard] section will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RouteMetric=</varname></term>
<listitem>
<para>The priority of the routes to the addresses specified in the
<varname>AllowedIPs=</varname>. Takes an integer in the range 0…4294967295. Defaults to
unset, and the value specified in the same setting in the [WireGuard] section will be used.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -70,6 +70,9 @@ int uname_architecture(void) {
{ "parisc64", ARCHITECTURE_PARISC64 }, { "parisc64", ARCHITECTURE_PARISC64 },
{ "parisc", ARCHITECTURE_PARISC }, { "parisc", ARCHITECTURE_PARISC },
#elif defined(__loongarch64)
{ "loongarch64", ARCHITECTURE_LOONGARCH64 },
#elif defined(__m68k__) #elif defined(__m68k__)
{ "m68k", ARCHITECTURE_M68K }, { "m68k", ARCHITECTURE_M68K },
@ -148,6 +151,7 @@ static const char *const architecture_table[_ARCHITECTURE_MAX] = {
[ARCHITECTURE_X86_64] = "x86-64", [ARCHITECTURE_X86_64] = "x86-64",
[ARCHITECTURE_X86] = "x86", [ARCHITECTURE_X86] = "x86",
[ARCHITECTURE_IA64] = "ia64", [ARCHITECTURE_IA64] = "ia64",
[ARCHITECTURE_LOONGARCH64] = "loongarch64",
[ARCHITECTURE_M68K] = "m68k", [ARCHITECTURE_M68K] = "m68k",
[ARCHITECTURE_MIPS64_LE] = "mips64-le", [ARCHITECTURE_MIPS64_LE] = "mips64-le",
[ARCHITECTURE_MIPS64] = "mips64", [ARCHITECTURE_MIPS64] = "mips64",

View File

@ -20,6 +20,7 @@ typedef enum {
ARCHITECTURE_ARM_BE, ARCHITECTURE_ARM_BE,
ARCHITECTURE_CRIS, ARCHITECTURE_CRIS,
ARCHITECTURE_IA64, ARCHITECTURE_IA64,
ARCHITECTURE_LOONGARCH64,
ARCHITECTURE_M68K, ARCHITECTURE_M68K,
ARCHITECTURE_MIPS, ARCHITECTURE_MIPS,
ARCHITECTURE_MIPS64, ARCHITECTURE_MIPS64,
@ -197,6 +198,10 @@ int uname_architecture(void);
# elif defined(__SH4A__) # elif defined(__SH4A__)
# define LIB_ARCH_TUPLE "sh4a-linux-gnu" # define LIB_ARCH_TUPLE "sh4a-linux-gnu"
# endif # endif
#elif defined(__loongarch64)
# pragma message "Please update the Arch tuple of loongarch64 after psABI is stable"
# define native_architecture() ARCHITECTURE_LOONGARCH64
# define LIB_ARCH_TUPLE "loongarch64-linux-gnu"
#elif defined(__m68k__) #elif defined(__m68k__)
# define native_architecture() ARCHITECTURE_M68K # define native_architecture() ARCHITECTURE_M68K
# define LIB_ARCH_TUPLE "m68k-linux-gnu" # define LIB_ARCH_TUPLE "m68k-linux-gnu"

View File

@ -70,6 +70,13 @@ static inline int errno_or_else(int fallback) {
return -abs(fallback); return -abs(fallback);
} }
/* For send()/recv() or read()/write(). */
static inline bool ERRNO_IS_TRANSIENT(int r) {
return IN_SET(abs(r),
EAGAIN,
EINTR);
}
/* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5. /* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5.
* *
* Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the
@ -100,10 +107,8 @@ static inline bool ERRNO_IS_DISCONNECT(int r) {
* the accept(2) man page. */ * the accept(2) man page. */
static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) { static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) {
return ERRNO_IS_DISCONNECT(r) || return ERRNO_IS_DISCONNECT(r) ||
IN_SET(abs(r), ERRNO_IS_TRANSIENT(r) ||
EAGAIN, abs(r) == EOPNOTSUPP;
EINTR,
EOPNOTSUPP);
} }
/* Resource exhaustion, could be our fault or general system trouble */ /* Resource exhaustion, could be our fault or general system trouble */

View File

@ -453,7 +453,7 @@ int acquire_terminal(
l = read(notify, &buffer, sizeof(buffer)); l = read(notify, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EINTR, EAGAIN)) if (ERRNO_IS_TRANSIENT(errno))
continue; continue;
return -errno; return -errno;

View File

@ -3191,7 +3191,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
l = read(fd, &buffer, sizeof(buffer)); l = read(fd, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EINTR, EAGAIN)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return log_error_errno(errno, "Failed to read control group inotify events: %m"); return log_error_errno(errno, "Failed to read control group inotify events: %m");

View File

@ -2445,18 +2445,19 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
} }
n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC); n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
if (IN_SET(n, -EAGAIN, -EINTR)) if (n < 0) {
if (ERRNO_IS_TRANSIENT(n))
return 0; /* Spurious wakeup, try again */ return 0; /* Spurious wakeup, try again */
if (n == -EXFULL) { if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring."); log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0; return 0;
} }
if (n < 0)
/* If this is any other, real error, then let's stop processing this socket. This of course /* If this is any other, real error, then let's stop processing this socket. This of course
* means we won't take notification messages anymore, but that's still better than busy * means we won't take notification messages anymore, but that's still better than busy
* looping around this: being woken up over and over again but being unable to actually read * looping around this: being woken up over and over again but being unable to actually read
* the message off the socket. */ * the message off the socket. */
return log_error_errno(n, "Failed to receive notification message: %m"); return log_error_errno(n, "Failed to receive notification message: %m");
}
CMSG_FOREACH(cmsg, &msghdr) { CMSG_FOREACH(cmsg, &msghdr) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
@ -2716,19 +2717,18 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
} }
n = read(m->signal_fd, &sfsi, sizeof(sfsi)); n = read(m->signal_fd, &sfsi, sizeof(sfsi));
if (n != sizeof(sfsi)) { if (n < 0) {
if (n >= 0) { if (ERRNO_IS_TRANSIENT(errno))
log_warning("Truncated read from signal fd (%zu bytes), ignoring!", n);
return 0;
}
if (IN_SET(errno, EINTR, EAGAIN))
return 0; return 0;
/* We return an error here, which will kill this handler, /* We return an error here, which will kill this handler,
* to avoid a busy loop on read error. */ * to avoid a busy loop on read error. */
return log_error_errno(errno, "Reading from signal fd failed: %m"); return log_error_errno(errno, "Reading from signal fd failed: %m");
} }
if (n != sizeof(sfsi)) {
log_warning("Truncated read from signal fd (%zu bytes), ignoring!", n);
return 0;
}
log_received_signal(sfsi.ssi_signo == SIGCHLD || log_received_signal(sfsi.ssi_signo == SIGCHLD ||
(sfsi.ssi_signo == SIGTERM && MANAGER_IS_USER(m)) (sfsi.ssi_signo == SIGTERM && MANAGER_IS_USER(m))
@ -4263,7 +4263,7 @@ int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t re
l = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT); l = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EINTR, EAGAIN)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return log_error_errno(errno, "Failed to read from user lookup fd: %m"); return log_error_errno(errno, "Failed to read from user lookup fd: %m");

View File

@ -184,7 +184,7 @@ int path_spec_fd_event(PathSpec *s, uint32_t revents) {
l = read(s->inotify_fd, &buffer, sizeof(buffer)); l = read(s->inotify_fd, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return log_error_errno(errno, "Failed to read inotify event: %m"); return log_error_errno(errno, "Failed to read inotify event: %m");

View File

@ -1122,10 +1122,11 @@ static int on_notify_socket(sd_event_source *s, int fd, uint32_t revents, void *
assert(m); assert(m);
n = read_datagram(fd, &sender, &datagram, &passed_fd); n = read_datagram(fd, &sender, &datagram, &passed_fd);
if (IN_SET(n, -EAGAIN, -EINTR)) if (n < 0) {
if (ERRNO_IS_TRANSIENT(n))
return 0; return 0;
if (n < 0)
return log_error_errno(n, "Failed to read notify datagram: %m"); return log_error_errno(n, "Failed to read notify datagram: %m");
}
if (sender.pid <= 0) { if (sender.pid <= 0) {
log_warning("Received notify datagram without valid sender PID, ignoring."); log_warning("Received notify datagram without valid sender PID, ignoring.");

View File

@ -567,10 +567,11 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
int r; int r;
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (IN_SET(n, -EAGAIN, -EINTR)) if (n < 0) {
if (ERRNO_IS_TRANSIENT(n))
return 0; return 0;
if (n < 0)
return (int) n; return (int) n;
}
cmsg_close_all(&msghdr); cmsg_close_all(&msghdr);

View File

@ -326,7 +326,7 @@ static int server_read_dev_kmsg(Server *s) {
return 0; return 0;
} }
if (IN_SET(errno, EAGAIN, EINTR, EPIPE)) if (ERRNO_IS_TRANSIENT(errno) || errno == EPIPE)
return 0; return 0;
return log_error_errno(errno, "Failed to read from /dev/kmsg: %m"); return log_error_errno(errno, "Failed to read from /dev/kmsg: %m");

View File

@ -1317,14 +1317,15 @@ int server_process_datagram(
iovec = IOVEC_MAKE(s->buffer, MALLOC_ELEMENTSOF(s->buffer) - 1); /* Leave room for trailing NUL we add later */ iovec = IOVEC_MAKE(s->buffer, MALLOC_ELEMENTSOF(s->buffer) - 1); /* Leave room for trailing NUL we add later */
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (IN_SET(n, -EINTR, -EAGAIN)) if (n < 0) {
if (ERRNO_IS_TRANSIENT(n))
return 0; return 0;
if (n == -EXFULL) { if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring."); log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0; return 0;
} }
if (n < 0)
return log_error_errno(n, "recvmsg() failed: %m"); return log_error_errno(n, "recvmsg() failed: %m");
}
CMSG_FOREACH(cmsg, &msghdr) CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET && if (cmsg->cmsg_level == SOL_SOCKET &&

View File

@ -588,7 +588,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EINTR, EAGAIN)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
log_warning_errno(errno, "Failed to read from stream: %m"); log_warning_errno(errno, "Failed to read from stream: %m");

View File

@ -1945,7 +1945,7 @@ static int client_receive_message_udp(
len = recv(fd, message, buflen, 0); len = recv(fd, message, buflen, 0);
if (len < 0) { if (len < 0) {
/* see comment above for why we shouldn't error out on ENETDOWN. */ /* see comment above for why we shouldn't error out on ENETDOWN. */
if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) if (ERRNO_IS_TRANSIENT(errno) || errno == ENETDOWN)
return 0; return 0;
return log_dhcp_client_errno(client, errno, return log_dhcp_client_errno(client, errno,
@ -2035,12 +2035,12 @@ static int client_receive_message_raw(
iov = IOVEC_MAKE(packet, buflen); iov = IOVEC_MAKE(packet, buflen);
len = recvmsg_safe(fd, &msg, 0); len = recvmsg_safe(fd, &msg, 0);
if (IN_SET(len, -EAGAIN, -EINTR, -ENETDOWN)) if (len < 0) {
if (ERRNO_IS_TRANSIENT(len) || len == -ENETDOWN)
return 0; return 0;
if (len < 0)
return log_dhcp_client_errno(client, len, return log_dhcp_client_errno(client, len,
"Could not receive message from raw socket: %m"); "Could not receive message from raw socket: %m");
}
if ((size_t) len < sizeof(DHCPPacket)) if ((size_t) len < sizeof(DHCPPacket))
return 0; return 0;

View File

@ -1206,10 +1206,12 @@ static int server_receive_message(sd_event_source *s, int fd,
iov = IOVEC_MAKE(message, datagram_size); iov = IOVEC_MAKE(message, datagram_size);
len = recvmsg_safe(fd, &msg, 0); len = recvmsg_safe(fd, &msg, 0);
if (IN_SET(len, -EAGAIN, -EINTR)) if (len < 0) {
if (ERRNO_IS_TRANSIENT(len))
return 0; return 0;
if (len < 0)
return len; return len;
}
if ((size_t) len < sizeof(DHCPMessage)) if ((size_t) len < sizeof(DHCPMessage))
return 0; return 0;

View File

@ -1479,10 +1479,10 @@ static int client_receive_message(
len = recvmsg_safe(fd, &msg, MSG_DONTWAIT); len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
if (len < 0) { if (len < 0) {
/* see comment above for why we shouldn't error out on ENETDOWN. */ /* see comment above for why we shouldn't error out on ENETDOWN. */
if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) if (ERRNO_IS_TRANSIENT(len) || len == -ENETDOWN)
return 0; return 0;
return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m"); return log_dhcp6_client_errno(client, len, "Could not receive message from UDP socket: %m");
} }
if ((size_t) len < sizeof(DHCP6Message)) { if ((size_t) len < sizeof(DHCP6Message)) {

View File

@ -362,7 +362,7 @@ static int ipv4acd_on_packet(
n = recv(fd, &packet, sizeof(struct ether_arp), 0); n = recv(fd, &packet, sizeof(struct ether_arp), 0);
if (n < 0) { if (n < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m");

View File

@ -212,7 +212,7 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents
length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
if (length < 0) { if (length < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m"); log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m");

View File

@ -149,7 +149,7 @@ static int bus_socket_write_auth(sd_bus *b) {
} }
if (k < 0) if (k < 0)
return errno == EAGAIN ? 0 : -errno; return ERRNO_IS_TRANSIENT(errno) ? 0 : -errno;
iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k); iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
return 1; return 1;
@ -565,10 +565,11 @@ static int bus_socket_read_auth(sd_bus *b) {
} else } else
handle_cmsg = true; handle_cmsg = true;
} }
if (k == -EAGAIN) if (k < 0) {
if (ERRNO_IS_TRANSIENT(k))
return 0; return 0;
if (k < 0)
return (int) k; return (int) k;
}
if (k == 0) { if (k == 0) {
if (handle_cmsg) if (handle_cmsg)
cmsg_close_all(&mh); /* paranoia, we shouldn't have gotten any fds on EOF */ cmsg_close_all(&mh); /* paranoia, we shouldn't have gotten any fds on EOF */
@ -1073,7 +1074,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
} }
if (k < 0) if (k < 0)
return errno == EAGAIN ? 0 : -errno; return ERRNO_IS_TRANSIENT(errno) ? 0 : -errno;
*idx += (size_t) k; *idx += (size_t) k;
return 1; return 1;
@ -1230,10 +1231,11 @@ int bus_socket_read_message(sd_bus *bus) {
} else } else
handle_cmsg = true; handle_cmsg = true;
} }
if (k == -EAGAIN) if (k < 0) {
if (ERRNO_IS_TRANSIENT(k))
return 0; return 0;
if (k < 0)
return (int) k; return (int) k;
}
if (k == 0) { if (k == 0) {
if (handle_cmsg) if (handle_cmsg)
cmsg_close_all(&mh); /* On EOF we shouldn't have gotten an fd, but let's make sure */ cmsg_close_all(&mh); /* On EOF we shouldn't have gotten an fd, but let's make sure */

View File

@ -445,7 +445,7 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
buflen = recvmsg(m->sock, &smsg, 0); buflen = recvmsg(m->sock, &smsg, 0);
if (buflen < 0) { if (buflen < 0) {
if (errno != EINTR) if (ERRNO_IS_TRANSIENT(errno))
log_debug_errno(errno, "sd-device-monitor: Failed to receive message: %m"); log_debug_errno(errno, "sd-device-monitor: Failed to receive message: %m");
return -errno; return -errno;
} }

View File

@ -3142,7 +3142,7 @@ static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) {
ss = read(fd, &x, sizeof(x)); ss = read(fd, &x, sizeof(x));
if (ss < 0) { if (ss < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return -errno; return -errno;
@ -3348,7 +3348,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, i
n = read(d->fd, &si, sizeof(si)); n = read(d->fd, &si, sizeof(si));
if (n < 0) { if (n < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return -errno; return -errno;
@ -3402,7 +3402,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t
n = read(d->fd, &d->buffer, sizeof(d->buffer)); n = read(d->fd, &d->buffer, sizeof(d->buffer));
if (n < 0) { if (n < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return -errno; return -errno;

View File

@ -2698,7 +2698,7 @@ _public_ int sd_journal_process(sd_journal *j) {
l = read(j->inotify_fd, &buffer, sizeof(buffer)); l = read(j->inotify_fd, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return got_something ? determine_change(j) : SD_JOURNAL_NOP; return got_something ? determine_change(j) : SD_JOURNAL_NOP;
return -errno; return -errno;

View File

@ -235,12 +235,13 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
assert(iov); assert(iov);
n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0)); n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
if (n < 0) {
if (n == -ENOBUFS) if (n == -ENOBUFS)
return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun"); return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
if (IN_SET(n, -EAGAIN, -EINTR)) if (ERRNO_IS_TRANSIENT(n))
return 0; return 0;
if (n < 0)
return (int) n; return (int) n;
}
if (sender.nl.nl_pid != 0) { if (sender.nl.nl_pid != 0) {
/* not from the kernel, ignore */ /* not from the kernel, ignore */

View File

@ -462,7 +462,7 @@ _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
l = read(fd, &buffer, sizeof(buffer)); l = read(fd, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return -errno; return -errno;

View File

@ -418,7 +418,7 @@ static void* thread_worker(void *p) {
length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0); length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0);
if (length < 0) { if (length < 0) {
if (errno == EINTR) if (ERRNO_IS_TRANSIENT(errno))
continue; continue;
break; break;
@ -847,7 +847,7 @@ _public_ int sd_resolve_process(sd_resolve *resolve) {
l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0); l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0);
if (l < 0) { if (l < 0) {
if (errno == EAGAIN) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return -errno; return -errno;

View File

@ -229,12 +229,16 @@ WireGuard.FwMark, config_parse_unsigned,
WireGuard.ListenPort, config_parse_wireguard_listen_port, 0, offsetof(Wireguard, port) WireGuard.ListenPort, config_parse_wireguard_listen_port, 0, offsetof(Wireguard, port)
WireGuard.PrivateKey, config_parse_wireguard_private_key, 0, 0 WireGuard.PrivateKey, config_parse_wireguard_private_key, 0, 0
WireGuard.PrivateKeyFile, config_parse_wireguard_private_key_file, 0, 0 WireGuard.PrivateKeyFile, config_parse_wireguard_private_key_file, 0, 0
WireGuard.RouteTable, config_parse_wireguard_route_table, 0, offsetof(Wireguard, route_table)
WireGuard.RouteMetric, config_parse_wireguard_route_priority, 0, offsetof(Wireguard, route_priority)
WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0, 0 WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0, 0
WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0 WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0
WireGuardPeer.PublicKey, config_parse_wireguard_peer_key, 0, 0 WireGuardPeer.PublicKey, config_parse_wireguard_peer_key, 0, 0
WireGuardPeer.PresharedKey, config_parse_wireguard_peer_key, 0, 0 WireGuardPeer.PresharedKey, config_parse_wireguard_peer_key, 0, 0
WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0 WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0
WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0 WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0
WireGuardPeer.RouteTable, config_parse_wireguard_peer_route_table, 0, 0
WireGuardPeer.RouteMetric, config_parse_wireguard_peer_route_priority,0, 0
Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id) Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id)
Xfrm.Independent, config_parse_bool, 0, offsetof(Xfrm, independent) Xfrm.Independent, config_parse_bool, 0, offsetof(Xfrm, independent)
BatmanAdvanced.Aggregation, config_parse_bool, 0, offsetof(BatmanAdvanced, aggregation) BatmanAdvanced.Aggregation, config_parse_bool, 0, offsetof(BatmanAdvanced, aggregation)

View File

@ -7,6 +7,7 @@
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/ipv6_route.h>
#include "sd-resolve.h" #include "sd-resolve.h"
@ -18,6 +19,8 @@
#include "memory-util.h" #include "memory-util.h"
#include "netlink-util.h" #include "netlink-util.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-route-util.h"
#include "networkd-route.h"
#include "networkd-util.h" #include "networkd-util.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
@ -696,7 +699,7 @@ int config_parse_wireguard_allowed_ips(
*ipmask = (WireguardIPmask) { *ipmask = (WireguardIPmask) {
.family = family, .family = family,
.ip.in6 = addr.in6, .ip = addr,
.cidr = prefixlen, .cidr = prefixlen,
}; };
@ -827,6 +830,186 @@ int config_parse_wireguard_keepalive(
return 0; return 0;
} }
int config_parse_wireguard_route_table(
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) {
NetDev *netdev = userdata;
uint32_t *table = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
if (isempty(rvalue)) {
*table = RT_TABLE_MAIN;
return 0;
}
if (streq(rvalue, "off")) {
*table = 0;
return 0;
}
r = manager_get_route_table_from_string(netdev->manager, rvalue, table);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
return 0;
}
int config_parse_wireguard_peer_route_table(
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) {
_cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL;
NetDev *netdev = userdata;
Wireguard *w;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(netdev);
assert(netdev->manager);
w = WIREGUARD(netdev);
assert(w);
r = wireguard_peer_new_static(w, filename, section_line, &peer);
if (r < 0)
return log_oom();
if (isempty(rvalue)) {
peer->route_table_set = false; /* Use the table specified in [WireGuard] section. */
TAKE_PTR(peer);
return 0;
}
if (streq(rvalue, "off")) {
peer->route_table = 0; /* Disabled. */
peer->route_table_set = true;
TAKE_PTR(peer);
return 0;
}
r = manager_get_route_table_from_string(netdev->manager, rvalue, &peer->route_table);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
peer->route_table_set = true;
TAKE_PTR(peer);
return 0;
}
int config_parse_wireguard_route_priority(
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) {
uint32_t *priority = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*priority = 0;
return 0;
}
r = safe_atou32(rvalue, priority);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
return 0;
}
int config_parse_wireguard_peer_route_priority(
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) {
_cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL;
Wireguard *w;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(userdata);
w = WIREGUARD(userdata);
assert(w);
r = wireguard_peer_new_static(w, filename, section_line, &peer);
if (r < 0)
return log_oom();
if (isempty(rvalue)) {
peer->route_priority_set = false; /* Use the priority specified in [WireGuard] section. */
TAKE_PTR(peer);
return 0;
}
r = safe_atou32(rvalue, &peer->route_priority);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
peer->route_priority_set = true;
TAKE_PTR(peer);
return 0;
}
static void wireguard_init(NetDev *netdev) { static void wireguard_init(NetDev *netdev) {
Wireguard *w; Wireguard *w;
@ -835,6 +1018,7 @@ static void wireguard_init(NetDev *netdev) {
assert(w); assert(w);
w->flags = WGDEVICE_F_REPLACE_PEERS; w->flags = WGDEVICE_F_REPLACE_PEERS;
w->route_table = RT_TABLE_MAIN;
} }
static void wireguard_done(NetDev *netdev) { static void wireguard_done(NetDev *netdev) {
@ -852,6 +1036,8 @@ static void wireguard_done(NetDev *netdev) {
hashmap_free_with_destructor(w->peers_by_section, wireguard_peer_free); hashmap_free_with_destructor(w->peers_by_section, wireguard_peer_free);
set_free(w->peers_with_unresolved_endpoint); set_free(w->peers_with_unresolved_endpoint);
set_free(w->peers_with_failed_endpoint); set_free(w->peers_with_failed_endpoint);
set_free(w->routes);
} }
static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_KEY_LEN]) { static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_KEY_LEN]) {
@ -924,9 +1110,40 @@ static int wireguard_verify(NetDev *netdev, const char *filename) {
"%s: Missing PrivateKey= or PrivateKeyFile=, " "%s: Missing PrivateKey= or PrivateKeyFile=, "
"Ignoring network device.", filename); "Ignoring network device.", filename);
LIST_FOREACH_SAFE(peers, peer, peer_next, w->peers) LIST_FOREACH_SAFE(peers, peer, peer_next, w->peers) {
if (wireguard_peer_verify(peer) < 0) WireguardIPmask *ipmask;
if (wireguard_peer_verify(peer) < 0) {
wireguard_peer_free(peer); wireguard_peer_free(peer);
continue;
}
if ((peer->route_table_set ? peer->route_table : w->route_table) == 0)
continue;
LIST_FOREACH(ipmasks, ipmask, peer->ipmasks) {
_cleanup_(route_freep) Route *route = NULL;
r = route_new(&route);
if (r < 0)
return log_oom();
route->family = ipmask->family;
route->dst = ipmask->ip;
route->dst_prefixlen = ipmask->cidr;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_STATIC;
route->table = peer->route_table_set ? peer->route_table : w->route_table;
route->priority = peer->route_priority_set ? peer->route_priority : w->route_priority;
if (route->priority == 0 && route->family == AF_INET6)
route->priority = IP6_RT_PRIO_USER;
route->source = NETWORK_CONFIG_SOURCE_STATIC;
r = set_ensure_consume(&w->routes, &route_hash_ops, TAKE_PTR(route));
if (r < 0)
return log_oom();
}
}
return 0; return 0;
} }

View File

@ -33,6 +33,11 @@ typedef struct WireguardPeer {
char *endpoint_host; char *endpoint_host;
char *endpoint_port; char *endpoint_port;
uint32_t route_table;
uint32_t route_priority;
bool route_table_set;
bool route_priority_set;
LIST_HEAD(WireguardIPmask, ipmasks); LIST_HEAD(WireguardIPmask, ipmasks);
LIST_FIELDS(struct WireguardPeer, peers); LIST_FIELDS(struct WireguardPeer, peers);
} WireguardPeer; } WireguardPeer;
@ -55,6 +60,10 @@ struct Wireguard {
unsigned n_retries; unsigned n_retries;
sd_event_source *resolve_retry_event_source; sd_event_source *resolve_retry_event_source;
Set *routes;
uint32_t route_table;
uint32_t route_priority;
}; };
DEFINE_NETDEV_CAST(WIREGUARD, Wireguard); DEFINE_NETDEV_CAST(WIREGUARD, Wireguard);
@ -68,3 +77,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key_file); CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key_file);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file); CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive); CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_peer_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_route_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_peer_route_priority);

View File

@ -19,6 +19,7 @@
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "vrf.h" #include "vrf.h"
#include "wireguard.h"
int route_new(Route **ret) { int route_new(Route **ret) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
@ -242,7 +243,7 @@ int route_compare_func(const Route *a, const Route *b) {
} }
} }
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
route_hash_ops, route_hash_ops,
Route, Route,
route_hash_func, route_hash_func,
@ -673,7 +674,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
return log_link_error_errno(link, r, "Could not set route table: %m"); return log_link_error_errno(link, r, "Could not set route table: %m");
/* Table attribute to allow more than 256. */ /* Table attribute to allow more than 256. */
r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table)); r = sd_netlink_message_append_u32(req, RTA_TABLE, route->table);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m"); return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m");
} }
@ -865,6 +866,28 @@ static bool route_by_kernel(const Route *route) {
return false; return false;
} }
static void link_unmark_wireguard_routes(Link *link) {
Route *route, *existing;
NetDev *netdev;
Wireguard *w;
assert(link);
if (!streq_ptr(link->kind, "wireguard"))
return;
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
return;
w = WIREGUARD(netdev);
if (!w)
return;
SET_FOREACH(route, w->routes)
if (route_get(NULL, link, route, &existing) >= 0)
route_unmark(existing);
}
int link_drop_foreign_routes(Link *link) { int link_drop_foreign_routes(Link *link) {
Route *route; Route *route;
int k, r; int k, r;
@ -914,6 +937,8 @@ int link_drop_foreign_routes(Link *link) {
route_unmark(existing); route_unmark(existing);
} }
link_unmark_wireguard_routes(link);
r = 0; r = 0;
SET_FOREACH(route, link->routes) { SET_FOREACH(route, link->routes) {
if (!route_is_marked(route)) if (!route_is_marked(route))
@ -1342,6 +1367,36 @@ static int link_request_static_route(Link *link, Route *route) {
&link->static_route_messages, static_route_handler, NULL); &link->static_route_messages, static_route_handler, NULL);
} }
static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
NetDev *netdev;
Wireguard *w;
Route *route;
int r;
assert(link);
if (!streq_ptr(link->kind, "wireguard"))
return 0;
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
return 0;
w = WIREGUARD(netdev);
if (!w)
return 0;
SET_FOREACH(route, w->routes) {
if (only_ipv4 && route->family != AF_INET)
continue;
r = link_request_static_route(link, route);
if (r < 0)
return r;
}
return 0;
}
int link_request_static_routes(Link *link, bool only_ipv4) { int link_request_static_routes(Link *link, bool only_ipv4) {
Route *route; Route *route;
int r; int r;
@ -1363,6 +1418,10 @@ int link_request_static_routes(Link *link, bool only_ipv4) {
return r; return r;
} }
r = link_request_wireguard_routes(link, only_ipv4);
if (r < 0)
return r;
if (link->static_route_messages == 0) { if (link->static_route_messages == 0) {
link->static_routes_configured = true; link->static_routes_configured = true;
link_check_ready(link); link_check_ready(link);
@ -1723,12 +1782,16 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
return 0; return 0;
} }
r = sd_netlink_message_read_u32(message, RTA_TABLE, &tmp->table);
if (r == -ENODATA) {
r = sd_rtnl_message_route_get_table(message, &table); r = sd_rtnl_message_route_get_table(message, &table);
if (r >= 0)
tmp->table = table;
}
if (r < 0) { if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m"); log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m");
return 0; return 0;
} }
tmp->table = table;
r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority); r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority);
if (r < 0 && r != -ENODATA) { if (r < 0 && r != -ENODATA) {

View File

@ -70,6 +70,7 @@ typedef struct Route {
void route_hash_func(const Route *route, struct siphash *state); void route_hash_func(const Route *route, struct siphash *state);
int route_compare_func(const Route *a, const Route *b); int route_compare_func(const Route *a, const Route *b);
extern const struct hash_ops route_hash_ops;
int route_new(Route **ret); int route_new(Route **ret);
Route *route_free(Route *route); Route *route_free(Route *route);

View File

@ -4211,14 +4211,15 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
} }
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (IN_SET(n, -EAGAIN, -EINTR)) if (n < 0) {
if (ERRNO_IS_TRANSIENT(n))
return 0; return 0;
if (n == -EXFULL) { if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring."); log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0; return 0;
} }
if (n < 0)
return log_warning_errno(n, "Couldn't read notification socket: %m"); return log_warning_errno(n, "Couldn't read notification socket: %m");
}
cmsg_close_all(&msghdr); cmsg_close_all(&msghdr);

View File

@ -108,10 +108,7 @@ static int process_managed_oom_message(Manager *m, uid_t uid, JsonVariant *param
if (streq(message.property, "ManagedOOMMemoryPressure") && message.limit > 0) { if (streq(message.property, "ManagedOOMMemoryPressure") && message.limit > 0) {
int permyriad = UINT32_SCALE_TO_PERMYRIAD(message.limit); int permyriad = UINT32_SCALE_TO_PERMYRIAD(message.limit);
r = store_loadavg_fixed_point( r = store_loadavg_fixed_point(permyriad / 100LU, permyriad % 100LU, &limit);
(unsigned long) permyriad / 100,
(unsigned long) permyriad % 100,
&limit);
if (r < 0) if (r < 0)
continue; continue;
} }

View File

@ -323,7 +323,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
ssize_t ss = dns_stream_writev(s, iov, ELEMENTSOF(iov), 0); ssize_t ss = dns_stream_writev(s, iov, ELEMENTSOF(iov), 0);
if (ss < 0) { if (ss < 0) {
if (!IN_SET(-ss, EINTR, EAGAIN)) if (!ERRNO_IS_TRANSIENT(ss))
return dns_stream_complete(s, -ss); return dns_stream_complete(s, -ss);
} else { } else {
progressed = true; progressed = true;
@ -347,7 +347,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
ss = dns_stream_read(s, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read); ss = dns_stream_read(s, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read);
if (ss < 0) { if (ss < 0) {
if (!IN_SET(-ss, EINTR, EAGAIN)) if (!ERRNO_IS_TRANSIENT(ss))
return dns_stream_complete(s, -ss); return dns_stream_complete(s, -ss);
} else if (ss == 0) } else if (ss == 0)
return dns_stream_complete(s, ECONNRESET); return dns_stream_complete(s, ECONNRESET);
@ -400,7 +400,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
(uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size), (uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size),
sizeof(s->read_size) + be16toh(s->read_size) - s->n_read); sizeof(s->read_size) + be16toh(s->read_size) - s->n_read);
if (ss < 0) { if (ss < 0) {
if (!IN_SET(-ss, EINTR, EAGAIN)) if (!ERRNO_IS_TRANSIENT(ss))
return dns_stream_complete(s, -ss); return dns_stream_complete(s, -ss);
} else if (ss == 0) } else if (ss == 0)
return dns_stream_complete(s, ECONNRESET); return dns_stream_complete(s, ECONNRESET);

View File

@ -792,10 +792,13 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->allocated); iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->allocated);
l = recvmsg_safe(fd, &mh, 0); l = recvmsg_safe(fd, &mh, 0);
if (IN_SET(l, -EAGAIN, -EINTR)) if (l < 0) {
if (ERRNO_IS_TRANSIENT(l))
return 0; return 0;
if (l <= 0)
return l; return l;
}
if (l == 0)
return 0;
assert(!(mh.msg_flags & MSG_TRUNC)); assert(!(mh.msg_flags & MSG_TRUNC));

View File

@ -153,15 +153,16 @@ static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, cha
return -EUNATCH; return -EUNATCH;
r = lookup_key(keyname, &serial); r = lookup_key(keyname, &serial);
if (ERRNO_IS_NOT_SUPPORTED(r) || r == -EPERM) /* when retrieving the distinction between "kernel or if (r < 0) {
* container manager don't support or allow this" and /* when retrieving the distinction between "kernel or container manager don't support
* "no matching key known" doesn't matter. Note that we * or allow this" and "no matching key known" doesn't matter. Note that we propagate
* propagate EACCESS here (even if EPERM not) since * EACCESS here (even if EPERM not) since that is used if the keyring is available but
* that is used if the keyring is available but we lack * we lack access to the key. */
* access to the key. */ if (ERRNO_IS_NOT_SUPPORTED(r) || r == -EPERM)
return -ENOKEY; return -ENOKEY;
if (r < 0)
return r; return r;
}
return retrieve_key(serial, ret); return retrieve_key(serial, ret);
} }
@ -290,12 +291,13 @@ int ask_password_plymouth(
k = read(fd, buffer + p, sizeof(buffer) - p); k = read(fd, buffer + p, sizeof(buffer) - p);
if (k < 0) { if (k < 0) {
if (IN_SET(errno, EINTR, EAGAIN)) if (ERRNO_IS_TRANSIENT(errno))
continue; continue;
r = -errno; r = -errno;
goto finish; goto finish;
} else if (k == 0) { }
if (k == 0) {
r = -EIO; r = -EIO;
goto finish; goto finish;
} }
@ -521,7 +523,7 @@ int ask_password_tty(
n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1); n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1);
if (n < 0) { if (n < 0) {
if (IN_SET(errno, EINTR, EAGAIN)) if (ERRNO_IS_TRANSIENT(errno))
continue; continue;
r = -errno; r = -errno;
@ -881,20 +883,21 @@ int ask_password_agent(
}; };
n = recvmsg_safe(socket_fd, &msghdr, 0); n = recvmsg_safe(socket_fd, &msghdr, 0);
if (IN_SET(n, -EAGAIN, -EINTR)) if (n < 0) {
if (ERRNO_IS_TRANSIENT(n))
continue; continue;
if (n == -EXFULL) { if (n == -EXFULL) {
log_debug("Got message with truncated control data, ignoring."); log_debug("Got message with truncated control data, ignoring.");
continue; continue;
} }
if (n < 0) {
r = (int) n; r = (int) n;
goto finish; goto finish;
} }
cmsg_close_all(&msghdr); cmsg_close_all(&msghdr);
if (n <= 0) { if (n == 0) {
log_debug("Message too short"); log_debug("Message too short");
continue; continue;
} }

View File

@ -10,6 +10,7 @@
#include <unistd.h> #include <unistd.h>
#include "barrier.h" #include "barrier.h"
#include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "io-util.h" #include "io-util.h"
#include "macro.h" #include "macro.h"
@ -178,7 +179,7 @@ static bool barrier_write(Barrier *b, uint64_t buf) {
assert(b->me >= 0); assert(b->me >= 0);
do { do {
len = write(b->me, &buf, sizeof(buf)); len = write(b->me, &buf, sizeof(buf));
} while (len < 0 && IN_SET(errno, EAGAIN, EINTR)); } while (len < 0 && ERRNO_IS_TRANSIENT(errno));
if (len != sizeof(buf)) if (len != sizeof(buf))
goto error; goto error;
@ -230,7 +231,7 @@ static bool barrier_read(Barrier *b, int64_t comp) {
/* events on @them signal new data for us */ /* events on @them signal new data for us */
len = read(b->them, &buf, sizeof(buf)); len = read(b->them, &buf, sizeof(buf));
if (len < 0 && IN_SET(errno, EAGAIN, EINTR)) if (len < 0 && ERRNO_IS_TRANSIENT(errno))
continue; continue;
if (len != sizeof(buf)) if (len != sizeof(buf))

View File

@ -28,16 +28,7 @@ const GptPartitionType gpt_partition_type_table[] = {
_GPT_ARCH_SEXTET(ARM, "arm"), _GPT_ARCH_SEXTET(ARM, "arm"),
_GPT_ARCH_SEXTET(ARM64, "arm64"), _GPT_ARCH_SEXTET(ARM64, "arm64"),
_GPT_ARCH_SEXTET(IA64, "ia64"), _GPT_ARCH_SEXTET(IA64, "ia64"),
_GPT_ARCH_SEXTET(LOONGARCH64, "loongarch64"),
// TODO: Replace with `_GPT_ARCH_SEXTET(LOONGARCH64, "loongarch64")` once
// https://github.com/systemd/systemd/pull/21288 is merged. */
{ GPT_ROOT_LOONGARCH64, "root-loongarch64", _ARCHITECTURE_INVALID, .is_root = true },
{ GPT_ROOT_LOONGARCH64_VERITY, "root-loongarch64-verity", _ARCHITECTURE_INVALID, .is_root_verity = true },
{ GPT_ROOT_LOONGARCH64_VERITY_SIG, "root-loongarch64-verity-sig", _ARCHITECTURE_INVALID, .is_root_verity_sig = true },
{ GPT_USR_LOONGARCH64, "usr-loongarch64", _ARCHITECTURE_INVALID, .is_usr = true },
{ GPT_USR_LOONGARCH64_VERITY, "usr-loongarch64-verity", _ARCHITECTURE_INVALID, .is_usr_verity = true },
{ GPT_USR_LOONGARCH64_VERITY_SIG, "usr-loongarch64-verity-sig", _ARCHITECTURE_INVALID, .is_usr_verity_sig = true },
_GPT_ARCH_SEXTET(MIPS_LE, "mips-le"), _GPT_ARCH_SEXTET(MIPS_LE, "mips-le"),
_GPT_ARCH_SEXTET(MIPS64_LE, "mips64-le"), _GPT_ARCH_SEXTET(MIPS64_LE, "mips64-le"),
_GPT_ARCH_SEXTET(PPC, "ppc"), _GPT_ARCH_SEXTET(PPC, "ppc"),

View File

@ -129,7 +129,9 @@ static int rm_rf_children_inner(
assert(fd >= 0); assert(fd >= 0);
assert(fname); assert(fname);
if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { if (is_dir < 0 ||
root_dev ||
(is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) {
r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags); r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags);
if (r < 0) if (r < 0)

View File

@ -39,53 +39,84 @@ bool can_memlock(void);
if (sd_booted() > 0) { \ if (sd_booted() > 0) { \
x; \ x; \
} else { \ } else { \
printf("systemd not booted skipping '%s'\n", #x); \ printf("systemd not booted, skipping '%s'\n", #x); \
} }
/* Provide a convenient way to check if we're running in CI. */ /* Provide a convenient way to check if we're running in CI. */
const char *ci_environment(void); const char *ci_environment(void);
typedef struct TestFunc { typedef struct TestFunc {
void (*f)(void); union f {
const char * const n; void (*void_func)(void);
int (*int_func)(void);
} f;
const char * const name;
bool has_ret:1;
bool sd_booted:1;
} TestFunc; } TestFunc;
/* See static-destruct.h for an explanation of how this works. */ /* See static-destruct.h for an explanation of how this works. */
#define REGISTER_TEST(func) \ #define REGISTER_TEST(func, ...) \
static void func(void); \
_section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \ _section_("SYSTEMD_TEST_TABLE") _alignptr_ _used_ _variable_no_sanitize_address_ \
static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \ static const TestFunc UNIQ_T(static_test_table_entry, UNIQ) = { \
.f = &(func), \ .f = (union f) &(func), \
.n = STRINGIFY(func), \ .name = STRINGIFY(func), \
.has_ret = __builtin_types_compatible_p(typeof((union f){}.int_func), typeof(&(func))), \
##__VA_ARGS__ \
} }
extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[]; extern const TestFunc _weak_ __start_SYSTEMD_TEST_TABLE[];
extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[]; extern const TestFunc _weak_ __stop_SYSTEMD_TEST_TABLE[];
#define TEST(name) \ #define TEST(name, ...) \
REGISTER_TEST(test_##name); \ static void test_##name(void); \
REGISTER_TEST(test_##name, ##__VA_ARGS__); \
static void test_##name(void) static void test_##name(void)
static inline void run_test_table(void) { #define TEST_RET(name, ...) \
static int test_##name(void); \
REGISTER_TEST(test_##name, ##__VA_ARGS__); \
static int test_##name(void)
static inline int run_test_table(void) {
int r = EXIT_SUCCESS;
if (!__start_SYSTEMD_TEST_TABLE) if (!__start_SYSTEMD_TEST_TABLE)
return; return r;
const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*)); const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*));
while (t < __stop_SYSTEMD_TEST_TABLE) { while (t < __stop_SYSTEMD_TEST_TABLE) {
log_info("/* %s */", t->n);
t->f(); if (t->sd_booted && sd_booted() <= 0) {
log_info("/* systemd not booted, skipping %s */", t->name);
if (t->has_ret && r == EXIT_SUCCESS)
r = EXIT_TEST_SKIP;
} else {
log_info("/* %s */", t->name);
if (t->has_ret) {
int r2 = t->f.int_func();
if (r == EXIT_SUCCESS)
r = r2;
} else
t->f.void_func();
}
t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*)); t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
} }
return r;
} }
#define DEFINE_CUSTOM_TEST_MAIN(log_level, intro, outro) \ #define DEFINE_CUSTOM_TEST_MAIN(log_level, intro, outro) \
int main(int argc, char *argv[]) { \ int main(int argc, char *argv[]) { \
int _r = EXIT_SUCCESS; \
test_setup_logging(log_level); \ test_setup_logging(log_level); \
save_argc_argv(argc, argv); \ save_argc_argv(argc, argv); \
intro; \ intro; \
run_test_table(); \ _r = run_test_table(); \
outro; \ outro; \
return EXIT_SUCCESS; \ return _r; \
} }
#define DEFINE_TEST_MAIN(log_level) DEFINE_CUSTOM_TEST_MAIN(log_level, , ) #define DEFINE_TEST_MAIN(log_level) DEFINE_CUSTOM_TEST_MAIN(log_level, , )

View File

@ -190,7 +190,7 @@ static int connection_shovel(
} else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) { } else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) {
*from_source = sd_event_source_unref(*from_source); *from_source = sd_event_source_unref(*from_source);
*from = safe_close(*from); *from = safe_close(*from);
} else if (!IN_SET(errno, EAGAIN, EINTR)) } else if (!ERRNO_IS_TRANSIENT(errno))
return log_error_errno(errno, "Failed to splice: %m"); return log_error_errno(errno, "Failed to splice: %m");
} }
@ -202,7 +202,7 @@ static int connection_shovel(
} else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) { } else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) {
*to_source = sd_event_source_unref(*to_source); *to_source = sd_event_source_unref(*to_source);
*to = safe_close(*to); *to = safe_close(*to);
} else if (!IN_SET(errno, EAGAIN, EINTR)) } else if (!ERRNO_IS_TRANSIENT(errno))
return log_error_errno(errno, "Failed to splice: %m"); return log_error_errno(errno, "Failed to splice: %m");
} }
} while (shoveled); } while (shoveled);

View File

@ -14,15 +14,13 @@
#include "tmpfile-util.h" #include "tmpfile-util.h"
#include "user-util.h" #include "user-util.h"
static int test_add_acls_for_user(void) { TEST_RET(add_acls_for_user) {
char fn[] = "/tmp/test-empty.XXXXXX"; char fn[] = "/tmp/test-empty.XXXXXX";
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
char *cmd; char *cmd;
uid_t uid; uid_t uid;
int r; int r;
log_info("/* %s */", __func__);
fd = mkostemp_safe(fn); fd = mkostemp_safe(fn);
assert_se(fd >= 0); assert_se(fd >= 0);
@ -71,6 +69,4 @@ static int test_add_acls_for_user(void) {
return 0; return 0;
} }
int main(int argc, char **argv) { DEFINE_TEST_MAIN(LOG_INFO);
return test_add_acls_for_user();
}

View File

@ -40,7 +40,7 @@ static void sleep_for(usec_t usecs) {
} }
#define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \ #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
static void _FUNCTION(void) { \ TEST(_FUNCTION) { \
Barrier b = BARRIER_NULL; \ Barrier b = BARRIER_NULL; \
pid_t pid1, pid2; \ pid_t pid1, pid2; \
\ \
@ -100,7 +100,7 @@ static void sleep_for(usec_t usecs) {
* pending HUP on the pipe. However, the barrier_sync() prefers reads on the * pending HUP on the pipe. However, the barrier_sync() prefers reads on the
* eventfd, thus we can safely wait on the barrier. * eventfd, thus we can safely wait on the barrier.
*/ */
TEST_BARRIER(test_barrier_sync, TEST_BARRIER(barrier_sync,
({ ({
set_alarm(BASE_TIME * 10); set_alarm(BASE_TIME * 10);
assert_se(barrier_place(&b)); assert_se(barrier_place(&b));
@ -122,7 +122,7 @@ TEST_BARRIER(test_barrier_sync,
* succeed as the child hasn't read the parent's barrier, yet. The following * succeed as the child hasn't read the parent's barrier, yet. The following
* barrier and sync synchronize the exit. * barrier and sync synchronize the exit.
*/ */
TEST_BARRIER(test_barrier_wait_next, TEST_BARRIER(barrier_wait_next,
({ ({
sleep_for(BASE_TIME); sleep_for(BASE_TIME);
set_alarm(BASE_TIME * 10); set_alarm(BASE_TIME * 10);
@ -148,7 +148,7 @@ TEST_BARRIER(test_barrier_wait_next,
* not look at barrier-links so this stall is expected. Thus this test times * not look at barrier-links so this stall is expected. Thus this test times
* out. * out.
*/ */
TEST_BARRIER(test_barrier_wait_next_twice, TEST_BARRIER(barrier_wait_next_twice,
({ ({
sleep_for(BASE_TIME); sleep_for(BASE_TIME);
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
@ -171,7 +171,7 @@ TEST_BARRIER(test_barrier_wait_next_twice,
* between both waits. This does not have any effect on the wait so it times out * between both waits. This does not have any effect on the wait so it times out
* like the other test. * like the other test.
*/ */
TEST_BARRIER(test_barrier_wait_next_twice_local, TEST_BARRIER(barrier_wait_next_twice_local,
({ ({
sleep_for(BASE_TIME); sleep_for(BASE_TIME);
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
@ -196,7 +196,7 @@ TEST_BARRIER(test_barrier_wait_next_twice_local,
* synced wait as the second wait. This works just fine because the local state * synced wait as the second wait. This works just fine because the local state
* has no barriers placed, therefore, the remote is always in sync. * has no barriers placed, therefore, the remote is always in sync.
*/ */
TEST_BARRIER(test_barrier_wait_next_twice_sync, TEST_BARRIER(barrier_wait_next_twice_sync,
({ ({
sleep_for(BASE_TIME); sleep_for(BASE_TIME);
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
@ -217,7 +217,7 @@ TEST_BARRIER(test_barrier_wait_next_twice_sync,
* synced wait as the second wait. This works just fine because the local state * synced wait as the second wait. This works just fine because the local state
* is in sync with the remote. * is in sync with the remote.
*/ */
TEST_BARRIER(test_barrier_wait_next_twice_local_sync, TEST_BARRIER(barrier_wait_next_twice_local_sync,
({ ({
sleep_for(BASE_TIME); sleep_for(BASE_TIME);
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
@ -239,7 +239,7 @@ TEST_BARRIER(test_barrier_wait_next_twice_local_sync,
* This tests sync_*() synchronizations and makes sure they work fine if the * This tests sync_*() synchronizations and makes sure they work fine if the
* local state is behind the remote state. * local state is behind the remote state.
*/ */
TEST_BARRIER(test_barrier_sync_next, TEST_BARRIER(barrier_sync_next,
({ ({
set_alarm(BASE_TIME * 10); set_alarm(BASE_TIME * 10);
assert_se(barrier_sync_next(&b)); assert_se(barrier_sync_next(&b));
@ -265,7 +265,7 @@ TEST_BARRIER(test_barrier_sync_next,
* This tests timeouts if sync_*() is used if local barriers are placed but the * This tests timeouts if sync_*() is used if local barriers are placed but the
* remote didn't place any. * remote didn't place any.
*/ */
TEST_BARRIER(test_barrier_sync_next_local, TEST_BARRIER(barrier_sync_next_local,
({ ({
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
assert_se(barrier_place(&b)); assert_se(barrier_place(&b));
@ -283,7 +283,7 @@ TEST_BARRIER(test_barrier_sync_next_local,
* This is the same as test_barrier_sync_next_local but aborts the sync in the * This is the same as test_barrier_sync_next_local but aborts the sync in the
* parent. Therefore, the sync_next() succeeds just fine due to the abortion. * parent. Therefore, the sync_next() succeeds just fine due to the abortion.
*/ */
TEST_BARRIER(test_barrier_sync_next_local_abort, TEST_BARRIER(barrier_sync_next_local_abort,
({ ({
set_alarm(BASE_TIME * 10); set_alarm(BASE_TIME * 10);
assert_se(barrier_place(&b)); assert_se(barrier_place(&b));
@ -299,7 +299,7 @@ TEST_BARRIER(test_barrier_sync_next_local_abort,
* Test matched wait_abortion() * Test matched wait_abortion()
* This runs wait_abortion() with remote abortion. * This runs wait_abortion() with remote abortion.
*/ */
TEST_BARRIER(test_barrier_wait_abortion, TEST_BARRIER(barrier_wait_abortion,
({ ({
set_alarm(BASE_TIME * 10); set_alarm(BASE_TIME * 10);
assert_se(barrier_wait_abortion(&b)); assert_se(barrier_wait_abortion(&b));
@ -315,7 +315,7 @@ TEST_BARRIER(test_barrier_wait_abortion,
* This runs wait_abortion() without any remote abortion going on. It thus must * This runs wait_abortion() without any remote abortion going on. It thus must
* timeout. * timeout.
*/ */
TEST_BARRIER(test_barrier_wait_abortion_unmatched, TEST_BARRIER(barrier_wait_abortion_unmatched,
({ ({
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
assert_se(barrier_wait_abortion(&b)); assert_se(barrier_wait_abortion(&b));
@ -331,7 +331,7 @@ TEST_BARRIER(test_barrier_wait_abortion_unmatched,
* Test matched wait_abortion() with local abortion * Test matched wait_abortion() with local abortion
* This runs wait_abortion() with local and remote abortion. * This runs wait_abortion() with local and remote abortion.
*/ */
TEST_BARRIER(test_barrier_wait_abortion_local, TEST_BARRIER(barrier_wait_abortion_local,
({ ({
set_alarm(BASE_TIME * 10); set_alarm(BASE_TIME * 10);
assert_se(barrier_abort(&b)); assert_se(barrier_abort(&b));
@ -347,7 +347,7 @@ TEST_BARRIER(test_barrier_wait_abortion_local,
* Test unmatched wait_abortion() with local abortion * Test unmatched wait_abortion() with local abortion
* This runs wait_abortion() with only local abortion. This must time out. * This runs wait_abortion() with only local abortion. This must time out.
*/ */
TEST_BARRIER(test_barrier_wait_abortion_local_unmatched, TEST_BARRIER(barrier_wait_abortion_local_unmatched,
({ ({
set_alarm(BASE_TIME); set_alarm(BASE_TIME);
assert_se(barrier_abort(&b)); assert_se(barrier_abort(&b));
@ -365,7 +365,7 @@ TEST_BARRIER(test_barrier_wait_abortion_local_unmatched,
* Place barrier and sync with the child. The child only exits()s, which should * Place barrier and sync with the child. The child only exits()s, which should
* cause an implicit abortion and wake the parent. * cause an implicit abortion and wake the parent.
*/ */
TEST_BARRIER(test_barrier_exit, TEST_BARRIER(barrier_exit,
({ ({
}), }),
TEST_BARRIER_WAIT_SUCCESS(pid1), TEST_BARRIER_WAIT_SUCCESS(pid1),
@ -382,7 +382,7 @@ TEST_BARRIER(test_barrier_exit,
* child-exit. We add a usleep() which triggers the alarm in the parent and * child-exit. We add a usleep() which triggers the alarm in the parent and
* causes the test to time out. * causes the test to time out.
*/ */
TEST_BARRIER(test_barrier_no_exit, TEST_BARRIER(barrier_no_exit,
({ ({
sleep_for(BASE_TIME * 2); sleep_for(BASE_TIME * 2);
}), }),
@ -404,7 +404,7 @@ TEST_BARRIER(test_barrier_no_exit,
* succeeds. Only if we place one more barrier, we're ahead of the remote, thus * succeeds. Only if we place one more barrier, we're ahead of the remote, thus
* we will fail due to HUP on the pipe. * we will fail due to HUP on the pipe.
*/ */
TEST_BARRIER(test_barrier_pending_exit, TEST_BARRIER(barrier_pending_exit,
({ ({
set_alarm(BASE_TIME * 4); set_alarm(BASE_TIME * 4);
sleep_for(BASE_TIME * 2); sleep_for(BASE_TIME * 2);
@ -421,10 +421,9 @@ TEST_BARRIER(test_barrier_pending_exit,
}), }),
TEST_BARRIER_WAIT_SUCCESS(pid2)); TEST_BARRIER_WAIT_SUCCESS(pid2));
int main(int argc, char *argv[]) { DEFINE_CUSTOM_TEST_MAIN(
int v; LOG_INFO,
test_setup_logging(LOG_INFO); ({
if (!slow_tests_enabled()) if (!slow_tests_enabled())
return log_tests_skipped("slow tests are disabled"); return log_tests_skipped("slow tests are disabled");
@ -436,29 +435,11 @@ int main(int argc, char *argv[]) {
* issues when running the test in a virtualized environments, limit it * issues when running the test in a virtualized environments, limit it
* to bare metal machines only, to minimize false-positives in CIs. * to bare metal machines only, to minimize false-positives in CIs.
*/ */
v = detect_virtualization(); int v = detect_virtualization();
if (IN_SET(v, -EPERM, -EACCES)) if (IN_SET(v, -EPERM, -EACCES))
return log_tests_skipped("Cannot detect virtualization"); return log_tests_skipped("Cannot detect virtualization");
if (v != VIRTUALIZATION_NONE) if (v != VIRTUALIZATION_NONE)
return log_tests_skipped("This test requires a baremetal machine"); return log_tests_skipped("This test requires a baremetal machine");
}),
test_barrier_sync(); /* no outro */);
test_barrier_wait_next();
test_barrier_wait_next_twice();
test_barrier_wait_next_twice_sync();
test_barrier_wait_next_twice_local();
test_barrier_wait_next_twice_local_sync();
test_barrier_sync_next();
test_barrier_sync_next_local();
test_barrier_sync_next_local_abort();
test_barrier_wait_abortion();
test_barrier_wait_abortion_unmatched();
test_barrier_wait_abortion_local();
test_barrier_wait_abortion_local_unmatched();
test_barrier_exit();
test_barrier_no_exit();
test_barrier_pending_exit();
return 0;
}

View File

@ -26,7 +26,7 @@ static void log_cgroup_mask(CGroupMask got, CGroupMask expected) {
log_info("Got mask: %s\n", g_store); log_info("Got mask: %s\n", g_store);
} }
static int test_cgroup_mask(void) { TEST_RET(cgroup_mask, .sd_booted = true) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep, *nomem_parent, *nomem_leaf; Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep, *nomem_parent, *nomem_leaf;
@ -138,7 +138,7 @@ static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) {
assert_se(streq_ptr(b, t)); assert_se(streq_ptr(b, t));
} }
static void test_cg_mask_to_string(void) { TEST(cg_mask_to_string) {
test_cg_mask_to_string_one(0, NULL); test_cg_mask_to_string_one(0, NULL);
test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices bpf-foreign bpf-socket-bind bpf-restrict-network-interfaces"); test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices bpf-foreign bpf-socket-bind bpf-restrict-network-interfaces");
test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu"); test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu");
@ -156,13 +156,4 @@ static void test_cg_mask_to_string(void) {
test_cg_mask_to_string_one(CGROUP_MASK_IO|CGROUP_MASK_BLKIO, "io blkio"); test_cg_mask_to_string_one(CGROUP_MASK_IO|CGROUP_MASK_BLKIO, "io blkio");
} }
int main(int argc, char* argv[]) { DEFINE_TEST_MAIN(LOG_DEBUG);
int rc = EXIT_SUCCESS;
test_setup_logging(LOG_DEBUG);
test_cg_mask_to_string();
TEST_REQ_RUNNING_SYSTEMD(rc = test_cgroup_mask());
return rc;
}

View File

@ -8,7 +8,7 @@
#include "tests.h" #include "tests.h"
#include "unit.h" #include "unit.h"
static int test_default_memory_low(void) { TEST_RET(default_memory_low, .sd_booted = true) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
Unit *root, *dml, Unit *root, *dml,
@ -135,12 +135,4 @@ static int test_default_memory_low(void) {
return 0; return 0;
} }
int main(int argc, char* argv[]) { DEFINE_TEST_MAIN(LOG_DEBUG);
int rc = EXIT_SUCCESS;
test_setup_logging(LOG_DEBUG);
TEST_REQ_RUNNING_SYSTEMD(rc = test_default_memory_low());
return rc;
}

View File

@ -28,7 +28,7 @@ static void check_p_d_u(const char *path, int code, const char *result) {
assert_se(streq_ptr(unit, result)); assert_se(streq_ptr(unit, result));
} }
static void test_path_decode_unit(void) { TEST(path_decode_unit) {
check_p_d_u("getty@tty2.service", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service", 0, "getty@tty2.service");
check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service");
check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service"); check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service");
@ -50,7 +50,7 @@ static void check_p_g_u(const char *path, int code, const char *result) {
assert_se(streq_ptr(unit, result)); assert_se(streq_ptr(unit, result));
} }
static void test_path_get_unit(void) { TEST(path_get_unit) {
check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service"); check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service");
check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service"); check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service");
check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service"); check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service");
@ -74,7 +74,7 @@ static void check_p_g_u_u(const char *path, int code, const char *result) {
assert_se(streq_ptr(unit, result)); assert_se(streq_ptr(unit, result));
} }
static void test_path_get_user_unit(void) { TEST(path_get_user_unit) {
check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service");
check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service");
check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service"); check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service");
@ -97,7 +97,7 @@ static void check_p_g_s(const char *path, int code, const char *result) {
assert_se(streq_ptr(s, result)); assert_se(streq_ptr(s, result));
} }
static void test_path_get_session(void) { TEST(path_get_session) {
check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2"); check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2");
check_p_g_s("/session-3.scope", 0, "3"); check_p_g_s("/session-3.scope", 0, "3");
check_p_g_s("/session-.scope", -ENXIO, NULL); check_p_g_s("/session-.scope", -ENXIO, NULL);
@ -111,7 +111,7 @@ static void check_p_g_o_u(const char *path, int code, uid_t result) {
assert_se(uid == result); assert_se(uid == result);
} }
static void test_path_get_owner_uid(void) { TEST(path_get_owner_uid) {
check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000); check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000);
check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006); check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006);
check_p_g_o_u("", -ENXIO, 0); check_p_g_o_u("", -ENXIO, 0);
@ -124,7 +124,7 @@ static void check_p_g_slice(const char *path, int code, const char *result) {
assert_se(streq_ptr(s, result)); assert_se(streq_ptr(s, result));
} }
static void test_path_get_slice(void) { TEST(path_get_slice) {
check_p_g_slice("/user.slice", 0, "user.slice"); check_p_g_slice("/user.slice", 0, "user.slice");
check_p_g_slice("/foobar", 0, SPECIAL_ROOT_SLICE); check_p_g_slice("/foobar", 0, SPECIAL_ROOT_SLICE);
check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice"); check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice");
@ -141,7 +141,7 @@ static void check_p_g_u_slice(const char *path, int code, const char *result) {
assert_se(streq_ptr(s, result)); assert_se(streq_ptr(s, result));
} }
static void test_path_get_user_slice(void) { TEST(path_get_user_slice) {
check_p_g_u_slice("/user.slice", -ENXIO, NULL); check_p_g_u_slice("/user.slice", -ENXIO, NULL);
check_p_g_u_slice("/foobar", -ENXIO, NULL); check_p_g_u_slice("/foobar", -ENXIO, NULL);
check_p_g_u_slice("/user.slice/user-waldo.slice", -ENXIO, NULL); check_p_g_u_slice("/user.slice/user-waldo.slice", -ENXIO, NULL);
@ -158,14 +158,14 @@ static void test_path_get_user_slice(void) {
check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice"); check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice");
} }
static void test_get_paths(void) { TEST(get_paths, .sd_booted = true) {
_cleanup_free_ char *a = NULL; _cleanup_free_ char *a = NULL;
assert_se(cg_get_root_path(&a) >= 0); assert_se(cg_get_root_path(&a) >= 0);
log_info("Root = %s", a); log_info("Root = %s", a);
} }
static void test_proc(void) { TEST(proc) {
_cleanup_closedir_ DIR *d = NULL; _cleanup_closedir_ DIR *d = NULL;
struct dirent *de; struct dirent *de;
int r; int r;
@ -220,7 +220,7 @@ static void test_escape_one(const char *s, const char *r) {
assert_se(streq(cg_unescape(b), s)); assert_se(streq(cg_unescape(b), s));
} }
static void test_escape(void) { TEST(escape, .sd_booted = true) {
test_escape_one("foobar", "foobar"); test_escape_one("foobar", "foobar");
test_escape_one(".foobar", "_.foobar"); test_escape_one(".foobar", "_.foobar");
test_escape_one("foobar.service", "foobar.service"); test_escape_one("foobar.service", "foobar.service");
@ -234,7 +234,7 @@ static void test_escape(void) {
test_escape_one(".", "_."); test_escape_one(".", "_.");
} }
static void test_controller_is_valid(void) { TEST(controller_is_valid) {
assert_se(cg_controller_is_valid("foobar")); assert_se(cg_controller_is_valid("foobar"));
assert_se(cg_controller_is_valid("foo_bar")); assert_se(cg_controller_is_valid("foo_bar"));
assert_se(cg_controller_is_valid("name=foo")); assert_se(cg_controller_is_valid("name=foo"));
@ -260,7 +260,7 @@ static void test_slice_to_path_one(const char *unit, const char *path, int error
assert_se(streq_ptr(ret, path)); assert_se(streq_ptr(ret, path));
} }
static void test_slice_to_path(void) { TEST(slice_to_path) {
test_slice_to_path_one("foobar.slice", "foobar.slice", 0); test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0); test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL); test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
@ -292,16 +292,14 @@ static void test_shift_path_one(const char *raw, const char *root, const char *s
assert_se(streq(s, shifted)); assert_se(streq(s, shifted));
} }
static void test_shift_path(void) { TEST(shift_path) {
test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo");
test_shift_path_one("/foobar/waldo", "", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "", "/foobar/waldo");
test_shift_path_one("/foobar/waldo", "/foobar", "/waldo"); test_shift_path_one("/foobar/waldo", "/foobar", "/waldo");
test_shift_path_one("/foobar/waldo", "/hogehoge", "/foobar/waldo"); test_shift_path_one("/foobar/waldo", "/hogehoge", "/foobar/waldo");
} }
static void test_mask_supported(void) { TEST(mask_supported, .sd_booted = true) {
CGroupMask m; CGroupMask m;
CGroupController c; CGroupController c;
@ -311,7 +309,7 @@ static void test_mask_supported(void) {
printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c))); printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c)));
} }
static void test_is_cgroup_fs(void) { TEST(is_cgroup_fs, .sd_booted = true) {
struct statfs sfs; struct statfs sfs;
assert_se(statfs("/sys/fs/cgroup", &sfs) == 0); assert_se(statfs("/sys/fs/cgroup", &sfs) == 0);
if (is_temporary_fs(&sfs)) if (is_temporary_fs(&sfs))
@ -319,7 +317,7 @@ static void test_is_cgroup_fs(void) {
assert_se(is_cgroup_fs(&sfs)); assert_se(is_cgroup_fs(&sfs));
} }
static void test_fd_is_cgroup_fs(void) { TEST(fd_is_cgroup_fs, .sd_booted = true) {
int fd; int fd;
fd = open("/sys/fs/cgroup", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); fd = open("/sys/fs/cgroup", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
@ -333,7 +331,7 @@ static void test_fd_is_cgroup_fs(void) {
fd = safe_close(fd); fd = safe_close(fd);
} }
static void test_cg_tests(void) { TEST(cg_tests) {
int all, hybrid, systemd, r; int all, hybrid, systemd, r;
r = cg_unified(); r = cg_unified();
@ -364,7 +362,7 @@ static void test_cg_tests(void) {
assert_se(!systemd); assert_se(!systemd);
} }
static void test_cg_get_keyed_attribute(void) { TEST(cg_get_keyed_attribute) {
_cleanup_free_ char *val = NULL; _cleanup_free_ char *val = NULL;
char *vals3[3] = {}, *vals3a[3] = {}; char *vals3[3] = {}, *vals3a[3] = {};
int i, r; int i, r;
@ -429,27 +427,4 @@ static void test_cg_get_keyed_attribute(void) {
} }
} }
int main(void) { DEFINE_TEST_MAIN(LOG_DEBUG);
test_setup_logging(LOG_DEBUG);
test_path_decode_unit();
test_path_get_unit();
test_path_get_user_unit();
test_path_get_session();
test_path_get_owner_uid();
test_path_get_slice();
test_path_get_user_slice();
TEST_REQ_RUNNING_SYSTEMD(test_get_paths());
test_proc();
TEST_REQ_RUNNING_SYSTEMD(test_escape());
test_controller_is_valid();
test_slice_to_path();
test_shift_path();
TEST_REQ_RUNNING_SYSTEMD(test_mask_supported());
TEST_REQ_RUNNING_SYSTEMD(test_is_cgroup_fs());
TEST_REQ_RUNNING_SYSTEMD(test_fd_is_cgroup_fs());
test_cg_tests();
test_cg_get_keyed_attribute();
return 0;
}

View File

@ -30,7 +30,7 @@
/* Nontrivial value serves as a placeholder to check that parsing function (didn't) change it */ /* Nontrivial value serves as a placeholder to check that parsing function (didn't) change it */
#define CGROUP_LIMIT_DUMMY 3 #define CGROUP_LIMIT_DUMMY 3
static int test_unit_file_get_set(void) { TEST_RET(unit_file_get_set) {
int r; int r;
Hashmap *h; Hashmap *h;
UnitFileList *p; UnitFileList *p;
@ -78,7 +78,7 @@ static void check_execcommand(ExecCommand *c,
assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore); assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
} }
static void test_config_parse_exec(void) { TEST(config_parse_exec) {
/* int config_parse_exec( /* int config_parse_exec(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -422,7 +422,7 @@ static void test_config_parse_exec(void) {
exec_command_free_list(c); exec_command_free_list(c);
} }
static void test_config_parse_log_extra_fields(void) { TEST(config_parse_log_extra_fields) {
/* int config_parse_log_extra_fields( /* int config_parse_log_extra_fields(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -486,7 +486,7 @@ static void test_config_parse_log_extra_fields(void) {
log_info("/* %s bye */", __func__); log_info("/* %s bye */", __func__);
} }
static void test_install_printf(void) { TEST(install_printf, .sd_booted = true) {
char name[] = "name.service", char name[] = "name.service",
path[] = "/run/systemd/system/name.service"; path[] = "/run/systemd/system/name.service";
UnitFileInstallInfo i = { .name = name, .path = path, }; UnitFileInstallInfo i = { .name = name, .path = path, };
@ -565,7 +565,7 @@ static uint64_t make_cap(int cap) {
return ((uint64_t) 1ULL << (uint64_t) cap); return ((uint64_t) 1ULL << (uint64_t) cap);
} }
static void test_config_parse_capability_set(void) { TEST(config_parse_capability_set) {
/* int config_parse_capability_set( /* int config_parse_capability_set(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -618,7 +618,7 @@ static void test_config_parse_capability_set(void) {
assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
} }
static void test_config_parse_rlimit(void) { TEST(config_parse_rlimit) {
struct rlimit * rl[_RLIMIT_MAX] = {}; struct rlimit * rl[_RLIMIT_MAX] = {};
assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0); assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
@ -732,7 +732,7 @@ static void test_config_parse_rlimit(void) {
rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]); rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
} }
static void test_config_parse_pass_environ(void) { TEST(config_parse_pass_environ) {
/* int config_parse_pass_environ( /* int config_parse_pass_environ(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -769,11 +769,11 @@ static void test_config_parse_pass_environ(void) {
assert_se(streq(passenv[0], "normal_name")); assert_se(streq(passenv[0], "normal_name"));
} }
static void test_unit_dump_config_items(void) { TEST(unit_dump_config_items) {
unit_dump_config_items(stdout); unit_dump_config_items(stdout);
} }
static void test_config_parse_memory_limit(void) { TEST(config_parse_memory_limit) {
/* int config_parse_memory_limit( /* int config_parse_memory_limit(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -829,7 +829,7 @@ static void test_config_parse_memory_limit(void) {
} }
static void test_contains_instance_specifier_superset(void) { TEST(contains_instance_specifier_superset) {
assert_se(contains_instance_specifier_superset("foobar@a%i")); assert_se(contains_instance_specifier_superset("foobar@a%i"));
assert_se(contains_instance_specifier_superset("foobar@%ia")); assert_se(contains_instance_specifier_superset("foobar@%ia"));
assert_se(contains_instance_specifier_superset("foobar@%n")); assert_se(contains_instance_specifier_superset("foobar@%n"));
@ -851,7 +851,7 @@ static void test_contains_instance_specifier_superset(void) {
assert_se(!contains_instance_specifier_superset("@%a%b")); assert_se(!contains_instance_specifier_superset("@%a%b"));
} }
static void test_unit_is_recursive_template_dependency(void) { TEST(unit_is_recursive_template_dependency) {
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
Unit *u; Unit *u;
int r; int r;
@ -894,29 +894,15 @@ static void test_unit_is_recursive_template_dependency(void) {
assert_se(unit_is_likely_recursive_template_dependency(u, "foobar@foobar@123.mount", "foobar@%n.mount") == 0); assert_se(unit_is_likely_recursive_template_dependency(u, "foobar@foobar@123.mount", "foobar@%n.mount") == 0);
} }
int main(int argc, char *argv[]) { DEFINE_CUSTOM_TEST_MAIN(
LOG_INFO,
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r; ({
if (enter_cgroup_subroot(NULL) == -ENOMEDIUM)
test_setup_logging(LOG_INFO);
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available"); return log_tests_skipped("cgroupfs not available");
assert_se(runtime_dir = setup_fake_runtime_dir()); assert_se(runtime_dir = setup_fake_runtime_dir());
}),
r = test_unit_file_get_set(); /* no outro */);
test_config_parse_exec();
test_config_parse_log_extra_fields();
test_config_parse_capability_set();
test_config_parse_rlimit();
test_config_parse_pass_environ();
TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
test_unit_dump_config_items();
test_config_parse_memory_limit();
test_contains_instance_specifier_superset();
test_unit_is_recursive_template_dependency();
return r;
}

View File

@ -14,7 +14,7 @@
#include "util.h" #include "util.h"
#include "virt.h" #include "virt.h"
static void test_namespace_cleanup_tmpdir(void) { TEST(namespace_cleanup_tmpdir) {
{ {
_cleanup_(namespace_cleanup_tmpdirp) char *dir; _cleanup_(namespace_cleanup_tmpdirp) char *dir;
assert_se(dir = strdup(RUN_SYSTEMD_EMPTY)); assert_se(dir = strdup(RUN_SYSTEMD_EMPTY));
@ -27,7 +27,7 @@ static void test_namespace_cleanup_tmpdir(void) {
} }
} }
static void test_tmpdir(const char *id, const char *A, const char *B) { static void test_tmpdir_one(const char *id, const char *A, const char *B) {
_cleanup_free_ char *a, *b; _cleanup_free_ char *a, *b;
struct stat x, y; struct stat x, y;
char *c, *d; char *c, *d;
@ -63,6 +63,26 @@ static void test_tmpdir(const char *id, const char *A, const char *B) {
} }
} }
TEST(tmpdir) {
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL;
sd_id128_t bid;
assert_se(sd_id128_get_boot(&bid) >= 0);
x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
assert_se(x && y);
test_tmpdir_one("abcd.service", x, y);
z = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
zz = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
assert_se(z && zz);
test_tmpdir_one("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
}
static void test_shareable_ns(unsigned long nsflag) { static void test_shareable_ns(unsigned long nsflag) {
_cleanup_close_pair_ int s[2] = { -1, -1 }; _cleanup_close_pair_ int s[2] = { -1, -1 };
pid_t pid1, pid2, pid3; pid_t pid1, pid2, pid3;
@ -121,15 +141,15 @@ static void test_shareable_ns(unsigned long nsflag) {
assert_se(n == 1); assert_se(n == 1);
} }
static void test_netns(void) { TEST(netns) {
test_shareable_ns(CLONE_NEWNET); test_shareable_ns(CLONE_NEWNET);
} }
static void test_ipcns(void) { TEST(ipcns) {
test_shareable_ns(CLONE_NEWIPC); test_shareable_ns(CLONE_NEWIPC);
} }
static void test_protect_kernel_logs(void) { TEST(protect_kernel_logs) {
int r; int r;
pid_t pid; pid_t pid;
static const NamespaceInfo ns_info = { static const NamespaceInfo ns_info = {
@ -200,37 +220,10 @@ static void test_protect_kernel_logs(void) {
assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS); assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS);
} }
int main(int argc, char *argv[]) { DEFINE_CUSTOM_TEST_MAIN(
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL; LOG_INFO,
sd_id128_t bid; ({
if (!have_namespaces())
test_setup_logging(LOG_INFO); return log_tests_skipped("Don't have namespace support");
}),
test_namespace_cleanup_tmpdir(); /* no outro */);
if (!have_namespaces()) {
log_tests_skipped("Don't have namespace support");
return EXIT_TEST_SKIP;
}
assert_se(sd_id128_get_boot(&bid) >= 0);
x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
assert_se(x && y);
test_tmpdir("abcd.service", x, y);
z = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
zz = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
assert_se(z && zz);
test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
test_netns();
test_ipcns();
test_protect_kernel_logs();
return EXIT_SUCCESS;
}

View File

@ -94,7 +94,7 @@ TEST(parse_mode) {
assert_se(parse_mode(" 1", &m) >= 0 && m == 1); assert_se(parse_mode(" 1", &m) >= 0 && m == 1);
} }
TEST(parse_size) { TEST(parse_size_iec) {
uint64_t bytes; uint64_t bytes;
assert_se(parse_size("", 1024, &bytes) == -EINVAL); assert_se(parse_size("", 1024, &bytes) == -EINVAL);
@ -164,6 +164,76 @@ TEST(parse_size) {
assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
} }
TEST(parse_size_si) {
uint64_t bytes;
assert_se(parse_size("", 1000, &bytes) == -EINVAL);
assert_se(parse_size("111", 1000, &bytes) == 0);
assert_se(bytes == 111);
assert_se(parse_size("111.4", 1000, &bytes) == 0);
assert_se(bytes == 111);
assert_se(parse_size(" 112 B", 1000, &bytes) == 0);
assert_se(bytes == 112);
assert_se(parse_size(" 112.6 B", 1000, &bytes) == 0);
assert_se(bytes == 112);
assert_se(parse_size("3.5 K", 1000, &bytes) == 0);
assert_se(bytes == 3*1000 + 500);
assert_se(parse_size("3. K", 1000, &bytes) == 0);
assert_se(bytes == 3*1000);
assert_se(parse_size("3.0 K", 1000, &bytes) == 0);
assert_se(bytes == 3*1000);
assert_se(parse_size("3. 0 K", 1000, &bytes) == -EINVAL);
assert_se(parse_size(" 4 M 11.5K", 1000, &bytes) == 0);
assert_se(bytes == 4*1000*1000 + 11 * 1000 + 500);
assert_se(parse_size("3B3.5G", 1000, &bytes) == -EINVAL);
assert_se(parse_size("3.5G3B", 1000, &bytes) == 0);
assert_se(bytes == 3ULL*1000*1000*1000 + 500*1000*1000 + 3);
assert_se(parse_size("3.5G 4B", 1000, &bytes) == 0);
assert_se(bytes == 3ULL*1000*1000*1000 + 500*1000*1000 + 4);
assert_se(parse_size("3B3G4T", 1000, &bytes) == -EINVAL);
assert_se(parse_size("4T3G3B", 1000, &bytes) == 0);
assert_se(bytes == (4ULL*1000 + 3)*1000*1000*1000 + 3);
assert_se(parse_size(" 4 T 3 G 3 B", 1000, &bytes) == 0);
assert_se(bytes == (4ULL*1000 + 3)*1000*1000*1000 + 3);
assert_se(parse_size("12P", 1000, &bytes) == 0);
assert_se(bytes == 12ULL * 1000*1000*1000*1000*1000);
assert_se(parse_size("12P12P", 1000, &bytes) == -EINVAL);
assert_se(parse_size("3E 2P", 1000, &bytes) == 0);
assert_se(bytes == (3 * 1000 + 2ULL) * 1000*1000*1000*1000*1000);
assert_se(parse_size("12X", 1000, &bytes) == -EINVAL);
assert_se(parse_size("12.5X", 1000, &bytes) == -EINVAL);
assert_se(parse_size("12.5e3", 1000, &bytes) == -EINVAL);
assert_se(parse_size("1000E", 1000, &bytes) == -ERANGE);
assert_se(parse_size("-1", 1000, &bytes) == -ERANGE);
assert_se(parse_size("-1000E", 1000, &bytes) == -ERANGE);
assert_se(parse_size("-1000P", 1000, &bytes) == -ERANGE);
assert_se(parse_size("-10B 20K", 1000, &bytes) == -ERANGE);
}
TEST(parse_range) { TEST(parse_range) {
unsigned lower, upper; unsigned lower, upper;

View File

@ -93,5 +93,13 @@ int main(void) {
printf("timeval: %zu\n", sizeof(struct timeval)); printf("timeval: %zu\n", sizeof(struct timeval));
printf("timespec: %zu\n", sizeof(struct timespec)); printf("timespec: %zu\n", sizeof(struct timespec));
void *x = malloc(100);
printf("local variable: %p\n", &function_pointer);
printf("glibc function: %p\n", memcpy);
printf("heap allocation: %p\n", x);
free(x);
return 0; return 0;
} }

View File

@ -17,9 +17,8 @@
#include "tests.h" #include "tests.h"
#include "util.h" #include "util.h"
static void test_parse_sleep_config(void) { TEST(parse_sleep_config) {
_cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
log_info("/* %s */", __func__);
assert_se(parse_sleep_config(&sleep_config) == 0); assert_se(parse_sleep_config(&sleep_config) == 0);
@ -43,7 +42,7 @@ static void test_parse_sleep_config(void) {
log_debug(" states: %s", hys); log_debug(" states: %s", hys);
} }
static int test_fiemap(const char *path) { static int test_fiemap_one(const char *path) {
_cleanup_free_ struct fiemap *fiemap = NULL; _cleanup_free_ struct fiemap *fiemap = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
int r; int r;
@ -71,7 +70,20 @@ static int test_fiemap(const char *path) {
return 0; return 0;
} }
static void test_sleep(void) { TEST_RET(fiemap) {
int r = 0;
assert_se(test_fiemap_one(saved_argv[0]) == 0);
for (int i = 1; i < saved_argc; i++) {
int k = test_fiemap_one(saved_argv[i]);
if (r == 0)
r = k;
}
return r;
}
TEST(sleep) {
_cleanup_strv_free_ char _cleanup_strv_free_ char
**standby = strv_new("standby"), **standby = strv_new("standby"),
**mem = strv_new("mem"), **mem = strv_new("mem"),
@ -83,8 +95,6 @@ static void test_sleep(void) {
**freeze = strv_new("freeze"); **freeze = strv_new("freeze");
int r; int r;
log_info("/* %s */", __func__);
printf("Secure boot: %sd\n", enable_disable(is_efi_secure_boot())); printf("Secure boot: %sd\n", enable_disable(is_efi_secure_boot()));
log_info("/= individual sleep modes =/"); log_info("/= individual sleep modes =/");
@ -108,25 +118,10 @@ static void test_sleep(void) {
log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
} }
int main(int argc, char* argv[]) { DEFINE_CUSTOM_TEST_MAIN(
int i, r = 0, k; LOG_DEBUG,
({
test_setup_logging(LOG_DEBUG);
if (getuid() != 0) if (getuid() != 0)
log_warning("This program is unlikely to work for unprivileged users"); log_warning("This program is unlikely to work for unprivileged users");
}),
test_parse_sleep_config(); /* no outro */);
test_sleep();
if (argc <= 1)
assert_se(test_fiemap(argv[0]) == 0);
else
for (i = 1; i < argc; i++) {
k = test_fiemap(argv[i]);
if (r == 0)
r = k;
}
return r;
}

View File

@ -33,9 +33,7 @@ static void test_unit_name_is_valid_one(const char *name, UnitNameFlags flags, b
assert_se(unit_name_is_valid(name, flags) == expected); assert_se(unit_name_is_valid(name, flags) == expected);
} }
static void test_unit_name_is_valid(void) { TEST(unit_name_is_valid) {
log_info("/* %s */", __func__);
test_unit_name_is_valid_one("foo.service", UNIT_NAME_ANY, true); test_unit_name_is_valid_one("foo.service", UNIT_NAME_ANY, true);
test_unit_name_is_valid_one("foo.service", UNIT_NAME_PLAIN, true); test_unit_name_is_valid_one("foo.service", UNIT_NAME_PLAIN, true);
test_unit_name_is_valid_one("foo.service", UNIT_NAME_INSTANCE, false); test_unit_name_is_valid_one("foo.service", UNIT_NAME_INSTANCE, false);
@ -91,9 +89,7 @@ static void test_unit_name_replace_instance_one(const char *pattern, const char
assert_se(streq_ptr(t, expected)); assert_se(streq_ptr(t, expected));
} }
static void test_unit_name_replace_instance(void) { TEST(unit_name_replace_instance) {
log_info("/* %s */", __func__);
test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0); test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0);
test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0); test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL); test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL);
@ -119,9 +115,7 @@ static void test_unit_name_from_path_one(const char *path, const char *suffix, c
} }
} }
static void test_unit_name_from_path(void) { TEST(unit_name_from_path) {
log_info("/* %s */", __func__);
test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0); test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0);
test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0); test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0); test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
@ -149,9 +143,7 @@ static void test_unit_name_from_path_instance_one(const char *pattern, const cha
} }
} }
static void test_unit_name_from_path_instance(void) { TEST(unit_name_from_path_instance) {
log_info("/* %s */", __func__);
test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0); test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0); test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0); test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0);
@ -170,9 +162,7 @@ static void test_unit_name_to_path_one(const char *unit, const char *path, int r
assert_se(streq_ptr(path, p)); assert_se(streq_ptr(path, p));
} }
static void test_unit_name_to_path(void) { TEST(unit_name_to_path) {
log_info("/* %s */", __func__);
test_unit_name_to_path_one("home.mount", "/home", 0); test_unit_name_to_path_one("home.mount", "/home", 0);
test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0); test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0);
test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL); test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL);
@ -201,9 +191,7 @@ static void test_unit_name_mangle_one(bool allow_globs, const char *pattern, con
} }
} }
static void test_unit_name_mangle(void) { TEST(unit_name_mangle) {
log_info("/* %s */", __func__);
test_unit_name_mangle_one(false, "foo.service", "foo.service", 0); test_unit_name_mangle_one(false, "foo.service", "foo.service", 0);
test_unit_name_mangle_one(false, "/home", "home.mount", 1); test_unit_name_mangle_one(false, "/home", "home.mount", 1);
test_unit_name_mangle_one(false, "/dev/sda", "dev-sda.device", 1); test_unit_name_mangle_one(false, "/dev/sda", "dev-sda.device", 1);
@ -220,14 +208,12 @@ static void test_unit_name_mangle(void) {
test_unit_name_mangle_one(true, "ü*", "\\xc3\\xbc*", 1); test_unit_name_mangle_one(true, "ü*", "\\xc3\\xbc*", 1);
} }
static int test_unit_printf(void) { TEST_RET(unit_printf, .sd_booted = true) {
_cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL; _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
Unit *u; Unit *u;
int r; int r;
log_info("/* %s */", __func__);
assert_se(specifier_machine_id('m', NULL, NULL, NULL, &mid) >= 0 && mid); assert_se(specifier_machine_id('m', NULL, NULL, NULL, &mid) >= 0 && mid);
assert_se(specifier_boot_id('b', NULL, NULL, NULL, &bid) >= 0 && bid); assert_se(specifier_boot_id('b', NULL, NULL, NULL, &bid) >= 0 && bid);
assert_se(host = gethostname_malloc()); assert_se(host = gethostname_malloc());
@ -328,9 +314,7 @@ static int test_unit_printf(void) {
return 0; return 0;
} }
static void test_unit_instance_is_valid(void) { TEST(unit_instance_is_valid) {
log_info("/* %s */", __func__);
assert_se(unit_instance_is_valid("fooBar")); assert_se(unit_instance_is_valid("fooBar"));
assert_se(unit_instance_is_valid("foo-bar")); assert_se(unit_instance_is_valid("foo-bar"));
assert_se(unit_instance_is_valid("foo.stUff")); assert_se(unit_instance_is_valid("foo.stUff"));
@ -343,9 +327,7 @@ static void test_unit_instance_is_valid(void) {
assert_se(!unit_instance_is_valid("foo/bar")); assert_se(!unit_instance_is_valid("foo/bar"));
} }
static void test_unit_prefix_is_valid(void) { TEST(unit_prefix_is_valid) {
log_info("/* %s */", __func__);
assert_se(unit_prefix_is_valid("fooBar")); assert_se(unit_prefix_is_valid("fooBar"));
assert_se(unit_prefix_is_valid("foo-bar")); assert_se(unit_prefix_is_valid("foo-bar"));
assert_se(unit_prefix_is_valid("foo.stUff")); assert_se(unit_prefix_is_valid("foo.stUff"));
@ -359,11 +341,9 @@ static void test_unit_prefix_is_valid(void) {
assert_se(!unit_prefix_is_valid("@foo-bar")); assert_se(!unit_prefix_is_valid("@foo-bar"));
} }
static void test_unit_name_change_suffix(void) { TEST(unit_name_change_suffix) {
char *t; char *t;
log_info("/* %s */", __func__);
assert_se(unit_name_change_suffix("foo.mount", ".service", &t) == 0); assert_se(unit_name_change_suffix("foo.mount", ".service", &t) == 0);
assert_se(streq(t, "foo.service")); assert_se(streq(t, "foo.service"));
free(t); free(t);
@ -373,11 +353,9 @@ static void test_unit_name_change_suffix(void) {
free(t); free(t);
} }
static void test_unit_name_build(void) { TEST(unit_name_build) {
char *t; char *t;
log_info("/* %s */", __func__);
assert_se(unit_name_build("foo", "bar", ".service", &t) == 0); assert_se(unit_name_build("foo", "bar", ".service", &t) == 0);
assert_se(streq(t, "foo@bar.service")); assert_se(streq(t, "foo@bar.service"));
free(t); free(t);
@ -391,9 +369,7 @@ static void test_unit_name_build(void) {
free(t); free(t);
} }
static void test_slice_name_is_valid(void) { TEST(slice_name_is_valid) {
log_info("/* %s */", __func__);
assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE)); assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE));
assert_se( slice_name_is_valid("foo.slice")); assert_se( slice_name_is_valid("foo.slice"));
assert_se( slice_name_is_valid("foo-bar.slice")); assert_se( slice_name_is_valid("foo-bar.slice"));
@ -422,12 +398,10 @@ static void test_slice_name_is_valid(void) {
assert_se(!slice_name_is_valid("foo@bar.service")); assert_se(!slice_name_is_valid("foo@bar.service"));
} }
static void test_build_subslice(void) { TEST(build_subslice) {
char *a; char *a;
char *b; char *b;
log_info("/* %s */", __func__);
assert_se(slice_build_subslice(SPECIAL_ROOT_SLICE, "foo", &a) >= 0); assert_se(slice_build_subslice(SPECIAL_ROOT_SLICE, "foo", &a) >= 0);
assert_se(slice_build_subslice(a, "bar", &b) >= 0); assert_se(slice_build_subslice(a, "bar", &b) >= 0);
free(a); free(a);
@ -449,9 +423,7 @@ static void test_build_parent_slice_one(const char *name, const char *expect, in
assert_se(streq_ptr(s, expect)); assert_se(streq_ptr(s, expect));
} }
static void test_build_parent_slice(void) { TEST(build_parent_slice) {
log_info("/* %s */", __func__);
test_build_parent_slice_one(SPECIAL_ROOT_SLICE, NULL, 0); test_build_parent_slice_one(SPECIAL_ROOT_SLICE, NULL, 0);
test_build_parent_slice_one("foo.slice", SPECIAL_ROOT_SLICE, 1); test_build_parent_slice_one("foo.slice", SPECIAL_ROOT_SLICE, 1);
test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1); test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1);
@ -470,12 +442,10 @@ static void test_build_parent_slice(void) {
test_build_parent_slice_one("@.slice", NULL, -EINVAL); test_build_parent_slice_one("@.slice", NULL, -EINVAL);
} }
static void test_unit_name_to_instance(void) { TEST(unit_name_to_instance) {
UnitNameFlags r; UnitNameFlags r;
char *instance; char *instance;
log_info("/* %s */", __func__);
r = unit_name_to_instance("foo@bar.service", &instance); r = unit_name_to_instance("foo@bar.service", &instance);
assert_se(r == UNIT_NAME_INSTANCE); assert_se(r == UNIT_NAME_INSTANCE);
assert_se(streq(instance, "bar")); assert_se(streq(instance, "bar"));
@ -504,11 +474,9 @@ static void test_unit_name_to_instance(void) {
assert_se(!instance); assert_se(!instance);
} }
static void test_unit_name_escape(void) { TEST(unit_name_escape) {
_cleanup_free_ char *r; _cleanup_free_ char *r;
log_info("/* %s */", __func__);
r = unit_name_escape("ab+-c.a/bc@foo.service"); r = unit_name_escape("ab+-c.a/bc@foo.service");
assert_se(r); assert_se(r);
assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service")); assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
@ -522,9 +490,7 @@ static void test_u_n_t_one(const char *name, const char *expected, int ret) {
assert_se(streq_ptr(f, expected)); assert_se(streq_ptr(f, expected));
} }
static void test_unit_name_template(void) { TEST(unit_name_template) {
log_info("/* %s */", __func__);
test_u_n_t_one("foo@bar.service", "foo@.service", 0); test_u_n_t_one("foo@bar.service", "foo@.service", 0);
test_u_n_t_one("foo.mount", NULL, -EINVAL); test_u_n_t_one("foo.mount", NULL, -EINVAL);
} }
@ -536,9 +502,7 @@ static void test_unit_name_path_unescape_one(const char *name, const char *path,
assert_se(streq_ptr(path, p)); assert_se(streq_ptr(path, p));
} }
static void test_unit_name_path_unescape(void) { TEST(unit_name_path_unescape) {
log_info("/* %s */", __func__);
test_unit_name_path_unescape_one("foo", "/foo", 0); test_unit_name_path_unescape_one("foo", "/foo", 0);
test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0); test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0);
test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0); test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0);
@ -560,9 +524,7 @@ static void test_unit_name_to_prefix_one(const char *input, int ret, const char
assert_se(streq_ptr(k, output)); assert_se(streq_ptr(k, output));
} }
static void test_unit_name_to_prefix(void) { TEST(unit_name_to_prefix) {
log_info("/* %s */", __func__);
test_unit_name_to_prefix_one("foobar.service", 0, "foobar"); test_unit_name_to_prefix_one("foobar.service", 0, "foobar");
test_unit_name_to_prefix_one("", -EINVAL, NULL); test_unit_name_to_prefix_one("", -EINVAL, NULL);
test_unit_name_to_prefix_one("foobar", -EINVAL, NULL); test_unit_name_to_prefix_one("foobar", -EINVAL, NULL);
@ -582,9 +544,7 @@ static void test_unit_name_from_dbus_path_one(const char *input, int ret, const
assert_se(streq_ptr(k, output)); assert_se(streq_ptr(k, output));
} }
static void test_unit_name_from_dbus_path(void) { TEST(unit_name_from_dbus_path) {
log_info("/* %s */", __func__);
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2emount", 0, "-.mount"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2emount", 0, "-.mount");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2eslice", 0, "-.slice"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2eslice", 0, "-.slice");
@ -870,9 +830,7 @@ static void test_unit_name_from_dbus_path(void) {
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/wpa_5fsupplicant_2eservice", 0, "wpa_supplicant.service"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/wpa_5fsupplicant_2eservice", 0, "wpa_supplicant.service");
} }
static void test_unit_name_prefix_equal(void) { TEST(unit_name_prefix_equal) {
log_info("/* %s */", __func__);
assert_se(unit_name_prefix_equal("a.service", "a.service")); assert_se(unit_name_prefix_equal("a.service", "a.service"));
assert_se(unit_name_prefix_equal("a.service", "a.mount")); assert_se(unit_name_prefix_equal("a.service", "a.mount"));
assert_se(unit_name_prefix_equal("a@b.service", "a.service")); assert_se(unit_name_prefix_equal("a@b.service", "a.service"));
@ -886,39 +844,15 @@ static void test_unit_name_prefix_equal(void) {
assert_se(!unit_name_prefix_equal("a", "a")); assert_se(!unit_name_prefix_equal("a", "a"));
} }
int main(int argc, char* argv[]) { DEFINE_CUSTOM_TEST_MAIN(
LOG_INFO,
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r, rc = 0; ({
if (enter_cgroup_subroot(NULL) == -ENOMEDIUM)
test_setup_logging(LOG_INFO);
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available"); return log_tests_skipped("cgroupfs not available");
assert_se(runtime_dir = setup_fake_runtime_dir()); assert_se(runtime_dir = setup_fake_runtime_dir());
}),
test_unit_name_is_valid(); /* no outro */);
test_unit_name_replace_instance();
test_unit_name_from_path();
test_unit_name_from_path_instance();
test_unit_name_mangle();
test_unit_name_to_path();
TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
test_unit_instance_is_valid();
test_unit_prefix_is_valid();
test_unit_name_change_suffix();
test_unit_name_build();
test_slice_name_is_valid();
test_build_subslice();
test_build_parent_slice();
test_unit_name_to_instance();
test_unit_name_escape();
test_unit_name_template();
test_unit_name_path_unescape();
test_unit_name_to_prefix();
test_unit_name_from_dbus_path();
test_unit_name_prefix_equal();
return rc;
}

View File

@ -23,12 +23,10 @@ static void test_deserialize_exec_command_one(Manager *m, const char *key, const
* always rejected with "Current command vanished from the unit file", and we don't leak anything. */ * always rejected with "Current command vanished from the unit file", and we don't leak anything. */
} }
static void test_deserialize_exec_command(void) { TEST(deserialize_exec_command) {
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
int r; int r;
log_info("/* %s */", __func__);
r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
if (manager_errno_skip_test(r)) { if (manager_errno_skip_test(r)) {
log_notice_errno(r, "Skipping test: manager_new: %m"); log_notice_errno(r, "Skipping test: manager_new: %m");
@ -50,19 +48,15 @@ static void test_deserialize_exec_command(void) {
test_deserialize_exec_command_one(m, "control-command", "ExecWhat 11 /a/b c d e", -EINVAL); test_deserialize_exec_command_one(m, "control-command", "ExecWhat 11 /a/b c d e", -EINVAL);
} }
int main(int argc, char *argv[]) { DEFINE_CUSTOM_TEST_MAIN(
LOG_DEBUG,
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r; ({
if (enter_cgroup_subroot(NULL) == -ENOMEDIUM)
test_setup_logging(LOG_DEBUG);
r = enter_cgroup_subroot(NULL);
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available"); return log_tests_skipped("cgroupfs not available");
assert_se(runtime_dir = setup_fake_runtime_dir()); assert_se(runtime_dir = setup_fake_runtime_dir());
}),
test_deserialize_exec_command(); /* no outro */);
return EXIT_SUCCESS;
}

View File

@ -85,7 +85,7 @@ static int inotify_handler(sd_event_source *s,
l = read(fd, &buffer, sizeof(buffer)); l = read(fd, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 0; return 0;
return log_warning_errno(errno, "Lost access to inotify: %m"); return log_warning_errno(errno, "Lost access to inotify: %m");

View File

@ -1349,7 +1349,7 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
l = read(fd, &buffer, sizeof(buffer)); l = read(fd, &buffer, sizeof(buffer));
if (l < 0) { if (l < 0) {
if (IN_SET(errno, EAGAIN, EINTR)) if (ERRNO_IS_TRANSIENT(errno))
return 1; return 1;
return log_error_errno(errno, "Failed to read inotify fd: %m"); return log_error_errno(errno, "Failed to read inotify fd: %m");

View File

@ -17,6 +17,8 @@ PrivateKey=
PrivateKeyFile= PrivateKeyFile=
FwMark= FwMark=
FirewallMark= FirewallMark=
RouteTable=
RouteMetric=
[MACVTAP] [MACVTAP]
Mode= Mode=
SourceMACAddress= SourceMACAddress=
@ -67,6 +69,8 @@ PresharedKeyFile=
PersistentKeepalive= PersistentKeepalive=
PublicKey= PublicKey=
AllowedIPs= AllowedIPs=
RouteTable=
RouteMetric=
[Tunnel] [Tunnel]
FooOverUDP= FooOverUDP=
IPv6FlowLabel= IPv6FlowLabel=

View File

@ -11,6 +11,8 @@ ListenPort=4500
# The key below should be overridden by PrivateKeyFile= # The key below should be overridden by PrivateKeyFile=
PrivateKey=EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong= PrivateKey=EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=
PrivateKeyFile=/run/systemd/network/25-wireguard-private-key.txt PrivateKeyFile=/run/systemd/network/25-wireguard-private-key.txt
RouteTable=1234
RouteMetric=123
# peer 1 # peer 1
[WireGuardPeer] [WireGuardPeer]

View File

@ -6,95 +6,3 @@ Name=wg98
Address=192.168.123.123/24 Address=192.168.123.123/24
Address=fd8d:4d6d:3ccb:0500::1/64 Address=fd8d:4d6d:3ccb:0500::1/64
IPv6AcceptRA=no IPv6AcceptRA=no
# nat64 via 1
[Route]
Destination = fd8d:4d6d:3ccb:0c79:2339:edce::/96
# nat64 via 2
[Route]
Destination = fd8d:4d6d:3ccb:a072:80da:de4f::/96
# nat64 via 3
[Route]
Destination = fd8d:4d6d:3ccb:f349:c4f0:10c1::/96
# nat64 via 4
[Route]
Destination = fd8d:4d6d:3ccb:b684:4f81:2e3e::/96
# nat64 via 5
[Route]
Destination = fd8d:4d6d:3ccb:c624:6bf7:4c09::/96
# nat64 via 6
[Route]
Destination = fd8d:4d6d:3ccb:9c11:d820:2e96::/96
# nat64 via 7
[Route]
Destination = fd8d:4d6d:3ccb:bad5:495d:8e9c::/96
# nat64 via 8
[Route]
Destination = fd8d:4d6d:3ccb:1e54:1415:35d0::/96
# nat64 via 9
[Route]
Destination = fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96
# nat64 via 10
[Route]
Destination = fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96
# nat64 via 11
[Route]
Destination = fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96
# nat64 via 12
[Route]
Destination = fd8d:4d6d:3ccb:d4f9:05dc:9296::/96
# nat64 via 13
[Route]
Destination = fd8d:4d6d:3ccb:b39c:9cdc:755a::/96
# nat64 via 14
[Route]
Destination = fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96
# nat64 via 15
[Route]
Destination = fd8d:4d6d:3ccb:900c:d437:ec27::/96
# nat64 via 16
[Route]
Destination = fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96
# nat64 via 17
[Route]
Destination = fd8d:4d6d:3ccb:e2e1:ae15:103f::/96
# nat64 via 18
[Route]
Destination = fd8d:4d6d:3ccb:5660:679d:3532::/96
# nat64 via 19
[Route]
Destination = fd8d:4d6d:3ccb:6825:573f:30f3::/96
# nat64 via 20
[Route]
Destination = fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96
# nat64 via 21
[Route]
Destination = fd8d:4d6d:3ccb:8d4d:0bab:7280::/96
# nat64 via 22
[Route]
Destination = fd8d:4d6d:3ccb:a3f3:df38:19b0::/96
# nat64 via 23
[Route]
Destination = fd8d:4d6d:3ccb:9742:9931:5217::/96

View File

@ -6,6 +6,9 @@ Kind=wireguard
[WireGuard] [WireGuard]
ListenPort=51820 ListenPort=51820
FwMark=1234 FwMark=1234
# settings below are ignored.
RouteTable=off
RouteMetric=456
[WireGuardPeer] [WireGuardPeer]
PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA= PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=
@ -14,3 +17,5 @@ AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24
Endpoint=192.168.27.3:51820 Endpoint=192.168.27.3:51820
PresharedKey=IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M= PresharedKey=IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=
PersistentKeepalive=20 PersistentKeepalive=20
RouteTable=1234
RouteMetric=123

View File

@ -1383,6 +1383,63 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output) print(output)
self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output) self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output)
output = check_output('ip -4 route show dev wg99 table 1234')
print(output)
self.assertIn('192.168.26.0/24 proto static metric 123', output)
output = check_output('ip -6 route show dev wg99 table 1234')
print(output)
self.assertIn('fd31:bf08:57cb::/48 proto static metric 123 pref medium', output)
output = check_output('ip -6 route show dev wg98 table 1234')
print(output)
self.assertIn('fd8d:4d6d:3ccb:500:c79:2339:edce:ece1 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:1dbf:ca8a:32d3:dd81 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:1e54:1415:35d0:a47c proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:270d:b5dd:4a3f:8909 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:5660:679d:3532:94d8 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:6825:573f:30f3:9472 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:6f2e:6888:c6fd:dfb9 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:8d4d:bab:7280:a09a proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:900c:d437:ec27:8822 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:9742:9931:5217:18d5 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:9c11:d820:2e96:9be0 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:a072:80da:de4f:add1 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:a3f3:df38:19b0:721 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:a94b:cd6a:a32d:90e6 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:b39c:9cdc:755a:ead3 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:b684:4f81:2e3e:132e proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:bad5:495d:8e9c:3427 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:bfe5:c3c3:5d77:fcb proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:c624:6bf7:4c09:3b59 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:d4f9:5dc:9296:a1a proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:dcdd:d33b:90c9:6088 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:e2e1:ae15:103f:f376 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:500:f349:c4f0:10c1:6b4 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:c79:2339:edce::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:1e54:1415:35d0::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:5660:679d:3532::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:6825:573f:30f3::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:8d4d:bab:7280::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:900c:d437:ec27::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:9742:9931:5217::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:9c11:d820:2e96::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:a072:80da:de4f::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:d4f9:5dc:9296::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 proto static metric 123 pref medium', output)
self.assertIn('fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 proto static metric 123 pref medium', output)
if shutil.which('wg'): if shutil.which('wg'):
call('wg') call('wg')

View File

@ -92,6 +92,11 @@ elif [ "${machine}" = "arm" ]; then
verity_guid=7386cdf2-203c-47a9-a498-f2ecce45a2d6 verity_guid=7386cdf2-203c-47a9-a498-f2ecce45a2d6
signature_guid=42b0455f-eb11-491d-98d3-56145ba9d037 signature_guid=42b0455f-eb11-491d-98d3-56145ba9d037
architecture="arm" architecture="arm"
elif [ "${machine}" = "loongarch64" ]; then
root_guid=77055800-792c-4f94-b39a-98c91b762bb6
verity_guid=f3393b22-e9af-4613-a948-9d3bfbd0c535
signature_guid=5afb67eb-ecc8-4f85-ae8e-ac1e7c50e7d0
architecture="loongarch64"
elif [ "${machine}" = "ia64" ]; then elif [ "${machine}" = "ia64" ]; then
root_guid=993d8d3d-f80e-4225-855a-9daf8ed7ea97 root_guid=993d8d3d-f80e-4225-855a-9daf8ed7ea97
verity_guid=86ed10d5-b607-45bb-8957-d350f23d0571 verity_guid=86ed10d5-b607-45bb-8957-d350f23d0571