]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #31000 from flatcar-hub/krnowak/mutable-overlays
authorLuca Boccassi <bluca@debian.org>
Mon, 26 Feb 2024 16:17:11 +0000 (16:17 +0000)
committerGitHub <noreply@github.com>
Mon, 26 Feb 2024 16:17:11 +0000 (16:17 +0000)
systemd-sysext: Implement optional mutability for extensions

219 files changed:
.github/development-freeze.yml
NEWS
README
README.md
TODO
docs/API_FILE_SYSTEMS.md [moved from docs/_userdocs/API_FILE_SYSTEMS.md with 99% similarity]
docs/ARCHITECTURE.md [moved from docs/_contributing/ARCHITECTURE.md with 100% similarity]
docs/AUTOMATIC_BOOT_ASSESSMENT.md [moved from docs/_booting/AUTOMATIC_BOOT_ASSESSMENT.md with 100% similarity]
docs/AUTOPKGTEST.md [moved from docs/_devdocs/AUTOPKGTEST.md with 100% similarity]
docs/BACKPORTS.md [moved from docs/_devdocs/BACKPORTS.md with 100% similarity]
docs/BLOCK_DEVICE_LOCKING.md [moved from docs/_interfaces/BLOCK_DEVICE_LOCKING.md with 100% similarity]
docs/BOOT.md [moved from docs/_devdocs/BOOT.md with 99% similarity]
docs/BOOT_LOADER_INTERFACE.md [moved from docs/_booting/BOOT_LOADER_INTERFACE.md with 100% similarity]
docs/BOOT_LOADER_SPECIFICATION.md [moved from docs/_booting/BOOT_LOADER_SPECIFICATION.md with 100% similarity]
docs/BUILDING_IMAGES.md [moved from docs/_concepts/BUILDING_IMAGES.md with 100% similarity]
docs/CATALOG.md [moved from docs/_devdocs/CATALOG.md with 99% similarity]
docs/CGROUP_DELEGATION.md [moved from docs/_interfaces/CGROUP_DELEGATION.md with 100% similarity]
docs/CODE_OF_CONDUCT.md [moved from docs/_contributing/CODE_OF_CONDUCT.md with 100% similarity]
docs/CODE_QUALITY.md [moved from docs/_contributing/CODE_QUALITY.md with 100% similarity]
docs/CODING_STYLE.md [moved from docs/_contributing/CODING_STYLE.md with 99% similarity]
docs/CONTAINER_INTERFACE.md [moved from docs/_interfaces/CONTAINER_INTERFACE.md with 100% similarity]
docs/CONTRIBUTING.md [moved from docs/_contributing/CONTRIBUTING.md with 100% similarity]
docs/CONTROL_GROUP_INTERFACE.md [moved from docs/_devdocs/CONTROL_GROUP_INTERFACE.md with 99% similarity]
docs/CONVERTING_TO_HOMED.md [moved from docs/_groups/CONVERTING_TO_HOMED.md with 100% similarity]
docs/COREDUMP.md [moved from docs/_concepts/COREDUMP.md with 100% similarity]
docs/CREDENTIALS.md [moved from docs/_concepts/CREDENTIALS.md with 100% similarity]
docs/DAEMON_SOCKET_ACTIVATION.md [moved from docs/_userdocs/DAEMON_SOCKET_ACTIVATION.md with 99% similarity]
docs/DEBUGGING.md [moved from docs/_userdocs/DEBUGGING.md with 99% similarity]
docs/DESKTOP_ENVIRONMENTS.md [moved from docs/_concepts/DESKTOP_ENVIRONMENTS.md with 100% similarity]
docs/DISTRO_PORTING.md [moved from docs/_concepts/DISTRO_PORTING.md with 100% similarity]
docs/ELF_PACKAGE_METADATA.md [moved from docs/_interfaces/ELF_PACKAGE_METADATA.md with 100% similarity]
docs/ENVIRONMENT.md [moved from docs/_interfaces/ENVIRONMENT.md with 100% similarity]
docs/FAQ.md [moved from docs/_userdocs/FAQ.md with 99% similarity]
docs/FILE_DESCRIPTOR_STORE.md [moved from docs/_interfaces/FILE_DESCRIPTOR_STORE.md with 100% similarity]
docs/GROUP_RECORD.md [moved from docs/_groups/GROUP_RECORD.md with 100% similarity]
docs/HACKING.md [moved from docs/_contributing/HACKING.md with 100% similarity]
docs/HOME_DIRECTORY.md [moved from docs/_groups/HOME_DIRECTORY.md with 100% similarity]
docs/INCOMPATIBILITIES.md [moved from docs/_userdocs/INCOMPATIBILITIES.md with 98% similarity]
docs/INHIBITOR_LOCKS.md [moved from docs/_devdocs/INHIBITOR_LOCKS.md with 100% similarity]
docs/INITRD_INTERFACE.md [moved from docs/_interfaces/INITRD_INTERFACE.md with 100% similarity]
docs/JOURNAL_EXPORT_FORMATS.md [moved from docs/_interfaces/JOURNAL_EXPORT_FORMATS.md with 100% similarity]
docs/JOURNAL_FILE_FORMAT.md [moved from docs/_interfaces/JOURNAL_FILE_FORMAT.md with 100% similarity]
docs/JOURNAL_NATIVE_PROTOCOL.md [moved from docs/_interfaces/JOURNAL_NATIVE_PROTOCOL.md with 100% similarity]
docs/MEMORY_PRESSURE.md [moved from docs/_interfaces/MEMORY_PRESSURE.md with 100% similarity]
docs/MINIMAL_BUILDS.md [moved from docs/_devdocs/MINIMAL_BUILDS.md with 100% similarity]
docs/MOUNT_REQUIREMENTS.md [moved from docs/_booting/MOUNT_REQUIREMENTS.md with 100% similarity]
docs/MY_SERVICE_CANT_GET_REATLIME.md [moved from docs/_userdocs/MY_SERVICE_CANT_GET_REATLIME.md with 99% similarity]
docs/NETWORK_ONLINE.md [moved from docs/_networking/NETWORK_ONLINE.md with 100% similarity]
docs/OPTIMIZATIONS.md [moved from docs/_devdocs/OPTIMIZATIONS.md with 100% similarity]
docs/PASSWORD_AGENTS.md [moved from docs/_interfaces/PASSWORD_AGENTS.md with 100% similarity]
docs/PORTABILITY_AND_STABILITY.md [moved from docs/_interfaces/PORTABILITY_AND_STABILITY.md with 100% similarity]
docs/PORTABLE_SERVICES.md [moved from docs/_concepts/PORTABLE_SERVICES.md with 100% similarity]
docs/PORTING_TO_NEW_ARCHITECTURES.md [moved from docs/_contributing/PORTING_TO_NEW_ARCHITECTURES.md with 100% similarity]
docs/PREDICTABLE_INTERFACE_NAMES.md [moved from docs/_networking/PREDICTABLE_INTERFACE_NAMES.md with 100% similarity]
docs/PRESET.md [moved from docs/_devdocs/PRESET.md with 100% similarity]
docs/RANDOM_SEEDS.md [moved from docs/_concepts/RANDOM_SEEDS.md with 100% similarity]
docs/RELEASE.md [moved from docs/_contributing/RELEASE.md with 100% similarity]
docs/RESOLVED-VPNS.md [moved from docs/_networking/RESOLVED-VPNS.md with 100% similarity]
docs/ROOT_STORAGE_DAEMONS.md [moved from docs/_interfaces/ROOT_STORAGE_DAEMONS.md with 100% similarity]
docs/SECURITY.md [moved from docs/_contributing/SECURITY.md with 100% similarity]
docs/SEPARATE_USR_IS_BROKEN.md [moved from docs/_userdocs/SEPARATE_USR_IS_BROKEN.md with 99% similarity]
docs/SYSLOG.md [moved from docs/_devdocs/SYSLOG.md with 100% similarity]
docs/SYSTEMD_FILE_HIERARCHY_REQUIREMENTS.md [moved from docs/_devdocs/SYSTEMD_FILE_HIERARCHY_REQUIREMENTS.md with 100% similarity]
docs/TEMPORARY_DIRECTORIES.md [moved from docs/_interfaces/TEMPORARY_DIRECTORIES.md with 100% similarity]
docs/TESTING_WITH_SANITIZERS.md [moved from docs/_contributing/TESTING_WITH_SANITIZERS.md with 100% similarity]
docs/THE_CASE_FOR_THE_USR_MERGE.md [moved from docs/_devdocs/THE_CASE_FOR_THE_USR_MERGE.md with 100% similarity]
docs/TIPS_AND_TRICKS.md [moved from docs/_userdocs/TIPS_AND_TRICKS.md with 99% similarity]
docs/TPM2_PCR_MEASUREMENTS.md [moved from docs/_booting/TPM2_PCR_MEASUREMENTS.md with 100% similarity]
docs/TRANSIENT-SETTINGS.md [moved from docs/_interfaces/TRANSIENT-SETTINGS.md with 100% similarity]
docs/TRANSLATORS.md [moved from docs/_contributing/TRANSLATORS.md with 100% similarity]
docs/UIDS-GIDS.md [moved from docs/_groups/UIDS-GIDS.md with 100% similarity]
docs/USERDB_AND_DESKTOPS.md [moved from docs/_groups/USERDB_AND_DESKTOPS.md with 100% similarity]
docs/USER_GROUP_API.md [moved from docs/_groups/USER_GROUP_API.md with 100% similarity]
docs/USER_NAMES.md [moved from docs/_groups/USER_NAMES.md with 100% similarity]
docs/USER_RECORD.md [moved from docs/_groups/USER_RECORD.md with 99% similarity]
docs/USER_RECORD_BLOB_DIRS.md
docs/VIRTUALIZED_TESTING.md [moved from docs/_devdocs/VIRTUALIZED_TESTING.md with 100% similarity]
docs/WRITING_DESKTOP_ENVIRONMENTS.md [moved from docs/_devdocs/WRITING_DESKTOP_ENVIRONMENTS.md with 100% similarity]
docs/WRITING_DISPLAY_MANAGERS.md [moved from docs/_devdocs/WRITING_DISPLAY_MANAGERS.md with 100% similarity]
docs/WRITING_NETWORK_CONFIGURATION_MANAGERS.md [moved from docs/_devdocs/WRITING_NETWORK_CONFIGURATION_MANAGERS.md with 94% similarity]
docs/WRITING_RESOLVER_CLIENTS.md [moved from docs/_devdocs/WRITING_RESOLVER_CLIENTS.md with 99% similarity]
docs/WRITING_VM_AND_CONTAINER_MANAGERS.md [moved from docs/_devdocs/WRITING_VM_AND_CONTAINER_MANAGERS.md with 100% similarity]
docs/_config.yml
docs/_data/extra_pages.json
docs/_data/project.json [deleted file]
docs/index.md
hwdb.d/60-sensor.hwdb
hwdb.d/70-av-production.hwdb
man/networkd.conf.xml
man/systemd-ssh-generator.xml
man/systemd-vmspawn.xml
man/systemd.network.xml
meson.build
meson_options.txt
rules.d/60-persistent-media-controller.rules [new file with mode: 0644]
src/basic/build-path.c [new file with mode: 0644]
src/basic/build-path.h [new file with mode: 0644]
src/basic/glyph-util.c
src/basic/glyph-util.h
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/meson.build
src/basic/process-util.c
src/basic/signal-util.c
src/basic/signal-util.h
src/basic/virt.c
src/boot/efi/measure.c
src/boot/efi/meson.build
src/boot/efi/proto/tcg.h
src/boot/efi/util.c
src/boot/efi/util.h
src/core/exec-invoke.c
src/core/manager.c
src/home/homed-home.c
src/home/homed.c
src/import/export.c
src/import/import-common.c
src/import/importd.c
src/journal-remote/journal-remote-main.c
src/journal-remote/journal-upload.c
src/journal/journald-server.c
src/libsystemd-network/icmp6-util-unix.c
src/libsystemd-network/icmp6-util.c
src/libsystemd-network/icmp6-util.h
src/libsystemd-network/sd-ndisc.c
src/libsystemd-network/sd-radv.c
src/libsystemd-network/test-ndisc-ra.c
src/libsystemd-network/test-ndisc-rs.c
src/libsystemd/sd-event/test-event.c
src/login/logind.c
src/login/pam_systemd.c
src/machine/machinectl.c
src/machine/machined.c
src/network/networkd-address.c
src/network/networkd-dhcp-common.c
src/network/networkd-dhcp-common.h
src/network/networkd-dhcp6.c
src/network/networkd-gperf.gperf
src/network/networkd-json.c
src/network/networkd-link.c
src/network/networkd-lldp-tx.c
src/network/networkd-manager-varlink.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-route-nexthop.c
src/network/networkd-route.c
src/network/networkd-state-file.c
src/network/networkd-sysctl.c
src/network/networkd-sysctl.h
src/network/networkd-util.c
src/network/networkd-util.h
src/network/networkd.c
src/network/wait-online/wait-online.c
src/nspawn/nspawn.c
src/oom/oomd.c
src/portable/portabled.c
src/resolve/resolved-dns-dnssec.c
src/resolve/resolved-dns-dnssec.h
src/resolve/resolved-dns-transaction.c
src/resolve/resolved.c
src/run/run.c
src/shared/ask-password-api.c
src/shared/format-table.h
src/shared/pretty-print.c
src/shared/ptyfwd.c
src/shared/ptyfwd.h
src/shared/varlink-io.systemd.Network.c
src/systemctl/systemctl-show.c
src/systemctl/systemctl-util.c
src/systemctl/systemctl-util.h
src/systemctl/systemctl-whoami.c
src/systemd/sd-dhcp-client-id.h
src/systemd/sd-dhcp-duid.h
src/systemd/sd-dhcp-option.h
src/systemd/sd-dhcp-server-lease.h
src/systemd/sd-ndisc-protocol.h
src/systemd/sd-ndisc-router.h
src/systemd/sd-ndisc.h
src/sysupdate/sysupdate-resource.c
src/sysupdate/sysupdate-transfer.c
src/sysupdate/sysupdate.h
src/test/meson.build
src/test/test-async.c
src/test/test-build-path.c [new file with mode: 0644]
src/test/test-execute.c
src/test/test-locale-util.c
src/test/test-mempress.c
src/timesync/timesyncd.c
src/timesync/wait-sync.c
src/tty-ask-password-agent/tty-ask-password-agent.c
src/udev/test-udev-rule-runner.c
src/udev/test-udev-spawn.c
src/udev/udev-manager.c
src/udev/udevadm-monitor.c
src/ukify/ukify.py
src/userdb/userdbd-manager.c
src/userdb/userdbd.c
src/version/version.h.in
src/vmspawn/vmspawn-scope.c
src/vmspawn/vmspawn-scope.h
src/vmspawn/vmspawn-settings.c
src/vmspawn/vmspawn-settings.h
src/vmspawn/vmspawn.c
test/test-network/conf/25-agent-client-peer.network
test/test-network/conf/25-agent-client.network
test/test-network/conf/25-agent-server-peer.network
test/test-network/conf/25-agent-server.network
test/test-network/conf/25-ipv6-proxy-ndp.network
test/test-network/conf/25-sysctl.network
test/test-network/conf/26-bridge-vlan-master-issue-20373.network
test/test-network/conf/26-bridge-vlan-slave-issue-20373.network
test/test-network/systemd-networkd-tests.py
test/units/testsuite-46.sh
tools/meson-vcs-tag.sh [deleted file]

index 564e5f02f1a4172b059af6a4f078cecf0147ba6b..999654b3e7629d6506115b1e2d5a141402489526 100644 (file)
@@ -6,7 +6,9 @@ policy:
   - tags: ['^\S*-rc\d+$']
     feedback:
       frozen-state: |
-        An -rc1 tag has been created and a release is being prepared, so please note that PRs introducing new features and APIs will be held back until the new version has been released.
+        > [!IMPORTANT]
+        > An -rc1 tag has been created and a release is being prepared, so please note that PRs introducing new features and APIs will be held back until the new version has been released.
       unfreeze-state: |
-        We had successfully released a new major release. We are no longer in a development freeze phase.
-        We will try our best to get back to your PR as soon as possible. Thank you for your patience.
+        > [!NOTE]
+        > We had successfully released a new major release. We are no longer in a development freeze phase.
+        > We will try our best to get back to your PR as soon as possible. Thank you for your patience.
diff --git a/NEWS b/NEWS
index bcf42ffd8e24ac3a597dbb15e9a31720ff6d95fa..1cac8d4ad79c2f1cfa52165f61145cdeb686c093 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,13 @@ CHANGES WITH 256 in spe:
           a private VLAN variant of the proxy ARP supported by the kernel
           under the name IPv4ProxyARPPrivateVLAN=.
 
+        * TPM 1.2 PCR measurement support has been removed from
+          systemd-stub. TPM 1.2 is obsolete and â€” due to the (by today's
+          standards) weak cryptographic algorithms it only supports â€” does not
+          actually provide the security benefits it's supposed to
+          provide. Given that the rest of systemd's codebase never supported
+          TPM 1.2 the support has now been removed from systemd-stub as well.
+
 CHANGES WITH 255:
 
         Announcements of Future Feature Removals and Incompatible Changes:
diff --git a/README b/README
index 3b62e369fa8373ac2fcf8f27cd503de951a8112d..e41ab1ab7d3dd59c806ebd0498fe57053f9ccecf 100644 (file)
--- a/README
+++ b/README
@@ -98,6 +98,8 @@ REQUIREMENTS:
           CONFIG_SECCOMP_FILTER (required for seccomp support)
           CONFIG_KCMP (for the kcmp() syscall, used to be under
                        CONFIG_CHECKPOINT_RESTORE before ~5.12)
+          CONFIG_NET_SCHED
+          CONFIG_NET_SCH_FQ_CODEL
 
         Required for CPUShares= in resource control unit settings:
           CONFIG_CGROUP_SCHED
index b3bcf9ed940dca35adef90db756dfb5e9d283d23..c4522a2bac635b07cc790dda5c5eea58588aa717 100644 (file)
--- a/README.md
+++ b/README.md
@@ -26,13 +26,13 @@ Information about build requirements is provided in the [README file](README).
 
 Consult our [NEWS file](NEWS) for information about what's new in the most recent systemd versions.
 
-Please see the [Code Map](docs/_contributing/ARCHITECTURE.md) for information about this repository's layout and content.
+Please see the [Code Map](docs/ARCHITECTURE.md) for information about this repository's layout and content.
 
-Please see the [Hacking guide](docs/_contributing/HACKING.md) for information on how to hack on systemd and test your modifications.
+Please see the [Hacking guide](docs/HACKING.md) for information on how to hack on systemd and test your modifications.
 
-Please see our [Contribution Guidelines](docs/_contributing/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
+Please see our [Contribution Guidelines](docs/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests.
 
-When preparing patches for systemd, please follow our [Coding Style Guidelines](docs/_contributing/CODING_STYLE.md).
+When preparing patches for systemd, please follow our [Coding Style Guidelines](docs/CODING_STYLE.md).
 
 If you are looking for support, please contact our [mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel), join our [IRC channel #systemd on libera.chat](https://web.libera.chat/#systemd) or [Matrix channel](https://matrix.to/#/#systemd-project:matrix.org)
 
diff --git a/TODO b/TODO
index 479bd94d6646314f5653c3947122166e8a28424f..c9f5a8537c165970f4d6cdacff80c6419f7f063b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -128,18 +128,22 @@ Deprecations and removals:
 * Once baseline is 4.13, remove support for INTERFACE_OLD= checks in "udevadm
   trigger"'s waiting logic, since we can then rely on uuid-tagged uevents
 
-* remove remaining tpm1.2 support from sd-stub
-
 Features:
 
-* vmspawn: to speed up boot let's disable all PCR banks in swtpm except for
-  SHA256. Probably means running swtpm_setup --state-dir â€¦ --tpm2 --pcr-banks
-  sha256.
-
 * in os-release define a field that can be initialized at build time from
   SOURCE_DATE_EPOCH (maybe even under that name?). Would then be used to
   initialize the timestamp logic of ConditionNeedsUpdate=.
 
+* ptyfwd: look for window title ANSI sequences and insert colored dot in front
+  of it while passing it through, to indicate whether we are in privileged, VM,
+  container terminal sessions.
+
+* nspawn/vmspawn/pid1: add ability to easily insert fully booted VMs/FOSC into
+  shell pipelines, i.e. add easy to use switch that turns off console status
+  output, and generates the right credentials for systemd-run-generator so that
+  a program is invoked, and its output captured, with correct EOF handling and
+  exit code propagation
+
 * new systemd-analyze "join" verb or so, for debugging services. Would be
   nsenter on steroids, i.e invoke a shell or command line in an environment as
   close as we can make it for the MainPID of a service. Should be built around
@@ -380,7 +384,7 @@ Features:
 
 * systemd-tpm2-setup should probably have a factory reset logic, i.e. when some
   kernel command line option is set we reset the TPM (equivalent of tpm2_clear
-  -c owner?).
+  -c owner? or rather echo 5 >/sys/class/tpm/tpm0/ppi/request?).
 
 * systemd-tpm2-setup should support a mode where we refuse booting if the SRK
   changed. (Must be opt-in, to not break systems which are supposed to be
similarity index 99%
rename from docs/_userdocs/API_FILE_SYSTEMS.md
rename to docs/API_FILE_SYSTEMS.md
index a7e350b7aa0d8b24de4340da4c2a430ba6653db5..84a1900e4198879409d82fa54db1da90f680b6ea 100644 (file)
@@ -50,4 +50,3 @@ You have three options:
 1. Disable any mounting on `/tmp` so that it resides on the same physical file system as the root directory. For that, execute `systemctl mask tmp.mount`
 2. Mount a different, physical file system to `/tmp`. For that, simply create an entry for it in `/etc/fstab` as you would do for any other file system.
 3. Keep `/tmp` but increase/decrease the size of it. For that, also just create an entry for it in `/etc/fstab` as you would do for any other `tmpfs` file system, and use the right `size=` option.
-
similarity index 100%
rename from docs/_devdocs/BACKPORTS.md
rename to docs/BACKPORTS.md
similarity index 99%
rename from docs/_devdocs/BOOT.md
rename to docs/BOOT.md
index 98bcc2ef3d4788b923a631e8bf07902161e93f76..574cc080cfd994b8b311477d2748096312e010a4 100644 (file)
@@ -109,4 +109,3 @@ Links:
 [https://github.com/systemd/systemd](https://github.com/systemd/systemd)
 
 [http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/](http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/)
-
similarity index 99%
rename from docs/_devdocs/CATALOG.md
rename to docs/CATALOG.md
index fa5e7b091e657ff3079bda3d9bbd331686a59958..bcbf5b90bceea6aec7145148b3fd615277aef891 100644 (file)
@@ -65,4 +65,3 @@ To add message catalog entries for log messages your application generates, plea
 * Use the [native Journal logging APIs](http://0pointer.de/blog/projects/journal-submit.html) to generate your messages, and define message IDs for all messages you want to add catalog entries for. You may use `journalctl --new-id128` to allocate new message IDs.
 * Write a catalog entry file for your messages and ship them in your package and install them to `/usr/lib/systemd/catalog/` (if you package your software with RPM use `%_journalcatalogdir`)
 * Ensure that after installation of your application's RPM/DEB "`journalctl --update-catalog`" is executed, in order to update the binary catalog index. (if you package your software with RPM use the `%journal_catalog_update` macro to achieve that.)
-
similarity index 99%
rename from docs/_contributing/CODING_STYLE.md
rename to docs/CODING_STYLE.md
index 0e761227348bd15fa52a98daa94a41f202e28da3..6d6e549f5c7bca80468a4a59c1cfdea50fef0485 100644 (file)
@@ -774,7 +774,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
 - A corollary of the above is: never use `clone()` where a `fork()` would do
   too. Also consider using `posix_spawn()` which combines `clone()` +
   `execve()` into one and has nice properties since it avoids becoming a CoW
-  trap by using `CLONE_VORK` and `CLONE_VM` together.
+  trap by using `CLONE_VFORK` and `CLONE_VM` together.
 
 - While we avoid forking off threads on our own, writing thread-safe code is a
   good idea where it might end up running inside of libsystemd.so or
similarity index 99%
rename from docs/_devdocs/CONTROL_GROUP_INTERFACE.md
rename to docs/CONTROL_GROUP_INTERFACE.md
index 1b9728e1b072ae0dd568533c6550fd37292bda16..11dc6a37ac7c7771fd86420df63c80797f5bd536 100644 (file)
@@ -205,7 +205,7 @@ The [`systemctl set-property`](http://www.freedesktop.org/software/systemd/man/s
 
 ### Enumeration
 
-To acquire a list of currently running units, use the `ListUnits()` call on the Manager bus object. To determine the scope/service unit and slice unit a process is running in use [`sd_pid_get_unit()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_unit.html) and `sd_pid_get_slice()`. These two calls are implemented in `libsystemd-login.so`. These call bypass the system bus (which they can because they are passive and do not require privileges) and are hence very effecient to invoke.
+To acquire a list of currently running units, use the `ListUnits()` call on the Manager bus object. To determine the scope/service unit and slice unit a process is running in use [`sd_pid_get_unit()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_unit.html) and `sd_pid_get_slice()`. These two calls are implemented in `libsystemd-login.so`. These call bypass the system bus (which they can because they are passive and do not require privileges) and are hence very efficient to invoke.
 
 ### VM and Container Managers
 
similarity index 100%
rename from docs/_concepts/COREDUMP.md
rename to docs/COREDUMP.md
similarity index 99%
rename from docs/_userdocs/DAEMON_SOCKET_ACTIVATION.md
rename to docs/DAEMON_SOCKET_ACTIVATION.md
index 797deaefd0ac1e7170200eac953a524402cc0f70..1a027a37c80de2b2585e6eb3b3ca56b7ea08683a 100644 (file)
@@ -120,4 +120,3 @@ It's possible to shut down the service and re-activate it using the web browser,
 sudo systemctl stop my-php-fpm-pool.socket my-php-fpm-pool.service
 sudo systemctl start my-php-fpm-pool.socket
 ```
-
similarity index 99%
rename from docs/_userdocs/DEBUGGING.md
rename to docs/DEBUGGING.md
index 1d3d829a3fc328ff7d729cc5a317510f6e55f552..dc1c8743b44e0ebcc69a3673dfcd809522aaeb26 100644 (file)
@@ -209,4 +209,3 @@ Whenever possible, the following should be mentioned and attached to your bug re
   * ideally after booting with `systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M printk.devkmsg=on`
 * The output of a systemd dump: `systemd-analyze dump > systemd-dump.txt`
 * The output of `/usr/lib/systemd/systemd --test --system --log-level=debug > systemd-test.txt 2>&1`
-
similarity index 99%
rename from docs/_userdocs/FAQ.md
rename to docs/FAQ.md
index 5239dbb0e5f986827fffce5825a89a561738a991..483645b1e72b17b700cb61de38fc0705a79a4c2e 100644 (file)
@@ -112,4 +112,3 @@ A: That's a long story, and that's why we have a wiki page of its own about this
 **Q: My systemd system always comes up with `/tmp` as a tiny `tmpfs`. How do I get rid of this?**
 
 A: That's also a long story, please have a look on [API File Systems](../API_FILE_SYSTEMS)
-
similarity index 98%
rename from docs/_userdocs/INCOMPATIBILITIES.md
rename to docs/INCOMPATIBILITIES.md
index be256deaf261eb6c5616d3b541d5f55289770678..75b60b66efd53270e1c2ea8ca3f83024e4b769ba 100644 (file)
@@ -27,7 +27,7 @@ systemd provides a fair degree of compatibility with the behavior exposed by the
 * On SysV systems changes to init scripts or any other files that define the boot process (such as /etc/fstab) usually had an immediate effect on everything started later. This is different on systemd-based systems where init script information and other boot-time configuration files are only reread when "systemctl daemon-reload" is issued. (Note that some commands, notably "systemctl enable"/"systemctl disable" do this implicitly however.) This is by design, and a safety feature, since it ensures that half-completed changes are not read at the wrong time.
 * Multiple entries for the same mount path in /etc/fstab are not supported. In systemd there's only a single unit definition for each mount path read at any time. Also the listing order of mounts in /etc/fstab has no effect, mounts are executed in parallel and dependencies between them generated automatically depending on path prefixes and source paths.
 * systemd's handling of the existing "nofail" mount option in /etc/fstab is stricter than it used to be on some sysvinit distributions: mount points that fail and are not listed as "nofail" will cause the boot to be stopped, for security reasons, as we we should not permit unprivileged code to run without everything listed â€” and not expressly exempted through "nofail" â€” being around. Hence, please mark all mounts where booting shall proceed regardless whether they succeeded or not with "nofail"
-* Some SysV systems support an "rc.local" script that is supposed to be called "last" during boot. In systemd, the script is supported, but the semantics are less strict, as there is simply no concept of "last service", as the boot process is event- and request-based, parallelized and compositive. In general, it's a good idea to write proper unit files with properly defined dependncies, and avoid making use of rc.local.
+* Some SysV systems support an "rc.local" script that is supposed to be called "last" during boot. In systemd, the script is supported, but the semantics are less strict, as there is simply no concept of "last service", as the boot process is event- and request-based, parallelized and compositive. In general, it's a good idea to write proper unit files with properly defined dependencies, and avoid making use of rc.local.
 * systemd assumes that the UID boundary between system and regular users is a choice the distribution makes, and not the administrator. Hence it expects this setting as compile-time option to be picked by the distribution. It will _not_ check /etc/login.defs during runtime.
 
 Note that there are some areas where systemd currently provides a certain amount of compatibility where we expect this compatibility to be removed eventually.
similarity index 99%
rename from docs/_userdocs/MY_SERVICE_CANT_GET_REATLIME.md
rename to docs/MY_SERVICE_CANT_GET_REATLIME.md
index eee389ad703416f669e12d657e5f5cef1e5cbdb7..20d31fbde7ee8c01ef98cd4b6983df020fd284a4 100644 (file)
@@ -26,4 +26,3 @@ Of course, that's quite a limitation, so here's how you work around this:
 Note that this all only applies to services. By default, user applications run in the root cgroup of the "cpu" hierarchy, which avoids these problems for normal user applications.
 
 In the long run we hope that the kernel is fixed to not require an RT budget to be assigned for any cgroup created before a process can acquire RT (i.e. a process' RT budget should be derived from the nearest ancestor cgroup which has a budget assigned, rather than unconditionally its own uninitialized budget.) Ideally, we'd also like to create a per-user cgroup by default, so that users with many processes get roughly the same amount of CPU as users with very few.
-
similarity index 100%
rename from docs/_devdocs/PRESET.md
rename to docs/PRESET.md
similarity index 99%
rename from docs/_userdocs/SEPARATE_USR_IS_BROKEN.md
rename to docs/SEPARATE_USR_IS_BROKEN.md
index aa821f4a72fcc045c787c5f285430eb4dc6aaa04..8e9390eff447a7581f5a613931a4c5aa94173e6b 100644 (file)
@@ -38,4 +38,3 @@ On the Fedora distribution we have succeeded to clean up the situation and the c
 In this new definition of /usr, the directory can be mounted read-only by default, while the rootfs may be either read-write or read-only (for stateless systems) and contains only the empty mount point directories, compat-symlinks to /usr and the host-specific data like /etc, /root, /srv. In comparison to today's setups, the rootfs will be very small. The host-specific data will be properly separated from the installed operating system. The new /usr could also easily be shared read-only across several systems. Such a setup would be more efficient, can provide additional security, is more flexible to use, provides saner options for custom setups, and is much simpler to setup and maintain.
 
 For more information on this please continue to [The Case for the /usr Merge](../THE_CASE_FOR_THE_USR_MERGE).
-
similarity index 100%
rename from docs/_devdocs/SYSLOG.md
rename to docs/SYSLOG.md
similarity index 99%
rename from docs/_userdocs/TIPS_AND_TRICKS.md
rename to docs/TIPS_AND_TRICKS.md
index d9a106a9228dbed9aa1690a31b6c2be6c5ce973a..f181f122a84ba02f4b64fb58f07139330495cabc 100644 (file)
@@ -183,4 +183,3 @@ $ systemd --test --system --unit=foobar.target
 ```
 
 for a boot target foobar.target. Note that this is mostly a debugging tool that actually does a lot more than just calculate the initial transaction, so don't build scripts based on this.
-
similarity index 100%
rename from docs/_groups/UIDS-GIDS.md
rename to docs/UIDS-GIDS.md
similarity index 99%
rename from docs/_groups/USER_RECORD.md
rename to docs/USER_RECORD.md
index b88a67e66b88f28dfb90a20db7b401576a1dfaf7..a92711f275997581044a328720a08185425c8bc6 100644 (file)
@@ -76,7 +76,7 @@ Similar to JSON User Records there are also
 
 JSON User Records are not suitable for storing all identity information about
 the user, such as binary data or large unstructured blobs of text. These parts
-of a user's identity should be stored in the [Blob Directories](USER_RECORD_BLOB_DIRS.md).
+of a user's identity should be stored in the [Blob Directories](USER_RECORD_BLOB_DIRS).
 
 JSON User Records may be transferred or written to disk in various protocols
 and formats. To inquire about such records defined on the local system use the
@@ -235,10 +235,10 @@ user record with a realm set is never compatible (for the purpose of updates,
 see above) with a user record without one set, even if the `userName` field matches.
 
 `blobDirectory` â†’ The absolute path to a world-readable copy of the user's blob
-directory. See [Blob Directories](USER_RECORD_BLOB_DIRS.md) for more details.
+directory. See [Blob Directories](USER_RECORD_BLOB_DIRS) for more details.
 
 `blobManifest` â†’ An object, which maps valid blob directory filenames (see
-[Blob Directories](USER_RECORD_BLOB_DIRS.md) for requirements) to SHA256 hashes
+[Blob Directories](USER_RECORD_BLOB_DIRS) for requirements) to SHA256 hashes
 formatted as hex strings. This exists for the purpose of including the contents
 of the blob directory in the record's signature. Managers that support blob
 directories and utilize signed user records (like `systemd-homed`) should use
index 8f5dd7914b071417734d61f55a0f13d34c54b5d5..fd030e796615fc64294cbd96012806dd9e330f40 100644 (file)
@@ -8,7 +8,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
 # User Record Blob Directories
 
 The blob directories are for storing binary or unstructured data that would
-otherwise be stored in [JSON User Records](USER_RECORD.md). For instance,
+otherwise be stored in [JSON User Records](USER_RECORD). For instance,
 this includes image files such as the user's avatar picture. This data,
 like most of the user record, will be made publicly available to the
 system.
similarity index 94%
rename from docs/_devdocs/WRITING_NETWORK_CONFIGURATION_MANAGERS.md
rename to docs/WRITING_NETWORK_CONFIGURATION_MANAGERS.md
index 61b24dc759e111e2676cd9d90d765b62b82ce025..3a02c3a1cb0cf518ae24d33ca2cff2a0e24fa371 100644 (file)
@@ -23,7 +23,7 @@ Note that `systemd-networkd` is already hooked up with `systemd-resolved`, expos
 
 ## Suggested Mode of Operation
 
-Whenever a network configuration manager sets up an interface for operation, it should pass the DNS configuration information for the interface to `systemd-resolved`. It's recommended to do that after the Linux network interface index ("ifindex") has been allocated, but before the interface has beeen upped (i.e. `IFF_UP` turned on). That way, `systemd-resolved` will be able to use the configuration the moment the network interface is available. (Note that `systemd-resolved` watches the kernel interfaces come and go, and will make use of them as soon as they are suitable to be used, which among other factors requires `IFF_UP` to be set). That said it is OK to change DNS configuration dynamically any time: simply pass the new data to resolved, and it is happy to use it.
+Whenever a network configuration manager sets up an interface for operation, it should pass the DNS configuration information for the interface to `systemd-resolved`. It's recommended to do that after the Linux network interface index ("ifindex") has been allocated, but before the interface has been upped (i.e. `IFF_UP` turned on). That way, `systemd-resolved` will be able to use the configuration the moment the network interface is available. (Note that `systemd-resolved` watches the kernel interfaces come and go, and will make use of them as soon as they are suitable to be used, which among other factors requires `IFF_UP` to be set). That said it is OK to change DNS configuration dynamically any time: simply pass the new data to resolved, and it is happy to use it.
 
 In order to pass the DNS configuration information to resolved, use the following methods of the `org.freedesktop.resolve1.Manager` interface of the `/org/freedesktop/resolve1` object, on the `org.freedesktop.resolve1` service:
 
similarity index 99%
rename from docs/_devdocs/WRITING_RESOLVER_CLIENTS.md
rename to docs/WRITING_RESOLVER_CLIENTS.md
index 9a08721257f698668b0666f1b68de0512de6983d..88a873a06ed7862be7bdc64d72f7bd455add38c8 100644 (file)
@@ -39,7 +39,7 @@ This example specifies _AF_UNSPEC_ as address family for the requested address.
 
 The example specifies a network interface index of "0", i.e. does not specify any at all, so that the request may be done on any. Note that the interface index is primarily relevant for LLMNR and MulticastDNS lookups, which distinguish different scopes for each network interface index.
 
-This examples makes no use of either the input flags parameter, nor the output flags parameter. See the _ResolveRecord()_ example below for information how to make use of the _SD_RESOLVED_AUTHENTICATED_ bit in the returned flags paramter.
+This examples makes no use of either the input flags parameter, nor the output flags parameter. See the _ResolveRecord()_ example below for information how to make use of the _SD_RESOLVED_AUTHENTICATED_ bit in the returned flags parameter.
 
 ```
 #include <arpa/inet.h>
@@ -135,7 +135,7 @@ Compile this with a command line like the following (under the assumption you sa
 gcc addrtest.c -o addrtest -Wall `pkg-config --cflags --libs libsystemd`
 ```
 
-## Resolving an Abitrary DNS Resource Record
+## Resolving an Arbitrary DNS Resource Record
 
 Use `ResolveRecord()` in order to resolve arbitrary resource records. The call will return the binary RRset data. This calls is useful to acquire resource records for which no high-level calls such as ResolveHostname(), ResolveAddress() and ResolveService() exist. In particular RRs such as MX, SSHFP, TLSA, CERT, OPENPGPKEY or IPSECKEY may be requested via this API.
 
index 3d44889f80d5435ccd94282bc0ff55f6286ea2ec..412db1f413ff15b2be687496cb34c9316ced087f 100644 (file)
@@ -4,32 +4,7 @@ title: systemd
 baseurl: "" # the subpath of your site, e.g. /blog/
 url: "https://systemd.io" # the base hostname & protocol for your site
 
+permalink: /:title/
+
 # Build settings
 markdown: kramdown
-
-collections:
-  concepts:
-    title: 'Concepts'
-    output: true
-  contributing:
-    title: 'Contributing'
-    output: true
-  userdocs:
-    output: true
-    title: 'Documentation for Users and Administrators'
-  booting:
-    title: 'Booting'
-    output: true
-  interfaces:
-    title: 'Interfaces'
-    output: true
-  networking:
-    title: 'Networking'
-    output: true
-  groups:
-    title: 'Users, Groups and Home Directories'
-    output: true
-  devdocs:
-    title: 'Documentation for Developers'
-    output: true
-
index 908e3a83dc0d3b3650978316786a3dd44d5eb2f1..d24e301329ca77259e177dd10a9f2c78ae9d1d2a 100644 (file)
@@ -1,4 +1,44 @@
 [
+  {
+    "category": "Project",
+    "title": "mkosi Project - Build Bespoke OS Images",
+    "url": "https://mkosi.systemd.io/"
+  },
+  {
+    "category": "Project",
+    "title": "Brand",
+    "url": "https://brand.systemd.io/"
+  },
+  {
+    "category": "Project",
+    "title": "Mailing List",
+    "url": "https://lists.freedesktop.org/mailman/listinfo/systemd-devel"
+  },
+  {
+    "category": "Project",
+    "title": "Mastodon",
+    "url": "https://mastodon.social/@pid_eins"
+  },
+  {
+    "category": "Project",
+    "title": "Releases",
+    "url": "https://github.com/systemd/systemd/releases"
+  },
+  {
+    "category": "Project",
+    "title": "GitHub Project Page",
+    "url": "https://github.com/systemd/systemd"
+  },
+  {
+    "category": "Project",
+    "title": "Issues",
+    "url": "https://github.com/systemd/systemd/issues"
+  },
+  {
+    "category": "Project",
+    "title": "Pull Requests",
+    "url": "https://github.com/systemd/systemd/pulls"
+  },
   {
     "category": "Manual Pages",
     "title": "Index",
   {
     "category": "The various distributions",
     "title": "Arch Linux bugtracker",
-    "url": "https://bugs.archlinux.org/?project=1&cat%5B%5D=31&string=systemd"
+    "url": "https://gitlab.archlinux.org/archlinux/packaging/packages/systemd/-/issues"
   },
   {
     "category": "The various distributions",
diff --git a/docs/_data/project.json b/docs/_data/project.json
deleted file mode 100644 (file)
index 606c784..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-[
-  {
-    "category": "Project",
-    "title": "mkosi Project - Build Bespoke OS Images",
-    "url": "https://mkosi.systemd.io/"
-  },
-  {
-    "collection": "project",
-    "title": "Brand",
-    "url": "https://brand.systemd.io/"
-  },
-  {
-    "collection": "project",
-    "title": "Mailing List",
-    "url": "https://lists.freedesktop.org/mailman/listinfo/systemd-devel"
-  },
-  {
-    "collection": "project",
-    "title": "Mastodon",
-    "url": "https://mastodon.social/@pid_eins"
-  },
-  {
-    "collection": "project",
-    "title": "Releases",
-    "url": "https://github.com/systemd/systemd/releases"
-  },
-  {
-    "collection": "project",
-    "title": "GitHub Project Page",
-    "url": "https://github.com/systemd/systemd"
-  },
-  {
-    "collection": "project",
-    "title": "Issues",
-    "url": "https://github.com/systemd/systemd/issues"
-  },
-  {
-    "collection": "project",
-    "title": "Pull Requests",
-    "url": "https://github.com/systemd/systemd/pulls"
-  }
-]
index cd3916ca32078f6eb1d16712791d84d8de6c139e..3c05c93550412da74cabf3b0da370cd714d86d5d 100644 (file)
@@ -12,27 +12,17 @@ systemd provides aggressive parallelization capabilities, uses socket and D-Bus
 Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution.
 
 ---
-## Project
-{% for page in site.data.project %}
-* [{{ page.title }}]({{ page.url | relative_url }}){% endfor %}
-
-<!-- Collections -->
-{% for c in site.collections %}
-<!-- hide autegenerated posts collection -->
-{% if c.label != "posts" %}
-## {{ c.title }}
-{% for item in site[c.label] %}
-* [{{ item.title }}]({{ item.url | relative_url }}){% endfor %}
-{% endif %}
-{% endfor %}
 
-<!-- external pages -->
-{% assign external_pages = site.data.extra_pages | group_by:"category" %}
+{% assign by_category = site.pages | group_by:"category" %}
+{% assign extra_pages = site.data.extra_pages | group_by:"category" %}
+{% assign merged = by_category | concat: extra_pages | sort:"name" %}
 
-{% for category in external_pages %}
-## {{ category.name }}
-{% assign sorted = category.items | sort:"title" %}{% for page in sorted %}
+{% for pair in merged %}
+  {% if pair.name != "" %}
+## {{ pair.name }}
+{% assign sorted = pair.items | sort:"title" %}{% for page in sorted %}
 * [{{ page.title }}]({{ page.url | relative_url }}){% endfor %}
+  {% endif %}
 {% endfor %}
 
 ## See also
index bbdb217440bf7d946cc79c305324e8ddd22b9c0e..ce800da5e476ed130b4e5fb57de47099bd9e82c6 100644 (file)
@@ -311,7 +311,7 @@ sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo*:pnC3W6_AP108_4GB:*
 
 # Chuwi Ubook X (CWI535)
 sensor:modalias:acpi:MXC6655*:dmi*:svnCHUWIInnovationAndTechnology*:pnUBookX:*
- ACCEL_MOUNT_MATRIX=0, 0, -1; 1, 0, 0; 0, 1, 0
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, -1
 
 #########################################
 # Connect
index 9890d726e5ad47e35aa4901e73b89dcc1e9df81b..a701d1c1eafada76ead161c5993bdd98ccea32de 100644 (file)
@@ -56,6 +56,10 @@ usb:v0FD9p006D*
 usb:v0FD9p0080*
  ID_AV_PRODUCTION_CONTROLLER=1
 
+# Stream Deck Plus
+usb:v0FD9p0084*
+ ID_AV_PRODUCTION_CONTROLLER=1
+
 # Stream Deck Pedal
 usb:v0FD9p0086*
  ID_AV_PRODUCTION_CONTROLLER=1
index 9477bfe5afd9293cf236c1247a19c3809714c323..2ab5cf1d7906c8ab004fb653448250d584260c38 100644 (file)
         <xi:include href="version-info.xml" xpointer="v248"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>IPv4Forwarding=</varname></term>
+        <listitem>
+          <para>Configures IPv4 packet forwarding for the system. Takes a boolean value. This controls the
+          <filename>net.ipv4.conf.default.forwarding</filename> and
+          <filename>net.ipv4.conf.all.forwarding</filename>sysctl options. See
+          <ulink url="https://docs.kernel.org/networking/ip-sysctl.html">IP Sysctl</ulink>
+          for more details about the sysctl options. Defaults to unset and the sysctl options will not be
+          changed.</para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>IPv6Forwarding=</varname></term>
+        <listitem>
+          <para>Configures IPv6 packet forwarding for the system. Takes a boolean value. This controls the
+          <filename>net.ipv6.conf.default.forwarding</filename> and
+          <filename>net.ipv6.conf.all.forwarding</filename> sysctl options. See
+          <ulink url="https://docs.kernel.org/networking/ip-sysctl.html">IP Sysctl</ulink>
+          for more details about the sysctl options. Defaults to unset and the sysctl options will not be
+          changed.</para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>IPv6PrivacyExtensions=</varname></term>
         <listitem>
index 2f4f2a6f0ed44ae2e5a676666c39769bd47393b0..98efc74fc81e3e303883fc3426db2a33eb1a3b00 100644 (file)
     <citerefentry><refentrytitle>systemd-ssh-proxy</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
     details on how to connect to these sockets via the <command>ssh</command> client.</para>
 
+    <para>The <varname>ssh.authorized_keys.root</varname> credential can be used to allow specific public keys
+    to log in over SSH. See
+    <citerefentry><refentrytitle>systemd.systemd-credentials</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+    for more information.</para>
+
     <para>The generator will use a packaged <filename>sshd@.service</filename> service template file if one
     exists, and otherwise generate a suitable service template file.</para>
 
index ed4dfc8bfab01ed17d314937d34c1464f3a46da4..d7fee0538ac8c5491a700a305fa07c7c0af6abc2 100644 (file)
           </listitem>
         </varlistentry>
 
-        <varlistentry>
-          <term><option>--qemu-gui</option></term>
-
-          <listitem><para>Start QEMU in graphical mode.</para>
-
-          <xi:include href="version-info.xml" xpointer="v255"/></listitem>
-        </varlistentry>
-
         <varlistentry>
           <term><option>-n</option></term>
           <term><option>--network-tap</option></term>
       </variablelist>
     </refsect2>
 
+    <refsect2>
+      <title>Input/Output Options</title>
+
+      <variablelist>
+        <varlistentry>
+          <term><option>--console=</option><replaceable>MODE</replaceable></term>
+
+          <listitem><para>Configures how to set up the console of the VM. Takes one of
+          <literal>interactive</literal>, <literal>read-only</literal>, <literal>native</literal>,
+          <literal>gui</literal>. Defaults to <literal>interactive</literal>. <literal>interactive</literal>
+          provides an interactive terminal interface to the VM. <literal>read-only</literal> is similar, but
+          is strictly read-only, i.e. does not accept any input from the user. <literal>native</literal> also
+          provides a TTY-based interface, but uses qemu native implementation (which means the qemu monitor
+          is available). <literal>gui</literal> shows the qemu graphical UI.</para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><option>--background=<replaceable>COLOR</replaceable></option></term>
+
+          <listitem><para>Change the terminal background color to the specified ANSI color as long as the VM
+          runs. The color specified should be an ANSI X3.64 SGR background color, i.e. strings such as
+          <literal>40</literal>, <literal>41</literal>, â€¦, <literal>47</literal>, <literal>48;2;…</literal>,
+          <literal>48;5;…</literal>. See <ulink
+          url="https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters">ANSI
+          Escape Code (Wikipedia)</ulink> for details. Assign an empty string to disable any coloring. This
+          only has an effect in <option>--console=interactive</option> and
+          <option>--console=read-only</option> modes.</para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+    </refsect2>
+
     <refsect2>
       <title>Credentials</title>
 
index adff23d1fedfa19ec6bb3adb6bcabf9dbb2c32f4..96228fc1985d800d1e6ced7d41c174b9def92e5a 100644 (file)
@@ -803,26 +803,43 @@ Table=1234</programlisting></para>
       </varlistentry>
 
       <varlistentry>
-        <term><varname>IPForward=</varname></term>
-        <listitem>
-          <para>Configures IP packet forwarding for the system. If enabled, incoming packets on any
-          network interface will be forwarded to any other interfaces according to the routing table.
-          Takes a boolean, or the values <literal>ipv4</literal> or <literal>ipv6</literal>, which only
-          enable IP packet forwarding for the specified address family. This controls the
-          <filename>net.ipv4.ip_forward</filename> and <filename>net.ipv6.conf.all.forwarding</filename>
-          sysctl options of the network interface (see
+        <term><varname>IPv4Forwarding=</varname></term>
+        <listitem>
+          <para>Configures IPv4 packet forwarding for the interface. Takes a boolean value. This controls the
+          <filename>net.ipv4.conf.<replaceable>INTERFACE</replaceable>.forwarding</filename> sysctl option of
+          the network interface. See
           <ulink url="https://docs.kernel.org/networking/ip-sysctl.html">IP Sysctl</ulink>
-          for details about sysctl options). Defaults to <literal>no</literal>.</para>
+          for more details about the sysctl option. Defaults to true if <varname>IPMasquerade=</varname> is
+          enabled for IPv4, otherwise the value specified to the same setting in
+          <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          will be used. If none of them are specified, the sysctl option will not be changed.</para>
+
+          <para>To control the global setting, use the same setting in
+          <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+          </para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+        </listitem>
+      </varlistentry>
 
-          <para>Note: this setting controls a global kernel option, and does so one way only: if a
-          network that has this setting enabled is set up the global setting is turned on. However,
-          it is never turned off again, even after all networks with this setting enabled are shut
-          down again.</para>
+      <varlistentry>
+        <term><varname>IPv6Forwarding=</varname></term>
+        <listitem>
+          <para>Configures IPv6 packet forwarding for the interface. Takes a boolean value. This controls the
+          <filename>net.ipv6.conf.<replaceable>INTERFACE</replaceable>.forwarding</filename> sysctl option of
+          the network interface. See
+          <ulink url="https://docs.kernel.org/networking/ip-sysctl.html">IP Sysctl</ulink>
+          for more details about the sysctl option. Defaults to true if <varname>IPMasquerade=</varname> is
+          enabled for IPv6 or <varname>IPv6SendRA=</varname> is enabled, otherwise the value specified to the
+          same setting in
+          <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          will be used. If none of them are specified, the sysctl option will not be changed.</para>
 
-          <para>To allow IP packet forwarding only between specific network interfaces use a firewall.
+          <para>To control the global setting, use the same setting in
+          <citerefentry><refentrytitle>networkd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
           </para>
 
-          <xi:include href="version-info.xml" xpointer="v219"/>
+          <xi:include href="version-info.xml" xpointer="v256"/>
         </listitem>
       </varlistentry>
 
@@ -832,9 +849,7 @@ Table=1234</programlisting></para>
           <para>Configures IP masquerading for the network interface. If enabled, packets forwarded
           from the network interface will be appear as coming from the local host. Takes one of
           <literal>ipv4</literal>, <literal>ipv6</literal>, <literal>both</literal>, or
-          <literal>no</literal>. Defaults to <literal>no</literal>. If enabled, this automatically sets
-          <varname>IPForward=</varname> to one of <literal>ipv4</literal>, <literal>ipv6</literal> or
-          <literal>yes</literal>.</para>
+          <literal>no</literal>. Defaults to <literal>no</literal>.</para>
           <para>Note. Any positive boolean values such as <literal>yes</literal> or
           <literal>true</literal> are now deprecated. Please use one of the values in the above.</para>
 
index 7b6f0716fecc305050bd5f68a350366b794130a7..5f5fa2eaf88fa17109a3b8c4fda7545a6058f5de 100644 (file)
@@ -1853,13 +1853,27 @@ xml_helper_py = find_program('tools/xml_helper.py')
 #####################################################################
 
 version_tag = get_option('version-tag')
-version_h = vcs_tag(
-        input : 'src/version/version.h.in',
-        output : 'version.h',
-        command: [project_source_root / 'tools/meson-vcs-tag.sh',
-                  project_source_root,
-                  version_tag,
-                 ])
+if version_tag == ''
+        version_tag = meson.project_version()
+endif
+
+conf.set_quoted('VERSION_TAG', version_tag)
+
+vcs_tag = get_option('vcs-tag')
+if vcs_tag and fs.is_dir(project_source_root / '.git')
+        version_h = vcs_tag(
+                input : 'src/version/version.h.in',
+                output : 'version.h',
+                fallback : '',
+                command : ['sh', '-c', 'echo "-g$(git -C . describe --abbrev=7 --match="" --always --dirty=^)"'],
+        )
+else
+        version_h = configure_file(
+                input : 'src/version/version.h.in',
+                output : 'version.h',
+                configuration : configuration_data({'VCS_TAG' : ''}),
+        )
+endif
 
 shared_lib_tag = get_option('shared-lib-tag')
 if shared_lib_tag == ''
@@ -2513,13 +2527,13 @@ install_data('LICENSE.GPL2',
              'LICENSE.LGPL2.1',
              'NEWS',
              'README',
-             'docs/_contributing/CODING_STYLE.md',
-             'docs/_concepts/DISTRO_PORTING.md',
-             'docs/_interfaces/ENVIRONMENT.md',
-             'docs/_contributing/HACKING.md',
-             'docs/_interfaces/TRANSIENT-SETTINGS.md',
-             'docs/_contributing/TRANSLATORS.md',
-             'docs/_groups/UIDS-GIDS.md',
+             'docs/CODING_STYLE.md',
+             'docs/DISTRO_PORTING.md',
+             'docs/ENVIRONMENT.md',
+             'docs/HACKING.md',
+             'docs/TRANSIENT-SETTINGS.md',
+             'docs/TRANSLATORS.md',
+             'docs/UIDS-GIDS.md',
              install_dir : docdir)
 
 install_subdir('LICENSES',
index b51af01721d419633afce4ed4e1a59bca508b3cf..4dea1a8bf31a7669033afbe7179367fbea1f002b 100644 (file)
@@ -2,9 +2,11 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 option('version-tag', type : 'string',
-       description : 'override the git version string')
+       description : 'set the extended version string (defaults to project version)')
 option('shared-lib-tag', type : 'string',
        description : 'override the private shared library version tag (defaults to project version)')
+option('vcs-tag', type : 'boolean', value : true,
+       description : 'append current git commit to version output when git information is available')
 
 option('mode', type : 'combo', choices : ['developer', 'release'],
        description : 'autoenable features suitable for systemd development/release builds')
diff --git a/rules.d/60-persistent-media-controller.rules b/rules.d/60-persistent-media-controller.rules
new file mode 100644 (file)
index 0000000..bf614d9
--- /dev/null
@@ -0,0 +1,12 @@
+# do not edit this file, it will be overwritten on update
+
+# Media controller rules
+
+ACTION=="remove", GOTO="persistent_media_ctl_end"
+SUBSYSTEM!="media", GOTO="persistent_media_ctl_end"
+ENV{MAJOR}=="", GOTO="persistent_media_ctl_end"
+
+IMPORT{builtin}="path_id"
+ENV{ID_PATH}=="?*", KERNEL=="media*", SYMLINK+="media/by-path/$env{ID_PATH}-media-controller"
+
+LABEL="persistent_media_ctl_end"
diff --git a/src/basic/build-path.c b/src/basic/build-path.c
new file mode 100644 (file)
index 0000000..8ddef7b
--- /dev/null
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <elf.h>
+#include <link.h>
+#include <sys/auxv.h>
+
+#include "build-path.h"
+#include "errno-list.h"
+#include "errno-util.h"
+#include "macro.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "unistd.h"
+
+static int get_runpath_from_dynamic(const ElfW(Dyn) *d, const char **ret) {
+        size_t runpath_index = SIZE_MAX, rpath_index = SIZE_MAX;
+        const char *strtab = NULL;
+
+        assert(d);
+
+        /* Iterates through the PT_DYNAMIC section to find the DT_RUNPATH/DT_RPATH entries */
+
+        for (; d->d_tag != DT_NULL; d++) {
+
+                switch (d->d_tag) {
+
+                case DT_RUNPATH:
+                        runpath_index = (size_t) d->d_un.d_val;
+                        break;
+
+                case DT_RPATH:
+                        rpath_index = (size_t) d->d_un.d_val;
+                        break;
+
+                case DT_STRTAB:
+                        strtab = (const char *) d->d_un.d_val;
+                        break;
+                }
+
+                /* runpath wins, hence if we have the table and runpath we can exit the loop early */
+                if (strtab && runpath_index != SIZE_MAX)
+                        break;
+        }
+
+        if (!strtab)
+                return -ENOTRECOVERABLE;
+
+        /* According to dl.so runpath wins of both runpath and rpath are defined. */
+        if (runpath_index != SIZE_MAX) {
+                if (ret)
+                        *ret = strtab + runpath_index;
+                return 1;
+        }
+
+        if (rpath_index != SIZE_MAX) {
+                if (ret)
+                        *ret = strtab + rpath_index;
+                return 1;
+        }
+
+        if (ret)
+                *ret = NULL;
+
+        return 0;
+}
+
+static int get_runpath(const char **ret) {
+        unsigned long phdr, phent, phnum;
+
+        /* Finds the rpath/runpath in the program headers of the main executable we are running in */
+
+        phdr = getauxval(AT_PHDR);      /* Start offset of phdr */
+        if (phdr == 0)
+                return -ENOTRECOVERABLE;
+
+        phnum = getauxval(AT_PHNUM);    /* Number of entries in phdr */
+        if (phnum == 0)
+                return -ENOTRECOVERABLE;
+
+        phent = getauxval(AT_PHENT);    /* Size of entries in phdr */
+        if (phent < sizeof(ElfW(Phdr))) /* Safety check, that our idea of the structure matches the file */
+                return -ENOTRECOVERABLE;
+
+        ElfW(Addr) bias = 0, dyn = 0;
+        bool found_bias = false, found_dyn = false;
+
+        /* Iterate through the Phdr structures to find the PT_PHDR and PT_DYNAMIC sections */
+        for (unsigned long i = 0; i < phnum; i++) {
+                const ElfW(Phdr) *p = (const ElfW(Phdr)*) (phdr + (i * phent));
+
+                switch (p->p_type) {
+
+                case PT_PHDR:
+                        if (p->p_vaddr > phdr) /* safety overflow check */
+                                return -ENOTRECOVERABLE;
+
+                        bias = (ElfW(Addr)) phdr - p->p_vaddr;
+                        found_bias = true;
+                        break;
+
+                case PT_DYNAMIC:
+                        dyn = p->p_vaddr;
+                        found_dyn = true;
+                        break;
+                }
+
+                if (found_bias && found_dyn)
+                        break;
+        }
+
+        if (!found_dyn)
+                return -ENOTRECOVERABLE;
+
+        return get_runpath_from_dynamic((const ElfW(Dyn)*) (bias + dyn), ret);
+}
+
+int get_build_exec_dir(char **ret) {
+        int r;
+
+        /* Returns the build execution directory if we are invoked in a build environment. Specifically, this
+         * checks if the main program binary has an rpath/runpath set (i.e. an explicit directory where to
+         * look for shared libraries) to $ORIGIN. If so we know that this is not a regular installed binary,
+         * but one which shall acquire its libraries from below a directory it is located in, i.e. a build
+         * directory or similar. In that case it typically makes sense to also search for our auxiliary
+         * executables we fork() off in a directory close to our main program binary, rather than in the
+         * system.
+         *
+         * This function is supposed to be used when looking for "callout" binaries that are closely related
+         * to the main program (i.e. speak a specific protocol between each other). And where it's generally
+         * a good idea to use the binary from the build tree (if there is one) instead of the system.
+         *
+         * Note that this does *not* actually return the rpath/runpath but the instead the directory the main
+         * executable was found in. This follows the logic that the result is supposed to be used for
+         * executable binaries (i.e. stuff in bindir), not for shared libraries (i.e. stuff in libdir), and
+         * hence the literal shared library path would just be wrong.
+         *
+         * TLDR: if we look for callouts in this dir first, running binaries from the meson build tree
+         * automatically uses the right callout.
+         *
+         * Returns:
+         *     -ENOEXEC         â†’ We are not running in an rpath/runpath $ORIGIN environment
+         *     -ENOENT          â†’ We don't know our own binary path
+         *     -NOTRECOVERABLE  â†’ Dynamic binary information missing?
+         */
+
+        static int runpath_cached = -ERRNO_MAX-1;
+        if (runpath_cached == -ERRNO_MAX-1) {
+                const char *runpath = NULL;
+
+                runpath_cached = get_runpath(&runpath);
+
+                /* We only care if the runpath starts with $ORIGIN/ */
+                if (runpath_cached > 0 && !startswith(runpath, "$ORIGIN/"))
+                        runpath_cached = 0;
+        }
+        if (runpath_cached < 0)
+                return runpath_cached;
+        if (runpath_cached == 0)
+                return -ENOEXEC;
+
+        _cleanup_free_ char *exe = NULL;
+        r = get_process_exe(0, &exe);
+        if (r < 0)
+                return runpath_cached = r;
+
+        return path_extract_directory(exe, ret);
+}
+
+static int find_build_dir_binary(const char *fn, char **ret) {
+        int r;
+
+        assert(fn);
+        assert(ret);
+
+        _cleanup_free_ char *build_dir = NULL;
+        r = get_build_exec_dir(&build_dir);
+        if (r < 0)
+                return r;
+
+        _cleanup_free_ char *np = path_join(build_dir, fn);
+        if (!np)
+                return -ENOMEM;
+
+        *ret = TAKE_PTR(np);
+        return 0;
+}
+
+static int find_environment_binary(const char *fn, const char **ret) {
+
+        /* If a path such as /usr/lib/systemd/systemd-foobar is specified, then this will check for an
+         * environment variable SYSTEMD_FOOBAR_PATH and return it if set. */
+
+        _cleanup_free_ char *s = strdup(fn);
+        if (!s)
+                return -ENOMEM;
+
+        ascii_strupper(s);
+        string_replace_char(s, '-', '_');
+
+        if (!strextend(&s, "_PATH"))
+                return -ENOMEM;
+
+        const char *e;
+        e = secure_getenv(s);
+        if (!e)
+                return -ENXIO;
+
+        *ret = e;
+        return 0;
+}
+
+int invoke_callout_binary(const char *path, char *const argv[]) {
+        int r;
+
+        assert(path);
+
+        /* Just like execv(), but tries to execute the specified binary in the build dir instead, if known */
+
+        _cleanup_free_ char *fn = NULL;
+        r = path_extract_filename(path, &fn);
+        if (r < 0)
+                return r;
+        if (r == O_DIRECTORY) /* Uh? */
+                return -EISDIR;
+
+        const char *e;
+        if (find_environment_binary(fn, &e) >= 0) {
+                /* If there's an explicit environment variable set for this binary, prefer it */
+                execv(e, argv);
+                return -errno; /* The environment variable counts, let's fail otherwise */
+        }
+
+        _cleanup_free_ char *np = NULL;
+        if (find_build_dir_binary(fn, &np) >= 0)
+                execv(np, argv);
+
+        execv(path, argv);
+        return -errno;
+}
+
+int pin_callout_binary(const char *path) {
+        int r;
+
+        assert(path);
+
+        /* Similar to invoke_callout_binary(), but pins (i.e. O_PATH opens) the binary instead of executing it. */
+
+        _cleanup_free_ char *fn = NULL;
+        r = path_extract_filename(path, &fn);
+        if (r < 0)
+                return r;
+        if (r == O_DIRECTORY) /* Uh? */
+                return -EISDIR;
+
+        const char *e;
+        if (find_environment_binary(fn, &e) >= 0)
+                return RET_NERRNO(open(e, O_CLOEXEC|O_PATH));
+
+        _cleanup_free_ char *np = NULL;
+        if (find_build_dir_binary(fn, &np) >= 0) {
+                r = RET_NERRNO(open(np, O_CLOEXEC|O_PATH));
+                if (r >= 0)
+                        return r;
+        }
+
+        return RET_NERRNO(open(path, O_CLOEXEC|O_PATH));
+}
diff --git a/src/basic/build-path.h b/src/basic/build-path.h
new file mode 100644 (file)
index 0000000..6c38a4a
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int get_build_exec_dir(char **ret);
+
+int invoke_callout_binary(const char *path, char *const argv[]);
+
+int pin_callout_binary(const char *path);
index 2cec3d82cf0b140d06e164d043e7d58c3b54cd7d..b6b0f40ca6f378c62761f1f22f652f836c2f63e8 100644 (file)
@@ -77,6 +77,7 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) {
                         [SPECIAL_GLYPH_RED_CIRCLE]              = "o",
                         [SPECIAL_GLYPH_YELLOW_CIRCLE]           = "o",
                         [SPECIAL_GLYPH_BLUE_CIRCLE]             = "o",
+                        [SPECIAL_GLYPH_GREEN_CIRCLE]            = "o",
                 },
 
                 /* UTF-8 */
@@ -143,6 +144,7 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) {
                         [SPECIAL_GLYPH_RED_CIRCLE]              = u8"🔴",
                         [SPECIAL_GLYPH_YELLOW_CIRCLE]           = u8"🟡",
                         [SPECIAL_GLYPH_BLUE_CIRCLE]             = u8"🔵",
+                        [SPECIAL_GLYPH_GREEN_CIRCLE]            = u8"🟢",
                 },
         };
 
index e476fefe943c5bbf1c575da25d6fa0b46785a209..2f70b187fcd7062eacf1f329604c84e6381c18f6 100644 (file)
@@ -52,6 +52,7 @@ typedef enum SpecialGlyph {
         SPECIAL_GLYPH_RED_CIRCLE,
         SPECIAL_GLYPH_YELLOW_CIRCLE,
         SPECIAL_GLYPH_BLUE_CIRCLE,
+        SPECIAL_GLYPH_GREEN_CIRCLE,
         _SPECIAL_GLYPH_MAX,
         _SPECIAL_GLYPH_INVALID = -EINVAL,
 } SpecialGlyph;
index 8bd9c75d59605be3389a44866d5f85a178d8fbd8..82c8ff9a2d4cae0942defcd77ff469bddf8e789f 100644 (file)
@@ -91,14 +91,26 @@ bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a) {
                 be32toh(a->s6_addr32[3]) == UINT32_C(0x00000001);
 }
 
+bool in4_addr_is_multicast(const struct in_addr *a) {
+        assert(a);
+
+        return IN_MULTICAST(be32toh(a->s_addr));
+}
+
+bool in6_addr_is_multicast(const struct in6_addr *a) {
+        assert(a);
+
+        return IN6_IS_ADDR_MULTICAST(a);
+}
+
 int in_addr_is_multicast(int family, const union in_addr_union *u) {
         assert(u);
 
         if (family == AF_INET)
-                return IN_MULTICAST(be32toh(u->in.s_addr));
+                return in4_addr_is_multicast(&u->in);
 
         if (family == AF_INET6)
-                return IN6_IS_ADDR_MULTICAST(&u->in6);
+                return in6_addr_is_multicast(&u->in6);
 
         return -EAFNOSUPPORT;
 }
index 9fae3cae453ffb0bd6e0a92b3cadc59c257e5ca5..5c820c6ec6ac23aa0aba0ce2a80ee2b86b615af9 100644 (file)
@@ -40,6 +40,8 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) {
         return in_addr_data_is_null(a);
 }
 
+bool in4_addr_is_multicast(const struct in_addr *a);
+bool in6_addr_is_multicast(const struct in6_addr *a);
 int in_addr_is_multicast(int family, const union in_addr_union *u);
 
 bool in4_addr_is_link_local(const struct in_addr *a);
index 6b30908ce187d7e161434560010640f277c76c29..a9722d2121cc30fcb3795d5fdeae6ab0703c59fd 100644 (file)
@@ -10,6 +10,7 @@ basic_sources = files(
         'audit-util.c',
         'btrfs.c',
         'build.c',
+        'build-path.c',
         'bus-label.c',
         'cap-list.c',
         'capability-util.c',
index fb8f4ef06ea3f545d48decde2be7765ce64aee34..69635e65f81f9bb727e8de0f254441141c889a43 100644 (file)
@@ -510,7 +510,7 @@ static int get_process_link_contents(pid_t pid, const char *proc_file, char **re
         p = procfs_file_alloca(pid, proc_file);
 
         r = readlink_malloc(p, ret);
-        return r == -ENOENT ? -ESRCH : r;
+        return (r == -ENOENT && proc_mounted() > 0) ? -ESRCH : r;
 }
 
 int get_process_exe(pid_t pid, char **ret) {
index f8f4e509ad2855da83aa0565c0181963a5da44b5..661ad00b110cf08d2723b03f8c99d78caf5b694f 100644 (file)
@@ -18,7 +18,7 @@ int reset_all_signal_handlers(void) {
                 .sa_handler = SIG_DFL,
                 .sa_flags = SA_RESTART,
         };
-        int r = 0;
+        int ret = 0, r;
 
         for (int sig = 1; sig < _NSIG; sig++) {
 
@@ -26,14 +26,14 @@ int reset_all_signal_handlers(void) {
                 if (IN_SET(sig, SIGKILL, SIGSTOP))
                         continue;
 
-                /* On Linux the first two RT signals are reserved by
-                 * glibc, and sigaction() will return EINVAL for them. */
-                if (sigaction(sig, &sa, NULL) < 0)
-                        if (errno != EINVAL && r >= 0)
-                                r = -errno;
+                /* On Linux the first two RT signals are reserved by glibc, and sigaction() will return
+                 * EINVAL for them. */
+                r = RET_NERRNO(sigaction(sig, &sa, NULL));
+                if (r != -EINVAL)
+                        RET_GATHER(ret, r);
         }
 
-        return r;
+        return ret;
 }
 
 int reset_signal_mask(void) {
@@ -57,10 +57,7 @@ int sigaction_many_internal(const struct sigaction *sa, ...) {
                 if (sig == 0)
                         continue;
 
-                if (sigaction(sig, sa, NULL) < 0) {
-                        if (r >= 0)
-                                r = -errno;
-                }
+                RET_GATHER(r, RET_NERRNO(sigaction(sig, sa, NULL)));
         }
 
         va_end(ap);
@@ -87,7 +84,7 @@ static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
         return r;
 }
 
-int sigset_add_many(sigset_t *ss, ...) {
+int sigset_add_many_internal(sigset_t *ss, ...) {
         va_list ap;
         int r;
 
@@ -98,7 +95,7 @@ int sigset_add_many(sigset_t *ss, ...) {
         return r;
 }
 
-int sigprocmask_many(int how, sigset_t *old, ...) {
+int sigprocmask_many_internal(int how, sigset_t *old, ...) {
         va_list ap;
         sigset_t ss;
         int r;
@@ -113,10 +110,7 @@ int sigprocmask_many(int how, sigset_t *old, ...) {
         if (r < 0)
                 return r;
 
-        if (sigprocmask(how, &ss, old) < 0)
-                return -errno;
-
-        return 0;
+        return RET_NERRNO(sigprocmask(how, &ss, old));
 }
 
 static const char *const static_signal_table[] = {
index ad2ba841c6eccfffeb38ef2e50a650dc0c00648e..8826fbeb7b700e02f67dc8d09c18e19521bba7e8 100644 (file)
@@ -31,8 +31,11 @@ int sigaction_many_internal(const struct sigaction *sa, ...);
 #define sigaction_many(sa, ...)                                         \
         sigaction_many_internal(sa, __VA_ARGS__, -1)
 
-int sigset_add_many(sigset_t *ss, ...);
-int sigprocmask_many(int how, sigset_t *old, ...);
+int sigset_add_many_internal(sigset_t *ss, ...);
+#define sigset_add_many(...) sigset_add_many_internal(__VA_ARGS__, -1)
+
+int sigprocmask_many_internal(int how, sigset_t *old, ...);
+#define sigprocmask_many(...) sigprocmask_many_internal(__VA_ARGS__, -1)
 
 const char *signal_to_string(int i) _const_;
 int signal_from_string(const char *s) _pure_;
@@ -46,7 +49,7 @@ static inline void block_signals_reset(sigset_t *ss) {
 #define BLOCK_SIGNALS(...)                                                         \
         _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({        \
                 sigset_t _t;                                                       \
-                assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__, -1) >= 0); \
+                assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__) >= 0);     \
                 _t;                                                                \
         })
 
index 375ef28216dc75d7f09024078654dde7094bf250..98ef0ab3323aae2ea4b41ab57bdf0d0e089c19ce 100644 (file)
@@ -98,7 +98,7 @@ static Virtualization detect_vm_cpuid(void) {
 }
 
 static Virtualization detect_vm_device_tree(void) {
-#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
+#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__riscv)
         _cleanup_free_ char *hvtype = NULL;
         int r;
 
@@ -155,7 +155,7 @@ static Virtualization detect_vm_device_tree(void) {
 #endif
 }
 
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64) || defined(__riscv)
 static Virtualization detect_vm_dmi_vendor(void) {
         static const char* const dmi_vendors[] = {
                 "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
index 7e440b714e56ad218bf8294728ee8deea3ce43ca..2591c52f2200ee11df5692188abdcca8d2b99cd3 100644 (file)
 #include "tpm2-pcr.h"
 #include "util.h"
 
-static EFI_STATUS tpm1_measure_to_pcr_and_event_log(
-                const EFI_TCG_PROTOCOL *tcg,
-                uint32_t pcrindex,
-                EFI_PHYSICAL_ADDRESS buffer,
-                size_t buffer_size,
-                const char16_t *description) {
-
-        _cleanup_free_ TCG_PCR_EVENT *tcg_event = NULL;
-        EFI_PHYSICAL_ADDRESS event_log_last;
-        uint32_t event_number = 1;
-        size_t desc_len;
-
-        assert(tcg);
-        assert(description);
-
-        desc_len = strsize16(description);
-        tcg_event = xmalloc(offsetof(TCG_PCR_EVENT, Event) + desc_len);
-        *tcg_event = (TCG_PCR_EVENT) {
-                .EventSize = desc_len,
-                .PCRIndex = pcrindex,
-                .EventType = EV_IPL,
-        };
-        memcpy(tcg_event->Event, description, desc_len);
-
-        return tcg->HashLogExtendEvent(
-                        (EFI_TCG_PROTOCOL *) tcg,
-                        buffer, buffer_size,
-                        TCG_ALG_SHA,
-                        tcg_event,
-                        &event_number,
-                        &event_log_last);
-}
-
 static EFI_STATUS tpm2_measure_to_pcr_and_tagged_event_log(
                 EFI_TCG2_PROTOCOL *tcg,
                 uint32_t pcrindex,
@@ -187,37 +154,6 @@ static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) {
         return cc;
 }
 
-static EFI_TCG_PROTOCOL *tcg1_interface_check(void) {
-        EFI_PHYSICAL_ADDRESS event_log_location, event_log_last_entry;
-        EFI_TCG_BOOT_SERVICE_CAPABILITY capability = {
-                .Size = sizeof(capability),
-        };
-        EFI_STATUS err;
-        uint32_t features;
-        EFI_TCG_PROTOCOL *tcg;
-
-        err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG_PROTOCOL), NULL, (void **) &tcg);
-        if (err != EFI_SUCCESS)
-                return NULL;
-
-        err = tcg->StatusCheck(
-                        tcg,
-                        &capability,
-                        &features,
-                        &event_log_location,
-                        &event_log_last_entry);
-        if (err != EFI_SUCCESS)
-                return NULL;
-
-        if (capability.TPMDeactivatedFlag)
-                return NULL;
-
-        if (!capability.TPMPresentFlag)
-                return NULL;
-
-        return tcg;
-}
-
 static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
         EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
                 .Size = sizeof(capability),
@@ -248,7 +184,7 @@ static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
 }
 
 bool tpm_present(void) {
-        return tcg2_interface_check() || tcg1_interface_check();
+        return tcg2_interface_check();
 }
 
 EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
@@ -271,25 +207,18 @@ EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t
         if (tpm2)
                 err = tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
         else {
-                EFI_TCG_PROTOCOL *tpm1;
+                EFI_CC_MEASUREMENT_PROTOCOL *cc;
 
-                tpm1 = tcg1_interface_check();
-                if (tpm1)
-                        err = tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description);
+                cc = cc_interface_check();
+                if (cc)
+                        err = cc_measure_to_mr_and_event_log(cc, pcrindex, buffer, buffer_size, description);
                 else {
-                        EFI_CC_MEASUREMENT_PROTOCOL *cc;
-
-                        cc = cc_interface_check();
-                        if (cc)
-                                err = cc_measure_to_mr_and_event_log(cc, pcrindex, buffer, buffer_size, description);
-                        else {
-                                /* No active TPM found, so don't return an error */
+                        /* No active TPM found, so don't return an error */
 
-                                if (ret_measured)
-                                        *ret_measured = false;
+                        if (ret_measured)
+                                *ret_measured = false;
 
-                                return EFI_SUCCESS;
-                        }
+                        return EFI_SUCCESS;
                 }
         }
 
index 2e22bdf57fe3068fe824e95792e1ce1c18b8965e..b5d4e9630320cfbbf8c2028bf4d52ea388bcb585 100644 (file)
@@ -68,6 +68,7 @@ if meson.is_cross_build() and get_option('sbat-distro') == 'auto'
 elif get_option('sbat-distro') != ''
         efi_conf.set_quoted('SBAT_PROJECT', meson.project_name())
         efi_conf.set_quoted('PROJECT_VERSION', meson.project_version().split('~')[0])
+        efi_conf.set_quoted('VERSION_TAG', version_tag)
         efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL'))
         if get_option('sbat-distro-generation') < 1
                 error('SBAT Distro Generation must be a positive integer')
index b4b82962ef6b43f9528a0c90b2eb0b57f8398d4f..e243bf8b72b7ed505055dfc4d0d90674a1fbd907 100644 (file)
@@ -3,12 +3,9 @@
 
 #include "efi.h"
 
-#define EFI_TCG_PROTOCOL_GUID \
-        GUID_DEF(0xf541796d, 0xa62e, 0x4954, 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd)
 #define EFI_TCG2_PROTOCOL_GUID \
         GUID_DEF(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
 
-#define TCG_ALG_SHA 0x4
 #define EFI_TCG2_EVENT_HEADER_VERSION 1
 #define EV_IPL 13
 #define EV_EVENT_TAG UINT32_C(6)
@@ -48,16 +45,6 @@ typedef struct {
         uint32_t ActivePcrBanks;
 } EFI_TCG2_BOOT_SERVICE_CAPABILITY;
 
-typedef struct {
-        uint32_t PCRIndex;
-        uint32_t EventType;
-        struct {
-                uint8_t Digest[20];
-        } Digest;
-        uint32_t EventSize;
-        uint8_t Event[];
-} _packed_ TCG_PCR_EVENT;
-
 typedef struct {
         uint32_t HeaderSize;
         uint16_t HeaderVersion;
@@ -77,27 +64,6 @@ typedef struct {
         uint8_t Event[];
 } _packed_ EFI_TCG2_TAGGED_EVENT;
 
-typedef struct EFI_TCG_PROTOCOL EFI_TCG_PROTOCOL;
-struct EFI_TCG_PROTOCOL {
-        EFI_STATUS (EFIAPI *StatusCheck)(
-                        EFI_TCG_PROTOCOL *This,
-                        EFI_TCG_BOOT_SERVICE_CAPABILITY *ProtocolCapability,
-                        uint32_t *TCGFeatureFlags,
-                        EFI_PHYSICAL_ADDRESS *EventLogLocation,
-                        EFI_PHYSICAL_ADDRESS *EventLogLastEntry);
-        void *HashAll;
-        void *LogEvent;
-        void *PassThroughToTpm;
-        EFI_STATUS (EFIAPI *HashLogExtendEvent)(
-                        EFI_TCG_PROTOCOL *This,
-                        EFI_PHYSICAL_ADDRESS HashData,
-                        uint64_t HashDataLen,
-                        uint32_t AlgorithmId,
-                        TCG_PCR_EVENT *TCGLogData,
-                        uint32_t *EventNumber,
-                        EFI_PHYSICAL_ADDRESS *EventLogLastEntry);
-};
-
 typedef struct EFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
 struct EFI_TCG2_PROTOCOL {
         EFI_STATUS (EFIAPI *GetCapability)(
index 9cedc15d6a780a75b42c174c54251437c106f896..b5c8c6306e2d5e82a12e6caad34f03a108d808cb 100644 (file)
@@ -697,3 +697,9 @@ char16_t *get_extra_dir(const EFI_DEVICE_PATH *file_path) {
         remove_boot_count(file_path_str);
         return xasprintf("%ls.extra.d", file_path_str);
 }
+
+void *xmalloc(size_t size) {
+        void *p = NULL;
+        assert_se(BS->AllocatePool(EfiLoaderData, size, &p) == EFI_SUCCESS);
+        return p;
+}
index f01cb30b8e875529f0ffbe114c17f8a563ac041d..44614593ee9530c93d0f6f47a293fb8872df65e1 100644 (file)
@@ -29,11 +29,7 @@ static inline void freep(void *p) {
 #define _cleanup_free_ _cleanup_(freep)
 
 _malloc_ _alloc_(1) _returns_nonnull_ _warn_unused_result_
-static inline void *xmalloc(size_t size) {
-        void *p;
-        assert_se(BS->AllocatePool(EfiLoaderData, size, &p) == EFI_SUCCESS);
-        return p;
-}
+void *xmalloc(size_t size);
 
 _malloc_ _alloc_(1, 2) _returns_nonnull_ _warn_unused_result_
 static inline void *xmalloc_multiply(size_t n, size_t size) {
index 1bd21a2bdfeb6b5e7b69e0a5e2b4f18f3227e75a..b1298670c7e44c5194e29387e3cd392592cc1005 100644 (file)
@@ -1170,7 +1170,7 @@ static int setup_pam(
 
         /* Block SIGTERM, so that we know that it won't get lost in the child */
 
-        assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM) >= 0);
 
         parent_pid = getpid_cached();
 
index e8c747d96d9e5fe89ddf9b70d733ac5dd6b603b5..7a7669f315f6fed37a3ae2b268a0ab1e1845e590 100644 (file)
@@ -25,6 +25,7 @@
 #include "alloc-util.h"
 #include "audit-fd.h"
 #include "boot-timestamps.h"
+#include "build-path.h"
 #include "bus-common-errors.h"
 #include "bus-error.h"
 #include "bus-kernel.h"
@@ -1024,42 +1025,19 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags,
 
                 if (r < 0 && r != -EEXIST)
                         return r;
+        }
 
-                m->executor_fd = open(SYSTEMD_EXECUTOR_BINARY_PATH, O_CLOEXEC|O_PATH);
-                if (m->executor_fd < 0)
-                        return log_emergency_errno(errno,
-                                                   "Failed to open executor binary '%s': %m",
-                                                   SYSTEMD_EXECUTOR_BINARY_PATH);
-        } else if (!FLAGS_SET(test_run_flags, MANAGER_TEST_DONT_OPEN_EXECUTOR)) {
-                _cleanup_free_ char *self_exe = NULL, *executor_path = NULL;
-                _cleanup_close_ int self_dir_fd = -EBADF;
-                int level = LOG_DEBUG;
-
-                /* Prefer sd-executor from the same directory as the test, e.g.: when running unit tests from the
-                * build directory. Fallback to working directory and then the installation path. */
-                r = readlink_and_make_absolute("/proc/self/exe", &self_exe);
-                if (r < 0)
-                        return r;
-
-                self_dir_fd = open_parent(self_exe, O_CLOEXEC|O_PATH|O_DIRECTORY, 0);
-                if (self_dir_fd < 0)
-                        return self_dir_fd;
-
-                m->executor_fd = RET_NERRNO(openat(self_dir_fd, "systemd-executor", O_CLOEXEC|O_PATH));
-                if (m->executor_fd == -ENOENT)
-                        m->executor_fd = RET_NERRNO(openat(AT_FDCWD, "systemd-executor", O_CLOEXEC|O_PATH));
-                if (m->executor_fd == -ENOENT) {
-                        m->executor_fd = RET_NERRNO(open(SYSTEMD_EXECUTOR_BINARY_PATH, O_CLOEXEC|O_PATH));
-                        level = LOG_WARNING; /* Tests should normally use local builds */
-                }
+        if (!FLAGS_SET(test_run_flags, MANAGER_TEST_DONT_OPEN_EXECUTOR)) {
+                m->executor_fd = pin_callout_binary(SYSTEMD_EXECUTOR_BINARY_PATH);
                 if (m->executor_fd < 0)
-                        return m->executor_fd;
+                        return log_debug_errno(m->executor_fd, "Failed to pin executor binary: %m");
 
+                _cleanup_free_ char *executor_path = NULL;
                 r = fd_get_path(m->executor_fd, &executor_path);
                 if (r < 0)
                         return r;
 
-                log_full(level, "Using systemd-executor binary from '%s'.", executor_path);
+                log_debug("Using systemd-executor binary from '%s'.", executor_path);
         }
 
         /* Note that we do not set up the notify fd here. We do that after deserialization,
index a487eb1fd1ab7806127e5cc7e49eef96383c2f9c..f3c72926d796715280594cf6a7873d4aa3a477f3 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "blockdev-util.h"
 #include "btrfs-util.h"
+#include "build-path.h"
 #include "bus-common-errors.h"
 #include "bus-locator.h"
 #include "data-fd-util.h"
@@ -1276,7 +1277,7 @@ static int home_start_work(
                 return r;
         if (r == 0) {
                 _cleanup_free_ char *joined = NULL;
-                const char *homework, *suffix, *unix_path;
+                const char *suffix, *unix_path;
 
                 /* Child */
 
@@ -1320,12 +1321,8 @@ static int home_start_work(
                 if (r < 0)
                         log_warning_errno(r, "Failed to update $SYSTEMD_LOG_LEVEL, ignoring: %m");
 
-                /* Allow overriding the homework path via an environment variable, to make debugging
-                 * easier. */
-                homework = getenv("SYSTEMD_HOMEWORK_PATH") ?: SYSTEMD_HOMEWORK_PATH;
-
-                execl(homework, homework, verb, NULL);
-                log_error_errno(errno, "Failed to invoke %s: %m", homework);
+                r = invoke_callout_binary(SYSTEMD_HOMEWORK_PATH, STRV_MAKE(SYSTEMD_HOMEWORK_PATH, verb));
+                log_error_errno(r, "Failed to invoke %s: %m", SYSTEMD_HOMEWORK_PATH);
                 _exit(EXIT_FAILURE);
         }
 
index 04d9b56f076aa9dcc83019f75ae24586eaa14f9e..cfb498e47f919a28a5f43bcefb4d58b6e070697d 100644 (file)
@@ -29,7 +29,7 @@ static int run(int argc, char *argv[]) {
 
         umask(0022);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index 7e941a29afd61081d29db438f4b4449c84d7db2b..cd67349a4e70dd35f9bf23e55c661933a03dcd3e 100644 (file)
@@ -105,7 +105,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate event loop: %m");
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
 
@@ -181,7 +181,7 @@ static int export_raw(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate event loop: %m");
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
 
index 319aa078a75ffc1f5fa4190a9b504a85473a8f09..4a8a9a9c208d437caadda38923934c95c340fe02 100644 (file)
@@ -295,7 +295,7 @@ int import_allocate_event_with_signals(sd_event **ret) {
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate event loop: %m");
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
         (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler,  NULL);
         (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
 
index 3321155e84fa19427b07f708f58e6ff531bb5c15..24b8e9f92e4b05b651640b7342aabc76f2ef09ad 100644 (file)
@@ -6,6 +6,7 @@
 #include "sd-bus.h"
 
 #include "alloc-util.h"
+#include "build-path.h"
 #include "bus-common-errors.h"
 #include "bus-get-properties.h"
 #include "bus-log-control-api.h"
@@ -475,8 +476,10 @@ static int transfer_start(Transfer *t) {
                         cmd[k++] = t->local;
                 cmd[k] = NULL;
 
-                execv(cmd[0], (char * const *) cmd);
-                log_error_errno(errno, "Failed to execute %s tool: %m", cmd[0]);
+                assert(k < ELEMENTSOF(cmd));
+
+                r = invoke_callout_binary(cmd[0], (char * const *) cmd);
+                log_error_errno(r, "Failed to execute %s tool: %m", cmd[0]);
                 _exit(EXIT_FAILURE);
         }
 
@@ -1371,7 +1374,7 @@ static int run(int argc, char *argv[]) {
 
         umask(0022);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index 6c09c068c8088e91b5a5a8cf838138d9df64370f..7431403e4b4247f7f63544c8e1892354607b4c35 100644 (file)
@@ -540,7 +540,7 @@ static int setup_signals(RemoteServer *s) {
 
         assert(s);
 
-        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM) >= 0);
 
         r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
         if (r < 0)
index 97b5f929abd2388b6b9a81b962b31eea256806ae..50fa31a1330ad11b5fd927b5b5662704c064dae1 100644 (file)
@@ -397,7 +397,7 @@ static int setup_signals(Uploader *u) {
 
         assert(u);
 
-        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM) >= 0);
 
         r = sd_event_add_signal(u->events, &u->sigterm_event, SIGTERM, dispatch_sigterm, u);
         if (r < 0)
index 2c6f6e301df68166e9c4dc9ea7edc9eaf8ff129a..9e1ca08d23dc0c1806d5d1f73ac273ad791b0557 100644 (file)
@@ -1727,7 +1727,7 @@ static int server_setup_signals(Server *s) {
 
         assert(s);
 
-        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+18) >= 0);
 
         r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s);
         if (r < 0)
index 01edb854df3fb1a6d3aa4526c84882433adb0f77..5eac4a0e5357ef27a88b030067998ac613acb6b0 100644 (file)
@@ -16,15 +16,11 @@ static struct in6_addr dummy_link_local = {
         },
 };
 
-int icmp6_bind_router_solicitation(int ifindex) {
-        if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
+int icmp6_bind(int ifindex, bool is_router) {
+        if (!is_router && socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
                 return -errno;
 
-        return test_fd[0];
-}
-
-int icmp6_bind_router_advertisement(int ifindex) {
-        return test_fd[1];
+        return test_fd[is_router];
 }
 
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
index 72c20baadc8968061f5a43b03e9d7cc8b0ae0b5d..559167847f0980e34833c06786e6290bf370b0da 100644 (file)
 #include "network-common.h"
 #include "socket-util.h"
 
-#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
-        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
-
-#define IN6ADDR_ALL_NODES_MULTICAST_INIT \
-        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
-
-static int icmp6_bind_router_message(const struct icmp6_filter *filter,
-                                     const struct ipv6_mreq *mreq) {
-        int ifindex = mreq->ipv6mr_interface;
+int icmp6_bind(int ifindex, bool is_router) {
+        struct icmp6_filter filter = {};
+        struct ipv6_mreq mreq;
         _cleanup_close_ int s = -EBADF;
         int r;
 
-        assert(filter);
-        assert(mreq);
+        assert(ifindex > 0);
+
+        ICMP6_FILTER_SETBLOCKALL(&filter);
+        if (is_router) {
+                mreq = (struct ipv6_mreq) {
+                        .ipv6mr_multiaddr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
+                        .ipv6mr_interface = ifindex,
+                };
+                ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
+        } else {
+                mreq = (struct ipv6_mreq) {
+                        .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
+                        .ipv6mr_interface = ifindex,
+                };
+                ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
+        }
 
         s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
         if (s < 0)
                 return -errno;
 
-        if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, filter, sizeof(*filter)) < 0)
+        if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0)
                 return -errno;
 
-        if (setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq, sizeof(*mreq)) < 0)
+        if (setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
                 return -errno;
 
-        /* RFC 3315, section 6.7, bullet point 2 may indicate that an
-           IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
-           Empirical experiments indicates otherwise and therefore an
-           IPV6_MULTICAST_IF socket option is used here instead */
+        /* RFC 3315, section 6.7, bullet point 2 may indicate that an IPV6_PKTINFO socket option also applies
+         * for ICMPv6 multicast. Empirical experiments indicates otherwise and therefore an IPV6_MULTICAST_IF
+         * socket option is used here instead. */
         r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, ifindex);
         if (r < 0)
                 return r;
@@ -83,32 +88,6 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
         return TAKE_FD(s);
 }
 
-int icmp6_bind_router_solicitation(int ifindex) {
-        struct icmp6_filter filter = {};
-        struct ipv6_mreq mreq = {
-                .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
-                .ipv6mr_interface = ifindex,
-        };
-
-        ICMP6_FILTER_SETBLOCKALL(&filter);
-        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
-
-        return icmp6_bind_router_message(&filter, &mreq);
-}
-
-int icmp6_bind_router_advertisement(int ifindex) {
-        struct icmp6_filter filter = {};
-        struct ipv6_mreq mreq = {
-                .ipv6mr_multiaddr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
-                .ipv6mr_interface = ifindex,
-        };
-
-        ICMP6_FILTER_SETBLOCKALL(&filter);
-        ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
-
-        return icmp6_bind_router_message(&filter, &mreq);
-}
-
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
         struct sockaddr_in6 dst = {
                 .sin6_family = AF_INET6,
@@ -165,7 +144,6 @@ int icmp6_receive(
                 .msg_control = &control,
                 .msg_controllen = sizeof(control),
         };
-        struct in6_addr addr = {};
         ssize_t len;
 
         iov = IOVEC_MAKE(buffer, size);
@@ -177,17 +155,11 @@ int icmp6_receive(
         if ((size_t) len != size)
                 return -EINVAL;
 
-        if (msg.msg_namelen == sizeof(struct sockaddr_in6) &&
-            sa.in6.sin6_family == AF_INET6)  {
-
-                addr = sa.in6.sin6_addr;
-                if (!in6_addr_is_link_local(&addr) && !in6_addr_is_null(&addr))
-                        return -EADDRNOTAVAIL;
-
-        } else if (msg.msg_namelen > 0)
+        if (msg.msg_namelen != sizeof(struct sockaddr_in6) || sa.in6.sin6_family != AF_INET6)
                 return -EPFNOSUPPORT;
 
-        /* namelen == 0 only happens when running the test-suite over a socketpair */
+        if (!in6_addr_is_link_local(&sa.in6.sin6_addr) && !in6_addr_is_null(&sa.in6.sin6_addr))
+                return -EADDRNOTAVAIL;
 
         assert(!(msg.msg_flags & MSG_TRUNC));
 
@@ -198,6 +170,6 @@ int icmp6_receive(
         if (ret_timestamp)
                 triple_timestamp_from_cmsg(ret_timestamp, &msg);
         if (ret_sender)
-                *ret_sender = addr;
+                *ret_sender = sa.in6.sin6_addr;
         return 0;
 }
index 0a9ecb4c44d72cdc7c1481a5646a7a4a00e58bef..72db688b0b9e8c6ab21f905a4ecb973d9d615048 100644 (file)
@@ -6,6 +6,7 @@
 ***/
 
 #include <net/ethernet.h>
+#include <stdbool.h>
 
 #include "time-util.h"
 
@@ -17,8 +18,7 @@
         { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
 
-int icmp6_bind_router_solicitation(int ifindex);
-int icmp6_bind_router_advertisement(int ifindex);
+int icmp6_bind(int ifindex, bool is_router);
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr);
 int icmp6_receive(
                 int fd,
index 0b5626670b92237b3a1ea957c69e512514c5c3cf..1ebae2c2f3ed49b019fc491afc96d2d5d5b6f4fb 100644 (file)
@@ -31,7 +31,7 @@ static const char * const ndisc_event_table[_SD_NDISC_EVENT_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(ndisc_event, sd_ndisc_event_t);
 
-static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event_t event, sd_ndisc_router *rt) {
+static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event_t event, void *message) {
         assert(ndisc);
         assert(event >= 0 && event < _SD_NDISC_EVENT_MAX);
 
@@ -39,7 +39,7 @@ static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event_t event, sd_ndisc_rou
                 return (void) log_ndisc(ndisc, "Received '%s' event.", ndisc_event_to_string(event));
 
         log_ndisc(ndisc, "Invoking callback for '%s' event.", ndisc_event_to_string(event));
-        ndisc->callback(ndisc, event, rt, ndisc->userdata);
+        ndisc->callback(ndisc, event, message, ndisc->userdata);
 }
 
 int sd_ndisc_is_running(sd_ndisc *nd) {
@@ -196,6 +196,8 @@ static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) {
         if (r < 0)
                 return r;
 
+        (void) event_source_disable(nd->timeout_event_source);
+
         log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %s",
                   rt->flags & ND_RA_FLAG_MANAGED ? "MANAGED" : rt->flags & ND_RA_FLAG_OTHER ? "OTHER" : "none",
                   rt->preference == SD_NDISC_PREFERENCE_HIGH ? "high" : rt->preference == SD_NDISC_PREFERENCE_LOW ? "low" : "medium",
@@ -232,28 +234,29 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
         if (r < 0)
                 switch (r) {
                 case -EADDRNOTAVAIL:
-                        log_ndisc(nd, "Received RA from neither link-local nor null address. Ignoring.");
+                        log_ndisc(nd, "Received an ICMPv6 packet from neither link-local nor null address, ignoring.");
                         return 0;
 
                 case -EMULTIHOP:
-                        log_ndisc(nd, "Received RA with invalid hop limit. Ignoring.");
+                        log_ndisc(nd, "Received an ICMPv6 packet with an invalid hop limit, ignoring.");
                         return 0;
 
                 case -EPFNOSUPPORT:
-                        log_ndisc(nd, "Received invalid source address from ICMPv6 socket. Ignoring.");
+                        log_ndisc(nd, "Received an ICMPv6 packet with an invalid source address, ignoring.");
                         return 0;
 
                 default:
-                        log_ndisc_errno(nd, r, "Unexpected error while reading from ICMPv6, ignoring: %m");
+                        log_ndisc_errno(nd, r, "Unexpected error while receiving an ICMPv6 packet, ignoring: %m");
                         return 0;
                 }
 
         /* The function icmp6_receive() accepts the null source address, but RFC 4861 Section 6.1.2 states
          * that hosts MUST discard messages with the null source address. */
-        if (in6_addr_is_null(&rt->address))
-                log_ndisc(nd, "Received RA from null address. Ignoring.");
+        if (in6_addr_is_null(&rt->address)) {
+                log_ndisc(nd, "Received an ICMPv6 packet from null address, ignoring.");
+                return 0;
+        }
 
-        (void) event_source_disable(nd->timeout_event_source);
         (void) ndisc_handle_datagram(nd, rt);
         return 0;
 }
@@ -332,50 +335,74 @@ int sd_ndisc_stop(sd_ndisc *nd) {
         return 1;
 }
 
-int sd_ndisc_start(sd_ndisc *nd) {
+static int ndisc_setup_recv_event(sd_ndisc *nd) {
         int r;
-        usec_t time_now;
 
-        assert_return(nd, -EINVAL);
-        assert_return(nd->event, -EINVAL);
-        assert_return(nd->ifindex > 0, -EINVAL);
+        assert(nd);
+        assert(nd->event);
+        assert(nd->ifindex > 0);
 
-        if (sd_ndisc_is_running(nd))
-                return 0;
+        _cleanup_close_ int fd = -EBADF;
+        fd = icmp6_bind(nd->ifindex, /* is_router = */ false);
+        if (fd < 0)
+                return fd;
 
-        assert(!nd->recv_event_source);
+        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+        r = sd_event_add_io(nd->event, &s, fd, EPOLLIN, ndisc_recv, nd);
+        if (r < 0)
+                return r;
 
-        r = sd_event_now(nd->event, CLOCK_BOOTTIME, &time_now);
+        r = sd_event_source_set_priority(s, nd->event_priority);
         if (r < 0)
-                goto fail;
+                return r;
 
-        nd->fd = icmp6_bind_router_solicitation(nd->ifindex);
-        if (nd->fd < 0)
-                return nd->fd;
+        (void) sd_event_source_set_description(s, "ndisc-receive-router-message");
 
-        r = sd_event_add_io(nd->event, &nd->recv_event_source, nd->fd, EPOLLIN, ndisc_recv, nd);
+        nd->fd = TAKE_FD(fd);
+        nd->recv_event_source = TAKE_PTR(s);
+        return 1;
+}
+
+static int ndisc_setup_timer(sd_ndisc *nd) {
+        int r;
+
+        assert(nd);
+        assert(nd->event);
+
+        r = event_reset_time_relative(nd->event, &nd->timeout_event_source,
+                                      CLOCK_BOOTTIME,
+                                      USEC_PER_SEC / 2, 1 * USEC_PER_SEC, /* See RFC 8415 sec. 18.2.1 */
+                                      ndisc_timeout, nd,
+                                      nd->event_priority, "ndisc-timeout", true);
         if (r < 0)
-                goto fail;
+                return r;
 
-        r = sd_event_source_set_priority(nd->recv_event_source, nd->event_priority);
+        r = event_reset_time_relative(nd->event, &nd->timeout_no_ra,
+                                      CLOCK_BOOTTIME,
+                                      NDISC_TIMEOUT_NO_RA_USEC, 10 * USEC_PER_MSEC,
+                                      ndisc_timeout_no_ra, nd,
+                                      nd->event_priority, "ndisc-timeout-no-ra", true);
         if (r < 0)
-                goto fail;
+                return r;
 
-        (void) sd_event_source_set_description(nd->recv_event_source, "ndisc-receive-message");
+        return 0;
+}
 
-        r = event_reset_time(nd->event, &nd->timeout_event_source,
-                             CLOCK_BOOTTIME,
-                             time_now + USEC_PER_SEC / 2, 1 * USEC_PER_SEC, /* See RFC 8415 sec. 18.2.1 */
-                             ndisc_timeout, nd,
-                             nd->event_priority, "ndisc-timeout", true);
+int sd_ndisc_start(sd_ndisc *nd) {
+        int r;
+
+        assert_return(nd, -EINVAL);
+        assert_return(nd->event, -EINVAL);
+        assert_return(nd->ifindex > 0, -EINVAL);
+
+        if (sd_ndisc_is_running(nd))
+                return 0;
+
+        r = ndisc_setup_recv_event(nd);
         if (r < 0)
                 goto fail;
 
-        r = event_reset_time(nd->event, &nd->timeout_no_ra,
-                             CLOCK_BOOTTIME,
-                             time_now + NDISC_TIMEOUT_NO_RA_USEC, 10 * USEC_PER_MSEC,
-                             ndisc_timeout_no_ra, nd,
-                             nd->event_priority, "ndisc-timeout-no-ra", true);
+        r = ndisc_setup_timer(nd);
         if (r < 0)
                 goto fail;
 
index 97d306c49b2b067039bf77996acf6e8edca57261..71e7a71897024b6abc63588133c7ba7b4c1769b2 100644 (file)
@@ -121,30 +121,39 @@ static sd_radv *radv_free(sd_radv *ra) {
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free);
 
 static bool router_lifetime_is_valid(usec_t lifetime_usec) {
+        assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC <= UINT16_MAX * USEC_PER_SEC);
         return lifetime_usec == 0 ||
                 (lifetime_usec >= RADV_MIN_ROUTER_LIFETIME_USEC &&
                  lifetime_usec <= RADV_MAX_ROUTER_LIFETIME_USEC);
 }
 
-static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) {
+static int radv_send_router(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) {
+        assert(ra);
+        assert(router_lifetime_is_valid(lifetime_usec));
+
         struct sockaddr_in6 dst_addr = {
                 .sin6_family = AF_INET6,
                 .sin6_addr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
         };
-        struct nd_router_advert adv = {};
+        struct nd_router_advert adv = {
+                .nd_ra_type = ND_ROUTER_ADVERT,
+                .nd_ra_router_lifetime = usec_to_be16_sec(lifetime_usec),
+                .nd_ra_retransmit = usec_to_be32_msec(ra->retransmit_usec),
+        };
         struct {
                 struct nd_opt_hdr opthdr;
                 struct ether_addr slladdr;
         } _packed_ opt_mac = {
                 .opthdr = {
                         .nd_opt_type = ND_OPT_SOURCE_LINKADDR,
-                        .nd_opt_len = (sizeof(struct nd_opt_hdr) +
-                                       sizeof(struct ether_addr) - 1) /8 + 1,
+                        .nd_opt_len = DIV_ROUND_UP(sizeof(struct nd_opt_hdr) + sizeof(struct ether_addr), 8),
                 },
+                .slladdr = ra->mac_addr,
         };
         struct nd_opt_mtu opt_mtu =  {
                 .nd_opt_mtu_type = ND_OPT_MTU,
                 .nd_opt_mtu_len = 1,
+                .nd_opt_mtu_mtu = htobe32(ra->mtu),
         };
         /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, N pref64 prefixes, RDNSS,
          * DNSSL, and home agent. */
@@ -157,9 +166,6 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_us
         usec_t time_now;
         int r;
 
-        assert(ra);
-        assert(router_lifetime_is_valid(lifetime_usec));
-
         r = sd_event_now(ra->event, CLOCK_BOOTTIME, &time_now);
         if (r < 0)
                 return r;
@@ -167,25 +173,19 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_us
         if (dst && in6_addr_is_set(dst))
                 dst_addr.sin6_addr = *dst;
 
-        adv.nd_ra_type = ND_ROUTER_ADVERT;
+        /* The nd_ra_curhoplimit and nd_ra_flags_reserved fields cannot specified with nd_ra_router_lifetime
+         * simultaneously in the structured initializer in the above. */
         adv.nd_ra_curhoplimit = ra->hop_limit;
-        adv.nd_ra_retransmit = usec_to_be32_msec(ra->retransmit_usec);
         adv.nd_ra_flags_reserved = ra->flags;
-        assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC <= UINT16_MAX * USEC_PER_SEC);
-        adv.nd_ra_router_lifetime = usec_to_be16_sec(lifetime_usec);
         iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv));
 
-        /* MAC address is optional, either because the link does not use L2
-           addresses or load sharing is desired. See RFC 4861, Section 4.2 */
-        if (!ether_addr_is_null(&ra->mac_addr)) {
-                opt_mac.slladdr = ra->mac_addr;
+        /* MAC address is optional, either because the link does not use L2 addresses or load sharing is
+         * desired. See RFC 4861, Section 4.2. */
+        if (!ether_addr_is_null(&ra->mac_addr))
                 iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mac, sizeof(opt_mac));
-        }
 
-        if (ra->mtu > 0) {
-                opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu);
+        if (ra->mtu > 0)
                 iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mtu, sizeof(opt_mtu));
-        }
 
         LIST_FOREACH(prefix, p, ra->prefixes) {
                 usec_t lifetime_valid_usec, lifetime_preferred_usec;
@@ -263,15 +263,15 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
         if (r < 0)
                 switch (r) {
                 case -EADDRNOTAVAIL:
-                        log_radv(ra, "Received RS from neither link-local nor null address. Ignoring");
+                        log_radv(ra, "Received RS from neither link-local nor null address, ignoring.");
                         return 0;
 
                 case -EMULTIHOP:
-                        log_radv(ra, "Received RS with invalid hop limit. Ignoring.");
+                        log_radv(ra, "Received RS with invalid hop limit, ignoring.");
                         return 0;
 
                 case -EPFNOSUPPORT:
-                        log_radv(ra, "Received invalid source address from ICMPv6 socket. Ignoring.");
+                        log_radv(ra, "Received invalid source address from ICMPv6 socket, ignoring.");
                         return 0;
 
                 default:
@@ -288,12 +288,11 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
          * address option. See RFC 4861 Section 6.1.1. */
 
         const char *addr = IN6_ADDR_TO_STRING(&src);
-
-        r = radv_send(ra, &src, ra->lifetime_usec);
+        r = radv_send_router(ra, &src, ra->lifetime_usec);
         if (r < 0)
                 log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", addr);
         else
-                log_radv(ra, "Sent solicited Router Advertisement to %s", addr);
+                log_radv(ra, "Sent solicited Router Advertisement to %s.", addr);
 
         return 0;
 }
@@ -311,7 +310,7 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
         if (r < 0)
                 goto fail;
 
-        r = radv_send(ra, NULL, ra->lifetime_usec);
+        r = radv_send_router(ra, NULL, ra->lifetime_usec);
         if (r < 0)
                 log_radv_errno(ra, r, "Unable to send Router Advertisement, ignoring: %m");
 
@@ -371,9 +370,10 @@ int sd_radv_stop(sd_radv *ra) {
 
         log_radv(ra, "Stopping IPv6 Router Advertisement daemon");
 
-        /* RFC 4861, Section 6.2.5, send at least one Router Advertisement
-           with zero lifetime  */
-        r = radv_send(ra, NULL, 0);
+        /* RFC 4861, Section 6.2.5:
+         * the router SHOULD transmit one or more (but not more than MAX_FINAL_RTR_ADVERTISEMENTS) final
+         * multicast Router Advertisements on the interface with a Router Lifetime field of zero. */
+        r = radv_send_router(ra, NULL, 0);
         if (r < 0)
                 log_radv_errno(ra, r, "Unable to send last Router Advertisement with router lifetime set to zero, ignoring: %m");
 
@@ -384,6 +384,34 @@ int sd_radv_stop(sd_radv *ra) {
         return 0;
 }
 
+static int radv_setup_recv_event(sd_radv *ra) {
+        int r;
+
+        assert(ra);
+        assert(ra->event);
+        assert(ra->ifindex > 0);
+
+        _cleanup_close_ int fd = -EBADF;
+        fd = icmp6_bind(ra->ifindex, /* is_router = */ true);
+        if (fd < 0)
+                return fd;
+
+        _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+        r = sd_event_add_io(ra->event, &s, fd, EPOLLIN, radv_recv, ra);
+        if (r < 0)
+                return r;
+
+        r = sd_event_source_set_priority(s, ra->event_priority);
+        if (r < 0)
+                return r;
+
+        (void) sd_event_source_set_description(s, "radv-receive-message");
+
+        ra->fd = TAKE_FD(fd);
+        ra->recv_event_source = TAKE_PTR(s);
+        return 0;
+}
+
 int sd_radv_start(sd_radv *ra) {
         int r;
 
@@ -394,6 +422,10 @@ int sd_radv_start(sd_radv *ra) {
         if (ra->state != RADV_STATE_IDLE)
                 return 0;
 
+        r = radv_setup_recv_event(ra);
+        if (r < 0)
+                goto fail;
+
         r = event_reset_time(ra->event, &ra->timeout_event_source,
                              CLOCK_BOOTTIME,
                              0, 0,
@@ -402,22 +434,6 @@ int sd_radv_start(sd_radv *ra) {
         if (r < 0)
                 goto fail;
 
-        r = icmp6_bind_router_advertisement(ra->ifindex);
-        if (r < 0)
-                goto fail;
-
-        ra->fd = r;
-
-        r = sd_event_add_io(ra->event, &ra->recv_event_source, ra->fd, EPOLLIN, radv_recv, ra);
-        if (r < 0)
-                goto fail;
-
-        r = sd_event_source_set_priority(ra->recv_event_source, ra->event_priority);
-        if (r < 0)
-                goto fail;
-
-        (void) sd_event_source_set_description(ra->recv_event_source, "radv-receive-message");
-
         ra->state = RADV_STATE_ADVERTISING;
 
         log_radv(ra, "Started IPv6 Router Advertisement daemon");
@@ -674,7 +690,7 @@ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) {
                 return 0;
 
         /* If RAs have already been sent, send an RA immediately to announce the newly-added prefix */
-        r = radv_send(ra, NULL, ra->lifetime_usec);
+        r = radv_send_router(ra, NULL, ra->lifetime_usec);
         if (r < 0)
                 log_radv_errno(ra, r, "Unable to send Router Advertisement for added prefix %s, ignoring: %m", addr_p);
         else
@@ -770,7 +786,7 @@ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) {
                 return 0;
 
         /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
-        r = radv_send(ra, NULL, ra->lifetime_usec);
+        r = radv_send_router(ra, NULL, ra->lifetime_usec);
         if (r < 0)
                 log_radv_errno(ra, r, "Unable to send Router Advertisement for added route prefix %s, ignoring: %m",
                                strna(addr_p));
@@ -842,7 +858,7 @@ int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) {
                 return 0;
 
         /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
-        r = radv_send(ra, NULL, ra->lifetime_usec);
+        r = radv_send_router(ra, NULL, ra->lifetime_usec);
         if (r < 0)
                 log_radv_errno(ra, r, "Unable to send Router Advertisement for added PREF64 prefix %s, ignoring: %m",
                                strna(addr_p));
index 442b139f9b2a63cfc51e5c6de4d92f8606fdc293..c5f10cc7955e552d26af75f8d3251bfa5745c1c8 100644 (file)
@@ -20,37 +20,6 @@ static struct ether_addr mac_addr = {
         .ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 }
 };
 
-static uint8_t advertisement[] = {
-        /* ICMPv6 Router Advertisement, no checksum */
-        0x86, 0x00, 0x00, 0x00,  0x40, 0xc0, 0x00, 0xb4,
-        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
-        /* Source Link Layer Address Option */
-        0x01, 0x01, 0x78, 0x2b,  0xcb, 0xb3, 0x6d, 0x53,
-        /* Prefix Information Option */
-        0x03, 0x04, 0x40, 0xc0,  0x00, 0x00, 0x01, 0xf4,
-        0x00, 0x00, 0x01, 0xb8,  0x00, 0x00, 0x00, 0x00,
-        0x20, 0x01, 0x0d, 0xb8,  0xde, 0xad, 0xbe, 0xef,
-        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
-        /* Prefix Information Option */
-        0x03, 0x04, 0x40, 0xc0,  0x00, 0x00, 0x0e, 0x10,
-        0x00, 0x00, 0x07, 0x08,  0x00, 0x00, 0x00, 0x00,
-        0x20, 0x01, 0x0d, 0xb8,  0x0b, 0x16, 0xd0, 0x0d,
-        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
-        /* Prefix Information Option */
-        0x03, 0x04, 0x30, 0xc0,  0x00, 0x00, 0x0e, 0x10,
-        0x00, 0x00, 0x07, 0x08,  0x00, 0x00, 0x00, 0x00,
-        0x20, 0x01, 0x0d, 0xb8,  0xc0, 0x01, 0x0d, 0xad,
-        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
-        /* Recursive DNS Server Option */
-        0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-        0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-        /* DNS Search List Option */
-        0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-        0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
-        0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
 static bool test_stopped;
 static struct {
         struct in6_addr address;
@@ -271,49 +240,91 @@ TEST(radv) {
         assert_se(!ra);
 }
 
-static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        sd_radv *ra = userdata;
-        unsigned char buf[168];
-        size_t i;
-
-        assert_se(read(test_fd[0], &buf, sizeof(buf)) == sizeof(buf));
+static void dump_message(const uint8_t *buf, size_t len) {
+        assert(len >= sizeof(struct nd_router_advert));
 
-        /* router lifetime must be zero when test is stopped */
-        if (test_stopped) {
-                advertisement[6] = 0x00;
-                advertisement[7] = 0x00;
-        }
+        printf("Received Router Advertisement with lifetime %i sec\n",
+               (buf[6] << 8) + buf[7]);
 
-        printf ("Received Router Advertisement with lifetime %i\n",
-                (advertisement[6] << 8) + advertisement[7]);
-
-        /* test only up to buf size, rest is not yet implemented */
-        for (i = 0; i < sizeof(buf); i++) {
+        for (size_t i = 0; i < len; i++) {
                 if (!(i % 8))
                         printf("%3zu: ", i);
 
                 printf("0x%02x", buf[i]);
 
-                assert_se(buf[i] == advertisement[i]);
-
                 if ((i + 1) % 8)
                         printf(", ");
                 else
                         printf("\n");
         }
+}
 
-        if (test_stopped) {
-                sd_event *e;
+static void verify_message(const uint8_t *buf, size_t len) {
+        static const uint8_t advertisement[] = {
+                /* ICMPv6 Router Advertisement, no checksum */
+                0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                /* Source Link Layer Address Option */
+                0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
+                /* Prefix Information Option */
+                0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
+                0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                /* Prefix Information Option */
+                0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x0e, 0x10,
+                0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                /* Prefix Information Option */
+                0x03, 0x04, 0x30, 0xc0, 0x00, 0x00, 0x0e, 0x10,
+                0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
+                0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                /* Recursive DNS Server Option */
+                0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+                0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                /* DNS Search List Option */
+                0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+                0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
+                0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        };
+
+        /* verify only up to known options, rest is not yet implemented */
+        for (size_t i = 0, m = MIN(len, sizeof(advertisement)); i < m; i++) {
+                if (test_stopped)
+                        switch (i) {
+                        case 6 ... 7: /* router lifetime must be zero on stop. */
+                                assert_se(buf[i] == 0);
+                                continue;
+                        }
 
-                e = sd_radv_get_event(ra);
-                sd_event_exit(e, 0);
+                assert_se(buf[i] == advertisement[i]);
+        }
+}
+
+static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        sd_radv *ra = ASSERT_PTR(userdata);
+        _cleanup_free_ uint8_t *buf = NULL;
+        ssize_t buflen;
 
+        buflen = next_datagram_size_fd(fd);
+        assert_se(buflen >= 0);
+        assert_se(buf = new0(uint8_t, buflen));
+
+        assert_se(read(fd, buf, buflen) == buflen);
+
+        dump_message(buf, buflen);
+        verify_message(buf, buflen);
+
+        if (test_stopped) {
+                assert_se(sd_event_exit(sd_radv_get_event(ra), 0) >= 0);
                 return 0;
         }
 
         assert_se(sd_radv_stop(ra) >= 0);
         test_stopped = true;
-
         return 0;
 }
 
index 9c755ecbc64d9cb4fd6e94ff093e05e3d4c1767e..e37dfeededc669fc414b414b81704608737065f1 100644 (file)
@@ -202,7 +202,7 @@ static int send_ra(uint8_t flags) {
         return 0;
 }
 
-static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
+static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata) {
         sd_event *e = userdata;
         static unsigned idx = 0;
         uint64_t flags_array[] = {
@@ -219,6 +219,8 @@ static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router
         if (event != SD_NDISC_EVENT_ROUTER)
                 return;
 
+        sd_ndisc_router *rt = ASSERT_PTR(message);
+
         router_dump(rt);
 
         assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
index 63d3ee7284d79be6854dfc54bbd4ee768e8f3f96..e02de097baa44180489def6a1e23e90ce5349b6c 100644 (file)
@@ -92,7 +92,7 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
 
         assert_se(userdata == INT_TO_PTR('e'));
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2) >= 0);
 
         pid = fork();
         assert_se(pid >= 0);
@@ -142,7 +142,7 @@ static int defer_handler(sd_event_source *s, void *userdata) {
 
         assert_se(userdata == INT_TO_PTR('d'));
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1) >= 0);
 
         assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0);
         assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0);
@@ -254,7 +254,7 @@ static void test_basic_one(bool with_pidfd) {
         assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0);
 
         /* Test for floating event sources */
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1) >= 0);
         assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0);
 
         assert_se(write(a[1], &ch, 1) >= 0);
@@ -346,7 +346,7 @@ TEST(rtqueue) {
 
         assert_se(sd_event_default(&e) >= 0);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2) >= 0);
         assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0);
         assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0);
         assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0);
@@ -556,7 +556,7 @@ TEST(pidfd) {
         int pidfd;
         pid_t pid, pid2;
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
 
         pid = fork();
         if (pid == 0)
index 7b6467d63a040175b9f50bf5c62b6ed5ceda44bc..415d63da1f86c2e2a031930bdf711e2fdacf1792 100644 (file)
@@ -832,7 +832,7 @@ static int manager_connect_console(Manager *m) {
                                        SIGRTMIN, SIGRTMAX);
 
         assert_se(ignore_signals(SIGRTMIN + 1) >= 0);
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN) >= 0);
 
         r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
         if (r < 0)
@@ -1244,7 +1244,7 @@ static int run(int argc, char *argv[]) {
         (void) mkdir_label("/run/systemd/users", 0755);
         (void) mkdir_label("/run/systemd/sessions", 0755);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, SIGCHLD, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, SIGCHLD, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index 9aa298c6542ca01720bb5bb65c533827fe2203cb..2ea3f6c85089d4a242609e8823a0475b08987d5e 100644 (file)
@@ -835,7 +835,7 @@ static int create_session_message(
 
         if (!avoid_pidfd) {
                 pidfd = pidfd_open(getpid_cached(), 0);
-                if (pidfd < 0 && !ERRNO_IS_NOT_SUPPORTED(errno))
+                if (pidfd < 0 && !ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
                         return -errno;
         }
 
index 9c0aa035e5bcf3f5230c89389cce7b12d3b8878d..99b1f79460f697619c847c72443a1446f4fa0515 100644 (file)
@@ -1201,7 +1201,7 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT
         assert(master >= 0);
         assert(name);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT) >= 0);
 
         if (!arg_quiet) {
                 if (streq(name, ".host"))
@@ -1952,7 +1952,7 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
 
         if (!arg_quiet)
                 log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id);
index 108fe0327b5ff0c95a0f5da6afb5473f2f4884e3..99301408d340a92119e97a29871310cf2f2b859c 100644 (file)
@@ -342,7 +342,7 @@ static int run(int argc, char *argv[]) {
          * make sure this check stays in. */
         (void) mkdir_label("/run/systemd/machines", 0755);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index e301cf153d6ad474386b8ff54eda42d12ce6e11c..49a43753c5e7bdffa1050573fc795cd60b9e5b4f 100644 (file)
@@ -1180,8 +1180,8 @@ int address_remove(Address *address, Link *link) {
 }
 
 int address_remove_and_cancel(Address *address, Link *link) {
+        _cleanup_(request_unrefp) Request *req = NULL;
         bool waiting = false;
-        Request *req;
 
         assert(address);
         assert(link);
@@ -1193,6 +1193,7 @@ int address_remove_and_cancel(Address *address, Link *link) {
         /* Cancel the request for the address.  If the request is already called but we have not received the
          * notification about the request, then explicitly remove the address. */
         if (address_get_request(link, address, &req) >= 0) {
+                request_ref(req); /* avoid the request freed by request_detach() */
                 waiting = req->waiting_reply;
                 request_detach(req);
                 address_cancel_requesting(address);
index ac8baeb94ca063c8c25a5057a860cc1abf421bd0..2edd849cce131f2943c90dad5e6a45204fc4ffee 100644 (file)
@@ -40,12 +40,12 @@ uint32_t link_get_dhcp4_route_table(Link *link) {
         return link_get_vrf_table(link);
 }
 
-uint32_t link_get_ipv6_accept_ra_route_table(Link *link) {
+uint32_t link_get_ndisc_route_table(Link *link) {
         assert(link);
         assert(link->network);
 
-        if (link->network->ipv6_accept_ra_route_table_set)
-                return link->network->ipv6_accept_ra_route_table;
+        if (link->network->ndisc_route_table_set)
+                return link->network->ndisc_route_table;
         return link_get_vrf_table(link);
 }
 
@@ -281,7 +281,7 @@ int link_get_captive_portal(Link *link, const char **ret) {
                         return r;
         }
 
-        if (link->network->ipv6_accept_ra_use_captive_portal) {
+        if (link->network->ndisc_use_captive_portal) {
                 NDiscCaptivePortal *cp;
                 usec_t usec = 0;
 
@@ -409,10 +409,10 @@ int config_parse_dhcp_route_metric(
                 /* For backward compatibility. */
                 if (!network->dhcp_route_metric_set)
                         network->dhcp_route_metric = metric;
-                if (!network->ipv6_accept_ra_route_metric_set) {
-                        network->ipv6_accept_ra_route_metric_high = metric;
-                        network->ipv6_accept_ra_route_metric_medium = metric;
-                        network->ipv6_accept_ra_route_metric_low = metric;
+                if (!network->ndisc_route_metric_set) {
+                        network->ndisc_route_metric_high = metric;
+                        network->ndisc_route_metric_medium = metric;
+                        network->ndisc_route_metric_low = metric;
                 }
                 break;
         default:
@@ -422,7 +422,7 @@ int config_parse_dhcp_route_metric(
         return 0;
 }
 
-int config_parse_ipv6_accept_ra_route_metric(
+int config_parse_ndisc_route_metric(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -472,10 +472,10 @@ int config_parse_ipv6_accept_ra_route_metric(
                 }
         }
 
-        network->ipv6_accept_ra_route_metric_high = metric_high;
-        network->ipv6_accept_ra_route_metric_medium = metric_medium;
-        network->ipv6_accept_ra_route_metric_low = metric_low;
-        network->ipv6_accept_ra_route_metric_set = true;
+        network->ndisc_route_metric_high = metric_high;
+        network->ndisc_route_metric_medium = metric_medium;
+        network->ndisc_route_metric_low = metric_low;
+        network->ndisc_route_metric_set = true;
 
         return 0;
 }
@@ -717,8 +717,8 @@ int config_parse_dhcp_or_ra_route_table(
                 network->dhcp_route_table_set = true;
                 break;
         case AF_INET6:
-                network->ipv6_accept_ra_route_table = rt;
-                network->ipv6_accept_ra_route_table_set = true;
+                network->ndisc_route_table = rt;
+                network->ndisc_route_table_set = true;
                 break;
         default:
                 assert_not_reached();
index f888e03b961876d52894139ff0915ef69cb58984..c3e6a6d51cd8d39eab018d3a0b840c0626947ff5 100644 (file)
@@ -54,7 +54,7 @@ typedef struct DUID {
 } DUID;
 
 uint32_t link_get_dhcp4_route_table(Link *link);
-uint32_t link_get_ipv6_accept_ra_route_table(Link *link);
+uint32_t link_get_ndisc_route_table(Link *link);
 
 bool link_dhcp_enabled(Link *link, int family);
 static inline bool link_dhcp4_enabled(Link *link) {
@@ -95,7 +95,7 @@ DHCPOptionDataType dhcp_option_data_type_from_string(const char *d) _pure_;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_route_metric);
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_route_metric);
+CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_route_metric);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_hostname);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
index 27081e9d310d7ef8b77dd306f8c06f19f5a41a2b..d280251e07e16715b359ecd433291f227c199622 100644 (file)
@@ -799,7 +799,7 @@ int link_request_dhcp6_client(Link *link) {
 
         assert(link);
 
-        if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link))
+        if (!link_dhcp6_enabled(link) && !link_ndisc_enabled(link))
                 return 0;
 
         if (link->dhcp6_client)
index c9e3c937f47ff7376be5b94528afccc31836c03b..bff64633e03da13bdcab5fd5044e54a861c7fd63 100644 (file)
@@ -27,6 +27,8 @@ Network.ManageForeignRoutingPolicyRules, config_parse_bool,
 Network.ManageForeignRoutes,             config_parse_bool,                      0,          offsetof(Manager, manage_foreign_routes)
 Network.ManageForeignNextHops,           config_parse_bool,                      0,          offsetof(Manager, manage_foreign_nexthops)
 Network.RouteTable,                      config_parse_route_table_names,         0,          0
+Network.IPv4Forwarding,                  config_parse_tristate,                  0,          offsetof(Manager, ip_forwarding[0])
+Network.IPv6Forwarding,                  config_parse_tristate,                  0,          offsetof(Manager, ip_forwarding[1])
 Network.IPv6PrivacyExtensions,           config_parse_ipv6_privacy_extensions,   0,          offsetof(Manager, ipv6_privacy_extensions)
 DHCPv4.DUIDType,                         config_parse_duid_type,                 0,          offsetof(Manager, dhcp_duid)
 DHCPv4.DUIDRawData,                      config_parse_duid_rawdata,              0,          offsetof(Manager, dhcp_duid)
index 1e9c64f9f510c1af746aaa14c4a872d2ca293f5a..57bea190f5078f43e85b1ddc1bd9b360f64853aa 100644 (file)
@@ -490,7 +490,7 @@ static int dns_append_json(Link *link, JsonVariant **v) {
                         }
                 }
 
-                if (link->network->ipv6_accept_ra_use_dns) {
+                if (link->network->ndisc_use_dns) {
                         NDiscRDNSS *a;
 
                         SET_FOREACH(a, link->ndisc_rdnss) {
@@ -730,7 +730,7 @@ static int domains_append_json(Link *link, bool is_route, JsonVariant **v) {
                                 }
                 }
 
-                if (link->network->ipv6_accept_ra_use_domains == use_domains) {
+                if (link->network->ndisc_use_domains == use_domains) {
                         NDiscDNSSL *a;
 
                         SET_FOREACH(a, link->ndisc_dnssl) {
@@ -869,7 +869,7 @@ static int pref64_append_json(Link *link, JsonVariant **v) {
         assert(link);
         assert(v);
 
-        if (!link->network || !link->network->ipv6_accept_ra_use_pref64)
+        if (!link->network || !link->network->ndisc_use_pref64)
                 return 0;
 
         SET_FOREACH(i, link->ndisc_pref64) {
index 953910170240336485f807165880e56ff84bcf66..6304ead97ad69bd09026c804c762b64a71683781 100644 (file)
@@ -541,7 +541,7 @@ void link_check_ready(Link *link) {
          * Note, ignore NDisc when ConfigureWithoutCarrier= is enabled, as IPv6AcceptRA= is enabled by default. */
         if (!link_ipv4ll_enabled(link) && !link_dhcp4_enabled(link) &&
             !link_dhcp6_enabled(link) && !link_dhcp_pd_is_enabled(link) &&
-            (link->network->configure_without_carrier || !link_ipv6_accept_ra_enabled(link)))
+            (link->network->configure_without_carrier || !link_ndisc_enabled(link)))
                 goto ready;
 
         bool ipv4ll_ready =
@@ -559,8 +559,8 @@ void link_check_ready(Link *link) {
                 (!link->network->dhcp_pd_assign ||
                  link_check_addresses_ready(link, NETWORK_CONFIG_SOURCE_DHCP_PD));
         bool ndisc_ready =
-                link_ipv6_accept_ra_enabled(link) && link->ndisc_configured &&
-                (!link->network->ipv6_accept_ra_use_autonomous_prefix ||
+                link_ndisc_enabled(link) && link->ndisc_configured &&
+                (!link->network->ndisc_use_autonomous_prefix ||
                  link_check_addresses_ready(link, NETWORK_CONFIG_SOURCE_NDISC));
 
         /* If the uplink for PD is self, then request the corresponding DHCP protocol is also ready. */
index fc9196fc8be13ca81a15f66a2f35fd32f4d335a8..f48781ef8bb61c20cb6c148cae6e37470f8e32ad 100644 (file)
@@ -8,6 +8,7 @@
 #include "networkd-link.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
+#include "networkd-sysctl.h"
 #include "parse-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -69,9 +70,8 @@ int link_lldp_tx_configure(Link *link) {
                                         SD_LLDP_SYSTEM_CAPABILITIES_STATION |
                                         SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE |
                                         SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
-                                        (link->network->ip_forward != ADDRESS_FAMILY_NO) ?
-                                        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER :
-                                        SD_LLDP_SYSTEM_CAPABILITIES_STATION);
+                                        (link_get_ip_forwarding(link, AF_INET) > 0 || link_get_ip_forwarding(link, AF_INET6) > 0) ?
+                                        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : SD_LLDP_SYSTEM_CAPABILITIES_STATION);
         if (r < 0)
                 return r;
 
index 30aebb5d9e1a6ed621c667fbff3a504471b1f4da..8aefb686c65b8e1e1787d0f5cf9d8bafdf121b3d 100644 (file)
@@ -47,7 +47,7 @@ static int vl_method_get_namespace_id(Varlink *link, JsonVariant *parameters, Va
 
         r = netns_get_nsid(/* netnsfd= */ -EBADF, &nsid);
         if (r < 0)
-                log_warning_errno(r, "Failed to query network nsid, ignoring: %m");
+                log_full_errno(r == -ENODATA ? LOG_DEBUG : LOG_WARNING, r, "Failed to query network nsid, ignoring: %m");
 
         return varlink_replyb(link,
                               JSON_BUILD_OBJECT(
index 42c6371be5b18cbc98607f4242ad31f2a92424ef..c0d368ab1154b16cf0726ad47904a98b8ba877c6 100644 (file)
@@ -577,6 +577,7 @@ int manager_new(Manager **ret, bool test_mode) {
                 .dhcp_duid.type = DUID_TYPE_EN,
                 .dhcp6_duid.type = DUID_TYPE_EN,
                 .duid_product_uuid.type = DUID_TYPE_UUID,
+                .ip_forwarding = { -1, -1, },
         };
 
         *ret = TAKE_PTR(m);
@@ -659,6 +660,8 @@ int manager_start(Manager *m) {
 
         assert(m);
 
+        manager_set_sysctl(m);
+
         r = manager_start_speed_meter(m);
         if (r < 0)
                 return log_error_errno(r, "Failed to initialize speed meter: %m");
index 7788ce7d6f0835cf16775bf4f05de7f679db0062..8088e20b380b4b36abaaad8c722047e1f6a51c5c 100644 (file)
@@ -107,6 +107,9 @@ struct Manager {
         Hashmap *tuntap_fds_by_name;
 
         unsigned reloading;
+
+        /* sysctl */
+        int ip_forwarding[2];
 };
 
 int manager_new(Manager **ret, bool test_mode);
index d110482c0031b612dcb9d7be42bcef8810c684b2..24808413c185b1f4489aab742b487b669afd3463 100644 (file)
@@ -20,6 +20,7 @@
 #include "networkd-queue.h"
 #include "networkd-route.h"
 #include "networkd-state-file.h"
+#include "networkd-sysctl.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
@@ -34,7 +35,7 @@
  * Not sure if the threshold is high enough. Let's adjust later if not. */
 #define NDISC_PREF64_MAX 64U
 
-bool link_ipv6_accept_ra_enabled(Link *link) {
+bool link_ndisc_enabled(Link *link) {
         assert(link);
 
         if (!socket_ipv6_is_supported())
@@ -52,24 +53,28 @@ bool link_ipv6_accept_ra_enabled(Link *link) {
         if (!link_may_have_ipv6ll(link, /* check_multicast = */ true))
                 return false;
 
-        assert(link->network->ipv6_accept_ra >= 0);
-        return link->network->ipv6_accept_ra;
+        if (link->network->ndisc >= 0)
+                return link->network->ndisc;
+
+        /* Accept RAs if IPv6 forwarding is disabled, and ignore RAs if IPv6 forwarding is enabled. */
+        int t = link_get_ip_forwarding(link, AF_INET6);
+        if (t >= 0)
+                return !t;
+
+        /* Otherwise, defaults to true. */
+        return true;
 }
 
-void network_adjust_ipv6_accept_ra(Network *network) {
+void network_adjust_ndisc(Network *network) {
         assert(network);
 
         if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
-                if (network->ipv6_accept_ra > 0)
+                if (network->ndisc > 0)
                         log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link-local addressing is disabled or not supported. "
                                     "Disabling IPv6AcceptRA=.", network->filename);
-                network->ipv6_accept_ra = false;
+                network->ndisc = false;
         }
 
-        if (network->ipv6_accept_ra < 0)
-                /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
-                network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
-
         /* When RouterAllowList=, PrefixAllowList= or RouteAllowList= are specified, then
          * RouterDenyList=, PrefixDenyList= or RouteDenyList= are ignored, respectively. */
         if (!set_isempty(network->ndisc_allow_listed_router))
@@ -159,13 +164,13 @@ static void ndisc_set_route_priority(Link *link, Route *route) {
 
         switch (route->pref) {
         case SD_NDISC_PREFERENCE_LOW:
-                route->priority = link->network->ipv6_accept_ra_route_metric_low;
+                route->priority = link->network->ndisc_route_metric_low;
                 break;
         case SD_NDISC_PREFERENCE_MEDIUM:
-                route->priority = link->network->ipv6_accept_ra_route_metric_medium;
+                route->priority = link->network->ndisc_route_metric_medium;
                 break;
         case SD_NDISC_PREFERENCE_HIGH:
-                route->priority = link->network->ipv6_accept_ra_route_metric_high;
+                route->priority = link->network->ndisc_route_metric_high;
                 break;
         default:
                 assert_not_reached();
@@ -189,13 +194,13 @@ static int ndisc_request_route(Route *route, Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return r;
 
-        if (link->network->ipv6_accept_ra_use_mtu) {
+        if (link->network->ndisc_use_mtu) {
                 r = sd_ndisc_router_get_mtu(rt, &mtu);
                 if (r < 0 && r != -ENODATA)
                         return log_link_warning_errno(link, r, "Failed to get MTU from RA: %m");
         }
 
-        if (link->network->ipv6_accept_ra_use_hop_limit) {
+        if (link->network->ndisc_use_hop_limit) {
                 r = sd_ndisc_router_get_hop_limit(rt, &hop_limit);
                 if (r < 0 && r != -ENODATA)
                         return log_link_warning_errno(link, r, "Failed to get hop limit from RA: %m");
@@ -204,7 +209,7 @@ static int ndisc_request_route(Route *route, Link *link, sd_ndisc_router *rt) {
         route->source = NETWORK_CONFIG_SOURCE_NDISC;
         route->provider.in6 = router;
         if (!route->table_set)
-                route->table = link_get_ipv6_accept_ra_route_table(link);
+                route->table = link_get_ndisc_route_table(link);
         if (!route->protocol_set)
                 route->protocol = RTPROT_RA;
         r = route_metric_set(&route->metric, RTAX_MTU, mtu);
@@ -213,7 +218,7 @@ static int ndisc_request_route(Route *route, Link *link, sd_ndisc_router *rt) {
         r = route_metric_set(&route->metric, RTAX_HOPLIMIT, hop_limit);
         if (r < 0)
                 return r;
-        r = route_metric_set(&route->metric, RTAX_QUICKACK, link->network->ipv6_accept_ra_quickack);
+        r = route_metric_set(&route->metric, RTAX_QUICKACK, link->network->ndisc_quickack);
         if (r < 0)
                 return r;
 
@@ -283,7 +288,7 @@ static int ndisc_remove_route(Route *route, Link *link) {
         ndisc_set_route_priority(link, route);
 
         if (!route->table_set)
-                route->table = link_get_ipv6_accept_ra_route_table(link);
+                route->table = link_get_ndisc_route_table(link);
 
         r = route_adjust_nexthops(route, link);
         if (r < 0)
@@ -439,7 +444,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (r == 0)
                 return ndisc_router_drop_default(link, rt);
 
-        if (!link->network->ipv6_accept_ra_use_gateway &&
+        if (!link->network->ndisc_use_gateway &&
             hashmap_isempty(link->network->routes_by_section))
                 return 0;
 
@@ -462,7 +467,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to get router preference from RA: %m");
 
-        if (link->network->ipv6_accept_ra_use_gateway) {
+        if (link->network->ndisc_use_gateway) {
                 _cleanup_(route_unrefp) Route *route = NULL;
 
                 r = route_new(&route);
@@ -515,7 +520,7 @@ static int ndisc_router_process_icmp6_ratelimit(Link *link, sd_ndisc_router *rt)
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_icmp6_ratelimit)
+        if (!link->network->ndisc_use_icmp6_ratelimit)
                 return 0;
 
         /* Ignore the icmp6 ratelimit field of the RA header if the lifetime is zero. */
@@ -552,7 +557,7 @@ static int ndisc_router_process_reachable_time(Link *link, sd_ndisc_router *rt)
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_reachable_time)
+        if (!link->network->ndisc_use_reachable_time)
                 return 0;
 
         /* Ignore the reachable time field of the RA header if the lifetime is zero. */
@@ -590,7 +595,7 @@ static int ndisc_router_process_retransmission_time(Link *link, sd_ndisc_router
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_retransmission_time)
+        if (!link->network->ndisc_use_retransmission_time)
                 return 0;
 
         /* Ignore the retransmission time field of the RA header if the lifetime is zero. */
@@ -628,7 +633,7 @@ static int ndisc_router_process_hop_limit(Link *link, sd_ndisc_router *rt) {
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_hop_limit)
+        if (!link->network->ndisc_use_hop_limit)
                 return 0;
 
         /* Ignore the hop limit field of the RA header if the lifetime is zero. */
@@ -671,7 +676,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_autonomous_prefix)
+        if (!link->network->ndisc_use_autonomous_prefix)
                 return 0;
 
         r = sd_ndisc_router_prefix_get_address(rt, &prefix);
@@ -751,7 +756,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_onlink_prefix)
+        if (!link->network->ndisc_use_onlink_prefix)
                 return 0;
 
         r = sd_ndisc_router_prefix_get_valid_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
@@ -805,7 +810,7 @@ static int ndisc_router_drop_onlink_prefix(Link *link, sd_ndisc_router *rt) {
          * covered by the prefix are off-link. The only way to cancel a previous on-link indication is to
          * advertise that prefix with the L-bit set and the Lifetime set to zero. */
 
-        if (!link->network->ipv6_accept_ra_use_onlink_prefix)
+        if (!link->network->ndisc_use_onlink_prefix)
                 return 0;
 
         r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_usec);
@@ -902,7 +907,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
 
         assert(link);
 
-        if (!link->network->ipv6_accept_ra_use_route_prefix)
+        if (!link->network->ndisc_use_route_prefix)
                 return 0;
 
         r = sd_ndisc_router_route_get_lifetime_timestamp(rt, CLOCK_BOOTTIME, &lifetime_usec);
@@ -998,7 +1003,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_dns)
+        if (!link->network->ndisc_use_dns)
                 return 0;
 
         r = sd_ndisc_router_get_address(rt, &router);
@@ -1090,7 +1095,7 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
         assert(link->network);
         assert(rt);
 
-        if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_NO)
+        if (link->network->ndisc_use_domains == DHCP_USE_DOMAINS_NO)
                 return 0;
 
         r = sd_ndisc_router_get_address(rt, &router);
@@ -1195,7 +1200,7 @@ static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt)
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_captive_portal)
+        if (!link->network->ndisc_use_captive_portal)
                 return 0;
 
         r = sd_ndisc_router_get_address(rt, &router);
@@ -1315,7 +1320,7 @@ static int ndisc_router_process_pref64(Link *link, sd_ndisc_router *rt) {
         assert(link->network);
         assert(rt);
 
-        if (!link->network->ipv6_accept_ra_use_pref64)
+        if (!link->network->ndisc_use_pref64)
                 return 0;
 
         r = sd_ndisc_router_get_address(rt, &router);
@@ -1464,7 +1469,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
                 if (route->nexthop.ifindex != link->ifindex)
                         continue;
 
-                if (route->lifetime_usec >= timestamp_usec)
+                if (route->lifetime_usec > timestamp_usec)
                         continue; /* the route is still valid */
 
                 r = route_remove_and_cancel(route, link->manager);
@@ -1476,7 +1481,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
                 if (address->source != NETWORK_CONFIG_SOURCE_NDISC)
                         continue;
 
-                if (address->lifetime_valid_usec >= timestamp_usec)
+                if (address->lifetime_valid_usec > timestamp_usec)
                         continue; /* the address is still valid */
 
                 r = address_remove_and_cancel(address, link);
@@ -1485,7 +1490,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
         }
 
         SET_FOREACH(rdnss, link->ndisc_rdnss) {
-                if (rdnss->lifetime_usec >= timestamp_usec)
+                if (rdnss->lifetime_usec > timestamp_usec)
                         continue; /* the DNS server is still valid */
 
                 free(set_remove(link->ndisc_rdnss, rdnss));
@@ -1493,7 +1498,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
         }
 
         SET_FOREACH(dnssl, link->ndisc_dnssl) {
-                if (dnssl->lifetime_usec >= timestamp_usec)
+                if (dnssl->lifetime_usec > timestamp_usec)
                         continue; /* the DNS domain is still valid */
 
                 free(set_remove(link->ndisc_dnssl, dnssl));
@@ -1501,7 +1506,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
         }
 
         SET_FOREACH(cp, link->ndisc_captive_portals) {
-                if (cp->lifetime_usec >= timestamp_usec)
+                if (cp->lifetime_usec > timestamp_usec)
                         continue; /* the captive portal is still valid */
 
                 ndisc_captive_portal_free(set_remove(link->ndisc_captive_portals, cp));
@@ -1509,7 +1514,7 @@ static int ndisc_drop_outdated(Link *link, usec_t timestamp_usec) {
         }
 
         SET_FOREACH(p64, link->ndisc_pref64) {
-                if (p64->lifetime_usec >= timestamp_usec)
+                if (p64->lifetime_usec > timestamp_usec)
                         continue; /* the pref64 prefix is still valid */
 
                 free(set_remove(link->ndisc_pref64, p64));
@@ -1609,7 +1614,7 @@ static int ndisc_start_dhcp6_client(Link *link, sd_ndisc_router *rt) {
         if (r <= 0)
                 return r;
 
-        switch (link->network->ipv6_accept_ra_start_dhcp6_client) {
+        switch (link->network->ndisc_start_dhcp6_client) {
         case IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO:
                 return 0;
 
@@ -1730,7 +1735,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
         return 0;
 }
 
-static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
+static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata) {
         Link *link = ASSERT_PTR(userdata);
         int r;
 
@@ -1740,7 +1745,7 @@ static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router
         switch (event) {
 
         case SD_NDISC_EVENT_ROUTER:
-                r = ndisc_router_handler(link, rt);
+                r = ndisc_router_handler(link, ASSERT_PTR(message));
                 if (r < 0 && r != -EBADMSG) {
                         link_enter_failed(link);
                         return;
@@ -1754,8 +1759,9 @@ static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router
                         link_check_ready(link);
                 }
                 break;
+
         default:
-                assert_not_reached();
+                log_link_debug(link, "Received unsupported NDisc event, ignoring.");
         }
 }
 
@@ -1764,7 +1770,7 @@ static int ndisc_configure(Link *link) {
 
         assert(link);
 
-        if (!link_ipv6_accept_ra_enabled(link))
+        if (!link_ndisc_enabled(link))
                 return 0;
 
         if (link->ndisc)
@@ -1844,7 +1850,7 @@ int link_request_ndisc(Link *link) {
 
         assert(link);
 
-        if (!link_ipv6_accept_ra_enabled(link))
+        if (!link_ndisc_enabled(link))
                 return 0;
 
         if (link->ndisc)
@@ -1879,15 +1885,15 @@ void ndisc_flush(Link *link) {
         link->ndisc_pref64 = set_free(link->ndisc_pref64);
 }
 
-static const char* const ipv6_accept_ra_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
+static const char* const ndisc_start_dhcp6_client_table[_IPV6_ACCEPT_RA_START_DHCP6_CLIENT_MAX] = {
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO]     = "no",
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_ALWAYS] = "always",
         [IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES]    = "yes",
 };
 
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(ndisc_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client, IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES);
 
-DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_use_domains, dhcp_use_domains, DHCPUseDomains,
+DEFINE_CONFIG_PARSE_ENUM(config_parse_ndisc_use_domains, dhcp_use_domains, DHCPUseDomains,
                          "Failed to parse UseDomains= setting");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_accept_ra_start_dhcp6_client, ipv6_accept_ra_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
+DEFINE_CONFIG_PARSE_ENUM(config_parse_ndisc_start_dhcp6_client, ndisc_start_dhcp6_client, IPv6AcceptRAStartDHCP6Client,
                          "Failed to parse DHCPv6Client= setting");
index a463f42b52294ff3dca079d869d53f58793e130c..2766f5e4350d8ba0569e2d59c65277ca10104dc1 100644 (file)
@@ -52,9 +52,9 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
         return ((char*) n) + ALIGN(sizeof(NDiscDNSSL));
 }
 
-bool link_ipv6_accept_ra_enabled(Link *link);
+bool link_ndisc_enabled(Link *link);
 
-void network_adjust_ipv6_accept_ra(Network *network);
+void network_adjust_ndisc(Network *network);
 
 int ndisc_start(Link *link);
 int ndisc_stop(Link *link);
@@ -62,5 +62,5 @@ void ndisc_flush(Link *link);
 
 int link_request_ndisc(Link *link);
 
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_use_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_start_dhcp6_client);
+CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_use_domains);
index 236bac7aa674d7b6fdcfdc5132955dc2c412ee70..9171056156328e58385265befb99e96435fda185 100644 (file)
@@ -124,11 +124,13 @@ 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,                             offsetof(Network, dnssec_negative_trust_anchors)
 Network.NTP,                                 config_parse_ntp,                                         0,                             offsetof(Network, ntp)
-Network.IPForward,                           config_parse_address_family_with_kernel,                  0,                             offsetof(Network, ip_forward)
+Network.IPForward,                           config_parse_ip_forward_deprecated,                       0,                             0
+Network.IPv4Forwarding,                      config_parse_tristate,                                    0,                             offsetof(Network, ip_forwarding[0])
+Network.IPv6Forwarding,                      config_parse_tristate,                                    0,                             offsetof(Network, ip_forwarding[1])
 Network.IPMasquerade,                        config_parse_ip_masquerade,                               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)
-Network.IPv6AcceptRouterAdvertisements,      config_parse_tristate,                                    0,                             offsetof(Network, ipv6_accept_ra)
+Network.IPv6AcceptRA,                        config_parse_tristate,                                    0,                             offsetof(Network, ndisc)
+Network.IPv6AcceptRouterAdvertisements,      config_parse_tristate,                                    0,                             offsetof(Network, ndisc)
 Network.IPv6DuplicateAddressDetection,       config_parse_int,                                         0,                             offsetof(Network, ipv6_dad_transmits)
 Network.IPv6HopLimit,                        config_parse_uint8,                                       0,                             offsetof(Network, ipv6_hop_limit)
 Network.IPv6RetransmissionTimeSec,           config_parse_sec,                                         0,                             offsetof(Network, ipv6_retransmission_time)
@@ -290,23 +292,23 @@ DHCPv6.RapidCommit,                          config_parse_bool,
 DHCPv6.NetLabel,                             config_parse_string,                                      CONFIG_PARSE_STRING_SAFE,      offsetof(Network, dhcp6_netlabel)
 DHCPv6.SendRelease,                          config_parse_bool,                                        0,                             offsetof(Network, dhcp6_send_release)
 DHCPv6.NFTSet,                               config_parse_nft_set,                                     NFT_SET_PARSE_NETWORK,         offsetof(Network, dhcp6_nft_set_context)
-IPv6AcceptRA.UseGateway,                     config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_gateway)
-IPv6AcceptRA.UseRoutePrefix,                 config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_route_prefix)
-IPv6AcceptRA.UseAutonomousPrefix,            config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_autonomous_prefix)
-IPv6AcceptRA.UseOnLinkPrefix,                config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
-IPv6AcceptRA.UsePREF64,                      config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_pref64)
-IPv6AcceptRA.UseDNS,                         config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_dns)
-IPv6AcceptRA.UseDomains,                     config_parse_ipv6_accept_ra_use_domains,                  0,                             offsetof(Network, ipv6_accept_ra_use_domains)
-IPv6AcceptRA.UseMTU,                         config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_mtu)
-IPv6AcceptRA.UseHopLimit,                    config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_hop_limit)
-IPv6AcceptRA.UseReachableTime,               config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_reachable_time)
-IPv6AcceptRA.UseRetransmissionTime,          config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_retransmission_time)
-IPv6AcceptRA.UseICMP6RateLimit,              config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_icmp6_ratelimit)
-IPv6AcceptRA.DHCPv6Client,                   config_parse_ipv6_accept_ra_start_dhcp6_client,           0,                             offsetof(Network, ipv6_accept_ra_start_dhcp6_client)
+IPv6AcceptRA.UseGateway,                     config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_gateway)
+IPv6AcceptRA.UseRoutePrefix,                 config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_route_prefix)
+IPv6AcceptRA.UseAutonomousPrefix,            config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_autonomous_prefix)
+IPv6AcceptRA.UseOnLinkPrefix,                config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_onlink_prefix)
+IPv6AcceptRA.UsePREF64,                      config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_pref64)
+IPv6AcceptRA.UseDNS,                         config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_dns)
+IPv6AcceptRA.UseDomains,                     config_parse_ndisc_use_domains,                           0,                             offsetof(Network, ndisc_use_domains)
+IPv6AcceptRA.UseMTU,                         config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_mtu)
+IPv6AcceptRA.UseHopLimit,                    config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_hop_limit)
+IPv6AcceptRA.UseReachableTime,               config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_reachable_time)
+IPv6AcceptRA.UseRetransmissionTime,          config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_retransmission_time)
+IPv6AcceptRA.UseICMP6RateLimit,              config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_icmp6_ratelimit)
+IPv6AcceptRA.DHCPv6Client,                   config_parse_ndisc_start_dhcp6_client,                    0,                             offsetof(Network, ndisc_start_dhcp6_client)
 IPv6AcceptRA.RouteTable,                     config_parse_dhcp_or_ra_route_table,                      AF_INET6,                      0
-IPv6AcceptRA.RouteMetric,                    config_parse_ipv6_accept_ra_route_metric,                 0,                             0
-IPv6AcceptRA.QuickAck,                       config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_quickack)
-IPv6AcceptRA.UseCaptivePortal,               config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_captive_portal)
+IPv6AcceptRA.RouteMetric,                    config_parse_ndisc_route_metric,                          0,                             0
+IPv6AcceptRA.QuickAck,                       config_parse_bool,                                        0,                             offsetof(Network, ndisc_quickack)
+IPv6AcceptRA.UseCaptivePortal,               config_parse_bool,                                        0,                             offsetof(Network, ndisc_use_captive_portal)
 IPv6AcceptRA.RouterAllowList,                config_parse_in_addr_prefixes,                            AF_INET6,                      offsetof(Network, ndisc_allow_listed_router)
 IPv6AcceptRA.RouterDenyList,                 config_parse_in_addr_prefixes,                            AF_INET6,                      offsetof(Network, ndisc_deny_listed_router)
 IPv6AcceptRA.PrefixAllowList,                config_parse_in_addr_prefixes,                            AF_INET6,                      offsetof(Network, ndisc_allow_listed_prefix)
@@ -609,7 +611,7 @@ DHCP.RapidCommit,                            config_parse_bool,
 DHCP.ForceDHCPv6PDOtherInformation,          config_parse_warn_compat,                                 DISABLED_LEGACY,               0
 DHCPv4.UseDomainName,                        config_parse_dhcp_use_domains,                            AF_INET,                       0
 DHCPv4.CriticalConnection,                   config_parse_tristate,                                    0,                             offsetof(Network, dhcp_critical)
-DHCPv6.RouteMetric,                          config_parse_ipv6_accept_ra_route_metric,                 AF_INET6,                      0
+DHCPv6.RouteMetric,                          config_parse_ndisc_route_metric,                          AF_INET6,                      0
 DHCPv6.ForceDHCPv6PDOtherInformation,        config_parse_warn_compat,                                 DISABLED_LEGACY,               0
 DHCPv6PrefixDelegation.SubnetId,             config_parse_dhcp_pd_subnet_id,                           0,                             offsetof(Network, dhcp_pd_subnet_id)
 DHCPv6PrefixDelegation.Announce,             config_parse_bool,                                        0,                             offsetof(Network, dhcp_pd_announce)
index 4101296275de0b8967eea52f29979f233f9be690..601820b1232cf9504fabff7ff552309789f728cd 100644 (file)
@@ -225,11 +225,8 @@ int network_verify(Network *network) {
             network->ipv6ll_address_gen_mode < 0)
                 network->ipv6ll_address_gen_mode = IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY;
 
-        /* IPMasquerade implies IPForward */
-        network->ip_forward |= network->ip_masquerade;
-
         network_adjust_ipv6_proxy_ndp(network);
-        network_adjust_ipv6_accept_ra(network);
+        network_adjust_ndisc(network);
         network_adjust_dhcp(network);
         network_adjust_radv(network);
         network_adjust_bridge_vlan(network);
@@ -465,6 +462,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .link_local = _ADDRESS_FAMILY_INVALID,
                 .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
 
+                .ip_forwarding = { -1, -1, },
                 .ipv4_accept_local = -1,
                 .ipv4_route_localnet = -1,
                 .ipv6_privacy_extensions = _IPV6_PRIVACY_EXTENSIONS_INVALID,
@@ -474,23 +472,23 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .proxy_arp_pvlan = -1,
                 .ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
 
-                .ipv6_accept_ra = -1,
-                .ipv6_accept_ra_use_dns = true,
-                .ipv6_accept_ra_use_gateway = true,
-                .ipv6_accept_ra_use_captive_portal = true,
-                .ipv6_accept_ra_use_route_prefix = true,
-                .ipv6_accept_ra_use_autonomous_prefix = true,
-                .ipv6_accept_ra_use_onlink_prefix = true,
-                .ipv6_accept_ra_use_mtu = true,
-                .ipv6_accept_ra_use_hop_limit = true,
-                .ipv6_accept_ra_use_reachable_time = true,
-                .ipv6_accept_ra_use_retransmission_time = true,
-                .ipv6_accept_ra_use_icmp6_ratelimit = true,
-                .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
-                .ipv6_accept_ra_route_metric_high = IPV6RA_ROUTE_METRIC_HIGH,
-                .ipv6_accept_ra_route_metric_medium = IPV6RA_ROUTE_METRIC_MEDIUM,
-                .ipv6_accept_ra_route_metric_low = IPV6RA_ROUTE_METRIC_LOW,
-                .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
+                .ndisc = -1,
+                .ndisc_use_dns = true,
+                .ndisc_use_gateway = true,
+                .ndisc_use_captive_portal = true,
+                .ndisc_use_route_prefix = true,
+                .ndisc_use_autonomous_prefix = true,
+                .ndisc_use_onlink_prefix = true,
+                .ndisc_use_mtu = true,
+                .ndisc_use_hop_limit = true,
+                .ndisc_use_reachable_time = true,
+                .ndisc_use_retransmission_time = true,
+                .ndisc_use_icmp6_ratelimit = true,
+                .ndisc_route_table = RT_TABLE_MAIN,
+                .ndisc_route_metric_high = IPV6RA_ROUTE_METRIC_HIGH,
+                .ndisc_route_metric_medium = IPV6RA_ROUTE_METRIC_MEDIUM,
+                .ndisc_route_metric_low = IPV6RA_ROUTE_METRIC_LOW,
+                .ndisc_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
 
                 .can_termination = -1,
 
index e9ee556312b09f6bf7a1d25df4ba3a20d065f6c3..b30e3b22098ff38cb9b513e78f906c329fa143e4 100644 (file)
@@ -320,7 +320,7 @@ struct Network {
         int ipoib_umcast;
 
         /* sysctl settings */
-        AddressFamily ip_forward;
+        int ip_forwarding[2];
         int ipv4_accept_local;
         int ipv4_route_localnet;
         int ipv6_dad_transmits;
@@ -334,31 +334,31 @@ struct Network {
         int ipv6_proxy_ndp;
         Set *ipv6_proxy_ndp_addresses;
 
-        /* IPv6 accept RA */
-        int ipv6_accept_ra;
-        bool ipv6_accept_ra_use_dns;
-        bool ipv6_accept_ra_use_gateway;
-        bool ipv6_accept_ra_use_route_prefix;
-        bool ipv6_accept_ra_use_autonomous_prefix;
-        bool ipv6_accept_ra_use_onlink_prefix;
-        bool ipv6_accept_ra_use_mtu;
-        bool ipv6_accept_ra_use_hop_limit;
-        bool ipv6_accept_ra_use_reachable_time;
-        bool ipv6_accept_ra_use_retransmission_time;
-        bool ipv6_accept_ra_use_icmp6_ratelimit;
-        bool ipv6_accept_ra_quickack;
-        bool ipv6_accept_ra_use_captive_portal;
-        bool ipv6_accept_ra_use_pref64;
+        /* NDisc support */
+        int ndisc;
+        bool ndisc_use_dns;
+        bool ndisc_use_gateway;
+        bool ndisc_use_route_prefix;
+        bool ndisc_use_autonomous_prefix;
+        bool ndisc_use_onlink_prefix;
+        bool ndisc_use_mtu;
+        bool ndisc_use_hop_limit;
+        bool ndisc_use_reachable_time;
+        bool ndisc_use_retransmission_time;
+        bool ndisc_use_icmp6_ratelimit;
+        bool ndisc_quickack;
+        bool ndisc_use_captive_portal;
+        bool ndisc_use_pref64;
         bool active_slave;
         bool primary_slave;
-        DHCPUseDomains ipv6_accept_ra_use_domains;
-        IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client;
-        uint32_t ipv6_accept_ra_route_table;
-        bool ipv6_accept_ra_route_table_set;
-        uint32_t ipv6_accept_ra_route_metric_high;
-        uint32_t ipv6_accept_ra_route_metric_medium;
-        uint32_t ipv6_accept_ra_route_metric_low;
-        bool ipv6_accept_ra_route_metric_set;
+        DHCPUseDomains ndisc_use_domains;
+        IPv6AcceptRAStartDHCP6Client ndisc_start_dhcp6_client;
+        uint32_t ndisc_route_table;
+        bool ndisc_route_table_set;
+        uint32_t ndisc_route_metric_high;
+        uint32_t ndisc_route_metric_medium;
+        uint32_t ndisc_route_metric_low;
+        bool ndisc_route_metric_set;
         Set *ndisc_deny_listed_router;
         Set *ndisc_allow_listed_router;
         Set *ndisc_deny_listed_prefix;
index f7a2201b6b0a0b7ed70a50b777d1328e95488c7d..8ba7505987aeec42c406d258bfd627c536f7588d 100644 (file)
@@ -840,7 +840,7 @@ int route_section_verify_nexthops(Route *route) {
                                                  "Ignoring [Route] section from line %u.",
                                                  route->section->filename, route->section->line);
 
-                if (route->nexthop.family == AF_INET6 && !route->network->ipv6_accept_ra)
+                if (route->nexthop.family == AF_INET6 && route->network->ndisc == 0)
                         return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                                  "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
                                                  "Ignoring [Route] section from line %u.",
index ee12f1664abe46b6a2b2db8e8e1a0e5808434d86..3c5de98e7c96181439a0b640855f4d0750302890 100644 (file)
@@ -600,8 +600,8 @@ int route_remove(Route *route, Manager *manager) {
 }
 
 int route_remove_and_cancel(Route *route, Manager *manager) {
+        _cleanup_(request_unrefp) Request *req = NULL;
         bool waiting = false;
-        Request *req;
 
         assert(route);
         assert(manager);
@@ -612,6 +612,7 @@ int route_remove_and_cancel(Route *route, Manager *manager) {
         /* Cancel the request for the route. If the request is already called but we have not received the
          * notification about the request, then explicitly remove the route. */
         if (route_get_request(manager, route, &req) >= 0) {
+                request_ref(req); /* avoid the request freed by request_detach() */
                 waiting = req->waiting_reply;
                 request_detach(req);
                 route_cancel_requesting(route);
index 859a28aa59f5641e14d1bcefe33bc8ef9603a498..1cd23bb4ca80ac9a7eb6e101ec4cc39a6ccd18e2 100644 (file)
@@ -123,7 +123,7 @@ static int link_put_dns(Link *link, OrderedSet **s) {
                 }
         }
 
-        if (link->network->ipv6_accept_ra_use_dns) {
+        if (link->network->ndisc_use_dns) {
                 NDiscRDNSS *a;
 
                 SET_FOREACH(a, link->ndisc_rdnss) {
@@ -254,7 +254,7 @@ static int link_put_domains(Link *link, bool is_route, OrderedSet **s) {
                 }
         }
 
-        if (link->network->ipv6_accept_ra_use_domains == use_domains) {
+        if (link->network->ndisc_use_domains == use_domains) {
                 NDiscDNSSL *a;
 
                 SET_FOREACH(a, link->ndisc_dnssl) {
@@ -559,7 +559,7 @@ static void link_save_domains(Link *link, FILE *f, OrderedSet *static_domains, D
                         fputstrv(f, domains, NULL, &space);
         }
 
-        if (link->network->ipv6_accept_ra_use_domains == use_domains) {
+        if (link->network->ndisc_use_domains == use_domains) {
                 NDiscDNSSL *dd;
 
                 SET_FOREACH(dd, link->ndisc_dnssl)
@@ -675,7 +675,7 @@ static int link_save(Link *link) {
                                             sd_dhcp6_lease_get_dns,
                                             NULL);
 
-                        if (link->network->ipv6_accept_ra_use_dns) {
+                        if (link->network->ndisc_use_dns) {
                                 NDiscRDNSS *dd;
 
                                 SET_FOREACH(dd, link->ndisc_rdnss)
index 8fa0ede5c2aee0057f4ce06dc905ae1006bf4770..f9db1f7f4af16c4c3085231d9f7aa234ebe33708 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/if.h>
 #include <linux/if_arp.h>
 
+#include "af-list.h"
 #include "missing_network.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "string-table.h"
 #include "sysctl-util.h"
 
+static void manager_set_ip_forwarding(Manager *manager, int family) {
+        int r, t;
+
+        assert(manager);
+        assert(IN_SET(family, AF_INET, AF_INET6));
+
+        if (family == AF_INET6 && !socket_ipv6_is_supported())
+                return;
+
+        t = manager->ip_forwarding[family == AF_INET6];
+        if (t < 0)
+                return; /* keep */
+
+        /* First, set the default value. */
+        r = sysctl_write_ip_property_boolean(family, "default", "forwarding", t);
+        if (r < 0)
+                log_warning_errno(r, "Failed to %s the default %s forwarding: %m",
+                                  enable_disable(t), af_to_ipv4_ipv6(family));
+
+        /* Then, set the value to all interfaces. */
+        r = sysctl_write_ip_property_boolean(family, "all", "forwarding", t);
+        if (r < 0)
+                log_warning_errno(r, "Failed to %s %s forwarding for all interfaces: %m",
+                                  enable_disable(t), af_to_ipv4_ipv6(family));
+}
+
+void manager_set_sysctl(Manager *manager) {
+        assert(manager);
+        assert(!manager->test_mode);
+
+        manager_set_ip_forwarding(manager, AF_INET);
+        manager_set_ip_forwarding(manager, AF_INET6);
+}
+
 static bool link_is_configured_for_family(Link *link, int family) {
         assert(link);
 
@@ -70,48 +105,50 @@ static int link_set_proxy_arp_pvlan(Link *link) {
         return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp_pvlan", link->network->proxy_arp_pvlan > 0);
 }
 
-static bool link_ip_forward_enabled(Link *link, int family) {
+int link_get_ip_forwarding(Link *link, int family) {
         assert(link);
+        assert(link->manager);
+        assert(link->network);
         assert(IN_SET(family, AF_INET, AF_INET6));
 
-        if (!link_is_configured_for_family(link, family))
-                return false;
-
-        return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6);
-}
+        /* If it is explicitly specified, then honor the setting. */
+        int t = link->network->ip_forwarding[family == AF_INET6];
+        if (t >= 0)
+                return t;
 
-static int link_set_ipv4_forward(Link *link) {
-        assert(link);
-
-        if (!link_ip_forward_enabled(link, AF_INET))
-                return 0;
+        /* If IPMasquerade= is enabled, also enable IP forwarding. */
+        if (family == AF_INET && FLAGS_SET(link->network->ip_masquerade, ADDRESS_FAMILY_IPV4))
+                return true;
+        if (family == AF_INET6 && FLAGS_SET(link->network->ip_masquerade, ADDRESS_FAMILY_IPV6))
+                return true;
 
-        /* We propagate the forwarding flag from one interface to the
-         * global setting one way. This means: as long as at least one
-         * interface was configured at any time that had IP forwarding
-         * enabled the setting will stay on for good. We do this
-         * primarily to keep IPv4 and IPv6 packet forwarding behaviour
-         * somewhat in sync (see below). */
+        /* If IPv6SendRA= is enabled, also enable IPv6 forwarding. */
+        if (family == AF_INET6 && link_radv_enabled(link))
+                return true;
 
-        return sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1");
+        /* Otherwise, use the global setting. */
+        return link->manager->ip_forwarding[family == AF_INET6];
 }
 
-static int link_set_ipv6_forward(Link *link) {
+static int link_set_ip_forwarding(Link *link, int family) {
+        int r, t;
+
         assert(link);
+        assert(IN_SET(family, AF_INET, AF_INET6));
 
-        if (!link_ip_forward_enabled(link, AF_INET6))
+        if (!link_is_configured_for_family(link, family))
                 return 0;
 
-        /* On Linux, the IPv6 stack does not know a per-interface
-         * packet forwarding setting: either packet forwarding is on
-         * for all, or off for all. We hence don't bother with a
-         * per-interface setting, but simply propagate the interface
-         * flag, if it is set, to the global flag, one-way. Note that
-         * while IPv4 would allow a per-interface flag, we expose the
-         * same behaviour there and also propagate the setting from
-         * one to all, to keep things simple (see above). */
+        t = link_get_ip_forwarding(link, family);
+        if (t < 0)
+                return 0; /* keep */
 
-        return sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1");
+        r = sysctl_write_ip_property_boolean(family, link->ifname, "forwarding", t);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to %s %s forwarding, ignoring: %m",
+                                              enable_disable(t), af_to_ipv4_ipv6(family));
+
+        return 0;
 }
 
 static int link_set_ipv4_rp_filter(Link *link) {
@@ -291,13 +328,8 @@ int link_set_sysctl(Link *link) {
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot configure proxy ARP private VLAN for interface, ignoring: %m");
 
-        r = link_set_ipv4_forward(link);
-        if (r < 0)
-                log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
-
-        r = link_set_ipv6_forward(link);
-        if (r < 0)
-                log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
+        (void) link_set_ip_forwarding(link, AF_INET);
+        (void) link_set_ip_forwarding(link, AF_INET6);
 
         r = link_set_ipv6_privacy_extensions(link);
         if (r < 0)
@@ -371,3 +403,24 @@ static const char* const ip_reverse_path_filter_table[_IP_REVERSE_PATH_FILTER_MA
 DEFINE_STRING_TABLE_LOOKUP(ip_reverse_path_filter, IPReversePathFilter);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_ip_reverse_path_filter, ip_reverse_path_filter, IPReversePathFilter,
                          "Failed to parse IP reverse path filter option");
+
+int config_parse_ip_forward_deprecated(
+                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) {
+
+        assert(filename);
+
+        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                   "IPForward= setting is deprecated. "
+                   "Please use IPv4Forwarding= and/or IPv6Forwarding= in networkd.conf for global setting, "
+                   "and the same settings in .network files for per-interface setting.");
+        return 0;
+}
index 064438462c014276faf0aa31a225d88903edca2d..a47dda015defbb86579f2a04e89b63dea05dfbcd 100644 (file)
@@ -6,6 +6,7 @@
 #include "conf-parser.h"
 
 typedef struct Link Link;
+typedef struct Manager Manager;
 
 typedef enum IPv6PrivacyExtensions {
         /* These values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values. Do not reorder! */
@@ -26,6 +27,9 @@ typedef enum IPReversePathFilter {
         _IP_REVERSE_PATH_FILTER_INVALID = -EINVAL,
 } IPReversePathFilter;
 
+void manager_set_sysctl(Manager *manager);
+
+int link_get_ip_forwarding(Link *link, int family);
 int link_set_sysctl(Link *link);
 int link_set_ipv6_mtu(Link *link);
 
@@ -37,3 +41,4 @@ IPReversePathFilter ip_reverse_path_filter_from_string(const char *s) _pure_;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
 CONFIG_PARSER_PROTOTYPE(config_parse_ip_reverse_path_filter);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_forward_deprecated);
index 33352ba772ec34c722408bff13073d26c8d20536..46f90088790e0203ddb75489952d12bf9f9fdeab 100644 (file)
@@ -116,48 +116,6 @@ DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFa
 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(ip_masquerade_address_family, AddressFamily);
 DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type_t);
 
-int config_parse_address_family_with_kernel(
-                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) {
-
-        AddressFamily *fwd = data, s;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        /* This function is mostly obsolete now. It simply redirects
-         * "kernel" to "no". In older networkd versions we used to
-         * distinguish IPForward=off from IPForward=kernel, where the
-         * former would explicitly turn off forwarding while the
-         * latter would simply not touch the setting. But that logic
-         * is gone, hence silently accept the old setting, but turn it
-         * to "no". */
-
-        s = address_family_from_string(rvalue);
-        if (s < 0) {
-                if (streq(rvalue, "kernel"))
-                        s = ADDRESS_FAMILY_NO;
-                else {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
-                        return 0;
-                }
-        }
-
-        *fwd = s;
-
-        return 0;
-}
-
 int config_parse_ip_masquerade(
                 const char *unit,
                 const char *filename,
index 9c360f55264f2db1ce6d56b6e392a959cbe1a4d0..c3b4586caead7d2df9b37981a9393efca323417d 100644 (file)
@@ -52,7 +52,6 @@ static inline uint32_t usec_to_sec(usec_t usec, usec_t now_usec) {
 }
 
 CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family);
-CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
 CONFIG_PARSER_PROTOTYPE(config_parse_ip_masquerade);
 CONFIG_PARSER_PROTOTYPE(config_parse_mud_url);
 
index 46c2c743467fcb01980f82b158c38a07cab5e04b..3384c7c3eae094eb9ad6d00d87e2f922ac11ef06 100644 (file)
@@ -18,6 +18,7 @@
 #include "networkd-manager.h"
 #include "service-util.h"
 #include "signal-util.h"
+#include "strv.h"
 #include "user-util.h"
 
 static int run(int argc, char *argv[]) {
@@ -69,17 +70,14 @@ static int run(int argc, char *argv[]) {
         /* Always create the directories people can create inotify watches in.
          * It is necessary to create the following subdirectories after drop_privileges()
          * to support old kernels not supporting AmbientCapabilities=. */
-        r = mkdir_safe_label("/run/systemd/netif/links", 0755, UID_INVALID, GID_INVALID, MKDIR_WARN_MODE);
-        if (r < 0)
-                log_warning_errno(r, "Could not create runtime directory 'links': %m");
-
-        r = mkdir_safe_label("/run/systemd/netif/leases", 0755, UID_INVALID, GID_INVALID, MKDIR_WARN_MODE);
-        if (r < 0)
-                log_warning_errno(r, "Could not create runtime directory 'leases': %m");
-
-        r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, UID_INVALID, GID_INVALID, MKDIR_WARN_MODE);
-        if (r < 0)
-                log_warning_errno(r, "Could not create runtime directory 'lldp': %m");
+        FOREACH_STRING(p,
+                       "/run/systemd/netif/links/",
+                       "/run/systemd/netif/leases/",
+                       "/run/systemd/netif/lldp/") {
+                r = mkdir_safe_label(p, 0755, UID_INVALID, GID_INVALID, MKDIR_WARN_MODE);
+                if (r < 0)
+                        log_warning_errno(r, "Could not create directory '%s': %m", p);
+        }
 
         r = manager_new(&m, /* test_mode = */ false);
         if (r < 0)
index 544c360eddcf980355c45c3e0d392cf21a08bb4d..4f8270ddfadbea6b8f511602fc4b4546bc310c6f 100644 (file)
@@ -204,7 +204,7 @@ static int run(int argc, char *argv[]) {
         if (arg_quiet)
                 log_set_max_level(LOG_ERR);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
 
         r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_required_family, arg_any, arg_timeout);
         if (r < 0)
index 49b57c51683463edcd3cf22c72b33658989d5428..1cb039ade4ae99407ee11fe1dd6bc332034a0ac3 100644 (file)
@@ -4443,6 +4443,9 @@ static void set_window_title(PTYForward *f) {
                 (void) pty_forward_set_titlef(f, "%sContainer %s on %s", strempty(dot), arg_machine, hn);
         else
                 (void) pty_forward_set_titlef(f, "%sContainer %s", strempty(dot), arg_machine);
+
+        if (dot)
+                (void) pty_forward_set_title_prefix(f, dot);
 }
 
 static int merge_settings(Settings *settings, const char *path) {
@@ -5988,13 +5991,15 @@ static int run(int argc, char *argv[]) {
                 _cleanup_free_ char *u = NULL;
                 (void) terminal_urlify_path(t, t, &u);
 
-                log_info("%s %sSpawning container %s on %s.%s\n"
-                         "%s %sPress %sCtrl-]%s three times within 1s to kill container.%s",
-                         special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), arg_machine, u ?: t, ansi_normal(),
-                         special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_normal());
+                log_info("%s %sSpawning container %s on %s.%s",
+                         special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), arg_machine, u ?: t, ansi_normal());
+
+                if (arg_console_mode == CONSOLE_INTERACTIVE)
+                        log_info("%s %sPress %sCtrl-]%s three times within 1s to kill container.%s",
+                                 special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_normal());
         }
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, SIGRTMIN+18) >= 0);
 
         r = make_reaper_process(true);
         if (r < 0) {
index ecc2eda5dc00fcf3920eef0b3fa756512d16b540..b43635d6d4411c49bb1f4cd49a727df21a641955 100644 (file)
@@ -164,7 +164,7 @@ static int run(int argc, char *argv[]) {
         if (!FLAGS_SET(mask, CGROUP_MASK_MEMORY))
                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Requires the cgroup memory controller.");
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
 
         if (arg_mem_pressure_usec > 0 && arg_mem_pressure_usec < 1 * USEC_PER_SEC)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DefaultMemoryPressureDurationSec= must be 0 or at least 1s");
index d4a01fa53b0f3a84ad0363b6243ba29324b1654b..d46ac018a308bcd91ae9966ee5b513a8a1475606 100644 (file)
@@ -141,7 +141,7 @@ static int run(int argc, char *argv[]) {
         if (argc != 1)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index 8788bd6b0bfd4c7eea5bfd86212641193f8a6752..a373b610b0eb9608047994e405b2167559df8117 100644 (file)
@@ -28,8 +28,9 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL);
 /* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
 #define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
 
-/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */
-#define NSEC3_ITERATIONS_MAX 2500
+/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value, but
+ * RFC9276 Â§ 3.2 says that we should reduce the acceptable iteration count */
+#define NSEC3_ITERATIONS_MAX 100
 
 /*
  * The DNSSEC Chain of trust:
@@ -1169,6 +1170,7 @@ int dnssec_verify_rrset_search(
                 DnsResourceRecord **ret_rrsig) {
 
         bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
+        unsigned nvalidations = 0;
         DnsResourceRecord *rrsig;
         int r;
 
@@ -1214,6 +1216,14 @@ int dnssec_verify_rrset_search(
                         if (realtime == USEC_INFINITY)
                                 realtime = now(CLOCK_REALTIME);
 
+                        /* Have we seen an unreasonable number of invalid signaures? */
+                        if (nvalidations > DNSSEC_INVALID_MAX) {
+                                if (ret_rrsig)
+                                        *ret_rrsig = NULL;
+                                *result = DNSSEC_TOO_MANY_VALIDATIONS;
+                                return (int) nvalidations;
+                        }
+
                         /* Yay, we found a matching RRSIG with a matching
                          * DNSKEY, awesome. Now let's verify all entries of
                          * the RRSet against the RRSIG and DNSKEY
@@ -1223,6 +1233,8 @@ int dnssec_verify_rrset_search(
                         if (r < 0)
                                 return r;
 
+                        nvalidations++;
+
                         switch (one_result) {
 
                         case DNSSEC_VALIDATED:
@@ -1233,7 +1245,7 @@ int dnssec_verify_rrset_search(
                                         *ret_rrsig = rrsig;
 
                                 *result = one_result;
-                                return 0;
+                                return (int) nvalidations;
 
                         case DNSSEC_INVALID:
                                 /* If the signature is invalid, let's try another
@@ -1280,7 +1292,7 @@ int dnssec_verify_rrset_search(
         if (ret_rrsig)
                 *ret_rrsig = NULL;
 
-        return 0;
+        return (int) nvalidations;
 }
 
 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
@@ -2565,6 +2577,7 @@ static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
         [DNSSEC_NSEC_MISMATCH]         = "nsec-mismatch",
         [DNSSEC_INCOMPATIBLE_SERVER]   = "incompatible-server",
         [DNSSEC_UPSTREAM_FAILURE]      = "upstream-failure",
+        [DNSSEC_TOO_MANY_VALIDATIONS]  = "too-many-validations",
 };
 DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
 
index 2f93a7f5852fbc279a9244d4e5be5398de107200..d8ff3bada987c6ae3044181e6d54957d9f1cb657 100644 (file)
@@ -9,12 +9,13 @@ typedef enum DnssecVerdict DnssecVerdict;
 #include "resolved-dns-rr.h"
 
 enum DnssecResult {
-        /* These five are returned by dnssec_verify_rrset() */
+        /* These six are returned by dnssec_verify_rrset() */
         DNSSEC_VALIDATED,
         DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */
         DNSSEC_INVALID,
         DNSSEC_SIGNATURE_EXPIRED,
         DNSSEC_UNSUPPORTED_ALGORITHM,
+        DNSSEC_TOO_MANY_VALIDATIONS,
 
         /* These two are added by dnssec_verify_rrset_search() */
         DNSSEC_NO_SIGNATURE,
@@ -46,6 +47,12 @@ enum DnssecVerdict {
 /* The longest digest we'll ever generate, of all digest algorithms we support */
 #define DNSSEC_HASH_SIZE_MAX (MAX(20, 32))
 
+/* The most invalid signatures we will tolerate for a single rrset */
+#define DNSSEC_INVALID_MAX 5
+
+/* The total number of signature validations we will tolerate for a single transaction */
+#define DNSSEC_VALIDATION_MAX 64
+
 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok);
 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig);
 
index a99f8e8a587f09d8eeacfa3553c7ac233729d849..954841bb7c0a5bd18b6b582a3c5909f26ee1759f 100644 (file)
@@ -3232,11 +3232,14 @@ static int dnssec_validate_records(
                 DnsTransaction *t,
                 Phase phase,
                 bool *have_nsec,
+                unsigned *nvalidations,
                 DnsAnswer **validated) {
 
         DnsResourceRecord *rr;
         int r;
 
+        assert(nvalidations);
+
         /* Returns negative on error, 0 if validation failed, 1 to restart validation, 2 when finished. */
 
         DNS_ANSWER_FOREACH(rr, t->answer) {
@@ -3278,6 +3281,7 @@ static int dnssec_validate_records(
                                 &rrsig);
                 if (r < 0)
                         return r;
+                *nvalidations += r;
 
                 log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result));
 
@@ -3475,7 +3479,8 @@ static int dnssec_validate_records(
                                            DNSSEC_SIGNATURE_EXPIRED,
                                            DNSSEC_NO_SIGNATURE))
                                         manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key);
-                                else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */
+                                else /* DNSSEC_MISSING_KEY, DNSSEC_UNSUPPORTED_ALGORITHM,
+                                        or DNSSEC_TOO_MANY_VALIDATIONS */
                                         manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key);
 
                                 /* This is a primary response to our question, and it failed validation.
@@ -3568,13 +3573,21 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
                 return r;
 
         phase = DNSSEC_PHASE_DNSKEY;
-        for (;;) {
+        for (unsigned nvalidations = 0;;) {
                 bool have_nsec = false;
 
-                r = dnssec_validate_records(t, phase, &have_nsec, &validated);
+                r = dnssec_validate_records(t, phase, &have_nsec, &nvalidations, &validated);
                 if (r <= 0)
                         return r;
 
+                if (nvalidations > DNSSEC_VALIDATION_MAX) {
+                        /* This reply requires an onerous number of signature validations to verify. Let's
+                         * not waste our time trying, as this shouldn't happen for well-behaved domains
+                         * anyway. */
+                        t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS;
+                        return 0;
+                }
+
                 /* Try again as long as we managed to achieve something */
                 if (r == 1)
                         continue;
index 1625c5189d0e95ef8e244b5420bf13b1afd45c73..664e7dd6539cac040e5c7942315e9253bc3329ef 100644 (file)
@@ -67,7 +67,7 @@ static int run(int argc, char *argv[]) {
                         return log_error_errno(r, "Failed to drop privileges: %m");
         }
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index b42ed44231053c34826c52fba2ff16a6b04c3da6..5181c18c20151f952ecd1a19f98b2950113d644f 100644 (file)
@@ -1610,6 +1610,8 @@ static void set_window_title(PTYForward *f) {
                 (void) pty_forward_set_titlef(f, "%s%s on %s", strempty(dot), cl, arg_host ?: hn);
         else
                 (void) pty_forward_set_titlef(f, "%s%s", strempty(dot), cl);
+
+        (void) pty_forward_set_title_prefix(f, dot);
 }
 
 static int start_transient_service(sd_bus *bus) {
@@ -1749,9 +1751,9 @@ static int start_transient_service(sd_bus *bus) {
                         return log_error_errno(r, "Failed to get event loop: %m");
 
                 if (master >= 0) {
-                        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
-                        (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL);
-                        (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL);
+                        assert_se(sigprocmask_many(SIG_BLOCK, /* old_sigset=*/ NULL, SIGWINCH) >= 0);
+
+                        (void) sd_event_set_signal_exit(c.event, true);
 
                         if (!arg_quiet)
                                 log_info("Press ^] three times within 1s to disconnect TTY.");
index 462b3d2e003b5c6d9aa8958e398d5f478c3033c1..bf79dc2633ca33048226f0292a80fd054bc16431 100644 (file)
@@ -713,7 +713,7 @@ int ask_password_agent(
                 return -EUNATCH;
 
         assert_se(sigemptyset(&mask) >= 0);
-        assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0);
+        assert_se(sigset_add_many(&mask, SIGINT, SIGTERM) >= 0);
         assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0);
 
         (void) mkdir_p_label("/run/systemd/ask-password", 0755);
index 36e1f94ca0b953cfa92bc4d8e6d29da4641c3097..b169eb0ba5a50ce8f59abfff2703f69dcb0f797b 100644 (file)
@@ -134,7 +134,7 @@ int table_set_sort_internal(Table *t, size_t first_column, ...);
 #define table_set_sort(...) table_set_sort_internal(__VA_ARGS__, SIZE_MAX)
 int table_set_reverse(Table *t, size_t column, bool b);
 int table_hide_column_from_display_internal(Table *t, ...);
-#define table_hide_column_from_display(t, ...) table_hide_column_from_display_internal(t, __VA_ARGS__, (size_t) -1)
+#define table_hide_column_from_display(t, ...) table_hide_column_from_display_internal(t, __VA_ARGS__, SIZE_MAX)
 
 int table_print(Table *t, FILE *f);
 int table_format(Table *t, char **ret);
index 946da5f42ddc752561be42726ca83cfb8010c481..a4e5809446c4c7b59548384b271e342c60ed0c5d 100644 (file)
@@ -452,7 +452,7 @@ int terminal_tint_color(double hue, char **ret) {
         else        /* otherwise pump it up */
                 s = 75;
 
-        v = MAX(30, v); /* Make sure we don't hide the color in black */
+        v = MAX(20, v); /* Make sure we don't hide the color in black */
 
         uint8_t r8, g8, b8;
         hsv_to_rgb(hue, s, v, &r8, &g8, &b8);
index df37325bd0bc3dd498bca14ccbf1d42de01c777f..f910f3aaf91b7659e2a76ff69054c3192d416cfd 100644 (file)
@@ -33,6 +33,7 @@ typedef enum AnsiColorState  {
         ANSI_COLOR_STATE_TEXT,
         ANSI_COLOR_STATE_ESC,
         ANSI_COLOR_STATE_CSI_SEQUENCE,
+        ANSI_COLOR_STATE_OSC_SEQUENCE,
         ANSI_COLOR_STATE_NEWLINE,
         ANSI_COLOR_STATE_CARRIAGE_RETURN,
         _ANSI_COLOR_STATE_MAX,
@@ -92,8 +93,10 @@ struct PTYForward {
         char *background_color;
         AnsiColorState ansi_color_state;
         char *csi_sequence;
+        char *osc_sequence;
 
-        char *title;
+        char *title;           /* Window title to show by default */
+        char *title_prefix;    /* If terminal client overrides window title, prefix this string */
 };
 
 #define ESCAPE_USEC (1*USEC_PER_SEC)
@@ -145,6 +148,7 @@ static void pty_forward_disconnect(PTYForward *f) {
         f->in_buffer_full = 0;
 
         f->csi_sequence = mfree(f->csi_sequence);
+        f->osc_sequence = mfree(f->osc_sequence);
         f->ansi_color_state = _ANSI_COLOR_STATE_INVALID;
 }
 
@@ -367,7 +371,9 @@ static int is_csi_background_reset_sequence(const char *seq) {
 
 static int insert_background_fix(PTYForward *f, size_t offset) {
         assert(f);
-        assert(f->background_color);
+
+        if (!f->background_color)
+                return 0;
 
         if (!is_csi_background_reset_sequence(strempty(f->csi_sequence)))
                 return 0;
@@ -380,13 +386,33 @@ static int insert_background_fix(PTYForward *f, size_t offset) {
         return insert_string(f, offset, s);
 }
 
+static int insert_window_title_fix(PTYForward *f, size_t offset) {
+        assert(f);
+
+        if (!f->title_prefix)
+                return 0;
+
+        if (!f->osc_sequence)
+                return 0;
+
+        const char *t = startswith(f->osc_sequence, "0;"); /* Set window title OSC sequence*/
+        if (!t)
+                return 0;
+
+        _cleanup_free_ char *joined = strjoin("\x1b]0;", f->title_prefix, t, "\a");
+        if (!joined)
+                return -ENOMEM;
+
+        return insert_string(f, offset, joined);
+}
+
 static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
         int r;
 
         assert(f);
         assert(offset <= f->out_buffer_full);
 
-        if (!f->background_color)
+        if (!f->background_color && !f->title_prefix)
                 return 0;
 
         if (FLAGS_SET(f->flags, PTY_FORWARD_DUMB_TERMINAL))
@@ -427,6 +453,9 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
                         if (c == '[') {
                                 f->ansi_color_state = ANSI_COLOR_STATE_CSI_SEQUENCE;
                                 continue;
+                        } else if (c == ']') {
+                                f->ansi_color_state = ANSI_COLOR_STATE_OSC_SEQUENCE;
+                                continue;
                         }
 
                         break;
@@ -464,6 +493,33 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
                         continue;
                 }
 
+                case ANSI_COLOR_STATE_OSC_SEQUENCE: {
+
+                        if ((uint8_t) c >= ' ') {
+                                if (strlen_ptr(f->osc_sequence) >= 64) {
+                                        /* Safety check: lets not accept unbounded OSC sequences */
+                                        f->osc_sequence = mfree(f->osc_sequence);
+                                        break;
+                                } else if (!strextend(&f->osc_sequence, CHAR_TO_STR(c)))
+                                        return -ENOMEM;
+                        } else {
+                                /* Otherwise, the OSC sequence is over */
+
+                                if (c == '\x07') {
+                                        r = insert_window_title_fix(f, i+1);
+                                        if (r < 0)
+                                                return r;
+
+                                        i += r;
+                                }
+
+                                f->osc_sequence = mfree(f->osc_sequence);
+                                f->ansi_color_state = ANSI_COLOR_STATE_TEXT;
+                        }
+
+                        continue;
+                }
+
                 default:
                         assert_not_reached();
                 }
@@ -888,6 +944,7 @@ PTYForward *pty_forward_free(PTYForward *f) {
         pty_forward_disconnect(f);
         free(f->background_color);
         free(f->title);
+        free(f->title_prefix);
         return mfree(f);
 }
 
@@ -1060,3 +1117,9 @@ int pty_forward_set_titlef(PTYForward *f, const char *format, ...) {
 
         return free_and_replace(f->title, title);
 }
+
+int pty_forward_set_title_prefix(PTYForward *f, const char *title_prefix) {
+        assert(f);
+
+        return free_and_strdup(&f->title_prefix, title_prefix);
+}
index f87becd0308b4f1afdf6c7121753d6cacaf1be39..248646d764b0ad0afa888acda3cadc8bbadda4d0 100644 (file)
@@ -44,7 +44,10 @@ int pty_forward_set_priority(PTYForward *f, int64_t priority);
 int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height);
 
 int pty_forward_set_background_color(PTYForward *f, const char *color);
+
 int pty_forward_set_title(PTYForward *f, const char *title);
 int pty_forward_set_titlef(PTYForward *f, const char *format, ...) _printf_(2,3);
 
+int pty_forward_set_title_prefix(PTYForward *f, const char *prefix);
+
 DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free);
index 7477d42de863a54c097e0abe94acd6974920acc9..feb1e52feb7d932fd5274ff243df367cce350ce7 100644 (file)
@@ -2,17 +2,19 @@
 
 #include "varlink-io.systemd.Network.h"
 
-static VARLINK_DEFINE_METHOD(GetStates,
-                             VARLINK_DEFINE_OUTPUT(AddressState, VARLINK_STRING, 0),
-                             VARLINK_DEFINE_OUTPUT(IPv4AddressState, VARLINK_STRING, 0),
-                             VARLINK_DEFINE_OUTPUT(IPv6AddressState, VARLINK_STRING, 0),
-                             VARLINK_DEFINE_OUTPUT(CarrierState, VARLINK_STRING, 0),
-                             VARLINK_DEFINE_OUTPUT(OnlineState, VARLINK_STRING, VARLINK_NULLABLE),
-                             VARLINK_DEFINE_OUTPUT(OperationalState, VARLINK_STRING, 0));
+static VARLINK_DEFINE_METHOD(
+                GetStates,
+                VARLINK_DEFINE_OUTPUT(AddressState, VARLINK_STRING, 0),
+                VARLINK_DEFINE_OUTPUT(IPv4AddressState, VARLINK_STRING, 0),
+                VARLINK_DEFINE_OUTPUT(IPv6AddressState, VARLINK_STRING, 0),
+                VARLINK_DEFINE_OUTPUT(CarrierState, VARLINK_STRING, 0),
+                VARLINK_DEFINE_OUTPUT(OnlineState, VARLINK_STRING, VARLINK_NULLABLE),
+                VARLINK_DEFINE_OUTPUT(OperationalState, VARLINK_STRING, 0));
 
-static VARLINK_DEFINE_METHOD(GetNamespaceId,
-                             VARLINK_DEFINE_OUTPUT(NamespaceId, VARLINK_INT, 0),
-                             VARLINK_DEFINE_OUTPUT(NamespaceNSID, VARLINK_INT, VARLINK_NULLABLE));
+static VARLINK_DEFINE_METHOD(
+                GetNamespaceId,
+                VARLINK_DEFINE_OUTPUT(NamespaceId, VARLINK_INT, 0),
+                VARLINK_DEFINE_OUTPUT(NamespaceNSID, VARLINK_INT, VARLINK_NULLABLE));
 
 VARLINK_DEFINE_INTERFACE(
                 io_systemd_Network,
index e81afee058f8982ebc40643f41952a3af0eb28bd..7926bfbecafc6933bb70b01ac2befbc917e4f593 100644 (file)
@@ -2200,96 +2200,6 @@ static int show_one(
         return 0;
 }
 
-static int get_unit_dbus_path_by_pid_fallback(
-                sd_bus *bus,
-                uint32_t pid,
-                char **ret_path,
-                char **ret_unit) {
-
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_free_ char *path = NULL, *unit = NULL;
-        char *p;
-        int r;
-
-        assert(bus);
-        assert(ret_path);
-        assert(ret_unit);
-
-        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", pid);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
-
-        r = sd_bus_message_read(reply, "o", &p);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        path = strdup(p);
-        if (!path)
-                return log_oom();
-
-        r = unit_name_from_dbus_path(path, &unit);
-        if (r < 0)
-                return log_oom();
-
-        *ret_unit = TAKE_PTR(unit);
-        *ret_path = TAKE_PTR(path);
-
-        return 0;
-}
-
-static int get_unit_dbus_path_by_pid(
-                sd_bus *bus,
-                uint32_t pid,
-                char **ret_path,
-                char **ret_unit) {
-
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_free_ char *path = NULL, *unit = NULL;
-        _cleanup_close_ int pidfd = -EBADF;
-        char *p, *u;
-        int r;
-
-        assert(bus);
-        assert(ret_path);
-        assert(ret_unit);
-
-        /* First, try to send a PIDFD across the wire, so that we can pin the process and there's no race
-         * condition possible while we wait for the D-Bus reply. If we either don't have PIDFD support in
-         * the kernel or the new D-Bus method is not available, then fallback to the older method that
-         * sends the numeric PID. */
-
-        pidfd = pidfd_open(pid, 0);
-        if (pidfd < 0 && ERRNO_IS_NOT_SUPPORTED(errno))
-                return get_unit_dbus_path_by_pid_fallback(bus, pid, ret_path, ret_unit);
-        if (pidfd < 0)
-                return log_error_errno(errno, "Failed to open PID %"PRIu32": %m", pid);
-
-        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPIDFD", &error, &reply, "h", pidfd);
-        if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
-                return get_unit_dbus_path_by_pid_fallback(bus, pid, ret_path, ret_unit);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
-
-        r = sd_bus_message_read(reply, "os", &p, &u);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        path = strdup(p);
-        if (!path)
-                return log_oom();
-
-        unit = strdup(u);
-        if (!unit)
-                return log_oom();
-
-        *ret_unit = TAKE_PTR(unit);
-        *ret_path = TAKE_PTR(path);
-
-        return 0;
-}
-
 static int show_all(
                 sd_bus *bus,
                 SystemctlShowMode show_mode,
@@ -2461,9 +2371,9 @@ int verb_show(int argc, char *argv[], void *userdata) {
 
                         } else {
                                 /* Interpret as PID */
-                                r = get_unit_dbus_path_by_pid(bus, id, &path, &unit);
+                                r = lookup_unit_by_pidref(bus, (pid_t) id, &unit, &path);
                                 if (r < 0) {
-                                        ret = r;
+                                        RET_GATHER(ret, r);
                                         continue;
                                 }
                         }
index de6f53aafe64a789fde630ca1c4c8b90b049860d..c3da750d641d2aaad48b2ce7ef57ea148da2b620 100644 (file)
@@ -18,6 +18,8 @@
 #include "glob-util.h"
 #include "macro.h"
 #include "path-util.h"
+#include "pidref.h"
+#include "process-util.h"
 #include "reboot-util.h"
 #include "set.h"
 #include "spawn-ask-password-agent.h"
@@ -762,9 +764,7 @@ int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list) {
         if (r < 0)
                 return log_error_errno(r, "Failed to append unit dependencies: %m");
 
-        strv_free(*list);
-        *list = TAKE_PTR(list_with_deps);
-        return 0;
+        return strv_free_and_replace(*list, list_with_deps);
 }
 
 int unit_get_dependencies(sd_bus *bus, const char *name, char ***ret) {
@@ -987,3 +987,149 @@ int halt_now(enum action a) {
                 assert_not_reached();
         }
 }
+
+int get_unit_by_pid(sd_bus *bus, pid_t pid, char **ret_unit, char **ret_path) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        int r;
+
+        assert(bus);
+        assert(pid >= 0); /* 0 is accepted by GetUnitByPID for querying our own process. */
+
+        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", (uint32_t) pid);
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_UNIT_FOR_PID))
+                        return log_error_errno(r, "%s", bus_error_message(&error, r));
+
+                return log_error_errno(r,
+                                       "Failed to get unit that PID " PID_FMT " belongs to: %s",
+                                       pid > 0 ? pid : getpid_cached(),
+                                       bus_error_message(&error, r));
+        }
+
+        _cleanup_free_ char *u = NULL, *p = NULL;
+        const char *path;
+
+        r = sd_bus_message_read_basic(reply, 'o', &path);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (ret_unit) {
+                r = unit_name_from_dbus_path(path, &u);
+                if (r < 0)
+                        return log_error_errno(r,
+                                               "Failed to extract unit name from D-Bus object path '%s': %m",
+                                               path);
+        }
+
+        if (ret_path) {
+                p = strdup(path);
+                if (!p)
+                        return log_oom();
+        }
+
+        if (ret_unit)
+                *ret_unit = TAKE_PTR(u);
+        if (ret_path)
+                *ret_path = TAKE_PTR(p);
+
+        return 0;
+}
+
+static int get_unit_by_pidfd(sd_bus *bus, const PidRef *pid, char **ret_unit, char **ret_path) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        int r;
+
+        assert(bus);
+        assert(pidref_is_set(pid));
+
+        if (pid->fd < 0)
+                return -EOPNOTSUPP;
+
+        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPIDFD", &error, &reply, "h", pid->fd);
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
+                        return -EOPNOTSUPP;
+
+                if (sd_bus_error_has_names(&error, BUS_ERROR_NO_UNIT_FOR_PID, BUS_ERROR_NO_SUCH_PROCESS))
+                        return log_error_errno(r, "%s", bus_error_message(&error, r));
+
+                return log_error_errno(r,
+                                       "Failed to get unit that PID " PID_FMT " belongs to: %s",
+                                       pid->pid, bus_error_message(&error, r));
+        }
+
+        _cleanup_free_ char *u = NULL, *p = NULL;
+        const char *path, *unit;
+
+        r = sd_bus_message_read(reply, "os", &path, &unit);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (ret_unit) {
+                u = strdup(unit);
+                if (!u)
+                        return log_oom();
+        }
+
+        if (ret_path) {
+                p = strdup(path);
+                if (!p)
+                        return log_oom();
+        }
+
+        if (ret_unit)
+                *ret_unit = TAKE_PTR(u);
+        if (ret_path)
+                *ret_path = TAKE_PTR(p);
+
+        return 0;
+}
+
+int lookup_unit_by_pidref(sd_bus *bus, pid_t pid, char **ret_unit, char **ret_path) {
+        int r;
+
+        assert(bus);
+        assert(pid >= 0); /* 0 means our own process */
+
+        if (arg_transport != BUS_TRANSPORT_LOCAL)
+                return get_unit_by_pid(bus, pid, ret_unit, ret_path);
+
+        static bool use_pidfd = true;
+        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+
+        r = pidref_set_pid(&pidref, pid);
+        if (r < 0)
+                return log_error_errno(r,
+                                       r == -ESRCH ?
+                                       "PID " PID_FMT " doesn't exist or is already gone." :
+                                       "Failed to create reference to PID " PID_FMT ": %m",
+                                       pid);
+
+        if (use_pidfd) {
+                r = get_unit_by_pidfd(bus, &pidref, ret_unit, ret_path);
+                if (r != -EOPNOTSUPP)
+                        return r;
+
+                use_pidfd = false;
+                log_debug_errno(r, "Unable to look up process using pidfd, falling back to pid.");
+        }
+
+        _cleanup_free_ char *u = NULL, *p = NULL;
+
+        r = get_unit_by_pid(bus, pidref.pid, ret_unit ? &u : NULL, ret_path ? &p : NULL);
+        if (r < 0)
+                return r;
+
+        r = pidref_verify(&pidref);
+        if (r < 0)
+                return log_error_errno(r, "Failed to verify our reference to PID " PID_FMT ": %m", pidref.pid);
+
+        if (ret_unit)
+                *ret_unit = TAKE_PTR(u);
+        if (ret_path)
+                *ret_path = TAKE_PTR(p);
+
+        return 0;
+}
index 17975e110d3adaf0235dd960bc4aa234665914d5..a950dde51552beb3897076f8366db17a92105403 100644 (file)
@@ -58,3 +58,6 @@ int mangle_names(const char *operation, char * const *original_names, char ***re
 UnitFileFlags unit_file_flags_from_args(void);
 
 int halt_now(enum action a);
+
+int get_unit_by_pid(sd_bus *bus, pid_t pid, char **ret_unit, char **ret_path);
+int lookup_unit_by_pidref(sd_bus *bus, pid_t pid, char **ret_unit, char **ret_path);
index bac72c897397a9900a96949bf413d737fb44703f..607f2db047956710fbe89164248a7db7c875dd03 100644 (file)
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include "bus-common-errors.h"
-#include "bus-error.h"
-#include "bus-locator.h"
 #include "format-util.h"
 #include "parse-util.h"
-#include "pidref.h"
-#include "process-util.h"
 #include "systemctl.h"
 #include "systemctl-util.h"
 #include "systemctl-whoami.h"
 
-static int get_unit_by_pid(sd_bus *bus, pid_t pid, char **ret) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_free_ char *unit = NULL;
-        const char *path;
-        int r;
-
-        assert(bus);
-        assert(pid >= 0); /* 0 is accepted by GetUnitByPID for querying our own process. */
-        assert(ret);
-
-        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPID", &error, &reply, "u", (uint32_t) pid);
-        if (r < 0) {
-                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_UNIT_FOR_PID))
-                        return log_error_errno(r, "%s", bus_error_message(&error, r));
-
-                return log_error_errno(r,
-                                       "Failed to get unit that PID " PID_FMT " belongs to: %s",
-                                       pid > 0 ? pid : getpid_cached(),
-                                       bus_error_message(&error, r));
-        }
-
-        r = sd_bus_message_read_basic(reply, 'o', &path);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        r = unit_name_from_dbus_path(path, &unit);
-        if (r < 0)
-                return log_error_errno(r, "Failed to extract unit name from D-Bus object path '%s': %m", path);
-
-        *ret = TAKE_PTR(unit);
-        return 0;
-}
-
-static int lookup_pidfd(sd_bus *bus, const PidRef *pid, char **ret) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        const char *unit;
-        int r;
-
-        assert(bus);
-        assert(pidref_is_set(pid));
-        assert(ret);
-
-        if (pid->fd < 0)
-                return -EOPNOTSUPP;
-
-        r = bus_call_method(bus, bus_systemd_mgr, "GetUnitByPIDFD", &error, &reply, "h", pid->fd);
-        if (r < 0) {
-                if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
-                        return -EOPNOTSUPP;
-
-                if (sd_bus_error_has_names(&error, BUS_ERROR_NO_UNIT_FOR_PID, BUS_ERROR_NO_SUCH_PROCESS))
-                        return log_error_errno(r, "%s", bus_error_message(&error, r));
-
-                return log_error_errno(r,
-                                       "Failed to get unit that PID " PID_FMT " belongs to: %s",
-                                       pid->pid, bus_error_message(&error, r));
-        }
-
-        r = sd_bus_message_read(reply, "os", NULL, &unit);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        char *u = strdup(unit);
-        if (!u)
-                return log_oom();
-
-        *ret = TAKE_PTR(u);
-
-        return 0;
-}
-
-static int lookup_pid(sd_bus *bus, const char *pidstr) {
-        _cleanup_free_ char *unit = NULL;
-        int r;
-
-        assert(bus);
-        assert(pidstr);
-
-        if (arg_transport == BUS_TRANSPORT_LOCAL) {
-                static bool use_pidfd = true;
-                _cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
-
-                r = pidref_set_pidstr(&pid, pidstr);
-                if (r < 0)
-                        return log_error_errno(r,
-                                               r == -ESRCH ?
-                                               "PID %s doesn't exist or is already gone." :
-                                               "Failed to create reference to PID %s: %m",
-                                               pidstr);
-
-                if (use_pidfd) {
-                        r = lookup_pidfd(bus, &pid, &unit);
-                        if (r == -EOPNOTSUPP) {
-                                use_pidfd = false;
-                                log_debug_errno(r, "Unable to look up process using pidfd, ignoring.");
-                        } else if (r < 0)
-                                return r;
-                }
-
-                if (!use_pidfd) {
-                        assert(!unit);
-
-                        r = get_unit_by_pid(bus, pid.pid, &unit);
-                        if (r < 0)
-                                return r;
-
-                        r = pidref_verify(&pid);
-                        if (r < 0)
-                                return log_error_errno(r,
-                                                       "Failed to verify our reference to PID " PID_FMT ": %m",
-                                                       pid.pid);
-                }
-        } else {
-                pid_t pid;
-
-                r = parse_pid(pidstr, &pid);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse PID %s: %m", pidstr);
-
-                r = get_unit_by_pid(bus, pid, &unit);
-                if (r < 0)
-                        return r;
-        }
-
-        puts(unit);
-        return 0;
-}
-
 int verb_whoami(int argc, char *argv[], void *userdata) {
         sd_bus *bus;
-        int r;
+        int r, ret = 0;
 
         r = acquire_bus(BUS_FULL, &bus);
         if (r < 0)
@@ -153,11 +18,12 @@ int verb_whoami(int argc, char *argv[], void *userdata) {
                 _cleanup_free_ char *unit = NULL;
 
                 if (arg_transport != BUS_TRANSPORT_LOCAL)
-                        return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Refusing to look up our local PID on remote host.");
+                        return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
+                                               "Refusing to look up our local PID on remote host.");
 
-                /* Our own process can never go away while querying, hence no need to open pidfd. */
+                /* Our own process can never go away while querying, hence no need to go through pidfd. */
 
-                r = get_unit_by_pid(bus, 0, &unit);
+                r = get_unit_by_pid(bus, 0, &unit, /* ret_path = */ NULL);
                 if (r < 0)
                         return r;
 
@@ -165,10 +31,20 @@ int verb_whoami(int argc, char *argv[], void *userdata) {
                 return 0;
         }
 
-        r = 0;
+        STRV_FOREACH(pidstr, strv_skip(argv, 1)) {
+                _cleanup_free_ char *unit = NULL;
+                pid_t pid;
+
+                r = parse_pid(*pidstr, &pid);
+                if (r < 0)
+                        return log_error_errno(r, "Invalid PID specified: %s", *pidstr);
 
-        STRV_FOREACH(pid, strv_skip(argv, 1))
-                RET_GATHER(r, lookup_pid(bus, *pid));
+                r = lookup_unit_by_pidref(bus, pid, &unit, /* ret_path = */ NULL);
+                if (r < 0)
+                        RET_GATHER(ret, r);
+                else
+                        puts(unit);
+        }
 
-        return r;
+        return ret;
 }
index c128efc84d78304df543a6037687c4e3e5e762c6..d6174c6747389a87f85a34b86efc532d028f4e5f 100644 (file)
@@ -3,7 +3,6 @@
 #define foosddhcpclientidhfoo
 
 /***
-  Copyright Â© 2013 Intel Corporation. All rights reserved.
   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
index b1d2772a3eb93d325d493d8794d06e48a0bf7853..555b40e9d8911e5199b99b1ca82500f9f8911187 100644 (file)
@@ -3,7 +3,6 @@
 #define foosddhcpduidhfoo
 
 /***
-  Copyright Â© 2013 Intel Corporation. All rights reserved.
   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
index 1486ec7f119ca74887d9649241297c74e3631a22..2c31ec2d57e8b0e018a2a04101a9f3f667b643fa 100644 (file)
@@ -3,7 +3,6 @@
 #define foosddhcpoptionhfoo
 
 /***
-  Copyright Â© 2013 Intel Corporation. All rights reserved.
   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
index 754f71953b0051f73c9dfd7d12ea13d4c7709382..b5c9ba70d35605e760d06204ccbd839c4c34fc78 100644 (file)
@@ -3,7 +3,6 @@
 #define foosddhcpserverleasehfoo
 
 /***
-  Copyright Â© 2013 Intel Corporation. All rights reserved.
   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
index 93c5d2086117bd7def8b7f661e571eb1afba9d15..c6064b67958b7723561722116f8b2c36d645abe7 100644 (file)
@@ -3,8 +3,6 @@
 #define foosdndiscprotocolfoo
 
 /***
-  Copyright Â© 2014 Intel Corporation. All rights reserved.
-
   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
index 7f1a0229e8cd56f9c8cc3230f223c273dc6da591..7cde2979ac7e36f26575e35c5efe775eed92b379 100644 (file)
@@ -3,8 +3,6 @@
 #define foosdndiscrouterfoo
 
 /***
-  Copyright Â© 2014 Intel Corporation. All rights reserved.
-
   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
index 1bc7c738894e26227c426c8b514477160ec55915..94f6da04879d25205d4fc636c19b214d0ff982e6 100644 (file)
@@ -43,7 +43,7 @@ __extension__ typedef enum sd_ndisc_event_t {
         _SD_ENUM_FORCE_S64(NDISC_EVENT)
 } sd_ndisc_event_t;
 
-typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata);
+typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event_t event, void *message, void *userdata);
 
 int sd_ndisc_new(sd_ndisc **ret);
 sd_ndisc *sd_ndisc_ref(sd_ndisc *nd);
index 96422626f4c61af5d0089ba4d3c0507fd0d84fff..5b7aee2b54c29b3dd63c18b6042c21d07cb73951 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "alloc-util.h"
 #include "blockdev-util.h"
+#include "build-path.h"
 #include "chase.h"
 #include "device-util.h"
 #include "devnum-util.h"
@@ -300,7 +301,7 @@ static int download_manifest(
                 /* Child */
 
                 const char *cmdline[] = {
-                        "systemd-pull",
+                        SYSTEMD_PULL_PATH,
                         "raw",
                         "--direct",                        /* just download the specified URL, don't download anything else */
                         "--verify", verify_signature ? "signature" : "no", /* verify the manifest file */
@@ -309,8 +310,8 @@ static int download_manifest(
                         NULL
                 };
 
-                execv(pull_binary_path(), (char *const*) cmdline);
-                log_error_errno(errno, "Failed to execute %s tool: %m", pull_binary_path());
+                r = invoke_callout_binary(SYSTEMD_PULL_PATH, (char *const*) cmdline);
+                log_error_errno(r, "Failed to execute %s tool: %m", SYSTEMD_PULL_PATH);
                 _exit(EXIT_FAILURE);
         };
 
index f8f4a154f99b6797197990a5bb9c7c6ec2dde8f8..b350f83065e2347d78154c56e81037fa32a8beaa 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "alloc-util.h"
 #include "blockdev-util.h"
+#include "build-path.h"
 #include "chase.h"
 #include "conf-parser.h"
 #include "dirent-util.h"
@@ -782,25 +783,23 @@ static void compile_pattern_fields(
         memcpy(ret->sha256sum, i->metadata.sha256sum, sizeof(ret->sha256sum));
 }
 
-static int run_helper(
+static int run_callout(
                 const char *name,
-                const char *path,
-                const char * const cmdline[]) {
+                char *cmdline[]) {
 
         int r;
 
         assert(name);
-        assert(path);
         assert(cmdline);
+        assert(cmdline[0]);
 
         r = safe_fork(name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
         if (r < 0)
                 return r;
         if (r == 0) {
                 /* Child */
-
-                execv(path, (char *const*) cmdline);
-                log_error_errno(errno, "Failed to execute %s tool: %m", path);
+                r = invoke_callout_binary(cmdline[0], (char *const*) cmdline);
+                log_error_errno(r, "Failed to execute %s tool: %m", cmdline[0]);
                 _exit(EXIT_FAILURE);
         }
 
@@ -907,36 +906,30 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
                          * importer has some tricks up its sleeve, such as sparse file generation, which we
                          * want to take benefit of, too.) */
 
-                        r = run_helper("(sd-import-raw)",
-                                       import_binary_path(),
-                                       (const char* const[]) {
-                                               "systemd-import",
+                        r = run_callout("(sd-import-raw)",
+                                        STRV_MAKE(
+                                               SYSTEMD_IMPORT_PATH,
                                                "raw",
                                                "--direct",          /* just copy/unpack the specified file, don't do anything else */
                                                arg_sync ? "--sync=yes" : "--sync=no",
                                                i->path,
-                                               t->temporary_path,
-                                               NULL
-                                       });
+                                               t->temporary_path));
                         break;
 
                 case RESOURCE_PARTITION:
 
                         /* regular file â†’ partition */
 
-                        r = run_helper("(sd-import-raw)",
-                                       import_binary_path(),
-                                       (const char* const[]) {
-                                               "systemd-import",
+                        r = run_callout("(sd-import-raw)",
+                                        STRV_MAKE(
+                                               SYSTEMD_IMPORT_PATH,
                                                "raw",
                                                "--direct",          /* just copy/unpack the specified file, don't do anything else */
                                                "--offset", offset,
                                                "--size-max", max_size,
                                                arg_sync ? "--sync=yes" : "--sync=no",
                                                i->path,
-                                               t->target.path,
-                                               NULL
-                                       });
+                                               t->target.path));
                         break;
 
                 default:
@@ -951,18 +944,15 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
 
                 /* directory/subvolume â†’ directory/subvolume */
 
-                r = run_helper("(sd-import-fs)",
-                               import_fs_binary_path(),
-                               (const char* const[]) {
-                                       "systemd-import-fs",
+                r = run_callout("(sd-import-fs)",
+                                STRV_MAKE(
+                                       SYSTEMD_IMPORT_FS_PATH,
                                        "run",
                                        "--direct",          /* just untar the specified file, don't do anything else */
                                        arg_sync ? "--sync=yes" : "--sync=no",
                                        t->target.type == RESOURCE_SUBVOLUME ? "--btrfs-subvol=yes" : "--btrfs-subvol=no",
                                        i->path,
-                                       t->temporary_path,
-                                       NULL
-                               });
+                                       t->temporary_path));
                 break;
 
         case RESOURCE_TAR:
@@ -970,18 +960,15 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
 
                 /* tar â†’ directory/subvolume */
 
-                r = run_helper("(sd-import-tar)",
-                               import_binary_path(),
-                               (const char* const[]) {
-                                       "systemd-import",
+                r = run_callout("(sd-import-tar)",
+                                STRV_MAKE(
+                                       SYSTEMD_IMPORT_PATH,
                                        "tar",
                                        "--direct",          /* just untar the specified file, don't do anything else */
                                        arg_sync ? "--sync=yes" : "--sync=no",
                                        t->target.type == RESOURCE_SUBVOLUME ? "--btrfs-subvol=yes" : "--btrfs-subvol=no",
                                        i->path,
-                                       t->temporary_path,
-                                       NULL
-                               });
+                                       t->temporary_path));
                 break;
 
         case RESOURCE_URL_FILE:
@@ -992,28 +979,24 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
 
                         /* url file â†’ regular file */
 
-                        r = run_helper("(sd-pull-raw)",
-                                       pull_binary_path(),
-                                       (const char* const[]) {
-                                               "systemd-pull",
+                        r = run_callout("(sd-pull-raw)",
+                                       STRV_MAKE(
+                                               SYSTEMD_PULL_PATH,
                                                "raw",
                                                "--direct",          /* just download the specified URL, don't download anything else */
                                                "--verify", digest,  /* validate by explicit SHA256 sum */
                                                arg_sync ? "--sync=yes" : "--sync=no",
                                                i->path,
-                                               t->temporary_path,
-                                               NULL
-                                       });
+                                               t->temporary_path));
                         break;
 
                 case RESOURCE_PARTITION:
 
                         /* url file â†’ partition */
 
-                        r = run_helper("(sd-pull-raw)",
-                                       pull_binary_path(),
-                                       (const char* const[]) {
-                                               "systemd-pull",
+                        r = run_callout("(sd-pull-raw)",
+                                        STRV_MAKE(
+                                               SYSTEMD_PULL_PATH,
                                                "raw",
                                                "--direct",              /* just download the specified URL, don't download anything else */
                                                "--verify", digest,      /* validate by explicit SHA256 sum */
@@ -1021,9 +1004,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
                                                "--size-max", max_size,
                                                arg_sync ? "--sync=yes" : "--sync=no",
                                                i->path,
-                                               t->target.path,
-                                               NULL
-                                       });
+                                               t->target.path));
                         break;
 
                 default:
@@ -1035,19 +1016,16 @@ int transfer_acquire_instance(Transfer *t, Instance *i) {
         case RESOURCE_URL_TAR:
                 assert(IN_SET(t->target.type, RESOURCE_DIRECTORY, RESOURCE_SUBVOLUME));
 
-                r = run_helper("(sd-pull-tar)",
-                               pull_binary_path(),
-                               (const char*const[]) {
-                                       "systemd-pull",
+                r = run_callout("(sd-pull-tar)",
+                                STRV_MAKE(
+                                       SYSTEMD_PULL_PATH,
                                        "tar",
                                        "--direct",          /* just download the specified URL, don't download anything else */
                                        "--verify", digest,  /* validate by explicit SHA256 sum */
                                        t->target.type == RESOURCE_SUBVOLUME ? "--btrfs-subvol=yes" : "--btrfs-subvol=no",
                                        arg_sync ? "--sync=yes" : "--sync=no",
                                        i->path,
-                                       t->temporary_path,
-                                       NULL
-                               });
+                                       t->temporary_path));
                 break;
 
         default:
index 6d387b7a5d3723e08b5eb6a681a49473acc7d49c..cba9bf489f8b87fcfa07aa8edd6192bcbf952801 100644 (file)
@@ -7,15 +7,3 @@
 extern bool arg_sync;
 extern uint64_t arg_instances_max;
 extern char *arg_root;
-
-static inline const char* import_binary_path(void) {
-        return secure_getenv("SYSTEMD_IMPORT_PATH") ?: SYSTEMD_IMPORT_PATH;
-}
-
-static inline const char* import_fs_binary_path(void) {
-        return secure_getenv("SYSTEMD_IMPORT_FS_PATH") ?: SYSTEMD_IMPORT_FS_PATH;
-}
-
-static inline const char *pull_binary_path(void) {
-        return secure_getenv("SYSTEMD_PULL_PATH") ?: SYSTEMD_PULL_PATH;
-}
index 877005e82f7cce064f69678047e7a7b0b7d886d1..c628eaa7dbe9f3dfa46b59e627f0e8b0f38424a5 100644 (file)
@@ -51,6 +51,7 @@ simple_tests += files(
         'test-bitmap.c',
         'test-blockdev-util.c',
         'test-bootspec.c',
+        'test-build-path.c',
         'test-bus-util.c',
         'test-calendarspec.c',
         'test-cgroup-setup.c',
index 75bc4d8238c34837c30a452237bb5dfb1ac9ce39..e9f10fdae3b39140f456218c08fa672b08919b60 100644 (file)
@@ -71,7 +71,7 @@ TEST(asynchronous_rm_rf) {
 
                 /* child */
 
-                assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+                assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
                 assert_se(make_reaper_process(true) >= 0);
 
                 assert_se(mkdtemp_malloc(NULL, &tt) >= 0);
diff --git a/src/test/test-build-path.c b/src/test/test-build-path.c
new file mode 100644 (file)
index 0000000..661b5fc
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "build-path.h"
+#include "log.h"
+#include "string-util.h"
+
+int main(int argc, char* argv[]) {
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        r = get_build_exec_dir(&p);
+        if (r == -ENOEXEC)
+                log_info("Not run from build dir.");
+        else if (r < 0)
+                log_error_errno(r, "Failed to find build dir: %m");
+        else
+                log_info("%s", strna(p));
+
+        return 0;
+}
index 4f6ad5dcaeef28b6fc345028d67f19eb7eb8e7bb..148e44b13dbd5a26de1713460025d932cb094753 100644 (file)
@@ -652,7 +652,7 @@ static int find_libraries(const char *exec, char ***ret) {
         assert_se(exec);
         assert_se(ret);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
 
         assert_se(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) == 0);
         assert_se(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) == 0);
index dd9a8134bf2e5ca0730c14e6659acac0be83946c..67d9c7e65cdfd786eac8267c284958cd9864f6d4 100644 (file)
@@ -82,7 +82,7 @@ TEST(keymaps) {
 
 #define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
 TEST(dump_special_glyphs) {
-        assert_cc(SPECIAL_GLYPH_BLUE_CIRCLE + 1 == _SPECIAL_GLYPH_MAX);
+        assert_cc(SPECIAL_GLYPH_GREEN_CIRCLE + 1 == _SPECIAL_GLYPH_MAX);
 
         log_info("is_locale_utf8: %s", yes_no(is_locale_utf8()));
 
@@ -130,6 +130,7 @@ TEST(dump_special_glyphs) {
         dump_glyph(SPECIAL_GLYPH_RED_CIRCLE);
         dump_glyph(SPECIAL_GLYPH_YELLOW_CIRCLE);
         dump_glyph(SPECIAL_GLYPH_BLUE_CIRCLE);
+        dump_glyph(SPECIAL_GLYPH_GREEN_CIRCLE);
 }
 
 DEFINE_TEST_MAIN(LOG_INFO);
index 23d09813d91473858d5049fe83e3fd8c179cf588..1c3f6463b2d1ef020cea886fc8fa765c9c316207 100644 (file)
@@ -233,7 +233,7 @@ TEST(real_pressure) {
                 _exit(EXIT_SUCCESS);
         }
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
         assert_se(sd_event_add_child(e, &cs, pid, WEXITED, real_pressure_child_callback, NULL) >= 0);
         assert_se(sd_event_source_set_child_process_own(cs, true) >= 0);
 
index 1d8ebecc91d92dae036b4538e5b62fa8d16cd20b..5c308a04bcfd2f75ae437a1e53ba304149e65384 100644 (file)
@@ -174,7 +174,7 @@ static int run(int argc, char *argv[]) {
                         return log_error_errno(r, "Failed to drop privileges: %m");
         }
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGRTMIN+18) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index 832e117096062b2b49884a1e7321d7da04510f2c..b6c167b0f9792d143ccde74642bc27ed56909566 100644 (file)
@@ -184,7 +184,7 @@ static int run(int argc, char * argv[]) {
         };
         int r;
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
 
         r = sd_event_default(&event);
         if (r < 0)
index df979be5cd74bb550a1a7ad2b8092fd02d901a11..31b284b5025b27f4ba12da6e3d5cf50d7a652be5 100644 (file)
@@ -356,7 +356,7 @@ static int process_and_watch_password_files(bool watch) {
         (void) mkdir_p_label("/run/systemd/ask-password", 0755);
 
         assert_se(sigemptyset(&mask) >= 0);
-        assert_se(sigset_add_many(&mask, SIGTERM, -1) >= 0);
+        assert_se(sigset_add_many(&mask, SIGTERM) >= 0);
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0);
 
         if (watch) {
@@ -556,7 +556,7 @@ static int ask_on_this_console(const char *tty, pid_t *ret_pid, char **arguments
 
         assert_se(sigaction(SIGCHLD, &sigchld, NULL) >= 0);
         assert_se(sigaction(SIGHUP, &sighup, NULL) >= 0);
-        assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGHUP, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGHUP, SIGCHLD) >= 0);
 
         r = safe_fork("(sd-passwd)", FORK_RESET_SIGNALS|FORK_LOG, ret_pid);
         if (r < 0)
index fa6c59c7627f645f48869bb6623013cb7acb996d..f5aa38ac3e65d7d184d37cd2985a87880bb4857d 100644 (file)
@@ -144,7 +144,7 @@ static int run(int argc, char *argv[]) {
 
         assert_se(event = udev_event_new(dev, NULL));
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD) >= 0);
 
         /* do what devtmpfs usually provides us */
         if (sd_device_get_devname(dev, &devname) >= 0) {
index 848667682174d75f1620c589c725040faea9f842..0102d8d707e0be171780b3db9c01798ca883c2c5 100644 (file)
@@ -97,7 +97,7 @@ int main(int argc, char *argv[]) {
 
         test_setup_logging(LOG_DEBUG);
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
 
         test_event_spawn_cat(true, SIZE_MAX);
         test_event_spawn_cat(false, SIZE_MAX);
index 31944c224723126f77f462583389b40551d09f67..0b6cfb1655a1165892ea3d4f20bea8083515f09b 100644 (file)
@@ -1308,7 +1308,7 @@ int manager_main(Manager *manager) {
         udev_watch_restore(manager->inotify_fd);
 
         /* block SIGCHLD for listening child events. */
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
 
         r = sd_event_default(&manager->event);
         if (r < 0)
index 27c4853c4d6df1deae7e9cb9852db8999fac056f..b1124df76a2fd67d9ecc17ad9643817c49ee0dd4 100644 (file)
@@ -208,7 +208,7 @@ int monitor_main(int argc, char *argv[], void *userdata) {
                 goto finalize;
         }
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT) >= 0);
         (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
         (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
 
index e5724c8ac20d084d009cd2e09464c41c9362c79c..1d6ad15383db01189c28b72b7fa1927fe7a09885 100755 (executable)
@@ -50,7 +50,7 @@ from typing import (Any,
 
 import pefile  # type: ignore
 
-__version__ = '{{PROJECT_VERSION_FULL}} ({{GIT_VERSION}})'
+__version__ = '{{PROJECT_VERSION_FULL}} ({{VERSION_TAG}})'
 
 EFI_ARCH_MAP = {
     # host_arch glob : [efi_arch, 32_bit_efi_arch if mixed mode is supported]
index 73b6d720262ecc2d6fd27d5f897b8f2a780d476c..8720721f43cd31f17b30f1ea557247cc99b9f5a5 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "sd-daemon.h"
 
+#include "build-path.h"
 #include "common-signal.h"
 #include "env-util.h"
 #include "fd-util.h"
@@ -191,11 +192,8 @@ static int start_one_worker(Manager *m) {
                         _exit(EXIT_FAILURE);
                 }
 
-                /* execl("/home/lennart/projects/systemd/build/systemd-userwork", "systemd-userwork", "xxxxxxxxxxxxxxxx", NULL); /\* With some extra space rename_process() can make use of *\/ */
-                /* execl("/usr/bin/valgrind", "valgrind", "/home/lennart/projects/systemd/build/systemd-userwork", "systemd-userwork", "xxxxxxxxxxxxxxxx", NULL); /\* With some extra space rename_process() can make use of *\/ */
-
-                execl(SYSTEMD_USERWORK_PATH, "systemd-userwork", "xxxxxxxxxxxxxxxx", NULL); /* With some extra space rename_process() can make use of */
-                log_error_errno(errno, "Failed start worker process: %m");
+                r = invoke_callout_binary(SYSTEMD_USERWORK_PATH, STRV_MAKE(SYSTEMD_USERWORK_PATH, "xxxxxxxxxxxxxxxx")); /* With some extra space rename_process() can make use of */
+                log_error_errno(r, "Failed start worker process: %m");
                 _exit(EXIT_FAILURE);
         }
 
index 89ac9c7ba9a3a8b7d9d1d25f69d2a4f3d06f41a0..cbe4c8e4f8510aa2fcd3105bb984b37fac84df99 100644 (file)
@@ -37,7 +37,7 @@ static int run(int argc, char *argv[]) {
         if (setenv("SYSTEMD_BYPASS_USERDB", "io.systemd.NameServiceSwitch:io.systemd.Multiplexer:io.systemd.DropIn", 1) < 0)
                 return log_error_errno(errno, "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
 
         r = manager_new(&m);
         if (r < 0)
index 083779aab0ec560b29262809f698b617fbfa1f35..01ff697434eb3699a2878eb235a3f7a41a3e59cc 100644 (file)
@@ -7,4 +7,4 @@
  * - where a simplified machine-parsable form is more useful, for example
  *   pkgconfig files and version information written to binary files.
  */
-#define GIT_VERSION "@VCS_TAG@"
+#define GIT_VERSION VERSION_TAG "@VCS_TAG@"
index 676dee05927199a6c3a87964f53cc55949a6a350..ff986b09d65f94d55ae7d1d71f66bd9e3aa4ab48 100644 (file)
@@ -175,6 +175,9 @@ static int message_add_commands(sd_bus_message *m, const char *exec_type, char *
 }
 
 void socket_service_pair_done(SocketServicePair *p) {
+        assert(p);
+
+        p->exec_start_pre = strv_free(p->exec_start_pre);
         p->exec_start = strv_free(p->exec_start);
         p->exec_stop_post = strv_free(p->exec_stop_post);
         p->unit_name_prefix = mfree(p->unit_name_prefix);
@@ -268,6 +271,12 @@ int start_socket_service_pair(sd_bus *bus, const char *scope, SocketServicePair
                         return bus_log_create_error(r);
         }
 
+        if (p->exec_start_pre) {
+                r = message_add_commands(m, "ExecStartPre", &p->exec_start_pre, 1);
+                if (r < 0)
+                        return r;
+        }
+
         r = message_add_commands(m, "ExecStart", &p->exec_start, 1);
         if (r < 0)
                 return r;
index b807c3b20306fa66ab9b9e4bad8dcd24c6772581..74c75117f08c0c055476a0c3579d0426481e4490 100644 (file)
@@ -8,6 +8,7 @@
 #include "macro.h"
 
 typedef struct SocketServicePair {
+        char **exec_start_pre;
         char **exec_start;
         char **exec_stop_post;
         char *unit_name_prefix;
index cb1a463781b6dcb3744aa2cc6f255f9d7d4f7714..780df553aac3d99a3aba97981a93afde5deda008 100644 (file)
@@ -1,3 +1,13 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "string-table.h"
 #include "vmspawn-settings.h"
+
+static const char *const console_mode_table[_CONSOLE_MODE_MAX] = {
+        [CONSOLE_INTERACTIVE] = "interactive",
+        [CONSOLE_READ_ONLY]   = "read-only",
+        [CONSOLE_NATIVE]      = "native",
+        [CONSOLE_GUI]         = "gui",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(console_mode, ConsoleMode);
index 60ea10e6de01ef45d17bc79989efce3f35a4094c..fe23aa23cf7bc3b47de42b5d072b1ca993e17e24 100644 (file)
@@ -1,8 +1,20 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <errno.h>
 #include <stdint.h>
 
+#include "macro.h"
+
+typedef enum ConsoleMode {
+        CONSOLE_INTERACTIVE,    /* ptyfwd */
+        CONSOLE_READ_ONLY,      /* ptyfwd, but in read-only mode */
+        CONSOLE_NATIVE,         /* qemu's native TTY handling */
+        CONSOLE_GUI,            /* qemu's graphical UI */
+        _CONSOLE_MODE_MAX,
+        _CONSOLE_MODE_INVALID = -EINVAL,
+} ConsoleMode;
+
 typedef enum SettingsMask {
         SETTING_START_MODE        = UINT64_C(1) << 0,
         SETTING_BIND_MOUNTS       = UINT64_C(1) << 11,
@@ -10,3 +22,6 @@ typedef enum SettingsMask {
         SETTING_CREDENTIALS       = UINT64_C(1) << 30,
         _SETTING_FORCE_ENUM_WIDTH = UINT64_MAX
 } SettingsMask;
+
+const char *console_mode_to_string(ConsoleMode m) _const_;
+ConsoleMode console_mode_from_string(const char *s) _pure_;
index f67c6a51bcc6eaa06264300d0e55aa93bcb66cde..ce7f1ef2e3ee8f8ae08d816d62d5358c10fcc70a 100644 (file)
@@ -46,6 +46,7 @@
 #include "path-util.h"
 #include "pretty-print.h"
 #include "process-util.h"
+#include "ptyfwd.h"
 #include "random-util.h"
 #include "rm-rf.h"
 #include "signal-util.h"
@@ -73,7 +74,7 @@ static unsigned arg_vsock_cid = VMADDR_CID_ANY;
 static int arg_tpm = -1;
 static char *arg_linux = NULL;
 static char **arg_initrds = NULL;
-static bool arg_qemu_gui = false;
+static ConsoleMode arg_console_mode = CONSOLE_INTERACTIVE;
 static NetworkStack arg_network_stack = NETWORK_STACK_NONE;
 static int arg_secure_boot = -1;
 static MachineCredentialContext arg_credentials = {};
@@ -87,6 +88,7 @@ static bool arg_runtime_directory_created = false;
 static bool arg_privileged = false;
 static char **arg_kernel_cmdline_extra = NULL;
 static char **arg_extra_drives = NULL;
+static char *arg_background = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -101,6 +103,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_runtime_mounts, runtime_mount_context_done);
 STATIC_DESTRUCTOR_REGISTER(arg_forward_journal, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_kernel_cmdline_extra, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_extra_drives, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
@@ -130,7 +133,6 @@ static int help(void) {
                "     --tpm=BOOL            Enable use of a virtual TPM\n"
                "     --linux=PATH          Specify the linux kernel for direct kernel boot\n"
                "     --initrd=PATH         Specify the initrd for direct kernel boot\n"
-               "     --qemu-gui            Start QEMU in graphical mode\n"
                "  -n --network-tap         Create a TAP device for networking\n"
                "     --network-user-mode   Use user mode networking\n"
                "     --secure-boot=BOOL    Enable searching for firmware supporting SecureBoot\n"
@@ -150,6 +152,9 @@ static int help(void) {
                "\n%3$sIntegration:%4$s\n"
                "     --forward-journal=FILE|DIR\n"
                "                           Forward the VM's journal to the host\n"
+               "\n%3$sInput/Output:%4$s\n"
+               "     --console=MODE        Console mode (interactive, native, gui)\n"
+               "     --background=COLOR    Set ANSI color for background\n"
                "\n%3$sCredentials:%4$s\n"
                "     --set-credential=ID:VALUE\n"
                "                           Pass a credential with literal value to the VM\n"
@@ -190,6 +195,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SET_CREDENTIAL,
                 ARG_LOAD_CREDENTIAL,
                 ARG_FIRMWARE,
+                ARG_CONSOLE,
+                ARG_BACKGROUND,
         };
 
         static const struct option options[] = {
@@ -212,7 +219,8 @@ static int parse_argv(int argc, char *argv[]) {
                 { "tpm",               required_argument, NULL, ARG_TPM               },
                 { "linux",             required_argument, NULL, ARG_LINUX             },
                 { "initrd",            required_argument, NULL, ARG_INITRD            },
-                { "qemu-gui",          no_argument,       NULL, ARG_QEMU_GUI          },
+                { "console",           required_argument, NULL, ARG_CONSOLE           },
+                { "qemu-gui",          no_argument,       NULL, ARG_QEMU_GUI          }, /* compat option */
                 { "network-tap",       no_argument,       NULL, 'n'                   },
                 { "network-user-mode", no_argument,       NULL, ARG_NETWORK_USER_MODE },
                 { "bind",              required_argument, NULL, ARG_BIND              },
@@ -224,6 +232,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "set-credential",    required_argument, NULL, ARG_SET_CREDENTIAL    },
                 { "load-credential",   required_argument, NULL, ARG_LOAD_CREDENTIAL   },
                 { "firmware",          required_argument, NULL, ARG_FIRMWARE          },
+                { "background",        required_argument, NULL, ARG_BACKGROUND        },
                 {}
         };
 
@@ -344,8 +353,15 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_CONSOLE:
+                        arg_console_mode = console_mode_from_string(optarg);
+                        if (arg_console_mode < 0)
+                                return log_error_errno(arg_console_mode, "Failed to parse specified console mode: %s", optarg);
+
+                        break;
+
                 case ARG_QEMU_GUI:
-                        arg_qemu_gui = true;
+                        arg_console_mode = CONSOLE_GUI;
                         break;
 
                 case 'n':
@@ -438,6 +454,12 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_BACKGROUND:
+                        r = free_and_strdup_warn(&arg_background, optarg);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -639,7 +661,12 @@ static int cmdline_add_vsock(char ***cmdline, int vsock_fd) {
         return 0;
 }
 
-static int start_tpm(sd_bus *bus, const char *scope, const char *tpm, const char **ret_state_tempdir) {
+static int start_tpm(
+                sd_bus *bus,
+                const char *scope,
+                const char *swtpm,
+                char **ret_state_tempdir) {
+
         _cleanup_(rm_rf_physical_and_freep) char *state_dir = NULL;
         _cleanup_free_ char *scope_prefix = NULL;
         _cleanup_(socket_service_pair_done) SocketServicePair ssp = {
@@ -649,7 +676,7 @@ static int start_tpm(sd_bus *bus, const char *scope, const char *tpm, const char
 
         assert(bus);
         assert(scope);
-        assert(tpm);
+        assert(swtpm);
         assert(ret_state_tempdir);
 
         r = unit_name_to_prefix(scope, &scope_prefix);
@@ -674,7 +701,16 @@ static int start_tpm(sd_bus *bus, const char *scope, const char *tpm, const char
         if (!ssp.listen_address)
                 return log_oom();
 
-        ssp.exec_start = strv_new(tpm, "socket", "--tpm2", "--tpmstate");
+        _cleanup_free_ char *swtpm_setup = NULL;
+        r = find_executable("swtpm_setup", &swtpm_setup);
+        if (r < 0)
+                return log_error_errno(r, "Failed to find swtpm_setup binary: %m");
+
+        ssp.exec_start_pre = strv_new(swtpm_setup, "--tpm-state", state_dir, "--tpm2", "--pcr-banks", "sha256");
+        if (!ssp.exec_start_pre)
+                return log_oom();
+
+        ssp.exec_start = strv_new(swtpm, "socket", "--tpm2", "--tpmstate");
         if (!ssp.exec_start)
                 return log_oom();
 
@@ -691,7 +727,6 @@ static int start_tpm(sd_bus *bus, const char *scope, const char *tpm, const char
                 return r;
 
         *ret_state_tempdir = TAKE_PTR(state_dir);
-
         return 0;
 }
 
@@ -1017,6 +1052,25 @@ static int merge_initrds(char **ret) {
         return 0;
 }
 
+static void set_window_title(PTYForward *f) {
+        _cleanup_free_ char *hn = NULL, *dot = NULL;
+
+        assert(f);
+
+        (void) gethostname_strict(&hn);
+
+        if (emoji_enabled())
+                dot = strjoin(special_glyph(SPECIAL_GLYPH_GREEN_CIRCLE), " ");
+
+        if (hn)
+                (void) pty_forward_set_titlef(f, "%sVirtual Machine %s on %s", strempty(dot), arg_machine, hn);
+        else
+                (void) pty_forward_set_titlef(f, "%sVirtual Machine %s", strempty(dot), arg_machine);
+
+        if (dot)
+                (void) pty_forward_set_title_prefix(f, dot);
+}
+
 static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
         _cleanup_(ovmf_config_freep) OvmfConfig *ovmf_config = NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
@@ -1209,12 +1263,54 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
         if (r < 0)
                 return log_oom();
 
-        if (arg_qemu_gui)
+        _cleanup_close_ int master = -EBADF;
+        PTYForwardFlags ptyfwd_flags = 0;
+        switch (arg_console_mode) {
+
+        case CONSOLE_READ_ONLY:
+                ptyfwd_flags |= PTY_FORWARD_READ_ONLY;
+
+                _fallthrough_;
+
+        case CONSOLE_INTERACTIVE:  {
+                _cleanup_free_ char *pty_path = NULL;
+
+                master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
+                if (master < 0)
+                        return log_error_errno(errno, "Failed to acquire pseudo tty: %m");
+
+                r = ptsname_malloc(master, &pty_path);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to determine tty name: %m");
+
+                if (unlockpt(master) < 0)
+                        return log_error_errno(errno, "Failed to unlock tty: %m");
+
+                if (strv_extend_many(
+                                &cmdline,
+                                "-nographic",
+                                "-nodefaults",
+                                "-chardev") < 0)
+                        return log_oom();
+
+                if (strv_extendf(&cmdline,
+                                 "serial,id=console,path=%s", pty_path) < 0)
+                        return log_oom();
+
+                r = strv_extend_many(
+                                &cmdline,
+                                "-serial", "chardev:console");
+                break;
+        }
+
+        case CONSOLE_GUI:
                 r = strv_extend_many(
                                 &cmdline,
                                 "-vga",
                                 "virtio");
-        else
+                break;
+
+        case CONSOLE_NATIVE:
                 r = strv_extend_many(
                                 &cmdline,
                                 "-nographic",
@@ -1222,6 +1318,11 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
                                 "-chardev", "stdio,mux=on,id=console,signal=off",
                                 "-serial", "chardev:console",
                                 "-mon", "console");
+                break;
+
+        default:
+                assert_not_reached();
+        }
         if (r < 0)
                 return log_oom();
 
@@ -1457,7 +1558,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
                 }
         }
 
-        _cleanup_free_ const char *tpm_state_tempdir = NULL;
+        _cleanup_free_ char *tpm_state_tempdir = NULL;
         if (swtpm) {
                 _cleanup_free_ char *escaped_state_dir = NULL;
 
@@ -1570,7 +1671,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
                 log_debug("Executing: %s", joined);
         }
 
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
+        assert_se(sigprocmask_many(SIG_BLOCK, /* old_sigset=*/ NULL, SIGCHLD, SIGWINCH) >= 0);
 
         _cleanup_(sd_event_source_unrefp) sd_event_source *notify_event_source = NULL;
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
@@ -1622,6 +1723,26 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
         /* Exit when the child exits */
         (void) event_add_child_pidref(event, NULL, &child_pidref, WEXITED, on_child_exit, NULL);
 
+        _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
+        if (master >= 0) {
+                r = pty_forward_new(event, master, ptyfwd_flags, &forward);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to create PTY forwarder: %m");
+
+                if (!arg_background) {
+                        _cleanup_free_ char *bg = NULL;
+
+                        r = terminal_tint_color(130 /* green */, &bg);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to determine terminal background color, not tinting.");
+                        else
+                                (void) pty_forward_set_background_color(forward, bg);
+                } else if (!isempty(arg_background))
+                        (void) pty_forward_set_background_color(forward, arg_background);
+
+                set_window_title(forward);
+        }
+
         r = sd_event_loop(event);
         if (r < 0)
                 return log_error_errno(r, "Failed to run event loop: %m");
@@ -1727,15 +1848,20 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return r;
 
-        if (!arg_quiet) {
+        if (!arg_quiet && arg_console_mode != CONSOLE_GUI) {
                 _cleanup_free_ char *u = NULL;
                 const char *vm_path = arg_image ?: arg_directory;
                 (void) terminal_urlify_path(vm_path, vm_path, &u);
 
-                log_info("%s %sSpawning VM %s on %s.%s\n"
-                         "%s %sPress %sCtrl-a x%s to kill VM.%s",
-                         special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), arg_machine, u ?: vm_path, ansi_normal(),
-                         special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_normal());
+                log_info("%s %sSpawning VM %s on %s.%s",
+                         special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), arg_machine, u ?: vm_path, ansi_normal());
+
+                if (arg_console_mode == CONSOLE_INTERACTIVE)
+                        log_info("%s %sPress %sCtrl-]%s three times within 1s to kill VM.%s",
+                                 special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_normal());
+                else if (arg_console_mode == CONSOLE_NATIVE)
+                        log_info("%s %sPress %sCtrl-a x%s to kill VM.%s",
+                                 special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_normal());
         }
 
         r = sd_listen_fds_with_names(true, &names);
index e31108b3418bb42636f6f9a47e0cd8013d503839..4d7d758d2977820ca2c38253b8cc303a74f60d91 100644 (file)
@@ -5,7 +5,7 @@ Name=client-peer
 [Network]
 Address=192.168.6.2/24
 DHCPServer=yes
-IPForward=ipv4
+IPv4Forwarding=yes
 IPv6AcceptRA=no
 
 [DHCPServer]
index cfa7e5a17d28791d9c2fb5c3d90c400e5e79e81d..219d40a9b7ca3f205360f787bf1a509a43694dfb 100644 (file)
@@ -4,5 +4,5 @@ Name=client
 
 [Network]
 DHCP=yes
-IPForward=ipv4
+IPv4Forwarding=yes
 IPv6AcceptRA=no
index 1f6fa4b5bb1781392e0715d3d008546be3c78813..5e005c79ecd09ffcec9f3bf1bf6e1f6be8fc88a6 100644 (file)
@@ -4,5 +4,5 @@ Name=server-peer
 
 [Network]
 Address=192.168.5.2/24
-IPForward=ipv4
+IPv4Forwarding=yes
 IPv6AcceptRA=no
index 905508f55f1c2015579b4964f87a5e636684ed86..0108039e6fa99c56bab70badafd90abb67f9348e 100644 (file)
@@ -4,7 +4,7 @@ Name=server
 
 [Network]
 Address=192.168.5.1/24
-IPForward=ipv4
+IPv4Forwarding=yes
 DHCPServer=yes
 IPv6AcceptRA=no
 
index 81302abf9d6a364466267d95e748b8e90f613eb4..d01a633952c904b49ff5f4a0b63f195a0ad72f79 100644 (file)
@@ -9,7 +9,6 @@ IPv6ProxyNDPAddress=2607:5300:203:5215:3::1
 IPv6ProxyNDPAddress=2607:5300:203:5215:2::1
 IPv6ProxyNDPAddress=2607:5300:203:5215:1::1
 IPv6AcceptRA=no
-IPForward=yes
 Address=66.70.129.136/32
 Address=66.70.129.142/32
 Address=66.70.129.143/32
index ff1ded4ef0f174d3e58a2f990a472e82f2f31267..759fe65fe88d994c5f3bc7ee89ea67e2975eb36c 100644 (file)
@@ -3,7 +3,8 @@
 Name=dummy98
 
 [Network]
-IPForward=yes
+IPv4Forwarding=yes
+IPv6Forwarding=yes
 IPv6DuplicateAddressDetection=3
 IPv6HopLimit=5
 IPv4ProxyARP=yes
index 7a697571e8200658f09ac9b92d203a7b7351f054..67011ac6c4e65bb7f557fb472b12f5bb714094cf 100644 (file)
@@ -4,7 +4,6 @@ Name=bridge99
 
 [Network]
 VLAN=vlan99
-IPForward=yes
 ConfigureWithoutCarrier=yes
 LLDP=yes
 IPv6AcceptRA=false
index 876219fca27b970d3a5fdf40c30656d338bbdf70..bc7c3b0501a564ce7d93431c415a68b101c5128a 100644 (file)
@@ -4,7 +4,6 @@ Name=test1
 
 [Network]
 IPv6AcceptRA=no
-IPForward=yes
 Bridge=bridge99
 LinkLocalAddressing=no
 EmitLLDP=nearest-bridge
index b1951ade204c4f55d3ecd926d0cf7e5cce037cfd..aa7bd1e87aa7cf576d0927cc42f7ccdd4077c477 100755 (executable)
@@ -5223,6 +5223,9 @@ class NetworkdRATests(unittest.TestCase, Utilities):
         start_networkd()
         self.wait_online('veth99:routable', 'veth-peer:degraded')
 
+        # IPv6SendRA=yes implies IPv6Forwarding.
+        self.check_ipv6_sysctl_attr('veth-peer', 'forwarding', '1')
+
         output = resolvectl('dns', 'veth99')
         print(output)
         self.assertRegex(output, 'fe80::')
index 52f92c5f570464e4e4ebbf02c97b3171745f435c..d097ccdac8c4cd09333f68ab36bb80ce6071ad25 100755 (executable)
@@ -305,7 +305,7 @@ homectl remove blob-user
 export PAGER=
 
 # Create a couple of user/group records to test io.systemd.DropIn
-# See docs/_groups/USER_RECORD.md and docs/_groups/GROUP_RECORD.md
+# See docs/USER_RECORD.md and docs/GROUP_RECORD.md
 mkdir -p /run/userdb/
 cat >"/run/userdb/dropingroup.group" <<\EOF
 {
diff --git a/tools/meson-vcs-tag.sh b/tools/meson-vcs-tag.sh
deleted file mode 100755 (executable)
index 16cf110..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-set -u
-set -o pipefail
-
-dir="${1:-.}"
-version_tag="${2:-}"
-
-if [ -n "${version_tag}" ]; then
-    # If -Dversion_tag= was used, just use that without further changes.
-    echo "${version_tag}"
-else
-    read -r project_version <"${dir}/meson.version"
-
-    # Check that we have either .git/ (a normal clone) or a .git file (a work-tree)
-    # and that we don't get confused if a tarball is extracted in a higher-level
-    # git repository.
-    #
-    # If the working tree has no tags (CI builds), the first git-describe will fail
-    # and we fall back to project_version-commitid instead.
-
-    c=''
-    if [ -e "${dir}/.git" ]; then
-        c="$(git -C "$dir" describe --abbrev=7 --dirty=^ 2>/dev/null)"
-        if [ -n "$c" ]; then
-            # git describe uses the most recent tag. However, for development versions (e.g. v256~devel), the
-            # most recent tag will be v255 as there is no tag for development versions. To deal with this, we
-            # replace the tag with the project version instead.
-            c="${project_version}-${c#*-}"
-        else
-            # This call might still fail with permission issues
-            suffix="$(git -C "$dir" describe --always --abbrev=7 --dirty=^ 2>/dev/null)"
-            [ -n "$suffix" ] && c="${project_version}-${suffix}"
-        fi
-    fi
-    [ -z "$c" ] && c="${project_version}"
-    # Replace any hyphens with carets which are allowed in versions by pacman whereas hyphens are not. Git
-    # versions with carets will also sort higher than their non-git version counterpart both in pacman
-    # versioning and in version format specification versioning.
-    echo "$c" | sed 's/^v//; s/-/^/g'
-fi