summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--README.md3
-rw-r--r--TODO14
-rw-r--r--docs/RANDOM_SEEDS.md12
-rw-r--r--hwdb/60-evdev.hwdb7
-rw-r--r--hwdb/60-keyboard.hwdb1
-rw-r--r--hwdb/60-sensor.hwdb8
-rw-r--r--man/resolvectl.xml2
-rw-r--r--man/systemd-nspawn.xml8
-rw-r--r--man/systemd-vconsole-setup.service.xml2
-rw-r--r--man/systemd.kill.xml2
-rw-r--r--man/systemd.network.xml35
-rw-r--r--po/uk.po128
-rw-r--r--rules/50-udev-default.rules.in3
-rw-r--r--rules/60-block.rules4
-rw-r--r--rules/60-persistent-storage.rules2
-rw-r--r--shell-completion/zsh/_busctl219
-rw-r--r--shell-completion/zsh/_resolvectl (renamed from shell-completion/zsh/_systemd-resolve)55
-rw-r--r--shell-completion/zsh/meson.build2
-rw-r--r--src/analyze/analyze-security.c2
-rw-r--r--src/basic/cgroup-util.c3
-rw-r--r--src/basic/extract-word.c2
-rw-r--r--src/basic/log.c28
-rw-r--r--src/basic/missing_syscall.h56
-rw-r--r--src/basic/terminal-util.c27
-rw-r--r--src/basic/time-util.c5
-rw-r--r--src/boot/bootctl.c7
-rw-r--r--src/boot/efi/linux.c24
-rw-r--r--src/boot/efi/meson.build3
-rw-r--r--src/boot/efi/shim.c12
-rw-r--r--src/core/cgroup.c5
-rw-r--r--src/core/dbus-execute.c15
-rw-r--r--src/core/dbus.c4
-rw-r--r--src/core/load-fragment.c6
-rw-r--r--src/core/manager.c24
-rw-r--r--src/core/meson.build7
-rw-r--r--src/core/mount.c3
-rw-r--r--src/core/service.c23
-rw-r--r--src/core/socket.c3
-rw-r--r--src/core/swap.c3
-rw-r--r--src/core/unit.c79
-rw-r--r--src/core/unit.h5
-rw-r--r--src/cryptsetup/cryptsetup-generator.c26
-rw-r--r--src/firstboot/firstboot.c4
-rw-r--r--src/fsck/fsck.c11
-rw-r--r--src/libsystemd-network/dhcp-option.c59
-rw-r--r--src/libsystemd-network/network-internal.c2
-rw-r--r--src/libsystemd/sd-hwdb/sd-hwdb.c3
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c2
-rw-r--r--src/libsystemd/sd-netlink/sd-netlink.c7
-rw-r--r--src/login/logind-action.c8
-rw-r--r--src/login/logind-button.c2
-rw-r--r--src/login/logind-inhibit.c2
-rw-r--r--src/network/networkctl.c2
-rw-r--r--src/network/networkd-address.c7
-rw-r--r--src/network/networkd-dhcp-common.c8
-rw-r--r--src/network/networkd-dhcp6.c8
-rw-r--r--src/network/networkd-ipv4ll.c6
-rw-r--r--src/network/networkd-link.c55
-rw-r--r--src/network/networkd-link.h4
-rw-r--r--src/network/networkd-manager.c227
-rw-r--r--src/network/networkd-manager.h2
-rw-r--r--src/network/networkd-neighbor.c225
-rw-r--r--src/network/networkd-neighbor.h16
-rw-r--r--src/network/networkd-network-gperf.gperf5
-rw-r--r--src/network/networkd-network.c4
-rw-r--r--src/network/networkd-network.h6
-rw-r--r--src/network/networkd-route.c25
-rw-r--r--src/network/networkd-route.h6
-rw-r--r--src/network/networkd-routing-policy-rule.c199
-rw-r--r--src/network/networkd-routing-policy-rule.h5
-rw-r--r--src/network/networkd-util.c25
-rw-r--r--src/network/networkd-util.h23
-rw-r--r--src/network/networkd.c4
-rw-r--r--src/network/test-network-tables.c2
-rw-r--r--src/network/test-networkd-conf.c2
-rw-r--r--src/network/test-routing-policy-rule.c16
-rw-r--r--src/shared/conf-parser.c2
-rw-r--r--src/shared/exit-status.c6
-rw-r--r--src/shared/pretty-print.c27
-rw-r--r--src/shared/seccomp-util.c7
-rw-r--r--src/shared/unit-file.c8
-rw-r--r--src/shared/watchdog.c11
-rw-r--r--src/systemctl/systemctl.c7
-rw-r--r--src/sysusers/sysusers.c6
-rw-r--r--src/test/test-exit-status.c11
-rw-r--r--src/timedate/timedated.c146
-rw-r--r--src/udev/udev-event.c47
-rw-r--r--src/udev/udev-node.c20
-rw-r--r--src/udev/udev-rules.c10
-rw-r--r--src/update-utmp/update-utmp.c3
-rwxr-xr-xtest/TEST-02-CRYPTSETUP/test.sh24
-rwxr-xr-xtest/TEST-18-FAILUREACTION/test.sh2
-rwxr-xr-xtest/TEST-19-DELEGATE/test.sh2
-rwxr-xr-xtest/TEST-24-UNIT-TESTS/test.sh22
-rwxr-xr-xtest/TEST-33-CLEAN-UNIT/test.sh7
l---------test/TEST-36-NUMAPOLICY/Makefile1
-rwxr-xr-xtest/TEST-36-NUMAPOLICY/test.sh46
-rwxr-xr-xtest/TEST-36-NUMAPOLICY/testsuite.sh323
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network1
-rw-r--r--test/test-functions41
-rw-r--r--test/test-network/conf/25-address-preferred-lifetime-zero.network (renamed from test/test-network/conf/25-address-preferred-lifetime-zero-ipv6.network)6
-rw-r--r--test/test-network/conf/25-gateway-next-static.network6
-rw-r--r--test/test-network/conf/25-gateway-static.network6
-rw-r--r--test/test-network/conf/25-neighbor-next.network9
-rw-r--r--test/test-network/conf/routing-policy-rule-test1.network12
-rwxr-xr-xtest/test-network/systemd-networkd-tests.py84
-rw-r--r--tmpfiles.d/meson.build35
-rw-r--r--tmpfiles.d/static-nodes-permissions.conf.in17
-rwxr-xr-xtravis-ci/managers/fuzzit.sh41
-rw-r--r--units/kmod-static-nodes.service.in4
-rw-r--r--units/systemd-logind.service.in1
-rw-r--r--units/systemd-random-seed.service.in2
113 files changed, 2311 insertions, 556 deletions
diff --git a/NEWS b/NEWS
index df303d329e..f6cf064281 100644
--- a/NEWS
+++ b/NEWS
@@ -429,6 +429,9 @@ CHANGES WITH 243 in spe:
option that permits selecting the timout how long to wait for a
device with an encryption key before asking for the password.
+ * IOWeight= has learnt to properly set the IO weight when using the
+ BFQ scheduler officially found in kernels 5.0+.
+
Contributions from: Aaron Barany, Adrian Bunk, Alan Jenkins, Andrej
Valek, Anita Zhang, Arian van Putten, Balint Reczey, Bastien Nocera,
Ben Boeckel, Benjamin Robin, camoz, Chen Qi, Chris Chiu, Chris Down,
diff --git a/README.md b/README.md
index 1c428b3088..688d24b498 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,8 @@
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
[![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
-[![Fuzzit Status](https://app.fuzzit.dev/badge?org_id=RxqRpGNXquIvqrmp4iJS&branch=master)](https://app.fuzzit.dev/admin/RxqRpGNXquIvqrmp4iJS/dashboard)<br/>
+[![Fuzzit Status](https://app.fuzzit.dev/badge?org_id=systemd&branch=master)](https://app.fuzzit.dev/orgs/systemd/dashboard)<br/>
+[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/systemd.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)<br/>
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
[![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
diff --git a/TODO b/TODO
index b10eafe663..78189ce5e9 100644
--- a/TODO
+++ b/TODO
@@ -19,6 +19,15 @@ Janitorial Clean-ups:
Features:
+* coredump: maybe when coredumping read a new xattr from /proc/$PID/exe that
+ may be used to mark a whole binary as non-coredumpable. Would fix:
+ https://bugs.freedesktop.org/show_bug.cgi?id=69447
+
+* adjust OOM score slightly for journald
+
+* beef up hibernation to optionally do swapon/swapoff immediately before/after
+ the hibernation
+
* beef up s2h to implement a battery watch loop: instead of entering
hibernation unconditionally after coming back from resume make a decision
based on the battery load level: if battery level is above a specific
@@ -449,9 +458,6 @@ Features:
* mount: automatically search for "main" partition of an image has multiple
partitions
-* expose the "privileged" flag of ExecCommand on the bus, and open it up to
- transient units
-
* in nss-systemd, if we run inside of RootDirectory= with PrivateUsers= set,
find a way to map the User=/Group= of the service to the right name. This way
a user/group for a service only has to exist on the host for the right
@@ -754,7 +760,6 @@ Features:
* journal:
- consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields
- - import and delete pstore filesystem content at startup
- journald: also get thread ID from client, plus thread name
- journal: when waiting for journal additions in the client always sleep at least 1s or so, in order to minimize wakeups
- add API to close/reopen/get fd for journal client fd in libsystemd-journal.
@@ -1024,7 +1029,6 @@ Features:
- Make sure ID_PATH is always exported and complete for
network devices where possible, so we can safely rely
on Path= matching
- - check MTUBytes parsing (expecting size_t but we are using unsigned)
* sd-rtnl:
- add support for more attribute types
diff --git a/docs/RANDOM_SEEDS.md b/docs/RANDOM_SEEDS.md
index 7edf7c2d6a..926238a3ae 100644
--- a/docs/RANDOM_SEEDS.md
+++ b/docs/RANDOM_SEEDS.md
@@ -190,12 +190,12 @@ boot, in order to ensure the entropy pool is filled up quickly.
master images of an OS are created, and thus replicated into every
installation. If OS image builders carefully reset the random seed file
before generating the image it should be safe to credit entropy, which can
- be enabled by setting the `$SYSTEMD_RANDOM_SEED` environment variable for
- the service to `1`. Note however, that this service typically runs
- relatively late during early boot: long after the initial RAM disk
- (`initrd`) completed, and after the `/var/` file system became
- writable. This is usually too late for many applications, it is hence not
- advised to rely exclusively on this functionality to seed the kernel's
+ be enabled by setting the `$SYSTEMD_RANDOM_SEED_CREDIT` environment variable
+ for the service to `1` (or even `force`, see man page). Note however, that
+ this service typically runs relatively late during early boot: long after
+ the initial RAM disk (`initrd`) completed, and after the `/var/` file system
+ became writable. This is usually too late for many applications, it is hence
+ not advised to rely exclusively on this functionality to seed the kernel's
entropy pool. Also note that this service synchronously waits until the
kernel's entropy pool is initialized before completing start-up. It may thus
be used by other services as synchronization point to order against, if they
diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
index afde1dd447..569b4cb771 100644
--- a/hwdb/60-evdev.hwdb
+++ b/hwdb/60-evdev.hwdb
@@ -345,6 +345,13 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnHP:pnHPSpectreNotebook*
EVDEV_ABS_35=1205:5691:47
EVDEV_ABS_36=1083:4808:65
+# HP Envy x360
+evdev:name:SynPS/2 Synaptics TouchPad:*svnHP:pnHPENVYx360Convertible15m-cn0xxx*
+ EVDEV_ABS_00=1302:5640:36
+ EVDEV_ABS_01=1119:4741:61
+ EVDEV_ABS_35=1302:5640:36
+ EVDEV_ABS_36=1119:4741:61
+
#########################################
# Lenovo
#########################################
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 8edd5d1959..c1f1d16638 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -510,6 +510,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:
# Pavilion and Spectre x360 13 (Prevents random airplane mode activation)
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360*13*:pvr*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360Convertible*:pvr*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*13*x360*:pvr*
KEYBOARD_KEY_d7=unknown
diff --git a/hwdb/60-sensor.hwdb b/hwdb/60-sensor.hwdb
index df7ad251d0..d46af48b17 100644
--- a/hwdb/60-sensor.hwdb
+++ b/hwdb/60-sensor.hwdb
@@ -160,6 +160,10 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrG1D_S165*:svnilife:pnS165:*
sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo:pnX1D3_C806N:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+# Chuwi Hi10 (CWI1515)
+sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrP02A_C106.60E:*:svnDefaultstring:pnDefaultstring:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
# Chuwi Hi10 Pro
sensor:modalias:acpi:BOSC0200*:dmi:*:svn*CHUWIINNOVATIONANDTECHNOLOGY*:pnHi10protablet:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
@@ -386,6 +390,10 @@ sensor:modalias:acpi:SMO8500*:dmi:*:svnMEDION:pnAkoyaE2212TMD99720:*
sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION*:pnE3216*:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+# Medion Akoya E3221 MD61237
+sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION:pnE3221MD61237:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
# Medion Akoya E3222 MD62450
sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION*:pnE3222*:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
diff --git a/man/resolvectl.xml b/man/resolvectl.xml
index a59fa4c66d..ccc1b378f8 100644
--- a/man/resolvectl.xml
+++ b/man/resolvectl.xml
@@ -200,7 +200,7 @@
<varlistentry>
<term><option>status [<replaceable>LINK</replaceable>…]</option></term>
- <listitem><para>Shows the global and per-link DNS settings in currently in effect. If no command is specified,
+ <listitem><para>Shows the global and per-link DNS settings currently in effect. If no command is specified,
this is the implied default.</para></listitem>
</varlistentry>
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 9f0be96b26..db3f10c3a2 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -713,10 +713,10 @@
<varlistentry>
<term><option>--private-users-chown</option></term>
- <listitem><para>If specified, all files and directories in the container's directory tree will adjusted so that
- they are owned to the appropriate UIDs/GIDs selected for the container (see above). This operation is
- potentially expensive, as it involves descending and iterating through the full directory tree of the
- container. Besides actual file ownership, file ACLs are adjusted as well.</para>
+ <listitem><para>If specified, all files and directories in the container's directory tree will be
+ adjusted so that they are owned by the appropriate UIDs/GIDs selected for the container (see above).
+ This operation is potentially expensive, as it involves iterating through the full directory tree of
+ the container. Besides actual file ownership, file ACLs are adjusted as well.</para>
<para>This option is implied if <option>--private-users=pick</option> is used. This option has no effect if
user namespacing is not used.</para></listitem>
diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml
index 268e69c0e7..7e76383720 100644
--- a/man/systemd-vconsole-setup.service.xml
+++ b/man/systemd-vconsole-setup.service.xml
@@ -33,7 +33,7 @@
<title>Description</title>
<para><filename>systemd-vconsole-setup</filename> sets up and configures either all virtual consoles, or — if the
- optional <replaceable>TTY</replaceable> parameter is provided — a specific one. When the system is booting up it's
+ optional <replaceable>TTY</replaceable> parameter is provided — a specific one. When the system is booting up, it's
called by <citerefentry><refentrytitle>systemd-udevd</refentrytitle><manvolnum>8</manvolnum></citerefentry> during
VT console subsystem initialization. Also,
<citerefentry><refentrytitle>systemd-localed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> invokes
diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml
index 1f9d622ce9..2c6fea7493 100644
--- a/man/systemd.kill.xml
+++ b/man/systemd.kill.xml
@@ -79,7 +79,7 @@
signal (see below) is sent to all remaining processes of the
unit's control group. If set to <option>none</option>, no
process is killed. In this case, only the stop command will be
- executed on unit stop, but no process be killed otherwise.
+ executed on unit stop, but no process will be killed otherwise.
Processes remaining alive after stop are left in their control
group and the control group continues to exist after stop
unless it is empty.</para>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index cdcca4aca8..155c0868b2 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -57,7 +57,7 @@
<filename>/run/systemd/network</filename> directories. Drop-in files in
<filename>/etc</filename> take precedence over those in <filename>/run</filename> which in turn
take precedence over those in <filename>/usr/lib</filename>. Drop-in files under any of these
- directories take precedence over the main netdev file wherever located.</para>
+ directories take precedence over the main network file wherever located.</para>
<para>Note that an interface without any static IPv6 addresses configured, and neither DHCPv6
nor IPv6LL enabled, shall be considered to have no IPv6 support. IPv6 will be automatically
@@ -90,7 +90,7 @@
<term><varname>MACAddress=</varname></term>
<listitem>
<para>A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below.
- This option may appear more than one, in which case the lists are merged. If the empty string is assigned to this option, the list
+ This option may appear more than once, in which case the lists are merged. If the empty string is assigned to this option, the list
of hardware addresses defined prior to this is reset.</para>
<para>Example:
@@ -1139,6 +1139,16 @@
<para>A boolean. Specifies whether the rule to be inverted. Defaults to false.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>Family=</varname></term>
+ <listitem>
+ <para>Takes a special value <literal>ipv4</literal>, <literal>ipv6</literal>, or
+ <literal>both</literal>. By default, the address family is determined by the address
+ specified in <varname>To=</varname> or <varname>From=</varname>. If neither
+ <varname>To=</varname> nor <varname>From=</varname> are specified, then defaults to
+ <literal>ipv4</literal>.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -2207,6 +2217,27 @@ DHCP=yes</programlisting>
</example>
<example>
+ <title>IPv6 Prefix Delegation</title>
+
+ <programlisting># /etc/systemd/network/55-ipv6-pd-upstream.network
+[Match]
+Name=enp1s0
+
+[Network]
+DHCP=ipv6</programlisting>
+
+ <programlisting># /etc/systemd/network/56-ipv6-pd-downstream.network
+[Match]
+Name=enp2s0
+
+[Network]
+IPv6PrefixDelegation=dhcpv6</programlisting>
+
+ <para>This will enable IPv6 PD on the interface enp1s0 as an upstream interface where the
+ DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to.</para>
+ </example>
+
+ <example>
<title>A bridge with two enslaved links</title>
<programlisting># /etc/systemd/network/25-bridge-static.network
diff --git a/po/uk.po b/po/uk.po
index 809ab60051..92893607bf 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2019-03-26 15:29+0000\n"
-"PO-Revision-Date: 2019-04-29 19:03+0300\n"
+"POT-Creation-Date: 2019-07-29 15:34+0000\n"
+"PO-Revision-Date: 2019-08-16 09:11+0300\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
"Language: uk\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<"
"=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-"X-Generator: Lokalize 19.03.70\n"
+"X-Generator: Lokalize 19.11.70\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
@@ -502,8 +502,8 @@ msgid ""
"Authentication is required to indicate to the boot loader to boot to the "
"boot loader menu."
msgstr ""
-"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажитися до"
-" меню завантажувача."
+"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажитися до "
+"меню завантажувача."
#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot a specific entry"
@@ -514,8 +514,8 @@ msgid ""
"Authentication is required to indicate to the boot loader to boot into a "
"specific boot loader entry."
msgstr ""
-"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажити"
-" певний пункт меню завантаження."
+"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажити "
+"певний пункт меню завантаження."
#: src/login/org.freedesktop.login1.policy:385
msgid "Set a wall message"
@@ -599,6 +599,95 @@ msgstr ""
"Потрібна автентифікація, щоб керувати локальними образами віртуальних машин "
"і контейнерів."
+#: src/network/org.freedesktop.network1.policy:22
+msgid "Set NTP servers"
+msgstr "Встановлення серверів NTP"
+
+#: src/network/org.freedesktop.network1.policy:23
+msgid "Authentication is required to set NTP servers."
+msgstr "Потрібна автентифікація, щоб встановити сервери NTP."
+
+#: src/network/org.freedesktop.network1.policy:33
+msgid "Set DNS servers"
+msgstr "Встановлення серверів DNS"
+
+#: src/network/org.freedesktop.network1.policy:34
+msgid "Authentication is required to set DNS servers."
+msgstr "Потрібна автентифікація, щоб встановити сервери DNS."
+
+#: src/network/org.freedesktop.network1.policy:44
+msgid "Set domains"
+msgstr "Встановлення доменів"
+
+#: src/network/org.freedesktop.network1.policy:45
+msgid "Authentication is required to set domains."
+msgstr "Потрібна автентифікація, щоб встановити домени."
+
+#: src/network/org.freedesktop.network1.policy:55
+msgid "Set default route"
+msgstr "Встановлення типового маршруту"
+
+#: src/network/org.freedesktop.network1.policy:56
+msgid "Authentication is required to set default route."
+msgstr "Потрібна автентифікація, щоб встановити типовий маршрут."
+
+#: src/network/org.freedesktop.network1.policy:66
+msgid "Enable/disable LLMNR"
+msgstr "Вмикання або вимикання LLMNR"
+
+#: src/network/org.freedesktop.network1.policy:67
+msgid "Authentication is required to enable or disable LLMNR."
+msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути LLMNR."
+
+#: src/network/org.freedesktop.network1.policy:77
+msgid "Enable/disable multicast DNS"
+msgstr "Вмикання або вимикання трансляційного DNS"
+
+#: src/network/org.freedesktop.network1.policy:78
+msgid "Authentication is required to enable or disable multicast DNS."
+msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути трансляційну DNS."
+
+#: src/network/org.freedesktop.network1.policy:88
+msgid "Enable/disable DNS over TLS"
+msgstr "Вмикання і вимикання DNS через TLS"
+
+#: src/network/org.freedesktop.network1.policy:89
+msgid "Authentication is required to enable or disable DNS over TLS."
+msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути DNS через TLS."
+
+#: src/network/org.freedesktop.network1.policy:99
+msgid "Enable/disable DNSSEC"
+msgstr "Вмикання або вимикання DNSSEC"
+
+#: src/network/org.freedesktop.network1.policy:100
+msgid "Authentication is required to enable or disable DNSSEC."
+msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути DNSSEC."
+
+#: src/network/org.freedesktop.network1.policy:110
+msgid "Set DNSSEC Negative Trust Anchors"
+msgstr "Встановлення прив'язок від'ємної довіри DNSSEC"
+
+#: src/network/org.freedesktop.network1.policy:111
+msgid "Authentication is required to set DNSSEC Negative Trust Anchros."
+msgstr ""
+"Потрібна автентифікація, щоб встановити прив'язки від'ємної довіри DNSSEC."
+
+#: src/network/org.freedesktop.network1.policy:121
+msgid "Revert NTP settings"
+msgstr "Повернення до початкових параметрів NTP"
+
+#: src/network/org.freedesktop.network1.policy:122
+msgid "Authentication is required to revert NTP settings."
+msgstr "Потрібна автентифікація, щоб повернутися до початкових параметрів NTP."
+
+#: src/network/org.freedesktop.network1.policy:132
+msgid "Revert DNS settings"
+msgstr "Повернення до початкових параметрів DNS"
+
+#: src/network/org.freedesktop.network1.policy:133
+msgid "Authentication is required to revert DNS settings."
+msgstr "Потрібна автентифікація, щоб повернутися до початкових параметрів DNS."
+
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
msgstr "Інспектування образу портативної служби"
@@ -625,8 +714,8 @@ msgstr "Вилучення або внесення змін до образу п
msgid ""
"Authentication is required to delete or modify a portable service image."
msgstr ""
-"Потрібна автентифікація, щоб вилучити образ портативної служби або внести до"
-" нього зміни."
+"Потрібна автентифікація, щоб вилучити образ портативної служби або внести до "
+"нього зміни."
#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
@@ -684,34 +773,41 @@ msgstr ""
"Потрібна автентифікація, щоб контролювати, чи синхронізування часу через "
"мережу запущено."
-#: src/core/dbus-unit.c:325
+#: src/core/dbus-unit.c:354
msgid "Authentication is required to start '$(unit)'."
msgstr "Потрібна автентифікація, щоб запустити «$(unit)»."
-#: src/core/dbus-unit.c:326
+#: src/core/dbus-unit.c:355
msgid "Authentication is required to stop '$(unit)'."
msgstr "Потрібна автентифікація, щоб зупинити «$(unit)»."
-#: src/core/dbus-unit.c:327
+#: src/core/dbus-unit.c:356
msgid "Authentication is required to reload '$(unit)'."
msgstr "Потрібна автентифікація, щоб перезавантажити «$(unit)»."
-#: src/core/dbus-unit.c:328 src/core/dbus-unit.c:329
+#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358
msgid "Authentication is required to restart '$(unit)'."
msgstr "Потрібна автентифікація, щоб перезапустити «$(unit)»."
-#: src/core/dbus-unit.c:434
+#: src/core/dbus-unit.c:530
msgid ""
"Authentication is required to send a UNIX signal to the processes of "
"'$(unit)'."
msgstr ""
"Потрібна автентифікація, щоб надіслати сигнал UNIX до процесів «$(unit)»."
-#: src/core/dbus-unit.c:465
+#: src/core/dbus-unit.c:561
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgstr "Потрібна автентифікація, щоб скинути «пошкоджений» стан з «$(unit)»."
-#: src/core/dbus-unit.c:498
+#: src/core/dbus-unit.c:594
msgid "Authentication is required to set properties on '$(unit)'."
msgstr "Потрібна автентифікація, щоб вказати властивості на «$(unit)»."
+#: src/core/dbus-unit.c:703
+msgid ""
+"Authentication is required to delete files and directories associated with "
+"'$(unit)'."
+msgstr ""
+"Потрібна автентифікація, щоб вилучити файли і каталоги, які пов'язано із"
+" «$(unit)»."
diff --git a/rules/50-udev-default.rules.in b/rules/50-udev-default.rules.in
index 580b8971a6..50747a1988 100644
--- a/rules/50-udev-default.rules.in
+++ b/rules/50-udev-default.rules.in
@@ -39,6 +39,9 @@ SUBSYSTEM=="cec", GROUP="video"
SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="render", MODE="@GROUP_RENDER_MODE@"
SUBSYSTEM=="kfd", GROUP="render", MODE="@GROUP_RENDER_MODE@"
+# When using static_node= with non-default permissions, also update
+# tmpfiles.d/static-nodes-permissions.conf.in to keep permissions synchronized.
+
SUBSYSTEM=="sound", GROUP="audio", \
OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer"
diff --git a/rules/60-block.rules b/rules/60-block.rules
index 491081f0b2..3134ab995e 100644
--- a/rules/60-block.rules
+++ b/rules/60-block.rules
@@ -8,4 +8,6 @@ ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_
ACTION=="change", SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST=="block", ATTR{block/*/uevent}="change"
# watch metadata changes, caused by tools closing the device node which was opened for writing
-ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*|nvme*|sd*|vd*|xvd*|pmem*|mmcblk*|dasd*|nbd*", OPTIONS+="watch"
+ACTION!="remove", SUBSYSTEM=="block", \
+ KERNEL=="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", \
+ OPTIONS+="watch"
diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
index 1d8880ef02..7802b1c94f 100644
--- a/rules/60-persistent-storage.rules
+++ b/rules/60-persistent-storage.rules
@@ -7,7 +7,7 @@ ACTION=="remove", GOTO="persistent_storage_end"
ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_end"
SUBSYSTEM!="block", GOTO="persistent_storage_end"
-KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end"
+KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end"
# ignore partitions that span the entire disk
TEST=="whole_disk", GOTO="persistent_storage_end"
diff --git a/shell-completion/zsh/_busctl b/shell-completion/zsh/_busctl
index 4e0362423c..0589e99326 100644
--- a/shell-completion/zsh/_busctl
+++ b/shell-completion/zsh/_busctl
@@ -37,6 +37,7 @@
else
local curcontext="$curcontext"
cmd="${${_busctl_cmds[(r)$words[1]:*]%%:*}}"
+ curcontext="${curcontext%:*:*}:busctl-${cmd}:"
if (( $+functions[_busctl_$cmd] )); then
_busctl_$cmd
else
@@ -45,6 +46,218 @@
fi
}
+__busctl() {
+ busctl $_bus_address --no-pager --no-legend "$@" 2>/dev/null
+}
+
+__dbus_matchspec() {
+ # https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing
+ _values -s, 'rules' \
+ 'type[Match on message type]:type:(signal method_call method_return error)' \
+ 'eavesdrop[Include unicast messages]:bool:(true false)' \
+ 'sender[Match messages sent by a particular sender]:sender:{compadd $(_busctl_get_service_names)}'\
+ 'interface[Match messages sent over or to a particular interface]:interface' \
+ 'member[Match messages which have the given method or signal name]:member' \
+ 'path[Match messages which are sent from or to the given object]:path' \
+ 'path_namespace[Match messages which are sent from or to the given namespace]:namespace' \
+ 'destination[Match messaged sent to the given unique name]:unique name:{compadd $(_busctl_get_unique_names)}'
+}
+
+(( $+functions[_busctl_get_json] )) || _busctl_get_json()
+{
+ local -a _json_forms
+ _json_forms=( $(__busctl --json=help; echo help) )
+ _values 'format' $_json_forms
+}
+
+(( $+functions[_busctl_get_service_names] )) || _busctl_get_service_names()
+{
+ local -a bus_names
+ bus_names=( $(__busctl call \
+ "org.freedesktop.DBus" \
+ "/org/freedesktop/DBus" \
+ "org.freedesktop.DBus" \
+ ListNames) )
+ echo ${(Q)bus_names[3,-1]}
+}
+
+(( $+functions[_busctl_get_unique_names] )) || _busctl_get_unique_names()
+{
+ local -a bus_names
+ local NAME OTHER
+ __busctl --unique list |
+ while read NAME OTHER; do
+ echo $NAME
+ done
+}
+
+(( $+functions[_busctl_get_objects] )) || _busctl_get_objects()
+{
+ local -a objects
+ local name="$1"
+ objects=($(__busctl --list tree $name ))
+ echo $objects
+}
+
+(( $+functions[_busctl_get_interfaces] )) || _busctl_get_interfaces()
+{
+ local NAME TYPE OTHER
+ __busctl introspect "$1" "$2" |
+ while read NAME TYPE OTHER; do
+ if [[ ${TYPE} == "interface" ]]; then
+ echo ${NAME}
+ fi
+ done
+}
+
+(( $+functions[_busctl_get_members] )) || _busctl_get_members()
+{
+ local member="$4"
+ local required="$5"
+ local NAME TYPE SIGNATURE VALUE FLAGS
+ __busctl introspect "$1" "$2" "$3" |
+ while read NAME TYPE SIGNATURE VALUE FLAGS; do
+ [[ -z "$member" || ${TYPE} == "$member" ]] &&
+ [[ -z "$required" || ${${(s: :)FLAGS}[-1]} == "$required" ]] &&
+ echo ${NAME#.}
+ done
+}
+
+(( $+functions[_busctl_get_signature] )) || _busctl_get_signature()
+{
+ local NAME TYPE SIGNATURE VALUE FLAGS
+ __busctl introspect "$1" "$2" "$3" |
+ while read NAME TYPE SIGNATURE VALUE FLAGS; do
+ if [[ ${NAME#.} == "$4" ]]; then
+ [[ ${SIGNATURE} != "-" ]] && echo ${SIGNATURE}
+ fi
+ done
+}
+
+(( $+functions[_busctl_status] )) || _busctl_status()
+{
+ local expl
+ _wanted busname expl 'busname' compadd "$@" - $(_busctl_get_service_names)
+}
+
+(( $+functions[_busctl_monitor] )) || _busctl_monitor()
+{
+ local expl
+ _wanted busname expl 'busname' compadd "$@" - $(_busctl_get_service_names)
+}
+
+(( $+functions[_busctl_tree] )) || _busctl_tree()
+{
+ local expl
+ _wanted busname expl 'busname' compadd "$@" - $(_busctl_get_service_names)
+}
+
+(( $+functions[_busctl_introspect] )) || _busctl_introspect()
+{
+ local expl
+ case $CURRENT in
+ 2)
+ _wanted busname expl 'busname' \
+ compadd "$@" - $(_busctl_get_service_names)
+ ;;
+ 3)
+ _wanted path expl 'path' \
+ compadd "$@" - $(_busctl_get_objects $words[2])
+ ;;
+ 4)
+ _wanted interface expl 'interface' \
+ compadd "$@" - $(_busctl_get_interfaces $words[2,3])
+ ;;
+ *)
+ _message "no more options"
+ esac
+}
+
+(( $+functions[_busctl_call] )) || _busctl_call()
+{
+ local expl
+ case $CURRENT in
+ 2)
+ _wanted busname expl 'busname' \
+ compadd "$@" - $(_busctl_get_service_names)
+ ;;
+ 3)
+ _wanted path expl 'path' \
+ compadd "$@" - $(_busctl_get_objects $words[2])
+ ;;
+ 4)
+ _wanted interface expl 'interface' \
+ compadd "$@" - $(_busctl_get_interfaces $words[2,3])
+ ;;
+ 5)
+ _wanted method expl 'method' \
+ compadd "$@" - $(_busctl_get_members $words[2,4] "method")
+ ;;
+ 6)
+ compadd "$@" - $(_busctl_get_signature $words[2,5])
+ ;;
+ *)
+ _message "no more options"
+ esac
+}
+
+(( $+functions[_busctl_get-property] )) || _busctl_get-property()
+{
+ local expl
+ case $CURRENT in
+ 2)
+ _wanted busname expl 'busname' \
+ compadd "$@" - $(_busctl_get_service_names)
+ ;;
+ 3)
+ _wanted path expl 'path' \
+ compadd "$@" - $(_busctl_get_objects $words[2])
+ ;;
+ 4)
+ _wanted interface expl 'interface' \
+ compadd "$@" - $(_busctl_get_interfaces $words[2,3])
+ ;;
+ 5)
+ _wanted property expl 'property' \
+ compadd "$@" - $(_busctl_get_members $words[2,4] "property")
+ ;;
+ *)
+ _message "no more options"
+ esac
+}
+
+(( $+functions[_busctl_set-property] )) || _busctl_set-property()
+{
+ local expl
+ case $CURRENT in
+ 2)
+ _wanted busname expl 'busname' \
+ compadd "$@" - $(_busctl_get_service_names)
+ ;;
+ 3)
+ _wanted path expl 'path' \
+ compadd "$@" - $(_busctl_get_objects $words[2])
+ ;;
+ 4)
+ _wanted interface expl 'interface' \
+ compadd "$@" - $(_busctl_get_interfaces $words[2,3])
+ ;;
+ 5)
+ _wanted property expl 'property' \
+ compadd "$@" - $(_busctl_get_members $words[2,4] "property" "writable")
+ ;;
+ 6)
+ compadd "$@" - $(_busctl_get_signature $words[2,5])
+ ;;
+ *)
+ _message "no more options"
+ esac
+}
+
+local -a _modes; _modes=("--user" "--system")
+# Use the last mode (they are exclusive and the last one is used).
+local _bus_address=${${words:*_modes}[(R)(${(j.|.)_modes})]}
+local curcontext=$curcontext state line
_arguments \
{-h,--help}'[Prints a short help text and exits.]' \
'--version[Prints a short version string and exits.]' \
@@ -59,10 +272,12 @@ _arguments \
'--unique[Only show unique names]' \
'--acquired[Only show acquired names]' \
'--activatable[Only show activatable names]' \
- '--match=[Only show matching messages]:match' \
+ '--match=[Only show matching messages]:match:__dbus_matchspec' \
'--list[Do not show tree, but simple object path list]' \
- '--quiet[Do not show method call reply]'\
+ {-q,--quiet}'[Do not show method call reply]'\
'--verbose[Show result values in long format]' \
+ '--json=[Show result values in long format]:format:_busctl_get_json' \
+ '-j[Show pretty json in interactive sessions, short json otherwise]' \
'--expect-reply=[Expect a method call reply]:boolean:(1 0)' \
'--auto-start=[Auto-start destination service]:boolean:(1 0)' \
'--allow-interactive-authorization=[Allow interactive authorization for operation]:boolean:(1 0)' \
diff --git a/shell-completion/zsh/_systemd-resolve b/shell-completion/zsh/_resolvectl
index 3b0ce311f2..7458f436a5 100644
--- a/shell-completion/zsh/_systemd-resolve
+++ b/shell-completion/zsh/_resolvectl
@@ -1,4 +1,4 @@
-#compdef systemd-resolve -*- shell-script -*-
+#compdef resolvectl systemd-resolve -*- shell-script -*-
# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
@@ -16,33 +16,54 @@
# You should have received a copy of the GNU Lesser General Public License
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-(( $+functions[_systemd-resolve_protocols] )) ||
- _systemd-resolve_protocols() {
+(( $+functions[_resolvectl_protocols] )) ||
+ _resolvectl_protocols() {
local -a _protocol
_protocol=( $(_call_program protocol ${service} --legend=no --protocol help; echo help) )
_values 'protocol' "$_protocol[@]"
}
-(( $+functions[_systemd-resolve_types] )) ||
- _systemd-resolve_types() {
+(( $+functions[_resolvectl_types] )) ||
+ _resolvectl_types() {
local -a _type
_type=( $(_call_program type ${service} --legend=no --type help; echo help) )
_values 'type' "$_type[@]"
}
-(( $+functions[_systemd-resolve_classes] )) ||
- _systemd-resolve_classes() {
+(( $+functions[_resolvectl_classes] )) ||
+ _resolvectl_classes() {
local -a _class
_class=( $(_call_program class ${service} --legend=no --class help; echo help) )
_values 'class' "$_class[@]"
}
-(( $+functions[_systemd-resolve_none] )) ||
- _systemd-resolve_none() {
- _alternative : \
- 'domain:DNS address:' \
- 'address:email address:'
- }
+(( $+functions[_resolvectl_commands] )) ||
+ _resolvectl_commands() {
+ local -a _resolvectl_cmds
+ _resolvectl_cmds=(
+ default-route:"Configure per-interface default-route setting"
+ dns:"Configure per-interface DNS configuration"
+ dnsovertls:"Configure per-interface dnsovertls enabled status"
+ dnssec:"Configure per-interface dnssec enabled status"
+ domain:"Configure per-interface search and route-only domains"
+ flush-caches:"Flushes all DNS resource record caches the service maintains locally"
+ llmnr:"Configure per-interface llmnr enabled status"
+ mdns:"Configure per-interface mdns enabled status"
+ nta:"Configure per-interface nta domains"
+ openpgp:"Retrieve openpgp keys for an email"
+ query:"Resolve domain names, IPv4 and IPv6 addresses"
+ reset-server-features:"Flushes all feature level information the resolver has learned about specific servers"
+ reset-statistics:"Resets the statistics counter show in statistics to zero"
+ revert:"Revert the per-interfce DNS configuration"
+ service:"Resolve DNS-SD and SRV services"
+ status:"Show the global and per-link DNS settings currently in effect"
+ tlsa:"Query tlsa public keys stored as TLSA resource records"
+ )
+
+ if (( CURRENT == 1 )); then
+ _describe -t commands 'resolvectl commands' _resolvectl_cmds
+ fi
+}
_arguments \
{-h,--help}'[Print a short help text and exit]' \
@@ -51,9 +72,9 @@ _arguments \
'-4[Resolve IPv4 addresses]' \
'-6[Resolve IPv6 addresses]' \
{-i+,--interface=}'[Look on interface]:interface:_net_interfaces' \
- {-p+,--protocol=}'[Look via protocol]:protocol:_systemd-resolve_protocols' \
- {-t+,--type=}'[Query RR with DNS type]:type:_systemd-resolve_types' \
- {-c+,--class=}'[Query RR with DNS class]:class:_systemd-resolve_classes' \
+ {-p+,--protocol=}'[Look via protocol]:protocol:_resolvectl_protocols' \
+ {-t+,--type=}'[Query RR with DNS type]:type:_resolvectl_types' \
+ {-c+,--class=}'[Query RR with DNS class]:class:_resolvectl_classes' \
'--service[Resolve services]' \
'--service-address=no[Do not resolve address for services]' \
'--service-txt=no[Do not resolve TXT records for services]' \
@@ -63,4 +84,4 @@ _arguments \
'--search=no[Do not use search domains]' \
'--statistics[Show resolver statistics]' \
'--reset-statistics[Reset resolver statistics]' \
- '*::default: _systemd-resolve_none'
+ '*::default: _resolvectl_commands'
diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build
index 792b06122f..6df9cc6ac2 100644
--- a/shell-completion/zsh/meson.build
+++ b/shell-completion/zsh/meson.build
@@ -33,7 +33,7 @@ if zshcompletiondir != 'no'
['_machinectl', 'ENABLE_MACHINED'],
['_networkctl', 'ENABLE_NETWORKD'],
['_systemd-inhibit', 'ENABLE_LOGIND'],
- ['_systemd-resolve', 'ENABLE_RESOLVE'],
+ ['_resolvectl', 'ENABLE_RESOLVE'],
['_systemd-tmpfiles', 'ENABLE_TMPFILES'],
['_timedatectl', 'ENABLE_TIMEDATED'],
]
diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c
index dd85f28288..848aeaed80 100644
--- a/src/analyze/analyze-security.c
+++ b/src/analyze/analyze-security.c
@@ -603,7 +603,7 @@ static int assess_ip_address_allow(
d = strdup("Service defines IP address whitelist with non-localhost entries");
b = 5;
} else if (info->ip_address_allow_localhost) {
- d = strdup("Service defines IP address whitelits with only localhost entries");
+ d = strdup("Service defines IP address whitelist with only localhost entries");
b = 2;
} else {
d = strdup("Service blocks all IP address ranges");
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index dff6543bf5..7b5839ccd6 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -342,7 +342,8 @@ int cg_kill(
return r;
/* Only in case of killing with SIGKILL and when using cgroupsv2, kill remaining threads manually as
- a workaround for kernel bug. It was fixed in 5.2-rc5 (c03cd7738a83). */
+ a workaround for kernel bug. It was fixed in 5.2-rc5 (c03cd7738a83), backported to 4.19.66
+ (4340d175b898) and 4.14.138 (feb6b123b7dd). */
r = cg_unified_controller(controller);
if (r < 0)
return r;
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index b7ae2ed1cd..34cfb36a4a 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -28,8 +28,6 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
assert(p);
assert(ret);
- /* Those two don't make sense together. */
- assert(!FLAGS_SET(flags, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE));
/* Bail early if called after last value or with no input */
if (!*p)
diff --git a/src/basic/log.c b/src/basic/log.c
index f047203271..8bcc18bc80 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -87,11 +87,13 @@ static int log_open_console(void) {
}
if (console_fd < 3) {
- console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (console_fd < 0)
- return console_fd;
+ int fd;
- console_fd = fd_move_above_stdio(console_fd);
+ fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ console_fd = fd_move_above_stdio(fd);
}
return 0;
@@ -372,13 +374,11 @@ static int write_to_console(
if (errno == EIO && getpid_cached() == 1) {
- /* If somebody tried to kick us from our
- * console tty (via vhangup() or suchlike),
- * try to reconnect */
+ /* If somebody tried to kick us from our console tty (via vhangup() or suchlike), try
+ * to reconnect. */
log_close_console();
- log_open_console();
-
+ (void) log_open_console();
if (console_fd < 0)
return 0;
@@ -586,7 +586,7 @@ int log_dispatch_internal(
level |= log_facility;
if (open_when_needed)
- log_open();
+ (void) log_open();
do {
char *e;
@@ -629,7 +629,7 @@ int log_dispatch_internal(
k = write_to_kmsg(level, error, file, line, func, buffer);
if (k < 0) {
log_close_kmsg();
- log_open_console();
+ (void) log_open_console();
}
}
@@ -795,7 +795,7 @@ _noreturn_ void log_assert_failed_realm(
const char *file,
int line,
const char *func) {
- log_open();
+ (void) log_open();
log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
"Assertion '%s' failed at %s:%u, function %s(). Aborting.");
abort();
@@ -807,7 +807,7 @@ _noreturn_ void log_assert_failed_unreachable_realm(
const char *file,
int line,
const char *func) {
- log_open();
+ (void) log_open();
log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
"Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
abort();
@@ -1356,5 +1356,5 @@ void log_setup_service(void) {
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
- log_open();
+ (void) log_open();
}
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index f590b91c66..6d9b12544d 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -32,7 +32,11 @@ static inline int missing_pivot_root(const char *new_root, const char *put_old)
/* ======================================================================= */
#if !HAVE_MEMFD_CREATE
-# ifndef __NR_memfd_create
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_memfd_create && __NR_memfd_create > 0)
+# if defined __NR_memfd_create
+# undef __NR_memfd_create
+# endif
# if defined __x86_64__
# define __NR_memfd_create 319
# elif defined __arm__
@@ -75,7 +79,11 @@ static inline int missing_memfd_create(const char *name, unsigned int flags) {
/* ======================================================================= */
#if !HAVE_GETRANDOM
-# ifndef __NR_getrandom
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_getrandom && __NR_getrandom > 0)
+# if defined __NR_getrandom
+# undef __NR_getrandom
+# endif
# if defined __x86_64__
# define __NR_getrandom 318
# elif defined(__i386__)
@@ -134,7 +142,11 @@ static inline pid_t missing_gettid(void) {
/* ======================================================================= */
#if !HAVE_NAME_TO_HANDLE_AT
-# ifndef __NR_name_to_handle_at
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_name_to_handle_at && __NR_name_to_handle_at > 0)
+# if defined __NR_name_to_handle_at
+# undef __NR_name_to_handle_at
+# endif
# if defined(__x86_64__)
# define __NR_name_to_handle_at 303
# elif defined(__i386__)
@@ -171,7 +183,11 @@ static inline int missing_name_to_handle_at(int fd, const char *name, struct fil
/* ======================================================================= */
#if !HAVE_SETNS
-# ifndef __NR_setns
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_setns && __NR_setns > 0)
+# if defined __NR_setns
+# undef __NR_setns
+# endif
# if defined(__x86_64__)
# define __NR_setns 308
# elif defined(__i386__)
@@ -208,7 +224,11 @@ static inline pid_t raw_getpid(void) {
/* ======================================================================= */
#if !HAVE_RENAMEAT2
-# ifndef __NR_renameat2
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_renameat2 && __NR_renameat2 > 0)
+# if defined __NR_renameat2
+# undef __NR_renameat2
+# endif
# if defined __x86_64__
# define __NR_renameat2 316
# elif defined __arm__
@@ -305,7 +325,11 @@ static inline key_serial_t missing_request_key(const char *type, const char *des
/* ======================================================================= */
#if !HAVE_COPY_FILE_RANGE
-# ifndef __NR_copy_file_range
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_copy_file_range && __NR_copy_file_range > 0)
+# if defined __NR_copy_file_range
+# undef __NR_copy_file_range
+# endif
# if defined(__x86_64__)
# define __NR_copy_file_range 326
# elif defined(__i386__)
@@ -343,7 +367,11 @@ static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in,
/* ======================================================================= */
#if !HAVE_BPF
-# ifndef __NR_bpf
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_bpf && __NR_bpf > 0)
+# if defined __NR_bpf
+# undef __NR_bpf
+# endif
# if defined __i386__
# define __NR_bpf 357
# elif defined __x86_64__
@@ -380,7 +408,11 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
/* ======================================================================= */
#ifndef __IGNORE_pkey_mprotect
-# ifndef __NR_pkey_mprotect
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_pkey_mprotect && __NR_pkey_mprotect > 0)
+# if defined __NR_pkey_mprotect
+# undef __NR_pkey_mprotect
+# endif
# if defined __i386__
# define __NR_pkey_mprotect 380
# elif defined __x86_64__
@@ -391,6 +423,8 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
# define __NR_pkey_mprotect 394
# elif defined __powerpc__
# define __NR_pkey_mprotect 386
+# elif defined __s390__
+# define __NR_pkey_mprotect 384
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_pkey_mprotect 4363
@@ -410,7 +444,11 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
/* ======================================================================= */
#if !HAVE_STATX
-# ifndef __NR_statx
+/* may be (invalid) negative number due to libseccomp, see PR 13319 */
+# if ! (defined __NR_statx && __NR_statx > 0)
+# if defined __NR_statx
+# undef __NR_statx
+# endif
# if defined __aarch64__ || defined __arm__
# define __NR_statx 397
# elif defined __alpha__
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index cf6af45fbb..c732e8021c 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -578,22 +578,29 @@ int vt_disallocate(const char *name) {
int make_console_stdio(void) {
int fd, r;
- /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
+ /* Make /dev/console the controlling terminal and stdin/stdout/stderr, if we can. If we can't use
+ * /dev/null instead. This is particularly useful if /dev/console is turned off, e.g. if console=null
+ * is specified on the kernel command line. */
fd = acquire_terminal("/dev/console", ACQUIRE_TERMINAL_FORCE|ACQUIRE_TERMINAL_PERMISSIVE, USEC_INFINITY);
- if (fd < 0)
- return log_error_errno(fd, "Failed to acquire terminal: %m");
+ if (fd < 0) {
+ log_warning_errno(fd, "Failed to acquire terminal, using /dev/null stdin/stdout/stderr instead: %m");
- r = reset_terminal_fd(fd, true);
- if (r < 0)
- log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
+ r = make_null_stdio();
+ if (r < 0)
+ return log_error_errno(r, "Failed to make /dev/null stdin/stdout/stderr: %m");
- r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */
- if (r < 0)
- return log_error_errno(r, "Failed to make terminal stdin/stdout/stderr: %m");
+ } else {
+ r = reset_terminal_fd(fd, true);
+ if (r < 0)
+ log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
- reset_terminal_feature_caches();
+ r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */
+ if (r < 0)
+ return log_error_errno(r, "Failed to make terminal stdin/stdout/stderr: %m");
+ }
+ reset_terminal_feature_caches();
return 0;
}
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index e13361463b..3018e81acb 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -1191,7 +1191,10 @@ bool ntp_synced(void) {
if (adjtimex(&txc) < 0)
return false;
- if (txc.status & STA_UNSYNC)
+ /* Consider the system clock synchronized if the reported maximum error is smaller than the maximum
+ * value (16 seconds). Ignore the STA_UNSYNC flag as it may have been set to prevent the kernel from
+ * touching the RTC. */
+ if (txc.maxerror >= 16000000)
return false;
return true;
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 9ecd9f78f3..ddc267401f 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -103,6 +103,7 @@ static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) {
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
if (ret_uuid)
*ret_uuid = SD_ID128_NULL;
+ arg_xbootldr_path = mfree(arg_xbootldr_path);
return 0;
}
if (r < 0)
@@ -1175,7 +1176,11 @@ static int verb_status(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- puts(arg_dollar_boot_path());
+ const char *path = arg_dollar_boot_path();
+ if (!path)
+ return log_error_errno(SYNTHETIC_ERRNO(EACCES), "Failed to determine XBOOTLDR location: %m");
+
+ puts(path);
}
if (arg_print_esp_path || arg_print_dollar_boot_path)
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
index 5b623f4b71..00a3551e09 100644
--- a/src/boot/efi/linux.c
+++ b/src/boot/efi/linux.c
@@ -6,24 +6,24 @@
#include "linux.h"
#include "util.h"
-#ifdef __x86_64__
-typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params);
-static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) {
- handover_f handover;
-
- asm volatile ("cli");
- handover = (handover_f)((UINTN)params->hdr.code32_start + 512 + params->hdr.handover_offset);
- handover(image, ST, params);
-}
+#ifdef __i386__
+#define __regparm0__ __attribute__((regparm(0)))
#else
-typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params) __attribute__((regparm(0)));
+#define __regparm0__
+#endif
+
+typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params) __regparm0__;
static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) {
handover_f handover;
+ UINTN start = (UINTN)params->hdr.code32_start;
- handover = (handover_f)((UINTN)params->hdr.code32_start + params->hdr.handover_offset);
+#ifdef __x86_64__
+ asm volatile ("cli");
+ start += 512;
+#endif
+ handover = (handover_f)(start + params->hdr.handover_offset);
handover(image, ST, params);
}
-#endif
EFI_STATUS linux_exec(EFI_HANDLE *image,
CHAR8 *cmdline, UINTN cmdline_len,
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
index dfec97028b..b8fd5105d0 100644
--- a/src/boot/efi/meson.build
+++ b/src/boot/efi/meson.build
@@ -135,6 +135,9 @@ if have_gnu_efi
compile_args += ['-mno-sse',
'-mno-mmx']
endif
+ if get_option('werror') == true
+ compile_args += ['-Werror']
+ endif
efi_ldflags = ['-T',
join_paths(efi_ldsdir, arch_lds),
diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c
index 9e072d294f..8db27547cc 100644
--- a/src/boot/efi/shim.c
+++ b/src/boot/efi/shim.c
@@ -14,14 +14,20 @@
#include "util.h"
#include "shim.h"
+#if defined(__x86_64__) || defined(__i386__)
+#define __sysv_abi__ __attribute__((sysv_abi))
+#else
+#define __sysv_abi__
+#endif
+
struct ShimLock {
- EFI_STATUS __attribute__((sysv_abi)) (*shim_verify) (VOID *buffer, UINT32 size);
+ EFI_STATUS __sysv_abi__ (*shim_verify) (VOID *buffer, UINT32 size);
/* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
* see shim.c/shim.h and PeHeader.h in the github shim repo */
- EFI_STATUS __attribute__((sysv_abi)) (*generate_hash) (VOID *data, UINT32 datasize, VOID *context, UINT8 *sha256hash, UINT8 *sha1hash);
+ EFI_STATUS __sysv_abi__ (*generate_hash) (VOID *data, UINT32 datasize, VOID *context, UINT8 *sha256hash, UINT8 *sha1hash);
- EFI_STATUS __attribute__((sysv_abi)) (*read_header) (VOID *data, UINT32 datasize, VOID *context);
+ EFI_STATUS __sysv_abi__ (*read_header) (VOID *data, UINT32 datasize, VOID *context);
};
static const EFI_GUID simple_fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 6e0afa4bca..60a7799361 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -1063,6 +1063,11 @@ static void cgroup_context_apply(
xsprintf(buf, "default %" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "io", "io.weight", buf);
+ /* FIXME: drop this when distro kernels properly support BFQ through "io.weight"
+ * See also: https://github.com/systemd/systemd/pull/13335 */
+ xsprintf(buf, "%" PRIu64 "\n", weight);
+ (void) set_attribute_and_warn(u, "io", "io.bfq.weight", buf);
+
if (has_io) {
CGroupIODeviceLatency *latency;
CGroupIODeviceLimit *limit;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index c816569f2b..85c310cd33 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -1000,16 +1000,11 @@ int bus_property_get_exec_ex_command_list(
}
static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
- char *res = NULL;
-
- asprintf(&res, "%s%s%s%s%s",
- FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "",
- FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "",
- FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
- FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "",
- FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC) ? "!!" : "");
-
- return res;
+ return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "",
+ FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "",
+ FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
+ FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "",
+ FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC) ? "!!" : "");
}
int bus_set_transient_exec_command(
diff --git a/src/core/dbus.c b/src/core/dbus.c
index a8ce9ac447..bbfad1be74 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -784,7 +784,7 @@ static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata)
* changed, so synthesize a name owner changed signal. */
if (!streq_ptr(unique, s->bus_name_owner))
- UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique);
+ UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, unique);
} else {
/* So, the name we're watching is not on the bus.
* This either means it simply hasn't appeared yet,
@@ -793,7 +793,7 @@ static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata)
* and synthesize a name loss signal in this case. */
if (s->bus_name_owner)
- UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL);
+ UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, NULL);
}
}
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 20079e1fb1..c7827df95d 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -98,14 +98,12 @@ int parse_confirm_spawn(const char *value, char **console) {
if (r == 0) {
*console = NULL;
return 0;
- }
-
- if (r > 0) /* on with default tty */
+ } else if (r > 0) /* on with default tty */
s = strdup("/dev/console");
else if (is_path(value)) /* on with fully qualified path */
s = strdup(value);
else /* on with only a tty file name, not a fully qualified path */
- s = strjoin("/dev/", value);
+ s = path_join("/dev/", value);
if (!s)
return -ENOMEM;
diff --git a/src/core/manager.c b/src/core/manager.c
index dfe8997f9d..8d691a19c3 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -4072,10 +4072,11 @@ static bool manager_get_show_status(Manager *m, StatusType type) {
const char *manager_get_confirm_spawn(Manager *m) {
static int last_errno = 0;
- const char *vc = m->confirm_spawn;
struct stat st;
int r;
+ assert(m);
+
/* Here's the deal: we want to test the validity of the console but don't want
* PID1 to go through the whole console process which might block. But we also
* want to warn the user only once if something is wrong with the console so we
@@ -4091,25 +4092,26 @@ const char *manager_get_confirm_spawn(Manager *m) {
* reason the configured console is not ready, we fallback to the default
* console. */
- if (!vc || path_equal(vc, "/dev/console"))
- return vc;
+ if (!m->confirm_spawn || path_equal(m->confirm_spawn, "/dev/console"))
+ return m->confirm_spawn;
- r = stat(vc, &st);
- if (r < 0)
+ if (stat(m->confirm_spawn, &st) < 0) {
+ r = -errno;
goto fail;
+ }
if (!S_ISCHR(st.st_mode)) {
- errno = ENOTTY;
+ r = -ENOTTY;
goto fail;
}
last_errno = 0;
- return vc;
+ return m->confirm_spawn;
+
fail:
- if (last_errno != errno) {
- last_errno = errno;
- log_warning_errno(errno, "Failed to open %s: %m, using default console", vc);
- }
+ if (last_errno != r)
+ last_errno = log_warning_errno(r, "Failed to open %s, using default console: %m", m->confirm_spawn);
+
return "/dev/console";
}
diff --git a/src/core/meson.build b/src/core/meson.build
index 267d65a3b2..fb6820e109 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -212,7 +212,6 @@ meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir))
meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir))
meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir))
-meson.add_install_script('sh', '-c',
- mkdir_p.format(join_paths(pkgsysconfdir, 'user')))
-meson.add_install_script('sh', '-c',
- mkdir_p.format(join_paths(sysconfdir, 'xdg/systemd')))
+meson.add_install_script('sh', '-c', mkdir_p.format(join_paths(pkgsysconfdir, 'system')))
+meson.add_install_script('sh', '-c', mkdir_p.format(join_paths(pkgsysconfdir, 'user')))
+meson.add_install_script('sh', '-c', mkdir_p.format(join_paths(sysconfdir, 'xdg/systemd')))
diff --git a/src/core/mount.c b/src/core/mount.c
index fb6a516318..4f37d3e9a9 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1323,9 +1323,10 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
}
unit_log_process_exit(
- u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ u,
"Mount process",
mount_exec_command_to_string(m->control_command_id),
+ f == MOUNT_SUCCESS,
code, status);
/* Note that due to the io event priority logic, we can be sure the new mountinfo is loaded
diff --git a/src/core/service.c b/src/core/service.c
index bfbfa4be65..d8cfb40145 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3417,14 +3417,11 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
f = SERVICE_SUCCESS;
}
- /* When this is a successful exit, let's log about the exit code on DEBUG level. If this is a failure
- * and the process exited on its own via exit(), then let's make this a NOTICE, under the assumption
- * that the service already logged the reason at a higher log level on its own. (Internally,
- * unit_log_process_exit() will possibly bump this to WARNING if the service died due to a signal.) */
unit_log_process_exit(
- u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ u,
"Main process",
service_exec_command_to_string(SERVICE_EXEC_START),
+ f == SERVICE_SUCCESS,
code, status);
if (s->result == SERVICE_SUCCESS)
@@ -3519,9 +3516,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
}
unit_log_process_exit(
- u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ u,
"Control process",
service_exec_command_to_string(s->control_command_id),
+ f == SERVICE_SUCCESS,
code, status);
if (s->state != SERVICE_RELOAD && s->result == SERVICE_SUCCESS)
@@ -4067,7 +4065,6 @@ static int service_get_timeout(Unit *u, usec_t *timeout) {
static void service_bus_name_owner_change(
Unit *u,
- const char *name,
const char *old_owner,
const char *new_owner) {
@@ -4075,17 +4072,15 @@ static void service_bus_name_owner_change(
int r;
assert(s);
- assert(name);
- assert(streq(s->bus_name, name));
assert(old_owner || new_owner);
if (old_owner && new_owner)
- log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", name, old_owner, new_owner);
+ log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", s->bus_name, old_owner, new_owner);
else if (old_owner)
- log_unit_debug(u, "D-Bus name %s no longer registered by %s", name, old_owner);
+ log_unit_debug(u, "D-Bus name %s no longer registered by %s", s->bus_name, old_owner);
else
- log_unit_debug(u, "D-Bus name %s now registered by %s", name, new_owner);
+ log_unit_debug(u, "D-Bus name %s now registered by %s", s->bus_name, new_owner);
s->bus_name_good = !!new_owner;
@@ -4118,11 +4113,11 @@ static void service_bus_name_owner_change(
/* Try to acquire PID from bus service */
- r = sd_bus_get_name_creds(u->manager->api_bus, name, SD_BUS_CREDS_PID, &creds);
+ r = sd_bus_get_name_creds(u->manager->api_bus, s->bus_name, SD_BUS_CREDS_PID, &creds);
if (r >= 0)
r = sd_bus_creds_get_pid(creds, &pid);
if (r >= 0) {
- log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, name, pid);
+ log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, pid);
service_set_main_pid(s, pid);
unit_watch_pid(UNIT(s), pid, false);
diff --git a/src/core/socket.c b/src/core/socket.c
index cc3dc5973d..46fe405a17 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -3014,9 +3014,10 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
}
unit_log_process_exit(
- u, f == SOCKET_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ u,
"Control process",
socket_exec_command_to_string(s->control_command_id),
+ f == SOCKET_SUCCESS,
code, status);
if (s->result == SOCKET_SUCCESS)
diff --git a/src/core/swap.c b/src/core/swap.c
index 303afc9f35..74381c0c95 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -1043,9 +1043,10 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
}
unit_log_process_exit(
- u, f == SWAP_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ u,
"Swap process",
swap_exec_command_to_string(s->control_command_id),
+ f == SWAP_SUCCESS,
code, status);
switch (s->state) {
diff --git a/src/core/unit.c b/src/core/unit.c
index 00181941fd..31ed473f91 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -3242,7 +3242,46 @@ static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd
new_owner = empty_to_null(new_owner);
if (UNIT_VTABLE(u)->bus_name_owner_change)
- UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
+ UNIT_VTABLE(u)->bus_name_owner_change(u, old_owner, new_owner);
+
+ return 0;
+}
+
+static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ const sd_bus_error *e;
+ const char *new_owner;
+ Unit *u = userdata;
+ int r;
+
+ assert(message);
+ assert(u);
+
+ u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
+
+ if (sd_bus_error_is_set(error)) {
+ log_error("Failed to get name owner from bus: %s", error->message);
+ return 0;
+ }
+
+ e = sd_bus_message_get_error(message);
+ if (sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner"))
+ return 0;
+
+ if (e) {
+ log_error("Unexpected error response from GetNameOwner: %s", e->message);
+ return 0;
+ }
+
+ r = sd_bus_message_read(message, "s", &new_owner);
+ if (r < 0) {
+ bus_log_parse_error(r);
+ return 0;
+ }
+
+ new_owner = empty_to_null(new_owner);
+
+ if (UNIT_VTABLE(u)->bus_name_owner_change)
+ UNIT_VTABLE(u)->bus_name_owner_change(u, NULL, new_owner);
return 0;
}
@@ -3264,7 +3303,19 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
"member='NameOwnerChanged',"
"arg0='", name, "'");
- return sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u);
+ int r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u);
+ if (r < 0)
+ return r;
+
+ return sd_bus_call_method_async(bus,
+ &u->get_name_owner_slot,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "GetNameOwner",
+ get_name_owner_handler,
+ u,
+ "s", name);
}
int unit_watch_bus_name(Unit *u, const char *name) {
@@ -3299,6 +3350,7 @@ void unit_unwatch_bus_name(Unit *u, const char *name) {
(void) hashmap_remove_value(u->manager->watch_bus, name, u);
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
+ u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
}
bool unit_can_serialize(Unit *u) {
@@ -4531,6 +4583,15 @@ int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const ch
return r;
(void) mkdir_p_label(p, 0755);
+
+ /* Make sure the drop-in dir is registered in our path cache. This way we don't need to stupidly
+ * recreate the cache after every drop-in we write. */
+ if (u->manager->unit_path_cache) {
+ r = set_put_strdup(u->manager->unit_path_cache, p);
+ if (r < 0)
+ return r;
+ }
+
r = write_string_file_atomic_label(q, wrapped);
if (r < 0)
return r;
@@ -5718,16 +5779,26 @@ void unit_log_skip(Unit *u, const char *result) {
void unit_log_process_exit(
Unit *u,
- int level,
const char *kind,
const char *command,
+ bool success,
int code,
int status) {
+ int level;
+
assert(u);
assert(kind);
- if (code != CLD_EXITED)
+ /* If this is a successful exit, let's log about the exit code on DEBUG level. If this is a failure
+ * and the process exited on its own via exit(), then let's make this a NOTICE, under the assumption
+ * that the service already logged the reason at a higher log level on its own. Otherwise, make it a
+ * WARNING. */
+ if (success)
+ level = LOG_DEBUG;
+ else if (code == CLD_EXITED)
+ level = LOG_NOTICE;
+ else
level = LOG_WARNING;
log_struct(level,
diff --git a/src/core/unit.h b/src/core/unit.h
index 47ec9877a6..4732d72202 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -146,6 +146,7 @@ typedef struct Unit {
/* The slot used for watching NameOwnerChanged signals */
sd_bus_slot *match_bus_slot;
+ sd_bus_slot *get_name_owner_slot;
/* References to this unit from clients */
sd_bus_track *bus_track;
@@ -528,7 +529,7 @@ typedef struct UnitVTable {
void (*notify_message)(Unit *u, const struct ucred *ucred, char **tags, FDSet *fds);
/* Called whenever a name this Unit registered for comes or goes away. */
- void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
+ void (*bus_name_owner_change)(Unit *u, const char *old_owner, const char *new_owner);
/* Called for each property that is being set */
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
@@ -851,7 +852,7 @@ static inline void unit_log_result(Unit *u, bool success, const char *result) {
unit_log_failure(u, result);
}
-void unit_log_process_exit(Unit *u, int level, const char *kind, const char *command, int code, int status);
+void unit_log_process_exit(Unit *u, const char *kind, const char *command, bool success, int code, int status);
int unit_exit_status(Unit *u);
int unit_success_action_exit_status(Unit *u);
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 960f4762b7..4815ded753 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -47,29 +47,33 @@ STATIC_DESTRUCTOR_REGISTER(arg_default_options, freep);
STATIC_DESTRUCTOR_REGISTER(arg_default_keyfile, freep);
static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) {
- _cleanup_free_ char *kfile = NULL, *kdev = NULL;
+ _cleanup_free_ char *keyfile = NULL, *keydev = NULL;
const char *c;
- assert(keyspec);
assert(ret_keyfile);
assert(ret_keydev);
+ if (!keyspec) {
+ *ret_keyfile = *ret_keydev = NULL;
+ return 0;
+ }
+
c = strrchr(keyspec, ':');
if (c) {
- kfile = strndup(keyspec, c-keyspec);
- kdev = strdup(c + 1);
- if (!kfile || !kdev)
+ keyfile = strndup(keyspec, c-keyspec);
+ keydev = strdup(c + 1);
+ if (!keyfile || !keydev)
return log_oom();
} else {
/* No keydev specified */
- kfile = strdup(keyspec);
- kdev = NULL;
- if (!kfile)
+ keyfile = strdup(keyspec);
+ keydev = NULL;
+ if (!keyfile)
return log_oom();
}
- *ret_keyfile = TAKE_PTR(kfile);
- *ret_keydev = TAKE_PTR(kdev);
+ *ret_keyfile = TAKE_PTR(keyfile);
+ *ret_keydev = TAKE_PTR(keydev);
return 0;
}
@@ -567,7 +571,7 @@ static int add_crypttab_devices(void) {
}
for (;;) {
- _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keydev = NULL, *keyfile = NULL, *keyspec = NULL, *options = NULL;
+ _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL, *keyfile = NULL, *keydev = NULL;
crypto_device *d = NULL;
char *l, *uuid;
int k;
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 1de5d12223..528e6452cf 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -553,8 +553,8 @@ static int prompt_root_password(void) {
print_welcome();
putchar('\n');
- msg1 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter a new root password (empty to skip): ");
- msg2 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter new root password again: ");
+ msg1 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter a new root password (empty to skip):");
+ msg2 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter new root password again:");
for (;;) {
_cleanup_strv_free_erase_ char **a = NULL, **b = NULL;
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 0a5863667c..935dce9d21 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -169,12 +169,12 @@ static int process_progress(int fd) {
f = fdopen(fd, "r");
if (!f) {
safe_close(fd);
- return -errno;
+ return log_debug_errno(errno, "Failed to use pipe: %m");
}
console = fopen("/dev/console", "we");
if (!console)
- return -ENOMEM;
+ return log_debug_errno(errno, "Failed to open /dev/console, can't print progress output: %m");
for (;;) {
int pass, m;
@@ -189,10 +189,9 @@ static int process_progress(int fd) {
r = log_warning_errno(errno, "Failed to read from progress pipe: %m");
else if (feof(f))
r = 0;
- else {
- log_warning("Failed to parse progress pipe data");
- r = -EBADMSG;
- }
+ else
+ r = log_warning_errno(SYNTHETIC_ERRNO(errno), "Failed to parse progress pipe data");
+
break;
}
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 0abb8fdef0..05386b615d 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -27,7 +27,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
case SD_DHCP_OPTION_PAD:
case SD_DHCP_OPTION_END:
- if (size < *offset + 1)
+ if (*offset + 1 > size)
return -ENOBUFS;
options[*offset] = code;
@@ -35,42 +35,45 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
break;
case SD_DHCP_OPTION_USER_CLASS: {
- size_t len = 0;
+ size_t total = 0;
char **s;
- STRV_FOREACH(s, (char **) optval)
- len += strlen(*s) + 1;
+ STRV_FOREACH(s, (char **) optval) {
+ size_t len = strlen(*s);
+
+ if (len > 255)
+ return -ENAMETOOLONG;
- if (size < *offset + len + 2)
+ total += 1 + len;
+ }
+
+ if (*offset + 2 + total > size)
return -ENOBUFS;
options[*offset] = code;
- options[*offset + 1] = len;
+ options[*offset + 1] = total;
*offset += 2;
STRV_FOREACH(s, (char **) optval) {
- len = strlen(*s);
-
- if (len > 255)
- return -ENAMETOOLONG;
+ size_t len = strlen(*s);
options[*offset] = len;
- memcpy_safe(&options[*offset + 1], *s, len);
- *offset += len + 1;
+ memcpy(&options[*offset + 1], *s, len);
+ *offset += 1 + len;
}
break;
}
default:
- if (size < *offset + optlen + 2)
+ if (*offset + 2 + optlen > size)
return -ENOBUFS;
options[*offset] = code;
options[*offset + 1] = optlen;
memcpy_safe(&options[*offset + 2], optval, optlen);
- *offset += optlen + 2;
+ *offset += 2 + optlen;
break;
}
@@ -81,22 +84,25 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
uint8_t overload,
uint8_t code, size_t optlen, const void *optval) {
- size_t file_offset = 0, sname_offset =0;
- bool file, sname;
+ const bool use_file = overload & DHCP_OVERLOAD_FILE;
+ const bool use_sname = overload & DHCP_OVERLOAD_SNAME;
int r;
assert(message);
assert(offset);
- file = overload & DHCP_OVERLOAD_FILE;
- sname = overload & DHCP_OVERLOAD_SNAME;
+ /* If *offset is in range [0, size), we are writing to ->options,
+ * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file,
+ * if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname))
+ * and use_sname, we are writing to ->sname.
+ */
if (*offset < size) {
/* still space in the options array */
r = option_append(message->options, size, offset, code, optlen, optval);
if (r >= 0)
return 0;
- else if (r == -ENOBUFS && (file || sname)) {
+ else if (r == -ENOBUFS && (use_file || use_sname)) {
/* did not fit, but we have more buffers to try
close the options array and move the offset to its end */
r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
@@ -108,8 +114,8 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
return r;
}
- if (overload & DHCP_OVERLOAD_FILE) {
- file_offset = *offset - size;
+ if (use_file) {
+ size_t file_offset = *offset - size;
if (file_offset < sizeof(message->file)) {
/* still space in the 'file' array */
@@ -117,7 +123,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
if (r >= 0) {
*offset = size + file_offset;
return 0;
- } else if (r == -ENOBUFS && sname) {
+ } else if (r == -ENOBUFS && use_sname) {
/* did not fit, but we have more buffers to try
close the file array and move the offset to its end */
r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
@@ -130,19 +136,18 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
}
}
- if (overload & DHCP_OVERLOAD_SNAME) {
- sname_offset = *offset - size - (file ? sizeof(message->file) : 0);
+ if (use_sname) {
+ size_t sname_offset = *offset - size - use_file*sizeof(message->file);
if (sname_offset < sizeof(message->sname)) {
/* still space in the 'sname' array */
r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval);
if (r >= 0) {
- *offset = size + (file ? sizeof(message->file) : 0) + sname_offset;
+ *offset = size + use_file*sizeof(message->file) + sname_offset;
return 0;
- } else {
+ } else
/* no space, or other error, give up */
return r;
- }
}
}
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index f18ec88300..1f2e5c7e65 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -254,7 +254,7 @@ int config_parse_match_strv(
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == 0)
return 0;
if (r == -ENOMEM)
diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c
index 79fe1a83a7..58124abd21 100644
--- a/src/libsystemd/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/sd-hwdb/sd-hwdb.c
@@ -457,8 +457,7 @@ _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **val
if (hwdb->properties_modified)
return -EAGAIN;
- ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, (void **)&entry, &k);
- if (!k)
+ if (!ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, (void **)&entry, &k))
return 0;
*key = k;
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index ccc497de09..751bf53d64 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -372,7 +372,7 @@ int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16
int r;
assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
- assert_return(IN_SET(ndm_family, AF_INET, AF_INET6, PF_BRIDGE), -EINVAL);
+ assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, PF_BRIDGE), -EINVAL);
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nlmsg_type);
diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c
index f3e267f007..02e9e9a26b 100644
--- a/src/libsystemd/sd-netlink/sd-netlink.c
+++ b/src/libsystemd/sd-netlink/sd-netlink.c
@@ -869,6 +869,13 @@ int sd_netlink_add_match(
return r;
break;
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_NEIGH);
+ if (r < 0)
+ return r;
+
+ break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTE);
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index fa92f4870a..140953eec1 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -61,8 +61,12 @@ int manager_handle_action(
int r;
assert(m);
- /* We should be called only with valid actions different than HANDLE_IGNORE. */
- assert(handle > HANDLE_IGNORE && handle < _HANDLE_ACTION_MAX);
+
+ /* If the key handling is turned off, don't do anything */
+ if (handle == HANDLE_IGNORE) {
+ log_debug("Refusing operation, as it is turned off.");
+ return 0;
+ }
if (inhibit_key == INHIBIT_HANDLE_LID_SWITCH) {
/* If the last system suspend or startup is too close,
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index 86c9121f27..5598fb2c0b 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -339,7 +339,7 @@ int button_open(Button *b) {
return log_error_errno(errno, "Failed to get input name for %s: %m", p);
(void) button_set_mask(b->name, fd);
-
+
b->io_event_source = sd_event_source_unref(b->io_event_source);
r = sd_event_add_io(b->manager->event, &b->io_event_source, fd, EPOLLIN, button_dispatch, b);
if (r < 0)
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 8a36155115..1883c97e4d 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -329,6 +329,8 @@ int inhibitor_create_fifo(Inhibitor *i) {
r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE-10);
if (r < 0)
return r;
+
+ (void) sd_event_source_set_description(i->event_source, "inhibitor-ref");
}
/* Open writing side */
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 654955ba08..3100a2e04e 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -893,7 +893,7 @@ static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) {
"%s on port %s%s%s%s",
strna(system_name), strna(port_id),
isempty(port_description) ? "" : " (",
- port_description,
+ strempty(port_description),
isempty(port_description) ? "" : ")");
if (r < 0)
return r;
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index a207bb0790..885cda3a03 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -260,6 +260,8 @@ static int address_add_internal(Link *link, Set **addresses,
r = set_put(*addresses, address);
if (r < 0)
return r;
+ if (r == 0)
+ return -EEXIST;
address->link = link;
@@ -976,10 +978,7 @@ int config_parse_address_scope(const char *unit,
bool address_is_ready(const Address *a) {
assert(a);
- if (a->family == AF_INET6)
- return !(a->flags & IFA_F_TENTATIVE);
- else
- return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
+ return !(a->flags & IFA_F_TENTATIVE);
}
int address_section_verify(Address *address) {
diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c
index d958d11d01..626b975839 100644
--- a/src/network/networkd-dhcp-common.c
+++ b/src/network/networkd-dhcp-common.c
@@ -18,7 +18,7 @@ int config_parse_dhcp(
void *data,
void *userdata) {
- AddressFamilyBoolean *dhcp = data, s;
+ AddressFamily *dhcp = data, s;
assert(filename);
assert(lvalue);
@@ -26,10 +26,10 @@ int config_parse_dhcp(
assert(data);
/* Note that this is mostly like
- * config_parse_address_family_boolean(), except that it
+ * config_parse_address_family(), except that it
* understands some old names for the enum values */
- s = address_family_boolean_from_string(rvalue);
+ s = address_family_from_string(rvalue);
if (s < 0) {
/* Previously, we had a slightly different enum here,
@@ -51,7 +51,7 @@ int config_parse_dhcp(
log_syntax(unit, LOG_WARNING, filename, line, 0,
"DHCP=%s is deprecated, please use DHCP=%s instead.",
- rvalue, address_family_boolean_to_string(s));
+ rvalue, address_family_to_string(s));
}
*dhcp = s;
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index b20aa78508..8ad736a82b 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -141,7 +141,7 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
(void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
- r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, 0, 0, 0, &route);
+ r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, NULL, 0, 0, 0, &route);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to add unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m",
strnull(buf),
@@ -295,7 +295,7 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
table = link_get_dhcp_route_table(link);
- r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, 0, 0, table, &route);
+ r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, NULL, 0, 0, table, &route);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to add unreachable route for DHCPv6 delegated subnet %s/%u: %m",
strnull(buf),
@@ -732,7 +732,7 @@ static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
assert_return(addr, -EINVAL);
r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64,
- 0, 0, 0, &route);
+ NULL, 0, 0, 0, &route);
if (r < 0)
return r;
@@ -799,7 +799,7 @@ int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
return -EINVAL;
(void) sd_radv_remove_prefix(l->radv, addr, 64);
- r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
+ r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, NULL, 0, 0, 0, &route);
if (r < 0)
return r;
diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c
index 71f6af6af2..e50a3150df 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -251,7 +251,7 @@ int config_parse_ipv4ll(
void *data,
void *userdata) {
- AddressFamilyBoolean *link_local = data;
+ AddressFamily *link_local = data;
int r;
assert(filename);
@@ -260,7 +260,7 @@ int config_parse_ipv4ll(
assert(data);
/* Note that this is mostly like
- * config_parse_address_family_boolean(), except that it
+ * config_parse_address_family(), except that it
* applies only to IPv4 */
r = parse_boolean(rvalue);
@@ -276,7 +276,7 @@ int config_parse_ipv4ll(
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
- lvalue, rvalue, address_family_boolean_to_string(*link_local));
+ lvalue, rvalue, address_family_to_string(*link_local));
return 0;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 17d37c1617..47d4d08aee 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -150,7 +150,7 @@ static bool link_dhcp4_server_enabled(Link *link) {
return link->network->dhcp_server;
}
-bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
+bool link_ipv4ll_enabled(Link *link, AddressFamily mask) {
assert(link);
assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0);
@@ -242,7 +242,7 @@ static bool link_ipv4_forward_enabled(Link *link) {
if (!link->network)
return false;
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID)
return false;
return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
@@ -260,7 +260,7 @@ static bool link_ipv6_forward_enabled(Link *link) {
if (!link->network)
return false;
- if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
+ if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID)
return false;
if (link_sysctl_ipv6_enabled(link) == 0)
@@ -699,6 +699,9 @@ static Link *link_free(Link *link) {
link->routes = set_free_with_destructor(link->routes, route_free);
link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free);
+ link->neighbors = set_free_with_destructor(link->neighbors, neighbor_free);
+ link->neighbors_foreign = set_free_with_destructor(link->neighbors_foreign, neighbor_free);
+
link->addresses = set_free_with_destructor(link->addresses, address_free);
link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free);
@@ -1945,6 +1948,8 @@ static int link_append_to_master(Link *link, NetDev *netdev) {
r = set_put(master->slaves, link);
if (r < 0)
return r;
+ if (r == 0)
+ return 0;
link_ref(link);
return 0;
@@ -2347,6 +2352,22 @@ static bool link_is_static_address_configured(Link *link, Address *address) {
return false;
}
+static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) {
+ Neighbor *net_neighbor;
+
+ assert(link);
+ assert(neighbor);
+
+ if (!link->network)
+ return false;
+
+ LIST_FOREACH(neighbors, net_neighbor, link->network->neighbors)
+ if (neighbor_equal(net_neighbor, neighbor))
+ return true;
+
+ return false;
+}
+
static bool link_is_static_route_configured(Link *link, Route *route) {
Route *net_route;
@@ -2392,6 +2413,7 @@ static bool link_address_is_dynamic(Link *link, Address *address) {
static int link_drop_foreign_config(Link *link) {
Address *address;
+ Neighbor *neighbor;
Route *route;
Iterator i;
int r;
@@ -2418,6 +2440,18 @@ static int link_drop_foreign_config(Link *link) {
}
}
+ SET_FOREACH(neighbor, link->neighbors_foreign, i) {
+ if (link_is_neighbor_configured(link, neighbor)) {
+ r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL);
+ if (r < 0)
+ return r;
+ } else {
+ r = neighbor_remove(neighbor, link, NULL);
+ if (r < 0)
+ return r;
+ }
+ }
+
SET_FOREACH(route, link->routes_foreign, i) {
/* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
@@ -2441,7 +2475,7 @@ static int link_drop_foreign_config(Link *link) {
continue;
if (link_is_static_route_configured(link, route)) {
- r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL);
+ r = route_add(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, NULL);
if (r < 0)
return r;
} else {
@@ -2456,6 +2490,7 @@ static int link_drop_foreign_config(Link *link) {
static int link_drop_config(Link *link) {
Address *address, *pool_address;
+ Neighbor *neighbor;
Route *route;
Iterator i;
int r;
@@ -2479,6 +2514,12 @@ static int link_drop_config(Link *link) {
}
}
+ SET_FOREACH(neighbor, link->neighbors, i) {
+ r = neighbor_remove(neighbor, link, NULL);
+ if (r < 0)
+ return r;
+ }
+
SET_FOREACH(route, link->routes, i) {
/* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
@@ -2686,6 +2727,8 @@ int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *re
configure:
while ((link = set_steal_first(manager->links_requesting_uuid))) {
+ link_unref(link);
+
r = link_configure(link);
if (r < 0)
link_enter_failed(link);
@@ -2758,6 +2801,8 @@ static int link_configure_duid(Link *link) {
r = set_put(m->duids_requesting_uuid, duid);
if (r < 0)
return log_oom();
+
+ link_ref(link);
}
return 0;
@@ -3014,7 +3059,7 @@ network_file_fail:
continue;
}
- r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route);
+ r = route_add(link, family, &route_dst, prefixlen, NULL, tos, priority, table, &route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add route: %m");
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index cd88388015..d077dfe772 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -75,6 +75,8 @@ typedef struct Link {
Set *addresses;
Set *addresses_foreign;
+ Set *neighbors;
+ Set *neighbors_foreign;
Set *routes;
Set *routes_foreign;
@@ -186,7 +188,7 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
int link_set_mtu(Link *link, uint32_t mtu);
-bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask);
+bool link_ipv4ll_enabled(Link *link, AddressFamily mask);
int link_stop_clients(Link *link, bool may_keep_dhcp);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 6037e8564f..a365bcbde7 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -432,7 +432,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
return 0;
}
- (void) route_get(link, family, &dst, dst_prefixlen, tos, priority, table, &route);
+ (void) route_get(link, family, &dst, dst_prefixlen, &gw, tos, priority, table, &route);
if (DEBUG_LOGGING) {
_cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL,
@@ -466,7 +466,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
case RTM_NEWROUTE:
if (!route) {
/* A route appeared that we did not request */
- r = route_add_foreign(link, family, &dst, dst_prefixlen, tos, priority, table, &route);
+ r = route_add_foreign(link, family, &dst, dst_prefixlen, &gw, tos, priority, table, &route);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
return 0;
@@ -488,6 +488,184 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
return 1;
}
+static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) {
+ int r;
+
+ assert(message);
+ assert(lladdr);
+ assert(size);
+ assert(str);
+
+ *str = NULL;
+
+ r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6);
+ if (r >= 0) {
+ *size = sizeof(lladdr->ip.in6);
+ if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0)
+ log_warning_errno(r, "Could not print lower address: %m");
+ return r;
+ }
+
+ r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac);
+ if (r >= 0) {
+ *size = sizeof(lladdr->mac);
+ *str = new(char, ETHER_ADDR_TO_STRING_MAX);
+ if (!*str) {
+ log_oom();
+ return r;
+ }
+ ether_addr_to_string(&lladdr->mac, *str);
+ return r;
+ }
+
+ r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in);
+ if (r >= 0) {
+ *size = sizeof(lladdr->ip.in);
+ if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0)
+ log_warning_errno(r, "Could not print lower address: %m");
+ return r;
+ }
+
+ return r;
+}
+
+int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
+ Manager *m = userdata;
+ Link *link = NULL;
+ Neighbor *neighbor = NULL;
+ int ifindex, family, r;
+ uint16_t type, state;
+ union in_addr_union in_addr = IN_ADDR_NULL;
+ _cleanup_free_ char *addr_str = NULL;
+ union lladdr_union lladdr;
+ size_t lladdr_size = 0;
+ _cleanup_free_ char *lladdr_str = NULL;
+
+ assert(rtnl);
+ assert(message);
+ assert(m);
+
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ log_warning_errno(r, "rtnl: failed to receive neighbor message, ignoring: %m");
+
+ return 0;
+ }
+
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
+ return 0;
+ } else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) {
+ log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type);
+ return 0;
+ }
+
+ r = sd_rtnl_message_neigh_get_state(message, &state);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m");
+ return 0;
+ } else if (!FLAGS_SET(state, NUD_PERMANENT)) {
+ log_debug("rtnl: received non-static neighbor, ignoring.");
+ return 0;
+ }
+
+ r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
+ return 0;
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex);
+ return 0;
+ }
+
+ r = link_get(m, ifindex, &link);
+ if (r < 0 || !link) {
+ /* when enumerating we might be out of sync, but we will get the neighbor again, so just
+ * ignore it */
+ if (!m->enumerating)
+ log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex);
+ return 0;
+ }
+
+ r = sd_rtnl_message_neigh_get_family(message, &family);
+ if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) {
+ log_link_warning(link, "rtnl: received neighbor message with invalid family, ignoring.");
+ return 0;
+ }
+
+ switch (family) {
+ case AF_INET:
+ r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ case AF_INET6:
+ r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("Received unsupported address family");
+ }
+
+ if (in_addr_to_string(family, &in_addr, &addr_str) < 0)
+ log_link_warning_errno(link, r, "Could not print address: %m");
+
+ r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m");
+ return 0;
+ }
+
+ (void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
+
+ switch (type) {
+ case RTM_NEWNEIGH:
+ if (neighbor)
+ log_link_debug(link, "Remembering neighbor: %s->%s",
+ strnull(addr_str), strnull(lladdr_str));
+ else {
+ /* A neighbor appeared that we did not request */
+ r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m",
+ strnull(addr_str), strnull(lladdr_str));
+ return 0;
+ } else
+ log_link_debug(link, "Remembering foreign neighbor: %s->%s",
+ strnull(addr_str), strnull(lladdr_str));
+ }
+
+ break;
+
+ case RTM_DELNEIGH:
+ if (neighbor) {
+ log_link_debug(link, "Forgetting neighbor: %s->%s",
+ strnull(addr_str), strnull(lladdr_str));
+ (void) neighbor_free(neighbor);
+ } else
+ log_link_info(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.",
+ strnull(addr_str), strnull(lladdr_str));
+
+ break;
+
+ default:
+ assert_not_reached("Received invalid RTNL message type");
+ }
+
+ return 1;
+}
+
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
_cleanup_free_ char *buf = NULL;
Manager *m = userdata;
@@ -1014,6 +1192,14 @@ static int manager_connect_rtnl(Manager *m) {
if (r < 0)
return r;
+ r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
+ if (r < 0)
+ return r;
+
r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
if (r < 0)
return r;
@@ -1555,6 +1741,41 @@ int manager_rtnl_enumerate_addresses(Manager *m) {
return r;
}
+int manager_rtnl_enumerate_neighbors(Manager *m) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+ sd_netlink_message *neigh;
+ int r;
+
+ assert(m);
+ assert(m->rtnl);
+
+ r = sd_rtnl_message_new_neigh(m->rtnl, &req, RTM_GETNEIGH, 0, AF_UNSPEC);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_request_dump(req, true);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_call(m->rtnl, req, 0, &reply);
+ if (r < 0)
+ return r;
+
+ for (neigh = reply; neigh; neigh = sd_netlink_message_next(neigh)) {
+ int k;
+
+ m->enumerating = true;
+
+ k = manager_rtnl_process_neighbor(m->rtnl, neigh, m);
+ if (k < 0)
+ r = k;
+
+ m->enumerating = false;
+ }
+
+ return r;
+}
+
int manager_rtnl_enumerate_routes(Manager *m) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
sd_netlink_message *route;
@@ -1818,6 +2039,8 @@ int manager_request_product_uuid(Manager *m, Link *link) {
r = set_put(m->duids_requesting_uuid, duid);
if (r < 0)
return log_oom();
+
+ link_ref(link);
}
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index 5422b56dc2..f5166dad12 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -77,10 +77,12 @@ bool manager_should_reload(Manager *m);
int manager_rtnl_enumerate_links(Manager *m);
int manager_rtnl_enumerate_addresses(Manager *m);
+int manager_rtnl_enumerate_neighbors(Manager *m);
int manager_rtnl_enumerate_routes(Manager *m);
int manager_rtnl_enumerate_rules(Manager *m);
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata);
+int manager_rtnl_process_neighbor(sd_netlink *nl, sd_netlink_message *message, void *userdata);
int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata);
int manager_rtnl_process_rule(sd_netlink *nl, sd_netlink_message *message, void *userdata);
diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c
index 191f6e3320..537f6be9e1 100644
--- a/src/network/networkd-neighbor.c
+++ b/src/network/networkd-neighbor.c
@@ -11,6 +11,7 @@
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-neighbor.h"
+#include "set.h"
void neighbor_free(Neighbor *neighbor) {
if (!neighbor)
@@ -21,10 +22,15 @@ void neighbor_free(Neighbor *neighbor) {
assert(neighbor->network->n_neighbors > 0);
neighbor->network->n_neighbors--;
- if (neighbor->section) {
+ if (neighbor->section)
hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
- network_config_section_free(neighbor->section);
- }
+ }
+
+ network_config_section_free(neighbor->section);
+
+ if (neighbor->link) {
+ set_remove(neighbor->link->neighbors, neighbor);
+ set_remove(neighbor->link->neighbors_foreign, neighbor);
}
free(neighbor);
@@ -81,9 +87,10 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
return 0;
}
-static int neighbor_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
+ assert(m);
assert(link);
assert(link->neighbor_messages > 0);
@@ -137,7 +144,7 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
if (r < 0)
return log_error_errno(r, "Could not append NDA_DST attribute: %m");
- r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_handler,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_configure_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");
@@ -145,9 +152,217 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
link->neighbor_messages++;
link_ref(link);
+ r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not add neighbor: %m");
+
return 0;
}
+static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(m);
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -ESRCH)
+ /* Neighbor may not exist because it already got deleted, ignore that. */
+ log_link_warning_errno(link, r, "Could not remove neighbor: %m");
+
+ return 1;
+}
+
+int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(neighbor);
+ assert(link);
+ assert(link->ifindex > 0);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+
+ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH,
+ link->ifindex, neighbor->family);
+ if (r < 0)
+ return log_error_errno(r, "Could not allocate RTM_DELNEIGH message: %m");
+
+ r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr);
+ if (r < 0)
+ return log_error_errno(r, "Could not append NDA_DST attribute: %m");
+
+ r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_remove_handler,
+ link_netlink_destroy_callback, link);
+ if (r < 0)
+ return log_error_errno(r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return 0;
+}
+
+static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
+ assert(neighbor);
+
+ siphash24_compress(&neighbor->family, sizeof(neighbor->family), state);
+
+ switch (neighbor->family) {
+ case AF_INET:
+ case AF_INET6:
+ /* Equality of neighbors are given by the pair (addr,lladdr) */
+ siphash24_compress(&neighbor->in_addr, FAMILY_ADDRESS_SIZE(neighbor->family), state);
+ siphash24_compress(&neighbor->lladdr, neighbor->lladdr_size, state);
+ break;
+ default:
+ /* treat any other address family as AF_UNSPEC */
+ break;
+ }
+}
+
+static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
+ int r;
+
+ r = CMP(a->family, b->family);
+ if (r != 0)
+ return r;
+
+ r = CMP(a->lladdr_size, b->lladdr_size);
+ if (r != 0)
+ return r;
+
+ switch (a->family) {
+ case AF_INET:
+ case AF_INET6:
+ r = memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family));
+ if (r != 0)
+ return r;
+ }
+
+ return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size);
+}
+
+DEFINE_PRIVATE_HASH_OPS(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func);
+
+int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
+ Neighbor neighbor, *existing;
+
+ assert(link);
+ assert(addr);
+ assert(lladdr);
+
+ neighbor = (Neighbor) {
+ .family = family,
+ .in_addr = *addr,
+ .lladdr = *lladdr,
+ .lladdr_size = lladdr_size,
+ };
+
+ existing = set_get(link->neighbors, &neighbor);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 1;
+ }
+
+ existing = set_get(link->neighbors_foreign, &neighbor);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int neighbor_add_internal(Link *link, Set **neighbors, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
+ _cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
+ int r;
+
+ assert(link);
+ assert(neighbors);
+ assert(addr);
+ assert(lladdr);
+
+ neighbor = new(Neighbor, 1);
+ if (!neighbor)
+ return -ENOMEM;
+
+ *neighbor = (Neighbor) {
+ .family = family,
+ .in_addr = *addr,
+ .lladdr = *lladdr,
+ .lladdr_size = lladdr_size,
+ };
+
+ r = set_ensure_allocated(neighbors, &neighbor_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = set_put(*neighbors, neighbor);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EEXIST;
+
+ neighbor->link = link;
+
+ if (ret)
+ *ret = neighbor;
+
+ neighbor = NULL;
+
+ return 0;
+}
+
+int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
+ Neighbor *neighbor;
+ int r;
+
+ r = neighbor_get(link, family, addr, lladdr, lladdr_size, &neighbor);
+ if (r == -ENOENT) {
+ /* Neighbor doesn't exist, make a new one */
+ r = neighbor_add_internal(link, &link->neighbors, family, addr, lladdr, lladdr_size, &neighbor);
+ if (r < 0)
+ return r;
+ } else if (r == 0) {
+ /* Neighbor is foreign, claim it as recognized */
+ r = set_ensure_allocated(&link->neighbors, &neighbor_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = set_put(link->neighbors, neighbor);
+ if (r < 0)
+ return r;
+
+ set_remove(link->neighbors_foreign, neighbor);
+ } else if (r == 1) {
+ /* Neighbor already exists */
+ } else
+ return r;
+
+ if (ret)
+ *ret = neighbor;
+ return 0;
+}
+
+int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
+ return neighbor_add_internal(link, &link->neighbors_foreign, family, addr, lladdr, lladdr_size, ret);
+}
+
+bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) {
+ if (n1 == n2)
+ return true;
+
+ if (!n1 || !n2)
+ return false;
+
+ return neighbor_compare_func(n1, n2) == 0;
+}
+
int neighbor_section_verify(Neighbor *neighbor) {
if (section_is_invalid(neighbor->section))
return -EINVAL;
diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h
index 09ccb55274..97ee1f6d73 100644
--- a/src/network/networkd-neighbor.h
+++ b/src/network/networkd-neighbor.h
@@ -15,6 +15,11 @@ typedef struct Neighbor Neighbor;
#include "networkd-network.h"
#include "networkd-util.h"
+union lladdr_union {
+ struct ether_addr mac;
+ union in_addr_union ip;
+};
+
struct Neighbor {
Network *network;
Link *link;
@@ -22,10 +27,7 @@ struct Neighbor {
int family;
union in_addr_union in_addr;
- union {
- struct ether_addr mac;
- union in_addr_union ip;
- } lladdr;
+ union lladdr_union lladdr;
size_t lladdr_size;
LIST_FIELDS(Neighbor, neighbors);
@@ -36,6 +38,12 @@ void neighbor_free(Neighbor *neighbor);
DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
+int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
+
+int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret);
+int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret);
+int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret);
+bool neighbor_equal(const Neighbor *n1, const Neighbor *n2);
int neighbor_section_verify(Neighbor *neighbor);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index e55228af38..d4d108ad25 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -59,7 +59,7 @@ Network.Xfrm, config_parse_stacked_netdev,
Network.VRF, config_parse_ifname, 0, offsetof(Network, vrf_name)
Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp)
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
-Network.LinkLocalAddressing, config_parse_link_local_address_family_boolean, 0, offsetof(Network, link_local)
+Network.LinkLocalAddressing, config_parse_link_local_address_family, 0, offsetof(Network, link_local)
Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device)
Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token)
@@ -76,7 +76,7 @@ Network.DNSOverTLS, config_parse_dns_over_tls_mode,
Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp)
-Network.IPForward, config_parse_address_family_boolean_with_kernel, 0, offsetof(Network, ip_forward)
+Network.IPForward, config_parse_address_family_with_kernel, 0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
@@ -122,6 +122,7 @@ RoutingPolicyRule.IPProtocol, config_parse_routing_policy_rule_ip_prot
RoutingPolicyRule.SourcePort, config_parse_routing_policy_rule_port_range, 0, 0
RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_port_range, 0, 0
RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_invert, 0, 0
+RoutingPolicyRule.Family, config_parse_routing_policy_rule_family, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 9d3c383378..6a8766ce68 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -281,7 +281,7 @@ int network_verify(Network *network) {
prefix_free(prefix);
LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
- if (section_is_invalid(rule->section))
+ if (routing_policy_rule_section_verify(rule) < 0)
routing_policy_rule_free(rule);
return 0;
@@ -395,7 +395,7 @@ int network_load_one(Manager *manager, const char *filename) {
.dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
/* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
- .link_local = _ADDRESS_FAMILY_BOOLEAN_INVALID,
+ .link_local = _ADDRESS_FAMILY_INVALID,
.ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
.ipv6_accept_ra = -1,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 0fa800841c..f8894f86dd 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -77,7 +77,7 @@ struct Network {
Hashmap *stacked_netdev_names;
/* DHCP Client Support */
- AddressFamilyBoolean dhcp;
+ AddressFamily dhcp;
DHCPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
char **dhcp_user_class;
@@ -123,7 +123,7 @@ struct Network {
uint32_t dhcp_server_pool_size;
/* IPV4LL Support */
- AddressFamilyBoolean link_local;
+ AddressFamily link_local;
bool ipv4ll_route;
bool default_route_on_device;
@@ -171,7 +171,7 @@ struct Network {
usec_t can_restart_us;
int can_triple_sampling;
- AddressFamilyBoolean ip_forward;
+ AddressFamily ip_forward;
bool ip_masquerade;
int ipv6_accept_ra;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 25ab527284..8a16e9111f 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -198,7 +198,11 @@ static int route_compare_func(const Route *a, const Route *b) {
if (r != 0)
return r;
- return memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family));
+ r = memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family));
+ if (r != 0)
+ return r;
+
+ return memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
default:
/* treat any other address family as AF_UNSPEC */
return 0;
@@ -318,6 +322,7 @@ int route_get(Link *link,
int family,
const union in_addr_union *dst,
unsigned char dst_prefixlen,
+ const union in_addr_union *gw,
unsigned char tos,
uint32_t priority,
uint32_t table,
@@ -332,6 +337,7 @@ int route_get(Link *link,
.family = family,
.dst = *dst,
.dst_prefixlen = dst_prefixlen,
+ .gw = gw ? *gw : IN_ADDR_NULL,
.tos = tos,
.priority = priority,
.table = table,
@@ -360,6 +366,7 @@ static int route_add_internal(
int family,
const union in_addr_union *dst,
unsigned char dst_prefixlen,
+ const union in_addr_union *gw,
unsigned char tos,
uint32_t priority,
uint32_t table,
@@ -379,6 +386,8 @@ static int route_add_internal(
route->family = family;
route->dst = *dst;
route->dst_prefixlen = dst_prefixlen;
+ route->dst = *dst;
+ route->gw = gw ? *gw : IN_ADDR_NULL;
route->tos = tos;
route->priority = priority;
route->table = table;
@@ -390,6 +399,8 @@ static int route_add_internal(
r = set_put(*routes, route);
if (r < 0)
return r;
+ if (r == 0)
+ return -EEXIST;
route->link = link;
@@ -406,18 +417,20 @@ int route_add_foreign(
int family,
const union in_addr_union *dst,
unsigned char dst_prefixlen,
+ const union in_addr_union *gw,
unsigned char tos,
uint32_t priority,
uint32_t table,
Route **ret) {
- return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret);
+ return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, gw, tos, priority, table, ret);
}
int route_add(Link *link,
int family,
const union in_addr_union *dst,
unsigned char dst_prefixlen,
+ const union in_addr_union *gw,
unsigned char tos,
uint32_t priority,
uint32_t table,
@@ -426,10 +439,10 @@ int route_add(Link *link,
Route *route;
int r;
- r = route_get(link, family, dst, dst_prefixlen, tos, priority, table, &route);
+ r = route_get(link, family, dst, dst_prefixlen, gw, tos, priority, table, &route);
if (r == -ENOENT) {
/* Route does not exist, create a new one */
- r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, tos, priority, table, &route);
+ r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, gw, tos, priority, table, &route);
if (r < 0)
return r;
} else if (r == 0) {
@@ -628,7 +641,7 @@ int route_configure(
return 0;
}
- if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
+ if (route_get(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, NULL) <= 0 &&
set_size(link->routes) >= routes_max())
return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
"Too many routes are configured, refusing: %m");
@@ -804,7 +817,7 @@ int route_configure(
lifetime = route->lifetime;
- r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route);
+ r = route_add(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, &route);
if (r < 0)
return log_link_error_errno(link, r, "Could not add route: %m");
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index 9d9c980d90..9bd4991520 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -56,9 +56,9 @@ void route_free(Route *route);
int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback);
int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback);
-int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
-int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
-int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
+int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, const union in_addr_union *gw, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
+int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, const union in_addr_union *gw, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
+int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, const union in_addr_union *gw, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
void route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type);
bool route_equal(Route *r1, Route *r2);
diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c
index 31a49ed905..5edc2444a7 100644
--- a/src/network/networkd-routing-policy-rule.c
+++ b/src/network/networkd-routing-policy-rule.c
@@ -3,6 +3,7 @@
#include <net/if.h>
#include <linux/fib_rules.h>
+#include "af-list.h"
#include "alloc-util.h"
#include "conf-parser.h"
#include "fileio.h"
@@ -10,6 +11,7 @@
#include "networkd-routing-policy-rule.h"
#include "netlink-util.h"
#include "networkd-manager.h"
+#include "networkd-util.h"
#include "parse-util.h"
#include "socket-util.h"
#include "string-util.h"
@@ -23,7 +25,6 @@ int routing_policy_rule_new(RoutingPolicyRule **ret) {
return -ENOMEM;
*rule = (RoutingPolicyRule) {
- .family = AF_INET,
.table = RT_TABLE_MAIN,
};
@@ -58,6 +59,44 @@ void routing_policy_rule_free(RoutingPolicyRule *rule) {
free(rule);
}
+static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *src) {
+ _cleanup_free_ char *iif = NULL, *oif = NULL;
+
+ assert(dest);
+ assert(src);
+
+ if (src->iif) {
+ iif = strdup(src->iif);
+ if (!iif)
+ return -ENOMEM;
+ }
+
+ if (src->oif) {
+ oif = strdup(src->oif);
+ if (!oif)
+ return -ENOMEM;
+ }
+
+ dest->family = src->family;
+ dest->from = src->from;
+ dest->from_prefixlen = src->from_prefixlen;
+ dest->to = src->to;
+ dest->to_prefixlen = src->to_prefixlen;
+ dest->invert_rule = src->invert_rule;
+ dest->tos = src->tos;
+ dest->fwmark = src->fwmark;
+ dest->fwmask = src->fwmask;
+ dest->priority = src->priority;
+ dest->table = src->table;
+ dest->iif = TAKE_PTR(iif);
+ dest->oif = TAKE_PTR(oif);
+ dest->protocol = src->protocol;
+ dest->sport = src->sport;
+ dest->dport = src->dport;
+
+ return 0;
+}
+
static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) {
assert(rule);
@@ -209,7 +248,11 @@ int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) {
if (r < 0)
return r;
- return set_put(m->rules, rule);
+ r = set_put(m->rules, rule);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ routing_policy_rule_free(rule);
}
return -ENOENT;
@@ -217,46 +260,21 @@ int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) {
static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
- _cleanup_free_ char *iif = NULL, *oif = NULL;
int r;
assert(m);
assert(rules);
assert(in);
- if (in->iif) {
- iif = strdup(in->iif);
- if (!iif)
- return -ENOMEM;
- }
-
- if (in->oif) {
- oif = strdup(in->oif);
- if (!oif)
- return -ENOMEM;
- }
-
r = routing_policy_rule_new(&rule);
if (r < 0)
return r;
rule->manager = m;
- rule->family = in->family;
- rule->from = in->from;
- rule->from_prefixlen = in->from_prefixlen;
- rule->to = in->to;
- rule->to_prefixlen = in->to_prefixlen;
- rule->invert_rule = in->invert_rule;
- rule->tos = in->tos;
- rule->fwmark = in->fwmark;
- rule->fwmask = in->fwmask;
- rule->priority = in->priority;
- rule->table = in->table;
- rule->iif = TAKE_PTR(iif);
- rule->oif = TAKE_PTR(oif);
- rule->protocol = in->protocol;
- rule->sport = in->sport;
- rule->dport = in->dport;
+
+ r = routing_policy_rule_copy(rule, in);
+ if (r < 0)
+ return r;
r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
if (r < 0)
@@ -265,6 +283,8 @@ static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPoli
r = set_put(*rules, rule);
if (r < 0)
return r;
+ if (r == 0)
+ return -EEXIST;
if (ret)
*ret = rule;
@@ -549,6 +569,50 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
return 1;
}
+int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
+ int r;
+
+ if (section_is_invalid(rule->section))
+ return -EINVAL;
+
+ if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) ||
+ (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "%s: address family specified by Family= conflicts with the address "
+ "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.",
+ rule->section->filename, rule->section->line);
+
+ if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) {
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL;
+
+ assert(rule->family == AF_UNSPEC);
+
+ /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */
+
+ r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6);
+ if (r < 0)
+ return r;
+
+ r = routing_policy_rule_copy(rule6, rule);
+ if (r < 0)
+ return r;
+
+ rule->family = AF_INET;
+ rule6->family = AF_INET6;
+
+ TAKE_PTR(rule6);
+ }
+
+ if (rule->family == AF_UNSPEC) {
+ if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6))
+ rule->family = AF_INET6;
+ else
+ rule->family = AF_INET;
+ }
+
+ return 0;
+}
+
static int parse_fwmark_fwmask(const char *s, uint32_t *fwmark, uint32_t *fwmask) {
_cleanup_free_ char *f = NULL;
char *p;
@@ -761,7 +825,10 @@ int config_parse_routing_policy_rule_prefix(
prefixlen = &n->from_prefixlen;
}
- r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen);
+ if (n->family == AF_UNSPEC)
+ r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen);
+ else
+ r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue);
return 0;
@@ -941,6 +1008,46 @@ int config_parse_routing_policy_rule_invert(
return 0;
}
+int config_parse_routing_policy_rule_family(
+ 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_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
+ Network *network = userdata;
+ AddressFamily a;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = routing_policy_rule_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ a = routing_policy_rule_address_family_from_string(rvalue);
+ if (a < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid address family '%s', ignoring.", rvalue);
+ return 0;
+ }
+
+ n->address_family = a;
+ n = NULL;
+
+ return 0;
+}
+
static int routing_policy_rule_read_full_file(const char *state_file, char **ret) {
_cleanup_free_ char *s = NULL;
size_t size;
@@ -971,6 +1078,7 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
SET_FOREACH(rule, rules, i) {
_cleanup_free_ char *from_str = NULL, *to_str = NULL;
bool space = false;
+ const char *family_str;
fputs("RULE=", f);
@@ -995,6 +1103,12 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
space = true;
}
+ family_str = af_to_name(rule->family);
+ if (family_str)
+ fprintf(f, "%sfamily=%s",
+ space ? " " : "",
+ family_str);
+
if (rule->tos != 0) {
fprintf(f, "%stos=%hhu",
space ? " " : "",
@@ -1002,6 +1116,10 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) {
space = true;
}
+ fprintf(f, "%spriority=%"PRIu32,
+ space ? " " : "",
+ rule->priority);
+
if (rule->fwmark != 0) {
fprintf(f, "%sfwmark=%"PRIu32"/%"PRIu32,
space ? " " : "",
@@ -1117,6 +1235,13 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
continue;
}
+ } else if (streq(a, "family")) {
+ r = af_from_name(b);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b);
+ continue;
+ }
+ rule->family = r;
} else if (streq(a, "tos")) {
r = safe_atou8(b, &rule->tos);
if (r < 0) {
@@ -1129,6 +1254,12 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
log_error_errno(r, "Failed to parse RPDB rule table, ignoring: %s", b);
continue;
}
+ } else if (streq(a, "priority")) {
+ r = safe_atou32(b, &rule->priority);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse RPDB rule priority, ignoring: %s", b);
+ continue;
+ }
} else if (streq(a, "fwmark")) {
r = parse_fwmark_fwmask(b, &rule->fwmark, &rule->fwmask);
@@ -1180,8 +1311,8 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", p);
continue;
}
-
- rule = NULL;
+ if (r > 0)
+ rule = NULL;
}
return 0;
diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h
index 512af3dfdd..6b8e310227 100644
--- a/src/network/networkd-routing-policy-rule.h
+++ b/src/network/networkd-routing-policy-rule.h
@@ -36,7 +36,8 @@ struct RoutingPolicyRule {
uint32_t fwmask;
uint32_t priority;
- int family;
+ AddressFamily address_family; /* Specified by Family= */
+ int family; /* Automatically determined by From= or To= */
unsigned char to_prefixlen;
unsigned char from_prefixlen;
@@ -56,6 +57,7 @@ int routing_policy_rule_new(RoutingPolicyRule **ret);
void routing_policy_rule_free(RoutingPolicyRule *rule);
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
+int routing_policy_rule_section_verify(RoutingPolicyRule *rule);
int routing_policy_rule_configure(RoutingPolicyRule *address, Link *link, link_netlink_message_handler_t callback);
int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback);
@@ -76,3 +78,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_ip_protocol);
CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_family);
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index d01de53f7b..3fd26836c6 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -8,14 +8,14 @@
#include "string-util.h"
#include "util.h"
-static const char * const address_family_boolean_table[_ADDRESS_FAMILY_BOOLEAN_MAX] = {
+static const char * const address_family_table[_ADDRESS_FAMILY_MAX] = {
[ADDRESS_FAMILY_NO] = "no",
[ADDRESS_FAMILY_YES] = "yes",
[ADDRESS_FAMILY_IPV4] = "ipv4",
[ADDRESS_FAMILY_IPV6] = "ipv6",
};
-static const char * const link_local_address_family_boolean_table[_ADDRESS_FAMILY_BOOLEAN_MAX] = {
+static const char * const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = {
[ADDRESS_FAMILY_NO] = "no",
[ADDRESS_FAMILY_YES] = "yes",
[ADDRESS_FAMILY_IPV4] = "ipv4",
@@ -24,12 +24,19 @@ static const char * const link_local_address_family_boolean_table[_ADDRESS_FAMIL
[ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback",
};
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family_boolean, AddressFamilyBoolean, ADDRESS_FAMILY_YES);
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family_boolean, AddressFamilyBoolean, ADDRESS_FAMILY_YES);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family_boolean, link_local_address_family_boolean,
- AddressFamilyBoolean, "Failed to parse option");
+static const char * const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = {
+ [ADDRESS_FAMILY_YES] = "both",
+ [ADDRESS_FAMILY_IPV4] = "ipv4",
+ [ADDRESS_FAMILY_IPV6] = "ipv6",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES);
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family, AddressFamily, ADDRESS_FAMILY_YES);
+DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family,
+ AddressFamily, "Failed to parse option");
-int config_parse_address_family_boolean_with_kernel(
+int config_parse_address_family_with_kernel(
const char* unit,
const char *filename,
unsigned line,
@@ -41,7 +48,7 @@ int config_parse_address_family_boolean_with_kernel(
void *data,
void *userdata) {
- AddressFamilyBoolean *fwd = data, s;
+ AddressFamily *fwd = data, s;
assert(filename);
assert(lvalue);
@@ -56,7 +63,7 @@ int config_parse_address_family_boolean_with_kernel(
* is gone, hence silently accept the old setting, but turn it
* to "no". */
- s = address_family_boolean_from_string(rvalue);
+ s = address_family_from_string(rvalue);
if (s < 0) {
if (streq(rvalue, "kernel"))
s = ADDRESS_FAMILY_NO;
diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h
index aafbac7df6..3a57819f39 100644
--- a/src/network/networkd-util.h
+++ b/src/network/networkd-util.h
@@ -5,7 +5,7 @@
#include "hash-funcs.h"
#include "macro.h"
-typedef enum AddressFamilyBoolean {
+typedef enum AddressFamily {
/* This is a bitmask, though it usually doesn't feel that way! */
ADDRESS_FAMILY_NO = 0,
ADDRESS_FAMILY_IPV4 = 1 << 0,
@@ -13,9 +13,9 @@ typedef enum AddressFamilyBoolean {
ADDRESS_FAMILY_YES = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
ADDRESS_FAMILY_FALLBACK_IPV4 = 1 << 2,
ADDRESS_FAMILY_FALLBACK = ADDRESS_FAMILY_FALLBACK_IPV4 | ADDRESS_FAMILY_IPV6,
- _ADDRESS_FAMILY_BOOLEAN_MAX,
- _ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
-} AddressFamilyBoolean;
+ _ADDRESS_FAMILY_MAX,
+ _ADDRESS_FAMILY_INVALID = -1,
+} AddressFamily;
typedef struct NetworkConfigSection {
unsigned line;
@@ -23,14 +23,17 @@ typedef struct NetworkConfigSection {
char filename[];
} NetworkConfigSection;
-CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family_boolean);
-CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean_with_kernel);
+CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
-const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
-AddressFamilyBoolean address_family_boolean_from_string(const char *s) _pure_;
+const char *address_family_to_string(AddressFamily b) _const_;
+AddressFamily address_family_from_string(const char *s) _pure_;
-const char *link_local_address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
-AddressFamilyBoolean link_local_address_family_boolean_from_string(const char *s) _pure_;
+const char *link_local_address_family_to_string(AddressFamily b) _const_;
+AddressFamily link_local_address_family_from_string(const char *s) _pure_;
+
+const char *routing_policy_rule_address_family_to_string(AddressFamily b) _const_;
+AddressFamily routing_policy_rule_address_family_from_string(const char *s) _pure_;
int kernel_route_expiration_supported(void);
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 090f3777a5..38bd9ff1ff 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -95,6 +95,10 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Could not enumerate addresses: %m");
+ r = manager_rtnl_enumerate_neighbors(m);
+ if (r < 0)
+ return log_error_errno(r, "Could not enumerate neighbors: %m");
+
r = manager_rtnl_enumerate_routes(m);
if (r < 0)
return log_error_errno(r, "Could not enumerate routes: %m");
diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c
index 711954e4a2..56932ba15c 100644
--- a/src/network/test-network-tables.c
+++ b/src/network/test-network-tables.c
@@ -41,7 +41,7 @@ int main(int argc, char **argv) {
test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE);
test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE);
- test_table_sparse(address_family_boolean, ADDRESS_FAMILY_BOOLEAN);
+ test_table_sparse(address_family, ADDRESS_FAMILY);
return EXIT_SUCCESS;
}
diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c
index 6883cbe1ec..2007acb781 100644
--- a/src/network/test-networkd-conf.c
+++ b/src/network/test-networkd-conf.c
@@ -240,7 +240,7 @@ static void test_config_parse_match_strv(void) {
"!baz",
"KEY=val",
"KEY2=val with space",
- "KEY3=val with \"quotation\"")));
+ "KEY3=val with \\quotation\\")));
}
int main(int argc, char **argv) {
diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c
index 57bfb6af68..d441099b5a 100644
--- a/src/network/test-routing-policy-rule.c
+++ b/src/network/test-routing-policy-rule.c
@@ -62,31 +62,31 @@ int main(int argc, char **argv) {
test_setup_logging(LOG_DEBUG);
test_rule_serialization("basic parsing",
- "RULE=from=1.2.3.4/32 to=2.3.4.5/32 tos=5 fwmark=1/2 table=10", NULL);
+ "RULE=from=1.2.3.4/32 to=2.3.4.5/32 family=AF_INET tos=5 priority=0 fwmark=1/2 table=10", NULL);
test_rule_serialization("ignored values",
"RULE=something=to=ignore from=1.2.3.4/32 from=1.2.3.4/32"
" \t to=2.3.4.5/24 to=2.3.4.5/32 tos=5 fwmark=2 fwmark=1 table=10 table=20",
"RULE=from=1.2.3.4/32"
- " to=2.3.4.5/32 tos=5 fwmark=1/0 table=20");
+ " to=2.3.4.5/32 family=AF_INET tos=5 priority=0 fwmark=1/0 table=20");
test_rule_serialization("ipv6",
- "RULE=from=1::2/64 to=2::3/64 table=6", NULL);
+ "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 table=6", NULL);
- assert_se(asprintf(&p, "RULE=from=1::2/64 to=2::3/64 table=%d", RT_TABLE_MAIN) >= 0);
+ assert_se(asprintf(&p, "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 table=%d", RT_TABLE_MAIN) >= 0);
test_rule_serialization("default table",
"RULE=from=1::2/64 to=2::3/64", p);
test_rule_serialization("incoming interface",
"RULE=from=1::2/64 to=2::3/64 table=1 iif=lo",
- "RULE=from=1::2/64 to=2::3/64 iif=lo table=1");
+ "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 iif=lo table=1");
test_rule_serialization("outgoing interface",
- "RULE=from=1::2/64 to=2::3/64 oif=eth0 table=1", NULL);
+ "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 oif=eth0 table=1", NULL);
test_rule_serialization("freeing interface names",
- "RULE=from=1::2/64 to=2::3/64 iif=e0 iif=e1 oif=e0 oif=e1 table=1",
- "RULE=from=1::2/64 to=2::3/64 iif=e1 oif=e1 table=1");
+ "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 iif=e0 iif=e1 oif=e0 oif=e1 table=1",
+ "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 iif=e1 oif=e1 table=1");
return 0;
}
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index a495c2538b..40792086da 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -760,7 +760,7 @@ int config_parse_strv(
for (;;) {
char *word = NULL;
- r = extract_first_word(&rvalue, &word, NULL, EXTRACT_UNQUOTE);
+ r = extract_first_word(&rvalue, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == 0)
break;
if (r == -ENOMEM)
diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c
index 44b1c9b749..82b1422b2d 100644
--- a/src/shared/exit-status.c
+++ b/src/shared/exit-status.c
@@ -18,8 +18,8 @@ const ExitStatusMapping exit_status_mappings[256] = {
* 8…63 │ (Currently unmapped)
* 64…78 │ BSD defined exit codes
* 79…199 │ (Currently unmapped)
- * 200…241 │ systemd's private error codes (might be extended to 254 in future development)
- * 242…254 │ (Currently unmapped, but see above)
+ * 200…242 │ systemd's private error codes (might be extended to 254 in future development)
+ * 243…254 │ (Currently unmapped, but see above)
*
* 255 │ EXIT_EXCEPTION (We use this to propagate exit-by-signal events. It's frequently used by others apps (like bash)
* │ to indicate exit reason that cannot really be expressed in a single exit status value — such as a propagated
@@ -99,7 +99,7 @@ const ExitStatusMapping exit_status_mappings[256] = {
const char* exit_status_to_string(int code, ExitStatusClass class) {
if (code < 0 || (size_t) code >= ELEMENTSOF(exit_status_mappings))
return NULL;
- return FLAGS_SET(exit_status_mappings[code].class, class) ? exit_status_mappings[code].name : NULL;
+ return class & exit_status_mappings[code].class ? exit_status_mappings[code].name : NULL;
}
const char* exit_status_class(int code) {
diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c
index 96e74a758f..5772918c37 100644
--- a/src/shared/pretty-print.c
+++ b/src/shared/pretty-print.c
@@ -213,13 +213,17 @@ void print_separator(void) {
fputs("\n\n", stdout);
}
-static int guess_type(const char **name, bool *is_usr, bool *is_collection, const char **extension) {
+static int guess_type(const char **name, char ***prefixes, bool *is_collection, const char **extension) {
/* Try to figure out if name is like tmpfiles.d/ or systemd/system-presets/,
* i.e. a collection of directories without a main config file. */
_cleanup_free_ char *n = NULL;
- bool usr = false, coll = false;
+ bool usr = false, run = false, coll = false;
const char *ext = ".conf";
+ /* This is static so that the array doesn't get deallocated when we exit the function */
+ static const char* const std_prefixes[] = { CONF_PATHS(""), NULL };
+ static const char* const usr_prefixes[] = { CONF_PATHS_USR(""), NULL };
+ static const char* const run_prefixes[] = { "/run/", NULL };
if (path_equal(*name, "environment.d"))
/* Special case: we need to include /etc/environment in the search path, even
@@ -252,6 +256,11 @@ static int guess_type(const char **name, bool *is_usr, bool *is_collection, cons
ext = ".list";
}
+ if (path_equal(n, "systemd/relabel-extra.d")) {
+ coll = run = true;
+ ext = ".relabel";
+ }
+
if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) {
coll = true;
ext = ".preset";
@@ -260,7 +269,7 @@ static int guess_type(const char **name, bool *is_usr, bool *is_collection, cons
if (path_equal(n, "systemd/user-preset"))
usr = true;
- *is_usr = usr;
+ *prefixes = (char**) (usr ? usr_prefixes : run ? run_prefixes : std_prefixes);
*is_collection = coll;
*extension = ext;
return 0;
@@ -269,19 +278,19 @@ static int guess_type(const char **name, bool *is_usr, bool *is_collection, cons
int conf_files_cat(const char *root, const char *name) {
_cleanup_strv_free_ char **dirs = NULL, **files = NULL;
_cleanup_free_ char *path = NULL;
- char **dir;
- bool is_usr, is_collection;
+ char **prefixes, **prefix;
+ bool is_collection;
const char *extension;
char **t;
int r;
- r = guess_type(&name, &is_usr, &is_collection, &extension);
+ r = guess_type(&name, &prefixes, &is_collection, &extension);
if (r < 0)
return r;
- STRV_FOREACH(dir, is_usr ? CONF_PATHS_USR_STRV("") : CONF_PATHS_STRV("")) {
- assert(endswith(*dir, "/"));
- r = strv_extendf(&dirs, "%s%s%s", *dir, name,
+ STRV_FOREACH(prefix, prefixes) {
+ assert(endswith(*prefix, "/"));
+ r = strv_extendf(&dirs, "%s%s%s", *prefix, name,
is_collection ? "" : ".d");
if (r < 0)
return log_error_errno(r, "Failed to build directory list: %m");
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 498e8ee84a..acfe435283 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -760,6 +760,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
"msync\0"
"sync\0"
"sync_file_range\0"
+ "sync_file_range2\0"
"syncfs\0"
},
[SYSCALL_FILTER_SET_SYSTEM_SERVICE] = {
@@ -1521,6 +1522,7 @@ int seccomp_memory_deny_write_execute(void) {
switch (arch) {
case SCMP_ARCH_X86:
+ case SCMP_ARCH_S390:
filter_syscall = SCMP_SYS(mmap2);
block_syscall = SCMP_SYS(mmap);
shmat_syscall = SCMP_SYS(shmat);
@@ -1545,13 +1547,14 @@ int seccomp_memory_deny_write_execute(void) {
case SCMP_ARCH_X86_64:
case SCMP_ARCH_X32:
case SCMP_ARCH_AARCH64:
- filter_syscall = SCMP_SYS(mmap); /* amd64, x32, and arm64 have only mmap */
+ case SCMP_ARCH_S390X:
+ filter_syscall = SCMP_SYS(mmap); /* amd64, x32, s390x, and arm64 have only mmap */
shmat_syscall = SCMP_SYS(shmat);
break;
/* Please add more definitions here, if you port systemd to other architectures! */
-#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__)
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390__) && !defined(__s390x__)
#warning "Consider adding the right mmap() syscall definitions here!"
#endif
}
diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c
index db73c9bd4b..e15ce26940 100644
--- a/src/shared/unit-file.c
+++ b/src/shared/unit-file.c
@@ -415,7 +415,7 @@ int unit_file_find_fragment(
return -ENOMEM;
/* The unit always has its own name if it's not a template. */
- if (unit_name_is_valid(unit_name, UNIT_NAME_PLAIN | UNIT_NAME_INSTANCE)) {
+ if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) {
r = set_put_strdup(names, unit_name);
if (r < 0)
return r;
@@ -430,12 +430,12 @@ int unit_file_find_fragment(
/* Add any aliases of the original name to the set of names */
nnn = hashmap_get(unit_name_map, basename(fragment));
STRV_FOREACH(t, nnn) {
- if (instance && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) {
+ if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) {
char *inst;
r = unit_name_replace_instance(*t, instance, &inst);
if (r < 0)
- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance);
+ return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance);
if (!streq(unit_name, inst))
log_debug("%s: %s has alias %s", __func__, unit_name, inst);
@@ -488,7 +488,7 @@ int unit_file_find_fragment(
}
if (!streq(unit_name, inst))
- log_info("%s: %s has alias %s", __func__, unit_name, inst);
+ log_debug("%s: %s has alias %s", __func__, unit_name, inst);
r = set_consume(names, TAKE_PTR(inst));
if (r < 0)
return r;
diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c
index c423af6917..98fefb3956 100644
--- a/src/shared/watchdog.c
+++ b/src/shared/watchdog.c
@@ -82,7 +82,16 @@ static int open_watchdog(void) {
}
int watchdog_set_device(char *path) {
- return free_and_strdup(&watchdog_device, path);
+ int r;
+
+ r = free_and_strdup(&watchdog_device, path);
+ if (r < 0)
+ return r;
+
+ if (r > 0) /* watchdog_device changed */
+ watchdog_fd = safe_close(watchdog_fd);
+
+ return r;
}
int watchdog_set_timeout(usec_t *usec) {
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index ec3e2a31dd..dcf76bed7c 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -83,6 +83,7 @@
#include "terminal-util.h"
#include "tmpfile-util.h"
#include "unit-def.h"
+#include "unit-file.h"
#include "unit-name.h"
#include "user-util.h"
#include "utf8.h"
@@ -5873,7 +5874,7 @@ static int cat(int argc, char *argv[], void *userdata) {
bool first = true;
int r;
- /* Include all units by default - i.e. continue as if the --all
+ /* Include all units by default — i.e. continue as if the --all
* option was used */
if (strv_isempty(arg_states))
arg_all = true;
@@ -7904,6 +7905,10 @@ static void help_states(void) {
DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
if (!arg_no_legend)
+ puts("\nAvailable unit file states:");
+ DUMP_STRING_TABLE(unit_file_state, UnitFileState, _UNIT_FILE_STATE_MAX);
+
+ if (!arg_no_legend)
puts("\nAvailable automount unit substates:");
DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index d4d3f3b4a5..1fc1b0ae96 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -428,7 +428,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
.pw_passwd = (char*) "x",
/* We default to the root directory as home */
- .pw_dir = i->home ? i->home : (char*) "/",
+ .pw_dir = i->home ?: (char*) "/",
/* Initialize the shell to nologin, with one exception:
* for root we patch in something special */
@@ -522,13 +522,13 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
ORDERED_HASHMAP_FOREACH(i, todo_uids, iterator) {
struct spwd n = {
.sp_namp = i->name,
- .sp_pwdp = (char*) "!!",
+ .sp_pwdp = (char*) "!!", /* lock this password, and make it invalid */
.sp_lstchg = lstchg,
.sp_min = -1,
.sp_max = -1,
.sp_warn = -1,
.sp_inact = -1,
- .sp_expire = -1,
+ .sp_expire = i->uid == 0 ? -1 : 1, /* lock account as a whole, unless this is root */
.sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
};
diff --git a/src/test/test-exit-status.c b/src/test/test-exit-status.c
index 3bcebd06a4..a007bda5c4 100644
--- a/src/test/test-exit-status.c
+++ b/src/test/test-exit-status.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "exit-status.h"
+#include "string-util.h"
#include "tests.h"
static void test_exit_status_to_string(void) {
@@ -31,11 +32,21 @@ static void test_exit_status_from_string(void) {
assert_se(exit_status_from_string("FAILURE") == 1);
}
+static void test_exit_status_NUMA_POLICY(void) {
+ log_info("/* %s */", __func__);
+
+ assert_se(streq(exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_FULL), "NUMA_POLICY"));
+ assert_se(streq(exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_SYSTEMD), "NUMA_POLICY"));
+ assert_se(!exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_BSD));
+ assert_se(!exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_LSB));
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_exit_status_to_string();
test_exit_status_from_string();
+ test_exit_status_NUMA_POLICY();
return 0;
}
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 074ba3c079..4f15a400ab 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -61,6 +61,25 @@ typedef struct Context {
LIST_HEAD(UnitStatusInfo, units);
} Context;
+#define log_unit_full(unit, level, error, ...) \
+ ({ \
+ const UnitStatusInfo *_u = (unit); \
+ log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, \
+ "UNIT=", _u->name, NULL, NULL, ##__VA_ARGS__); \
+ })
+
+#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)
+#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__)
+#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__)
+#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__)
+#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__)
+
+#define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__)
+#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__)
+#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__)
+#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__)
+#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__)
+
static void unit_status_info_clear(UnitStatusInfo *p) {
assert(p);
@@ -95,7 +114,7 @@ static void context_clear(Context *c) {
}
}
-static int context_add_ntp_service(Context *c, const char *s) {
+static int context_add_ntp_service(Context *c, const char *s, const char *source) {
UnitStatusInfo *u;
if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
@@ -117,6 +136,7 @@ static int context_add_ntp_service(Context *c, const char *s) {
}
LIST_APPEND(units, c->units, u);
+ log_unit_debug(u, "added from %s.", source);
return 0;
}
@@ -131,7 +151,7 @@ static int context_parse_ntp_services_from_environment(Context *c) {
if (!env)
return 0;
- log_debug("Using list of ntp services from environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES.");
+ log_debug("Using list of ntp services from environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES=%s.", env);
for (p = env;;) {
_cleanup_free_ char *word = NULL;
@@ -146,7 +166,7 @@ static int context_parse_ntp_services_from_environment(Context *c) {
break;
}
- r = context_add_ntp_service(c, word);
+ r = context_add_ntp_service(c, word, "$SYSTEMD_TIMEDATED_NTP_SERVICES");
if (r < 0)
log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word);
}
@@ -190,7 +210,7 @@ static int context_parse_ntp_services_from_disk(Context *c) {
if (isempty(word) || startswith("#", word))
continue;
- r = context_add_ntp_service(c, word);
+ r = context_add_ntp_service(c, word, *f);
if (r < 0)
log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word);
}
@@ -223,20 +243,6 @@ static int context_ntp_service_is_active(Context *c) {
return count;
}
-static int context_ntp_service_is_enabled(Context *c) {
- UnitStatusInfo *info;
- int count = 0;
-
- assert(c);
-
- /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
-
- LIST_FOREACH(units, info, c->units)
- count += !STRPTR_IN_SET(info->unit_file_state, "masked", "masked-runtime", "disabled", "bad");
-
- return count;
-}
-
static int context_ntp_service_exists(Context *c) {
UnitStatusInfo *info;
int count = 0;
@@ -272,31 +278,25 @@ static int context_read_data(Context *c) {
static int context_write_data_timezone(Context *c) {
_cleanup_free_ char *p = NULL;
- int r = 0;
assert(c);
if (isempty(c->zone)) {
if (unlink("/etc/localtime") < 0 && errno != ENOENT)
- r = -errno;
-
- return r;
+ return -errno;
+ return 0;
}
p = path_join("../usr/share/zoneinfo", c->zone);
if (!p)
return log_oom();
- r = symlink_atomic(p, "/etc/localtime");
- if (r < 0)
- return r;
-
- return 0;
+ return symlink_atomic(p, "/etc/localtime");
}
static int context_write_data_local_rtc(Context *c) {
- int r;
_cleanup_free_ char *s = NULL, *w = NULL;
+ int r;
assert(c);
@@ -406,7 +406,7 @@ static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m)
NULL,
u);
if (r < 0)
- return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+ return log_unit_error_errno(u, r, "Failed to get properties: %s", bus_error_message(&error, r));
}
return 0;
@@ -437,7 +437,9 @@ static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *er
if (n == 0) {
c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
- (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
+ (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
+ "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP",
+ NULL);
}
return 0;
@@ -463,6 +465,8 @@ static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *erro
"ss",
u->name,
"replace");
+ log_unit_full(u, r < 0 ? LOG_WARNING : LOG_DEBUG, r,
+ "%s unit: %m", start ? "Starting" : "Stopping");
if (r < 0)
return r;
@@ -486,8 +490,12 @@ static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *
/* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
- if (streq(u->unit_file_state, "enabled") == enable)
+ if (streq(u->unit_file_state, "enabled") == enable) {
+ log_unit_debug(u, "already %sd.", enable_disable(enable));
return 0;
+ }
+
+ log_unit_info(u, "%s unit.", enable ? "Enabling" : "Disabling");
if (enable)
r = sd_bus_call_method(
@@ -543,19 +551,16 @@ static int property_get_rtc_time(
void *userdata,
sd_bus_error *error) {
- struct tm tm;
- usec_t t;
+ struct tm tm = {};
+ usec_t t = 0;
int r;
- zero(tm);
r = clock_get_hwclock(&tm);
- if (r == -EBUSY) {
+ if (r == -EBUSY)
log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp.");
- t = 0;
- } else if (r == -ENOENT) {
+ else if (r == -ENOENT)
log_debug("/dev/rtc not found.");
- t = 0; /* no RTC found */
- } else if (r < 0)
+ else if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to read RTC: %m");
else
t = (usec_t) timegm(&tm) * USEC_PER_SEC;
@@ -692,7 +697,9 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
"DAYLIGHT=%i", daylight,
LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, tzname[daylight]));
- (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone", NULL);
+ (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
+ "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone",
+ NULL);
return sd_bus_reply_method_return(m, NULL);
}
@@ -732,8 +739,8 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
/* 1. Write new configuration file */
r = context_write_data_local_rtc(c);
if (r < 0) {
- log_error_errno(r, "Failed to set RTC to local/UTC: %m");
- return sd_bus_error_set_errnof(error, r, "Failed to set RTC to local/UTC: %m");
+ log_error_errno(r, "Failed to set RTC to %s: %m", lrtc ? "local" : "UTC");
+ return sd_bus_error_set_errnof(error, r, "Failed to set RTC to %s: %m", lrtc ? "local" : "UTC");
}
/* 2. Tell the kernel our timezone */
@@ -784,7 +791,9 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
log_info("RTC configured to %s time.", c->local_rtc ? "local" : "UTC");
- (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "LocalRTC", NULL);
+ (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
+ "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "LocalRTC",
+ NULL);
return sd_bus_reply_method_return(m, NULL);
}
@@ -889,6 +898,7 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
sd_bus *bus = sd_bus_message_get_bus(m);
Context *c = userdata;
UnitStatusInfo *u;
+ const UnitStatusInfo *selected = NULL;
int enable, interactive, q, r;
assert(m);
@@ -937,50 +947,52 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
return r;
}
- if (!enable)
+ if (enable)
LIST_FOREACH(units, u, c->units) {
- if (!streq(u->load_state, "loaded"))
- continue;
-
- q = unit_enable_or_disable(u, bus, error, enable);
- if (q < 0)
- r = q;
-
- q = unit_start_or_stop(u, bus, error, enable);
- if (q < 0)
- r = q;
- }
+ bool enable_this_one = !selected;
- else if (context_ntp_service_is_enabled(c) <= 0)
- LIST_FOREACH(units, u, c->units) {
if (!streq(u->load_state, "loaded"))
continue;
- r = unit_enable_or_disable(u, bus, error, enable);
+ r = unit_enable_or_disable(u, bus, error, enable_this_one);
if (r < 0)
- continue;
+ /* If enablement failed, don't start this unit. */
+ enable_this_one = false;
- r = unit_start_or_stop(u, bus, error, enable);
- break;
+ r = unit_start_or_stop(u, bus, error, enable_this_one);
+ if (r < 0)
+ log_unit_warning_errno(u, r, "Failed to %s %sd NTP unit, ignoring: %m",
+ enable_this_one ? "start" : "stop",
+ enable_disable(enable_this_one));
+ if (enable_this_one)
+ selected = u;
}
-
else
LIST_FOREACH(units, u, c->units) {
- if (!streq(u->load_state, "loaded") ||
- !streq(u->unit_file_state, "enabled"))
+ if (!streq(u->load_state, "loaded"))
continue;
- r = unit_start_or_stop(u, bus, error, enable);
- break;
+ q = unit_enable_or_disable(u, bus, error, false);
+ if (q < 0)
+ r = q;
+
+ q = unit_start_or_stop(u, bus, error, false);
+ if (q < 0)
+ r = q;
}
if (r < 0)
return r;
+ if (enable && !selected)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No NTP service found to enable.");
if (slot)
c->slot_job_removed = TAKE_PTR(slot);
- log_info("Set NTP to %sd", enable_disable(enable));
+ if (selected)
+ log_info("Set NTP to enabled (%s).", selected->name);
+ else
+ log_info("Set NTP to disabled.");
return sd_bus_reply_method_return(m, NULL);
}
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 2dacd78968..8cfa2cdf23 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -37,6 +37,7 @@
#include "user-util.h"
typedef struct Spawn {
+ sd_device *device;
const char *cmd;
pid_t pid;
usec_t timeout_warn_usec;
@@ -550,7 +551,8 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd
l = read(fd, p, size - 1);
if (l < 0) {
if (errno != EAGAIN)
- log_error_errno(errno, "Failed to read stdout of '%s': %m", spawn->cmd);
+ log_device_error_errno(spawn->device, errno,
+ "Failed to read stdout of '%s': %m", spawn->cmd);
return 0;
}
@@ -569,8 +571,8 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd
return 0;
STRV_FOREACH(q, v)
- log_debug("'%s'(%s) '%s'", spawn->cmd,
- fd == spawn->fd_stdout ? "out" : "err", *q);
+ log_device_debug(spawn->device, "'%s'(%s) '%s'", spawn->cmd,
+ fd == spawn->fd_stdout ? "out" : "err", *q);
}
return 0;
@@ -584,8 +586,9 @@ static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
kill_and_sigcont(spawn->pid, SIGKILL);
- log_error("Spawned process '%s' ["PID_FMT"] timed out after %s, killing", spawn->cmd, spawn->pid,
- format_timespan(timeout, sizeof(timeout), spawn->timeout_usec, USEC_PER_SEC));
+ log_device_error(spawn->device, "Spawned process '%s' ["PID_FMT"] timed out after %s, killing",
+ spawn->cmd, spawn->pid,
+ format_timespan(timeout, sizeof(timeout), spawn->timeout_usec, USEC_PER_SEC));
return 1;
}
@@ -596,8 +599,9 @@ static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *use
assert(spawn);
- log_warning("Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid,
- format_timespan(timeout, sizeof(timeout), spawn->timeout_warn_usec, USEC_PER_SEC));
+ log_device_warning(spawn->device, "Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete",
+ spawn->cmd, spawn->pid,
+ format_timespan(timeout, sizeof(timeout), spawn->timeout_warn_usec, USEC_PER_SEC));
return 1;
}
@@ -611,18 +615,18 @@ static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userd
switch (si->si_code) {
case CLD_EXITED:
if (si->si_status == 0)
- log_debug("Process '%s' succeeded.", spawn->cmd);
+ log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd);
else
- log_full(spawn->accept_failure ? LOG_DEBUG : LOG_WARNING,
- "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+ log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0,
+ "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
ret = si->si_status;
break;
case CLD_KILLED:
case CLD_DUMPED:
- log_error("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
+ log_device_error(spawn->device, "Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
break;
default:
- log_error("Process '%s' failed due to unknown reason.", spawn->cmd);
+ log_device_error(spawn->device, "Process '%s' failed due to unknown reason.", spawn->cmd);
}
sd_event_exit(sd_event_source_get_event(s), ret);
@@ -704,19 +708,21 @@ int udev_event_spawn(UdevEvent *event,
/* pipes from child to parent */
if (result || log_get_max_level() >= LOG_INFO)
if (pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) != 0)
- return log_error_errno(errno, "Failed to create pipe for command '%s': %m", cmd);
+ return log_device_error_errno(event->dev, errno,
+ "Failed to create pipe for command '%s': %m", cmd);
if (log_get_max_level() >= LOG_INFO)
if (pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) != 0)
- return log_error_errno(errno, "Failed to create pipe for command '%s': %m", cmd);
+ return log_device_error_errno(event->dev, errno,
+ "Failed to create pipe for command '%s': %m", cmd);
argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX);
if (!argv)
return log_oom();
if (isempty(argv[0]))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Invalid command '%s'", cmd);
+ return log_device_error_errno(event->dev, SYNTHETIC_ERRNO(EINVAL),
+ "Invalid command '%s'", cmd);
/* allow programs in /usr/lib/udev/ to be called without the path */
if (!path_is_absolute(argv[0])) {
@@ -733,11 +739,12 @@ int udev_event_spawn(UdevEvent *event,
if (r < 0)
return log_device_error_errno(event->dev, r, "Failed to get device properties");
- log_debug("Starting '%s'", cmd);
+ log_device_debug(event->dev, "Starting '%s'", cmd);
r = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
- return log_error_errno(r, "Failed to fork() to execute command '%s': %m", cmd);
+ return log_device_error_errno(event->dev, r,
+ "Failed to fork() to execute command '%s': %m", cmd);
if (r == 0) {
if (rearrange_stdio(-1, outpipe[WRITE_END], errpipe[WRITE_END]) < 0)
_exit(EXIT_FAILURE);
@@ -754,6 +761,7 @@ int udev_event_spawn(UdevEvent *event,
errpipe[WRITE_END] = safe_close(errpipe[WRITE_END]);
spawn = (Spawn) {
+ .device = event->dev,
.cmd = cmd,
.pid = pid,
.accept_failure = accept_failure,
@@ -767,7 +775,8 @@ int udev_event_spawn(UdevEvent *event,
};
r = spawn_wait(&spawn);
if (r < 0)
- return log_error_errno(r, "Failed to wait for spawned command '%s': %m", cmd);
+ return log_device_error_errno(event->dev, r,
+ "Failed to wait for spawned command '%s': %m", cmd);
if (result)
result[spawn.result_len] = '\0';
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 7e3447f7fa..f161402f3a 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -316,14 +316,25 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
Iterator i;
if (apply_mode || apply_uid || apply_gid) {
- log_device_debug(dev, "Setting permissions %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
+ log_device_debug(dev, "Setting permissions %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o",
+ devnode,
+ uid_is_valid(uid) ? uid : stats.st_uid,
+ gid_is_valid(gid) ? gid : stats.st_gid,
+ mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777);
r = chmod_and_chown(devnode, mode, uid, gid);
if (r < 0)
log_device_warning_errno(dev, r, "Failed to set owner/mode of %s to uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o: %m",
- devnode, uid, gid, mode);
+ devnode,
+ uid_is_valid(uid) ? uid : stats.st_uid,
+ gid_is_valid(gid) ? gid : stats.st_gid,
+ mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777);
} else
- log_device_debug(dev, "Preserve permissions of %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
+ log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o",
+ devnode,
+ uid_is_valid(uid) ? uid : stats.st_uid,
+ gid_is_valid(gid) ? gid : stats.st_gid,
+ mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777);
/* apply SECLABEL{$module}=$label */
ORDERED_HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) {
@@ -409,8 +420,7 @@ int udev_node_add(sd_device *dev, bool apply,
const char *id_filename = NULL;
(void) device_get_id_filename(dev, &id_filename);
- log_device_debug(dev, "Handling device node '%s', devnum=%s, mode=%#o, uid="UID_FMT", gid="GID_FMT,
- devnode, strnull(id_filename), mode, uid, gid);
+ log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strnull(id_filename));
}
r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 3473a7eb7e..1642f10535 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1401,8 +1401,10 @@ static int get_property_from_string(char *line, char **ret_key, char **ret_value
key = skip_leading_chars(line, NULL);
/* comment or empty line */
- if (IN_SET(key[0], '#', '\0'))
+ if (IN_SET(key[0], '#', '\0')) {
+ *ret_key = *ret_value = NULL;
return 0;
+ }
/* split key/value */
val = strchr(key, '=');
@@ -1429,7 +1431,7 @@ static int get_property_from_string(char *line, char **ret_key, char **ret_value
*ret_key = key;
*ret_value = val;
- return 0;
+ return 1;
}
static int import_parent_into_properties(sd_device *dev, const char *filter) {
@@ -1681,6 +1683,8 @@ static int udev_rule_apply_token_to_event(
line);
continue;
}
+ if (r == 0)
+ continue;
r = device_add_property(dev, key, value);
if (r < 0)
@@ -1719,6 +1723,8 @@ static int udev_rule_apply_token_to_event(
line);
continue;
}
+ if (r == 0)
+ continue;
r = device_add_property(dev, key, value);
if (r < 0)
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index bfc78b9739..56fb937647 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -191,6 +191,9 @@ static int on_runlevel(Context *c) {
if (runlevel < 0)
return runlevel;
+ if (runlevel == 0)
+ return log_warning("Failed to get new runlevel, utmp update skipped.");
+
if (previous == runlevel)
return 0;
diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh
index 16fda42754..801dc71569 100755
--- a/test/TEST-02-CRYPTSETUP/test.sh
+++ b/test/TEST-02-CRYPTSETUP/test.sh
@@ -7,15 +7,15 @@ TEST_NO_NSPAWN=1
check_result_qemu() {
ret=1
- mkdir -p $TESTDIR/root
- mount ${LOOPDEV}p1 $TESTDIR/root
- [[ -e $TESTDIR/root/testok ]] && ret=0
- [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
+ mkdir -p $initdir
+ mount ${LOOPDEV}p1 $initdir
+ [[ -e $initdir/testok ]] && ret=0
+ [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
- mount /dev/mapper/varcrypt $TESTDIR/root/var
- cp -a $TESTDIR/root/var/log/journal $TESTDIR
- umount $TESTDIR/root/var
- umount $TESTDIR/root
+ mount /dev/mapper/varcrypt $initdir/var
+ cp -a $initdir/var/log/journal $TESTDIR
+ umount $initdir/var
+ umount $initdir
cryptsetup luksClose /dev/mapper/varcrypt
[[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
ls -l $TESTDIR/journal/*/*.journal
@@ -30,8 +30,8 @@ test_setup() {
cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 ${LOOPDEV}p2 $TESTDIR/keyfile
cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile
mkfs.ext4 -L var /dev/mapper/varcrypt
- mkdir -p $TESTDIR/root/var
- mount /dev/mapper/varcrypt $TESTDIR/root/var
+ mkdir -p $initdir/var
+ mount /dev/mapper/varcrypt $initdir/var
# Create what will eventually be our root filesystem onto an overlay
(
@@ -77,8 +77,8 @@ EOF
}
cleanup_root_var() {
- ddebug "umount $TESTDIR/root/var"
- mountpoint $TESTDIR/root/var && umount $TESTDIR/root/var
+ ddebug "umount $initdir/var"
+ mountpoint $initdir/var && umount $initdir/var
[[ -b /dev/mapper/varcrypt ]] && cryptsetup luksClose /dev/mapper/varcrypt
}
diff --git a/test/TEST-18-FAILUREACTION/test.sh b/test/TEST-18-FAILUREACTION/test.sh
index 5c9ca9e427..503c5ca551 100755
--- a/test/TEST-18-FAILUREACTION/test.sh
+++ b/test/TEST-18-FAILUREACTION/test.sh
@@ -3,7 +3,7 @@ set -e
TEST_DESCRIPTION="FailureAction= operation"
. $TEST_BASE_DIR/test-functions
-QEMU_TIMEOUT=180
+QEMU_TIMEOUT=600
test_setup() {
create_empty_image_rootdir
diff --git a/test/TEST-19-DELEGATE/test.sh b/test/TEST-19-DELEGATE/test.sh
index abfb6a77a2..348c697f63 100755
--- a/test/TEST-19-DELEGATE/test.sh
+++ b/test/TEST-19-DELEGATE/test.sh
@@ -4,7 +4,7 @@ TEST_DESCRIPTION="test cgroup delegation in the unified hierarchy"
TEST_NO_NSPAWN=1
. $TEST_BASE_DIR/test-functions
-QEMU_TIMEOUT=180
+QEMU_TIMEOUT=600
UNIFIED_CGROUP_HIERARCHY=yes
test_setup() {
diff --git a/test/TEST-24-UNIT-TESTS/test.sh b/test/TEST-24-UNIT-TESTS/test.sh
index 2b622676ef..3c993e67f7 100755
--- a/test/TEST-24-UNIT-TESTS/test.sh
+++ b/test/TEST-24-UNIT-TESTS/test.sh
@@ -29,25 +29,25 @@ check_result_nspawn() {
check_result_qemu() {
local _ret=1
- mkdir -p $TESTDIR/root
- mount ${LOOPDEV}p1 $TESTDIR/root
- [[ -e $TESTDIR/root/testok ]] && _ret=0
- if [[ -s $TESTDIR/root/failed ]]; then
+ mkdir -p $initdir
+ mount ${LOOPDEV}p1 $initdir
+ [[ -e $initdir/testok ]] && _ret=0
+ if [[ -s $initdir/failed ]]; then
_ret=$(($_ret+1))
echo "=== Failed test log ==="
- cat $TESTDIR/root/failed
+ cat $initdir/failed
else
- if [[ -s $TESTDIR/root/skipped ]]; then
+ if [[ -s $initdir/skipped ]]; then
echo "=== Skipped test log =="
- cat $TESTDIR/root/skipped
+ cat $initdir/skipped
fi
- if [[ -s $TESTDIR/root/testok ]]; then
+ if [[ -s $initdir/testok ]]; then
echo "=== Passed tests ==="
- cat $TESTDIR/root/testok
+ cat $initdir/testok
fi
fi
- cp -a $TESTDIR/root/var/log/journal $TESTDIR
- umount $TESTDIR/root
+ cp -a $initdir/var/log/journal $TESTDIR
+ umount $initdir
[[ -n "$TIMED_OUT" ]] && _ret=$(($_ret+1))
return $_ret
}
diff --git a/test/TEST-33-CLEAN-UNIT/test.sh b/test/TEST-33-CLEAN-UNIT/test.sh
index 44082af4d4..aeda69baae 100755
--- a/test/TEST-33-CLEAN-UNIT/test.sh
+++ b/test/TEST-33-CLEAN-UNIT/test.sh
@@ -7,9 +7,7 @@ TEST_DESCRIPTION="test CleanUnit"
. $TEST_BASE_DIR/test-functions
test_setup() {
- create_empty_image
- mkdir -p $TESTDIR/root
- mount ${LOOPDEV}p1 $TESTDIR/root
+ create_empty_image_rootdir
(
LOG_LEVEL=5
@@ -41,9 +39,6 @@ EOF
setup_testsuite
) || return 1
setup_nspawn_root
-
- ddebug "umount $TESTDIR/root"
- umount $TESTDIR/root
}
do_test "$@"
diff --git a/test/TEST-36-NUMAPOLICY/Makefile b/test/TEST-36-NUMAPOLICY/Makefile
new file mode 120000
index 0000000000..e9f93b1104
--- /dev/null
+++ b/test/TEST-36-NUMAPOLICY/Makefile
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile \ No newline at end of file
diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh
new file mode 100755
index 0000000000..5e775b2d5a
--- /dev/null
+++ b/test/TEST-36-NUMAPOLICY/test.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+set -e
+TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options"
+TEST_NO_NSPAWN=1
+QEMU_OPTIONS="-numa node,nodeid=0"
+
+. $TEST_BASE_DIR/test-functions
+
+test_setup() {
+ create_empty_image_rootdir
+
+ (
+ LOG_LEVEL=5
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+ setup_basic_environment
+ dracut_install mktemp
+
+ # mask some services that we do not want to run in these tests
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service
+
+ # setup the testsuite service
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/bin/bash -x /testsuite.sh
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+NotifyAccess=all
+EOF
+ cp testsuite.sh $initdir/
+
+ setup_testsuite
+ ) || return 1
+ setup_nspawn_root
+}
+
+do_test "$@"
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
new file mode 100755
index 0000000000..a5ac788178
--- /dev/null
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
@@ -0,0 +1,323 @@
+#!/bin/bash
+set -ex
+set -o pipefail
+
+at_exit() {
+ if [ $? -ne 0 ]; then
+ # We're exiting with a non-zero EC, let's dump test artifacts
+ # for easier debugging
+ [ -f "$straceLog" ] && cat "$straceLog"
+ [ -f "$journalLog" ] && cat "$journalLog"
+ fi
+}
+
+trap at_exit EXIT
+
+systemd-analyze log-level debug
+systemd-analyze log-target journal
+
+# Log files
+straceLog='strace.log'
+journalLog='journal.log'
+
+# Systemd config files
+testUnit='numa-test.service'
+testUnitFile="/etc/systemd/system/$testUnit"
+testUnitNUMAConf="$testUnitFile.d/numa.conf"
+
+# Sleep constants (we should probably figure out something better but nothing comes to mind)
+journalSleep=5
+sleepAfterStart=1
+
+# Journal cursor for easier navigation
+journalCursorFile="jounalCursorFile"
+
+startStrace() {
+ coproc strace -qq -p 1 -o $straceLog -e set_mempolicy -s 1024 $1
+ # Wait for strace to properly "initialize"
+ sleep $sleepAfterStart
+}
+
+stopStrace() {
+ kill -s TERM $COPROC_PID
+ # Make sure the strace process is indeed dead
+ while kill -0 $COPROC_PID 2>/dev/null; do sleep 0.1; done
+}
+
+startJournalctl() {
+ # Save journal's cursor for later navigation
+ journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat
+}
+
+stopJournalctl() {
+ local unit="${1:-init.scope}"
+ # Using journalctl --sync should be better than using SIGRTMIN+1, as
+ # the --sync wait until the synchronization is complete
+ echo "Force journald to write all queued messages"
+ journalctl --sync
+ journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog"
+}
+
+checkNUMA() {
+ # NUMA enabled system should have at least NUMA node0
+ test -e /sys/devices/system/node/node0
+}
+
+writePID1NUMAPolicy() {
+ echo [Manager] > $confDir/numa.conf
+ echo NUMAPolicy=$1 >> $confDir/numa.conf
+ echo NUMAMask=$2>> $confDir/numa.conf
+}
+
+writeTestUnit() {
+ echo [Service] > $testUnitFile
+ echo ExecStart=/bin/sleep 3600 >> $testUnitFile
+ mkdir -p $testUnitFile.d/
+}
+
+writeTestUnitNUMAPolicy() {
+ echo [Service] > $testUnitNUMAConf
+ echo NUMAPolicy=$1 >> $testUnitNUMAConf
+ echo NUMAMask=$2>> $testUnitNUMAConf
+ systemctl daemon-reload
+}
+
+pid1ReloadWithStrace() {
+ startStrace
+ systemctl daemon-reload
+ sleep $sleepAfterStart
+ stopStrace
+}
+
+pid1ReloadWithJournal() {
+ startJournalctl
+ systemctl daemon-reload
+ stopJournalctl
+}
+
+pid1StartUnitWithStrace() {
+ startStrace '-f'
+ systemctl start $1
+ sleep $sleepAfterStart
+ stopStrace
+}
+
+pid1StartUnitWithJournal() {
+ startJournalctl
+ systemctl start $1
+ sleep $sleepAfterStart
+ stopJournalctl
+}
+
+pid1StopUnit() {
+ systemctl stop $1
+}
+
+systemctlCheckNUMAProperties() {
+ local LOGFILE="$(mktemp)"
+ systemctl show -p NUMAPolicy $1 > "$LOGFILE"
+ grep "NUMAPolicy=$2" "$LOGFILE"
+
+ > "$LOGFILE"
+
+ if [ -n $3 ]; then
+ systemctl show -p NUMAMask $1 > "$LOGFILE"
+ grep "NUMAMask=$3" "$LOGFILE"
+ fi
+}
+
+writeTestUnit
+
+# Create systemd config drop-in directory
+confDir="/etc/systemd/system.conf.d/"
+mkdir -p "$confDir"
+
+if ! checkNUMA; then
+ echo >&2 "NUMA is not supported on this machine, switching to a simple sanity check"
+
+ echo "PID1 NUMAPolicy=default && NUMAMask=0 check without NUMA support"
+ writePID1NUMAPolicy "default" "0"
+ startJournalctl
+ systemctl daemon-reload
+ stopJournalctl
+ grep "NUMA support not available, ignoring" "$journalLog"
+
+ echo "systemd-run NUMAPolicy=default && NUMAMask=0 check without NUMA support"
+ runUnit='numa-systemd-run-test.service'
+ startJournalctl
+ systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
+ sleep $sleepAfterStart
+ pid1StopUnit $runUnit
+ stopJournalctl $runUnit
+ grep "NUMA support not available, ignoring" "$journalLog"
+
+else
+ echo "PID1 NUMAPolicy support - Default policy w/o mask"
+ writePID1NUMAPolicy "default"
+ pid1ReloadWithStrace
+ # Kernel requires that nodemask argument is set to NULL when setting default policy
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+
+ echo "PID1 NUMAPolicy support - Default policy w/ mask"
+ writePID1NUMAPolicy "default" "0"
+ pid1ReloadWithStrace
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+
+ echo "PID1 NUMAPolicy support - Bind policy w/o mask"
+ writePID1NUMAPolicy "bind"
+ pid1ReloadWithJournal
+ grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
+
+ echo "PID1 NUMAPolicy support - Bind policy w/ mask"
+ writePID1NUMAPolicy "bind" "0"
+ pid1ReloadWithStrace
+ grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
+
+ echo "PID1 NUMAPolicy support - Interleave policy w/o mask"
+ writePID1NUMAPolicy "interleave"
+ pid1ReloadWithJournal
+ grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
+
+ echo "PID1 NUMAPolicy support - Interleave policy w/ mask"
+ writePID1NUMAPolicy "interleave" "0"
+ pid1ReloadWithStrace
+ grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
+
+ echo "PID1 NUMAPolicy support - Preferred policy w/o mask"
+ writePID1NUMAPolicy "preferred"
+ pid1ReloadWithJournal
+ # Preferred policy with empty node mask is actually allowed and should reset allocation policy to default
+ ! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog
+
+ echo "PID1 NUMAPolicy support - Preferred policy w/ mask"
+ writePID1NUMAPolicy "preferred" "0"
+ pid1ReloadWithStrace
+ grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
+
+ echo "PID1 NUMAPolicy support - Local policy w/o mask"
+ writePID1NUMAPolicy "local"
+ pid1ReloadWithStrace
+ # Kernel requires that nodemask argument is set to NULL when setting default policy
+ # The unpatched versions of strace don't recognize the MPOL_LOCAL constant and
+ # return a numerical constant instead (with a comment):
+ # set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0
+ # Let's cover this scenario as well
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+
+ echo "PID1 NUMAPolicy support - Local policy w/ mask"
+ writePID1NUMAPolicy "local" "0"
+ pid1ReloadWithStrace
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+
+ echo "Unit file NUMAPolicy support - Default policy w/o mask"
+ writeTestUnitNUMAPolicy "default"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "default"
+ pid1StopUnit $testUnit
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+
+ echo "Unit file NUMAPolicy support - Default policy w/ mask"
+ writeTestUnitNUMAPolicy "default" "0"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "default" "0"
+ pid1StopUnit $testUnit
+ # Maks must be ignored
+ grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog
+
+ echo "Unit file NUMAPolicy support - Bind policy w/o mask"
+ writeTestUnitNUMAPolicy "bind"
+ pid1StartUnitWithJournal $testUnit
+ pid1StopUnit $testUnit
+ grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
+
+ echo "Unit file NUMAPolicy support - Bind policy w/ mask"
+ writeTestUnitNUMAPolicy "bind" "0"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "bind" "0"
+ pid1StopUnit $testUnit
+ grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog
+
+ echo "Unit file NUMAPolicy support - Interleave policy w/o mask"
+ writeTestUnitNUMAPolicy "interleave"
+ pid1StartUnitWithStrace $testUnit
+ pid1StopUnit $testUnit
+ grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
+
+ echo "Unit file NUMAPolicy support - Interleave policy w/ mask"
+ writeTestUnitNUMAPolicy "interleave" "0"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "interleave" "0"
+ pid1StopUnit $testUnit
+ grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog
+
+ echo "Unit file NUMAPolicy support - Preferred policy w/o mask"
+ writeTestUnitNUMAPolicy "preferred"
+ pid1StartUnitWithJournal $testUnit
+ systemctlCheckNUMAProperties $testUnit "preferred"
+ pid1StopUnit $testUnit
+ ! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog
+
+ echo "Unit file NUMAPolicy support - Preferred policy w/ mask"
+ writeTestUnitNUMAPolicy "preferred" "0"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "preferred" "0"
+ pid1StopUnit $testUnit
+ grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog
+
+ echo "Unit file NUMAPolicy support - Local policy w/o mask"
+ writeTestUnitNUMAPolicy "local"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "local"
+ pid1StopUnit $testUnit
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+
+ echo "Unit file NUMAPolicy support - Local policy w/ mask"
+ writeTestUnitNUMAPolicy "local" "0"
+ pid1StartUnitWithStrace $testUnit
+ systemctlCheckNUMAProperties $testUnit "local" "0"
+ pid1StopUnit $testUnit
+ # Maks must be ignored
+ grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+
+ echo "systemd-run NUMAPolicy support"
+ runUnit='numa-systemd-run-test.service'
+
+ systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "default"
+ pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "default" ""
+ pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "bind" "0"
+ pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "interleave" "0"
+ pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "preferred" "0"
+ pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "local"
+ pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "local" ""
+ pid1StopUnit $runUnit
+fi
+
+# Cleanup
+rm -rf $testDir
+rm -rf $confDir
+systemctl daemon-reload
+
+systemd-analyze log-level info
+
+echo OK > /testok
+
+exit 0
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 7be38b0f34..848d4bd187 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -208,6 +208,7 @@ SourcePort=
DestinationPort=
IPProtocol=
InvertRule=
+Family=
[IPv6PrefixDelegation]
RouterPreference=
DNSLifetimeSec=
diff --git a/test/test-functions b/test/test-functions
index 37bdfd58dc..03bfcaf972 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -102,7 +102,7 @@ function find_qemu_bin() {
[ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu 2>/dev/null | grep '^/' -m1)
;;
ppc64*)
- [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-$ARCH 2>/dev/null | grep '^/' -m1)
+ [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-ppc64 2>/dev/null | grep '^/' -m1)
;;
esac
@@ -209,6 +209,7 @@ $KERNEL_APPEND \
-nographic \
-kernel $KERNEL_BIN \
-drive format=raw,cache=unsafe,file=${TESTDIR}/rootdisk.img \
+$QEMU_OPTIONS \
"
if [[ "$INITRD" && "$SKIP_INITRD" != "yes" ]]; then
@@ -515,6 +516,8 @@ install_systemd() {
# enable debug logging in PID1
echo LogLevel=debug >> $initdir/etc/systemd/system.conf
+ # store coredumps in journal
+ echo Storage=journal >> $initdir/etc/systemd/coredump.conf
}
get_ldpath() {
@@ -558,8 +561,8 @@ EOF
create_empty_image_rootdir() {
create_empty_image
- mkdir -p $TESTDIR/root
- mount ${LOOPDEV}p1 $TESTDIR/root
+ mkdir -p $initdir
+ mount ${LOOPDEV}p1 $initdir
TEST_SETUP_CLEANUP_ROOTDIR=1
}
@@ -619,13 +622,13 @@ check_result_nspawn() {
# can be overridden in specific test
check_result_qemu() {
local ret=1
- mkdir -p $TESTDIR/root
- mount ${LOOPDEV}p1 $TESTDIR/root
- [[ -e $TESTDIR/root/testok ]] && ret=0
- [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
- cp -a $TESTDIR/root/var/log/journal $TESTDIR
- check_asan_reports "$TESTDIR/root" || ret=$(($ret+1))
- umount $TESTDIR/root
+ mkdir -p $initdir
+ mount ${LOOPDEV}p1 $initdir
+ [[ -e $initdir/testok ]] && ret=0
+ [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
+ cp -a $initdir/var/log/journal $TESTDIR
+ check_asan_reports "$initdir" || ret=$(($ret+1))
+ umount $initdir
[[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
ls -l $TESTDIR/journal/*/*.journal
test -s $TESTDIR/failed && ret=$(($ret+1))
@@ -938,6 +941,7 @@ import_testdir() {
import_initdir() {
initdir=$TESTDIR/root
+ mkdir -p $initdir
export initdir
}
@@ -1665,12 +1669,16 @@ setup_suse() {
inst_simple "/usr/lib/systemd/system/haveged.service"
}
+_umount_dir() {
+ if mountpoint -q $1; then
+ ddebug "umount $1"
+ umount $1
+ fi
+}
+
_test_setup_cleanup() {
# only umount if create_empty_image_rootdir() was called to mount it
- if [[ $TEST_SETUP_CLEANUP_ROOTDIR ]]; then
- ddebug "umount $TESTDIR/root"
- umount $TESTDIR/root
- fi
+ [[ -z $TEST_SETUP_CLEANUP_ROOTDIR ]] || _umount_dir $initdir
}
# can be overridden in specific test
@@ -1682,10 +1690,7 @@ _test_cleanup() {
# (post-test) cleanup should always ignore failure and cleanup as much as possible
(
set +e
- if mountpoint $TESTDIR/root; then
- ddebug "umount $TESTDIR/root"
- umount $TESTDIR/root
- fi
+ _umount_dir $initdir
if [[ $LOOPDEV && -b $LOOPDEV ]]; then
ddebug "losetup -d $LOOPDEV"
losetup -d $LOOPDEV
diff --git a/test/test-network/conf/25-address-preferred-lifetime-zero-ipv6.network b/test/test-network/conf/25-address-preferred-lifetime-zero.network
index bfb278f31f..a1e7605103 100644
--- a/test/test-network/conf/25-address-preferred-lifetime-zero-ipv6.network
+++ b/test/test-network/conf/25-address-preferred-lifetime-zero.network
@@ -6,6 +6,9 @@ Name=dummy98
Address=hogehoge
Address=foofoo
+[Route]
+Gateway=20.20.20.1
+
[Address]
Address=10.2.3.4/16
PreferredLifetime=0
@@ -15,6 +18,9 @@ Scope=link
Address=2001:0db8:0:f101::1/64
[Address]
+Address=20.20.20.100/24
+
+[Address]
# this section must be ignored
Peer=hoge
Address=10.10.0.1/16
diff --git a/test/test-network/conf/25-gateway-next-static.network b/test/test-network/conf/25-gateway-next-static.network
new file mode 100644
index 0000000000..dfac8f48cd
--- /dev/null
+++ b/test/test-network/conf/25-gateway-next-static.network
@@ -0,0 +1,6 @@
+[Match]
+Name=dummy98
+
+[Network]
+Address=149.10.124.58/28
+Gateway=149.10.124.60
diff --git a/test/test-network/conf/25-gateway-static.network b/test/test-network/conf/25-gateway-static.network
new file mode 100644
index 0000000000..448a21f2b9
--- /dev/null
+++ b/test/test-network/conf/25-gateway-static.network
@@ -0,0 +1,6 @@
+[Match]
+Name=dummy98
+
+[Network]
+Address=149.10.124.58/28
+Gateway=149.10.124.59
diff --git a/test/test-network/conf/25-neighbor-next.network b/test/test-network/conf/25-neighbor-next.network
new file mode 100644
index 0000000000..d0591d5875
--- /dev/null
+++ b/test/test-network/conf/25-neighbor-next.network
@@ -0,0 +1,9 @@
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+
+[Neighbor]
+Address=192.168.10.1
+LinkLayerAddress=00:00:5e:00:02:66
diff --git a/test/test-network/conf/routing-policy-rule-test1.network b/test/test-network/conf/routing-policy-rule-test1.network
index 46b87c5a9a..ffcedc99a2 100644
--- a/test/test-network/conf/routing-policy-rule-test1.network
+++ b/test/test-network/conf/routing-policy-rule-test1.network
@@ -8,3 +8,15 @@ From= 192.168.100.18
Priority=111
IncomingInterface=test1
OutgoingInterface=test1
+
+[RoutingPolicyRule]
+IncomingInterface=test1
+Table=8
+Priority=100
+Family=ipv6
+
+[RoutingPolicyRule]
+IncomingInterface=test1
+Table=9
+Priority=101
+Family=both
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 76313cf026..8d123658a1 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -1412,7 +1412,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'24-keep-configuration-static.network',
'24-search-domain.network',
'25-address-link-section.network',
- '25-address-preferred-lifetime-zero-ipv6.network',
+ '25-address-preferred-lifetime-zero.network',
'25-address-static.network',
'25-bind-carrier.network',
'25-bond-active-backup-slave.netdev',
@@ -1422,6 +1422,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-ip6gre-tunnel-remote-any.netdev',
'25-ipv6-address-label-section.network',
'25-neighbor-section.network',
+ '25-neighbor-next.network',
'25-neighbor-ipv6.network',
'25-neighbor-ip-dummy.network',
'25-neighbor-ip.network',
@@ -1430,13 +1431,15 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-link-section-unmanaged.network',
'25-route-ipv6-src.network',
'25-route-static.network',
+ '25-gateway-static.network',
+ '25-gateway-next-static.network',
'25-sysctl-disable-ipv6.network',
'25-sysctl.network',
'configure-without-carrier.network',
'routing-policy-rule-dummy98.network',
'routing-policy-rule-test1.network']
- routing_policy_rule_tables = ['7', '8']
+ routing_policy_rule_tables = ['7', '8', '9']
routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
def setUp(self):
@@ -1490,17 +1493,20 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
def test_address_preferred_lifetime_zero_ipv6(self):
- copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
+ copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
start_networkd(5)
- self.check_link_exists('dummy98')
- self.check_operstate('dummy98', 'routable', setup_state='configuring')
+ self.wait_online(['dummy98:routable'])
output = check_output('ip address show dummy98')
print(output)
self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
+ output = check_output('ip route show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'default via 20.20.20.1 proto static')
+
def test_configure_without_carrier(self):
copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
start_networkd()
@@ -1517,15 +1523,36 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online(['test1:degraded'])
- output = check_output('ip rule')
+ output = check_output('ip rule list iif test1 priority 111')
print(output)
- self.assertRegex(output, '111')
+ self.assertRegex(output, '111:')
self.assertRegex(output, 'from 192.168.100.18')
self.assertRegex(output, r'tos (?:0x08|throughput)\s')
self.assertRegex(output, 'iif test1')
self.assertRegex(output, 'oif test1')
self.assertRegex(output, 'lookup 7')
+ output = check_output('ip rule list iif test1 priority 101')
+ print(output)
+ self.assertRegex(output, '101:')
+ self.assertRegex(output, 'from all')
+ self.assertRegex(output, 'iif test1')
+ self.assertRegex(output, 'lookup 9')
+
+ output = check_output('ip -6 rule list iif test1 priority 100')
+ print(output)
+ self.assertRegex(output, '100:')
+ self.assertRegex(output, 'from all')
+ self.assertRegex(output, 'iif test1')
+ self.assertRegex(output, 'lookup 8')
+
+ output = check_output('ip -6 rule list iif test1 priority 101')
+ print(output)
+ self.assertRegex(output, '101:')
+ self.assertRegex(output, 'from all')
+ self.assertRegex(output, 'iif test1')
+ self.assertRegex(output, 'lookup 9')
+
def test_routing_policy_rule_issue_11280(self):
copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
'routing-policy-rule-dummy98.network', '12-dummy.netdev')
@@ -1632,6 +1659,26 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
+ def test_gateway_reconfigure(self):
+ copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+ print('### ip -4 route show dev dummy98 default')
+ output = check_output('ip -4 route show dev dummy98 default')
+ print(output)
+ self.assertRegex(output, 'default via 149.10.124.59 proto static')
+ self.assertNotRegex(output, '149.10.124.60')
+
+ remove_unit_from_networkd_path(['25-gateway-static.network'])
+ copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
+ restart_networkd(3)
+ self.wait_online(['dummy98:routable'])
+ print('### ip -4 route show dev dummy98 default')
+ output = check_output('ip -4 route show dev dummy98 default')
+ print(output)
+ self.assertNotRegex(output, '149.10.124.59')
+ self.assertRegex(output, 'default via 149.10.124.60 proto static')
+
def test_ip_route_ipv6_src_route(self):
# a dummy device does not make the addresses go through tentative state, so we
# reuse a bond from an earlier test, which does make the addresses go through
@@ -1677,11 +1724,34 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online(['dummy98:degraded'], timeout='40s')
+ print('### ip neigh list dev dummy98')
output = check_output('ip neigh list dev dummy98')
print(output)
self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
+ def test_neighbor_reconfigure(self):
+ copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:degraded'], timeout='40s')
+
+ print('### ip neigh list dev dummy98')
+ output = check_output('ip neigh list dev dummy98')
+ print(output)
+ self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
+ self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
+
+ remove_unit_from_networkd_path(['25-neighbor-section.network'])
+ copy_unit_to_networkd_unit_path('25-neighbor-next.network')
+ restart_networkd(3)
+ self.wait_online(['dummy98:degraded'], timeout='40s')
+ print('### ip neigh list dev dummy98')
+ output = check_output('ip neigh list dev dummy98')
+ print(output)
+ self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
+ self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
+ self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
+
def test_neighbor_gre(self):
copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
'12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
diff --git a/tmpfiles.d/meson.build b/tmpfiles.d/meson.build
index f14b4fc6df..e77f46d06b 100644
--- a/tmpfiles.d/meson.build
+++ b/tmpfiles.d/meson.build
@@ -24,26 +24,33 @@ foreach pair : tmpfiles
endif
endforeach
-m4_files = [['etc.conf', ''],
- ['systemd.conf', ''],
- ['var.conf', ''],
- ]
+in_files = ['static-nodes-permissions.conf']
-foreach pair : m4_files
- if not enable_tmpfiles
- # do nothing
- elif pair[1] == '' or conf.get(pair[1]) == 1
+foreach file : in_files
+ gen = configure_file(
+ input : file + '.in',
+ output : file,
+ configuration : substs)
+ if enable_tmpfiles
+ install_data(gen,
+ install_dir : tmpfilesdir)
+ endif
+endforeach
+
+m4_files = ['etc.conf',
+ 'systemd.conf',
+ 'var.conf']
+
+foreach file : m4_files
+ if enable_tmpfiles
custom_target(
- 'tmpfiles.d_' + pair[0],
- input : pair[0] + '.m4',
- output: pair[0],
+ 'tmpfiles.d_' + file,
+ input : file + '.m4',
+ output: file,
command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : true,
install_dir : tmpfilesdir)
- else
- message('Not installing tmpfiles.d/@0@.m4 because @1@ is @2@'
- .format(pair[0], pair[1], conf.get(pair[1], 0)))
endif
endforeach
diff --git a/tmpfiles.d/static-nodes-permissions.conf.in b/tmpfiles.d/static-nodes-permissions.conf.in
new file mode 100644
index 0000000000..50cffe2cd9
--- /dev/null
+++ b/tmpfiles.d/static-nodes-permissions.conf.in
@@ -0,0 +1,17 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+# This file adds permissions on top of static-nodes.conf generated by
+# kmod-static-nodes.service. Rules specified here should match the
+# permissions specified for udev in 50-udev-default.rules.
+
+z /dev/snd/seq 0660 - audio -
+z /dev/snd/timer 0660 - audio -
+z /dev/loop-control 0660 - disk -
+z /dev/net/tun 0666 - - -
+z /dev/fuse 0666 - - -
+z /dev/kvm @DEV_KVM_MODE@ - kvm -
diff --git a/travis-ci/managers/fuzzit.sh b/travis-ci/managers/fuzzit.sh
index d29471ee50..db2657b9c3 100755
--- a/travis-ci/managers/fuzzit.sh
+++ b/travis-ci/managers/fuzzit.sh
@@ -32,7 +32,7 @@ fi
# Because we want Fuzzit to run on every pull-request and Travis/Azure doesnt support encrypted keys
# on pull-request we use a write-only key which is ok for now. maybe there will be a better solution in the future
-FUZZIT_API_KEY=7c1bd82fe0927ffe1b4bf1e2e86cc812b28dfe08a7080a7bf498e98715884a163402ee37ba95d4b1637247deffcea43e
+FUZZIT_API_KEY=6a8445a23c4a8ef6743ddecf8ab368300976dae9313bbe54f1cbf30801773b2a3095d4c34daab8d308b6f2e8b254c90e
FUZZIT_ADDITIONAL_FILES="./out/src/shared/libsystemd-shared-*.so"
# ASan options are borrowed almost verbatim from OSS-Fuzz
@@ -44,35 +44,10 @@ chmod +x fuzzit
./fuzzit auth ${FUZZIT_API_KEY}
-# The following was generated with
-# ./fuzzit get targets | jq --raw-output '.target_name + " " + .id' | perl -alne 'printf("./fuzzit c job \${FUZZIT_ARGS} %s ./out/%s \${FUZZIT_ADDITIONAL_FILES}\n", $F[1], $F[0])'
-./fuzzit c job ${FUZZIT_ARGS} 2ODbhEjfRF2AZtrUotMh ./out/fuzz-bus-label ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} 62XnUyWTLAvIRh1vFkEw ./out/fuzz-journald-stream ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} 6AdGwIiI3l1Edu9V4fvF ./out/fuzz-env-file ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} 7ubB4DVu2EiYgPVtRUNV ./out/fuzz-calendarspec ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} 8D0NrVtSwTpl23a9k0vv ./out/fuzz-nspawn-oci ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} 8tbrzwxsaIPalIRBHtK8 ./out/fuzz-link-parser ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} 9T5He9cANxHTBLaBURpz ./out/fuzz-journald-kmsg ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} BRaEBuU7QVlSp1HOjlDb ./out/fuzz-udev-database ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} DcE70rAA2mhrxdyBRH90 ./out/fuzz-udev-rules ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} KH6VEpV0ZoWynASJHm8z ./out/fuzz-dhcp6-client ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} MZNs1JG5UQstaIvfHYgb ./out/fuzz-netdev-parser ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} P1MpkewCNQCYLdMFggnU ./out/fuzz-journald-audit ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} RmD47BxVRbAZlq07XW30 ./out/fuzz-unit-file ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} S0dGMaaGwkvsLc0IqIJ7 ./out/fuzz-catalog ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} X7qIoGLAoBgjVf19SfvY ./out/fuzz-compress ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} YAfecldFs2xaXn0Ws1BE ./out/fuzz-dns-packet ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} bgRZAE9E5uXRbUX76tId ./out/fuzz-ndisc-rs ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} cXCm75EhdDf5t2sSBLRC ./out/fuzz-hostname-util ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} cbgsYEyX6776MHFotO9O ./out/fuzz-nspawn-settings ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} d8lokp0LCLYgQwI7vyx6 ./out/fuzz-journald-native-fd ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} eoc9rbm2jKqIEg6Kdonv ./out/fuzz-network-parser ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} ezQIlJWCX3xPUJdhLnWM ./out/fuzz-dhcp-server ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} ge3eTzephghWD3Stw2TE ./out/fuzz-journald-syslog ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} nPIt1SCDkGkSFDth5RlG ./out/fuzz-json ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} nU0lRNNkQrXirDMNOpR1 ./out/fuzz-varlink ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} pzrzgLQY2cG8Iexb0tOt ./out/fuzz-journal-remote ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} qCWFcENjlfWJX0Q3cIOT ./out/fuzz-journald-native ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} s7d3LuRbkETCPSyxUvW8 ./out/fuzz-time-util ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} udjVYJfH4N01vaHNF5Kv ./out/fuzz-lldp ${FUZZIT_ADDITIONAL_FILES}
-./fuzzit c job ${FUZZIT_ARGS} vbYVccyWoDdgqzrQeln8 ./out/fuzz-bus-message ${FUZZIT_ADDITIONAL_FILES}
+find out/ -maxdepth 1 -name 'fuzz-*' -executable -type f -exec basename '{}' \; | xargs --verbose -n1 -I%FUZZER% ./fuzzit c job ${FUZZIT_ARGS} %FUZZER%-asan-ubsan out/%FUZZER% ${FUZZIT_ADDITIONAL_FILES}
+
+export SANITIZER="memory -fsanitize-memory-track-origins"
+FUZZIT_ARGS="--type ${FUZZING_TYPE} --branch ${FUZZIT_BRANCH} --revision ${TRAVIS_COMMIT}"
+tools/oss-fuzz.sh
+
+find out/ -maxdepth 1 -name 'fuzz-*' -executable -type f -exec basename '{}' \; | xargs --verbose -n1 -I%FUZZER% ./fuzzit c job ${FUZZIT_ARGS} %FUZZER%-msan out/%FUZZER% ${FUZZIT_ADDITIONAL_FILES}
diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in
index a6c5eb228f..0971edf9ec 100644
--- a/units/kmod-static-nodes.service.in
+++ b/units/kmod-static-nodes.service.in
@@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
-Description=Create list of required static device nodes for the current kernel
+Description=Create list of static device nodes for the current kernel
DefaultDependencies=no
Before=sysinit.target systemd-tmpfiles-setup-dev.service
ConditionCapability=CAP_SYS_MODULE
@@ -17,4 +17,4 @@ ConditionFileNotEmpty=/lib/modules/%v/modules.devname
[Service]
Type=oneshot
RemainAfterExit=yes
-ExecStart=@KMOD@ static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf
+ExecStart=@KMOD@ static-nodes --format=tmpfiles --output=/run/tmpfiles.d/static-nodes.conf
diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in
index 927f97e94e..c6f5b81c1d 100644
--- a/units/systemd-logind.service.in
+++ b/units/systemd-logind.service.in
@@ -22,6 +22,7 @@ After=dbus.socket
[Service]
BusName=org.freedesktop.login1
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG CAP_LINUX_IMMUTABLE
+DeviceAllow=block-* r
DeviceAllow=char-/dev/console rw
DeviceAllow=char-drm rw
DeviceAllow=char-input rw
diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in
index 5a490420e9..c64e8a9091 100644
--- a/units/systemd-random-seed.service.in
+++ b/units/systemd-random-seed.service.in
@@ -14,7 +14,7 @@ DefaultDependencies=no
RequiresMountsFor=@RANDOM_SEED@
Conflicts=shutdown.target
After=systemd-remount-fs.service
-Before=sysinit.target shutdown.target
+Before=shutdown.target
ConditionVirtualization=!container
[Service]