]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #12392 from poettering/firstboot-salt
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 28 May 2019 12:36:54 +0000 (14:36 +0200)
committerGitHub <noreply@github.com>
Tue, 28 May 2019 12:36:54 +0000 (14:36 +0200)
generalize crypt_r() salt generation code

365 files changed:
.mkosi/mkosi.fedora
.travis.yml
NEWS
README.md
TODO
azure-pipelines.yml [new file with mode: 0644]
catalog/systemd.it.catalog.in
coccinelle/const-strlen.disabled [moved from coccinelle/const-strlen.cocci with 80% similarity]
coccinelle/debug-logging.cocci
coccinelle/dup-fcntl.cocci
coccinelle/empty-to-null.cocci
coccinelle/flags-set.cocci
coccinelle/in_set.cocci
coccinelle/isempty.cocci
coccinelle/memzero.cocci
coccinelle/mfree_return.cocci
coccinelle/not_in_set.cocci
coccinelle/run-coccinelle.sh
coccinelle/sd_event_source_disable_unref.cocci [new file with mode: 0644]
coccinelle/strempty.cocci
coccinelle/synthetic-errno.cocci
coccinelle/systemd-definitions.iso [new file with mode: 0644]
coccinelle/take-fd.cocci
docs/CODE_QUALITY.md
docs/DISTRO_PORTING.md
docs/TESTING_WITH_SANITIZERS.md [new file with mode: 0644]
docs/TRANSIENT-SETTINGS.md
docs/UIDS-GIDS.md
fuzz.yaml [new file with mode: 0644]
hwdb/60-keyboard.hwdb
hwdb/60-sensor.hwdb
man/bootctl.xml
man/html.in [new file with mode: 0755]
man/journalctl.xml
man/man.in [new file with mode: 0755]
man/meson.build
man/rules/meson.build
man/sd_bus_request_name.xml
man/sd_bus_set_description.xml
man/sd_bus_slot_set_description.xml
man/sd_event_source_unref.xml
man/systemd-analyze.xml
man/systemd-mount.xml
man/systemd-nspawn.xml
man/systemd-rc-local-generator.xml
man/systemd-tmpfiles.xml
man/systemd-udevd.service.xml
man/systemd.journal-fields.xml
man/systemd.link.xml
man/systemd.mount.xml
man/systemd.net-naming-scheme.xml [new file with mode: 0644]
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.resource-control.xml
man/systemd.socket.xml
man/systemd.time.xml
man/systemd.unit.xml
man/vtable-example.c
meson.build
meson_options.txt
po/it.po
po/pt_BR.po
po/uk.po
po/zh_TW.po
rules/99-systemd.rules.in
semaphoreci/semaphore-runner.sh
shell-completion/bash/bootctl
shell-completion/zsh/_systemd-inhibit
src/activate/activate.c
src/analyze/analyze.c
src/ask-password/ask-password.c
src/basic/alloc-util.c
src/basic/capability-util.c
src/basic/env-util.c
src/basic/env-util.h
src/basic/escape.c
src/basic/escape.h
src/basic/fs-util.h
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/linux/README
src/basic/linux/btrfs.h
src/basic/linux/btrfs_tree.h
src/basic/linux/fou.h
src/basic/linux/if.h
src/basic/linux/if_bonding.h
src/basic/linux/if_ether.h
src/basic/linux/if_link.h
src/basic/linux/if_tun.h
src/basic/linux/in.h
src/basic/linux/in6.h
src/basic/linux/update.sh [new file with mode: 0755]
src/basic/log.c
src/basic/macro.h
src/basic/mountpoint-util.c
src/basic/proc-cmdline.c
src/basic/process-util.c
src/basic/process-util.h
src/basic/random-util.c
src/basic/random-util.h
src/basic/rm-rf.c
src/basic/socket-util.h
src/basic/string-util.h
src/basic/terminal-util.c
src/basic/terminal-util.h
src/basic/time-util.c
src/basic/umask-util.h
src/basic/utf8.c
src/basic/utf8.h
src/boot/bootctl.c
src/busctl/busctl.c
src/cgls/cgls.c
src/cgtop/cgtop.c
src/core/cgroup.c
src/core/cgroup.h
src/core/dbus-cgroup.c
src/core/dbus-socket.c
src/core/dbus-unit.c
src/core/execute.c
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/main.c
src/core/manager.c
src/core/meson.build
src/core/mount.c
src/core/namespace.c
src/core/namespace.h
src/core/service.c
src/core/timer.c
src/coredump/coredump.c
src/coredump/coredumpctl.c
src/delta/delta.c
src/detect-virt/detect-virt.c
src/escape/escape.c
src/fstab-generator/fstab-generator.c
src/fuzz/fuzz-varlink.c [new file with mode: 0644]
src/fuzz/fuzz.h
src/fuzz/fuzzer-entry-point.c [new file with mode: 0644]
src/fuzz/meson.build
src/hostname/hostnamectl.c
src/id128/id128.c
src/import/curl-util.c
src/import/importd.c
src/journal-remote/journal-remote-main.c
src/journal-remote/journal-remote.c
src/journal/cat.c
src/journal/journal-file.c
src/journal/journal-file.h
src/journal/journal-verify.c
src/journal/journalctl.c
src/journal/journald-context.c
src/journal/journald-server.c
src/journal/journald-server.h
src/libsystemd-network/network-internal.c
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-radv.c
src/libsystemd-network/test-dhcp-client.c
src/libsystemd/libsystemd.sym
src/libsystemd/sd-bus/bus-message.c
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h
src/locale/localectl.c
src/login/inhibit.c
src/login/loginctl.c
src/login/logind-button.c
src/login/logind-core.c
src/login/logind-user.c
src/machine/machinectl.c
src/mount/mount-tool.c
src/network/meson.build
src/network/netdev/bond.c
src/network/netdev/bond.h
src/network/netdev/bridge.c
src/network/netdev/bridge.h
src/network/netdev/fou-tunnel.c
src/network/netdev/fou-tunnel.h
src/network/netdev/geneve.c
src/network/netdev/geneve.h
src/network/netdev/ipvlan.c
src/network/netdev/ipvlan.h
src/network/netdev/l2tp-tunnel.c
src/network/netdev/l2tp-tunnel.h
src/network/netdev/macsec.c
src/network/netdev/macsec.h
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/tunnel.c
src/network/netdev/tuntap.c
src/network/netdev/tuntap.h
src/network/netdev/vcan.h
src/network/netdev/veth.c
src/network/netdev/vlan.c
src/network/netdev/vxlan.c
src/network/netdev/vxlan.h
src/network/netdev/wireguard.c
src/network/netdev/wireguard.h
src/network/networkctl.c
src/network/networkd-address-pool.c
src/network/networkd-address.c
src/network/networkd-can.c [new file with mode: 0644]
src/network/networkd-can.h [new file with mode: 0644]
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-fdb.c
src/network/networkd-fdb.h
src/network/networkd-ipv4ll.c
src/network/networkd-ipv6-proxy-ndp.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-lldp-rx.c [new file with mode: 0644]
src/network/networkd-lldp-rx.h [new file with mode: 0644]
src/network/networkd-lldp-tx.c
src/network/networkd-lldp-tx.h
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-network-bus.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-radv.c
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-routing-policy-rule.h
src/network/networkd-util.c
src/network/networkd-util.h
src/network/networkd.c
src/network/test-network-tables.c
src/network/test-network.c
src/network/test-networkd-conf.c
src/network/wait-online/manager.c
src/notify/notify.c
src/nspawn/meson.build
src/nspawn/nspawn-oci.c
src/path/path.c
src/portable/portablectl.c
src/rc-local-generator/rc-local-generator.c
src/resolve/resolvectl.c
src/run/run.c
src/shared/ask-password-api.c
src/shared/bus-unit-util.c
src/shared/bus-util.c
src/shared/calendarspec.c
src/shared/cgroup-show.c
src/shared/cgroup-show.h
src/shared/dns-domain.c
src/shared/efivars.c
src/shared/format-table.h
src/shared/journal-importer.c
src/shared/json.c
src/shared/libmount-util.h
src/shared/logs-show.c
src/shared/loop-util.c
src/shared/machine-image.c
src/shared/meson.build
src/shared/mount-util.c
src/shared/seccomp-util.c
src/shared/seccomp-util.h
src/shared/sleep-config.c
src/shared/switch-root.c
src/shared/utmp-wtmp.c
src/shared/varlink.c [new file with mode: 0644]
src/shared/varlink.h [new file with mode: 0644]
src/shutdown/shutdown.c
src/shutdown/umount.c
src/sleep/sleep.c
src/systemd/sd-dhcp-client.h
src/systemd/sd-event.h
src/systemd/sd-netlink.h
src/test/meson.build
src/test/test-alloc-util.c
src/test/test-capability.c
src/test/test-cgroup-mask.c
src/test/test-cgroup-unit-default.c
src/test/test-escape.c
src/test/test-execute.c
src/test/test-libmount.c
src/test/test-libudev.c
src/test/test-ns.c
src/test/test-nss.c
src/test/test-process-util.c
src/test/test-seccomp.c
src/test/test-terminal-util.c
src/test/test-umask-util.c [new file with mode: 0644]
src/test/test-utf8.c
src/test/test-varlink.c [new file with mode: 0644]
src/timedate/timedatectl.c
src/timesync/timesyncd-manager.c
src/tmpfiles/tmpfiles.c
src/udev/ata_id/ata_id.c
src/udev/cdrom_id/cdrom_id.c
src/udev/net/link-config.c
src/udev/net/naming-scheme.h
src/udev/scsi_id/scsi_id.c
src/udev/scsi_id/scsi_serial.c
src/udev/udev-builtin-net_id.c
src/udev/udev-builtin-usb_id.c
src/udev/udev-event.c
src/udev/udev-node.c
src/udev/udevd.c
src/udev/v4l_id/v4l_id.c
src/vconsole/vconsole-setup.c
sysctl.d/50-default.conf
sysctl.d/50-pid-max.conf [new file with mode: 0644]
sysctl.d/meson.build
test/TEST-01-BASIC/test.sh
test/TEST-13-NSPAWN-SMOKE/test.sh
test/TEST-22-TMPFILES/test-09.sh [new file with mode: 0755]
test/TEST-32-OOMPOLICY/Makefile [moved from test/TEST-31-OOMPOLICY/Makefile with 100% similarity]
test/TEST-32-OOMPOLICY/test.sh [moved from test/TEST-31-OOMPOLICY/test.sh with 92% similarity]
test/TEST-32-OOMPOLICY/testsuite.sh [moved from test/TEST-31-OOMPOLICY/testsuite.sh with 91% similarity]
test/dml-passthrough-set-ml.service
test/fuzz/fuzz-netdev-parser/directives.netdev
test/fuzz/fuzz-network-parser/directives.network
test/fuzz/fuzz-varlink/array [new file with mode: 0644]
test/fuzz/fuzz-varlink/do-something [new file with mode: 0644]
test/fuzz/fuzz-varlink/huge-method [new file with mode: 0644]
test/fuzz/fuzz-varlink/method-call [new file with mode: 0644]
test/fuzz/fuzz-varlink/method-error [new file with mode: 0644]
test/fuzz/fuzz-varlink/method-reply [new file with mode: 0644]
test/fuzz/fuzz-varlink/oss-fuzz-14688 [new file with mode: 0644]
test/fuzz/fuzz-varlink/oss-fuzz-14708 [new file with mode: 0644]
test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf [new file with mode: 0644]
test/test-execute/exec-systemcallfilter-failing.service
test/test-execute/exec-systemcallfilter-failing2.service
test/test-functions
test/test-network/conf/21-vlan.network
test/test-network/conf/25-bond-balanced-tlb.netdev
test/test-network/conf/25-ipvlan.netdev
test/test-network/conf/25-ipvtap.netdev [new file with mode: 0644]
test/test-network/conf/25-macsec.network
test/test-network/conf/25-netdevsim.netdev [new file with mode: 0644]
test/test-network/conf/25-route-static.network
test/test-network/conf/25-tap.netdev
test/test-network/conf/25-tun.netdev
test/test-network/conf/25-tunnel-local-any.network [new file with mode: 0644]
test/test-network/conf/25-tunnel-remote-any.network [new file with mode: 0644]
test/test-network/conf/25-tunnel.network [new file with mode: 0644]
test/test-network/conf/25-vxcan.netdev [new file with mode: 0644]
test/test-network/conf/25-vxlan.netdev
test/test-network/conf/dhcp-client-ipv6-only.network
test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network [new file with mode: 0644]
test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network [new file with mode: 0644]
test/test-network/conf/ipvtap.network [new file with mode: 0644]
test/test-network/conf/macsec.network
test/test-network/conf/netdev-link-local-addressing-yes.network [new file with mode: 0644]
test/test-network/conf/vxlan-test1.network [new file with mode: 0644]
test/test-network/conf/vxlan.network
test/test-network/systemd-networkd-tests.py
tmpfiles.d/meson.build
tools/check-directives.sh
tools/meson-vcs-tag.sh
tools/oss-fuzz.sh
travis-ci/managers/debian.sh
travis-ci/managers/fedora.sh
travis-ci/managers/fuzzbuzz.sh [new file with mode: 0755]
travis-ci/managers/xenial.sh
travis-ci/requirements.txt
units/meson.build
units/system-update-cleanup.service
units/systemd-journal-flush.service.in

index ff43ecdfe6b2785076b4f8695e2d89120f798b38..b0673f707a39982cb4a1b93411e3c3c5c03de691 100644 (file)
@@ -5,7 +5,7 @@
 
 [Distribution]
 Distribution=fedora
-Release=29
+Release=30
 
 [Output]
 Format=raw_btrfs
index 6eae0bc3e4ed71a94c87dfc2b983b93bf687c5ff..ab6fe298c768d937444ed4cd56aacb1ab7cd77e0 100644 (file)
@@ -91,13 +91,6 @@ jobs:
           after_script:
               - $CI_MANAGERS/debian.sh CLEANUP
 
-        - name: Ubuntu Xenial
-          language: bash
-          script:
-              - set -e
-              - sudo $CI_MANAGERS/xenial.sh
-              - set +e
-
         - stage: Coverity
           language: bash
           env:
diff --git a/NEWS b/NEWS
index 057484cbae83ba76915655f51ffce87179a87145..979ee4b5e55fb686ff30e59758bc1e8502096f5e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,22 @@ systemd System and Service Manager
 
 CHANGES WITH 243 in spe:
 
+        * Previously, filters defined with SystemCallFilter= would have the
+          effect that an calling an offending system call would terminate the
+          calling thread. This behaviour never made much sense, since killing
+          individual threads of unexpecting processes is likely to create more
+          problems than it solves. With this release the default action changed
+          from killing the thread to killing the whole process. For this to
+          work correctly both a kernel version (>= 4.14) and a libseccomp
+          version (>= 2.4.0) supporting this new seccomp action is required. If
+          an older kernel or libseccomp is used the old behaviour continues to
+          be used. This change does not affect any services that have no system
+          call filters defined, or that use SystemCallErrorNumber= (and thus
+          see EPERM or another error instead of being killed when calling an
+          offending system call). Note that systemd documentation always
+          claimed that the whole process is killed. With this change behaviour
+          is thus adjusted to match the documentation.
+
         * The "kernel.pid_max" sysctl is now bumped to 4194304 by default,
           i.e. the full 22bit range the kernel allows, up from the old 16bit
           range. This should improve security and robustness a bit, as PID
@@ -19,6 +35,57 @@ CHANGES WITH 243 in spe:
           are harder to type, but we believe the change from 5 digit PIDs to 7
           digit PIDs is not too hampering for usability.
 
+        * MemoryLow and MemoryMin gained hierarchy-aware counterparts,
+          DefaultMemoryLow and DefaultMemoryMin, which can be used to
+          hierarchically set default memory protection values for a particular
+          subtree of the unit hierarchy.
+
+        * Memory protection directives can now take a value of zero, allowing
+          explicit opting out of a default value propagated by an ancestor.
+
+        * systemd now defaults to the "unified" cgroup hierarchy setup during
+          build-time, i.e. -Ddefault-hierarchy=unified is now the build-time
+          default. Previously, -Ddefault-hierarchy=hybrid was the default. This
+          change reflects the fact that cgroupsv2 support has matured
+          substantially in both systemd and in the kernel, and is clearly the
+          way forward. Downstream production distributions might want to
+          continue to use -Ddefault-hierarchy=hybrid (or even =legacy) for
+          their builds as unfortunately the popular container managers have not
+          caught up with the kernel API changes.
+
+        * Man pages are not built by default anymore (html pages were already
+          disabled by default), to make development builds quicker. When
+          building systemd for a full installation with documentation, meson
+          should be called -Dman=true and/or -Dhtml=true as appropriate. The
+          default was changed based on the assumption that quick one-off or
+          repeated development builds are much more common than full optimized
+          builds for installation, and people need to pass various other
+          options to when doing "proper" builds anyway, so the gain from making
+          development builds quicker is bigger than the one time disruption for
+          packagers.
+
+          Two scripts are created in the *build* directory to generate and
+          preview man and html pages on demand, e.g.:
+
+          build/man/man systemctl
+          build/man/html systemd.index
+
+        * /usr/sbin/halt.local is no longer supported. Implementation in
+          distributions was inconsistent and it seems this functionality was
+          very rarely used.
+
+          To replace this functionality, users should:
+          - either define a new unit and make it a dependency of final.target
+            (systemctl add-wants final.target my-halt-local.service)
+          - or move the shutdown script to /usr/lib/systemd/system-shutdown/
+            and ensure that it accepts "halt", "poweroff", "reboot", and
+            "kexec" as an argument, see the description in systemd-shutdown(8).
+
+        * When a [Match] section in .link or .network file is empty (contains
+          no match patterns), a warning will be emitted. Please add any "match
+          all" pattern instead, e.g. OriginalName=* or Name=* if case all
+          interfaces should really be matched.
+
           …
 
 CHANGES WITH 242:
index 31d530733aa88ce282e1ced58574735f16f8a5bd..5ed7cfceac9dec55a9e2ef58e25e7f16382b43e1 100644 (file)
--- a/README.md
+++ b/README.md
@@ -3,10 +3,12 @@
 <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
 <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
 [![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
+[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
 [![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
 [![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
-[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)
+[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)<br/>
+[![Build Status](https://dev.azure.com/evvers/systemd-systemd/_apis/build/status/systemd.systemd?branchName=master)](https://dev.azure.com/evvers/systemd-systemd/_build/latest?definitionId=1&branchName=master)
 
 ## Details
 
diff --git a/TODO b/TODO
index 4577c93612a5c160c277315dd765bd25322efe2e..e8f59d0932fb325f4b3f996103ebcab43dd64d10 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,6 +4,11 @@ Bugfixes:
   manager or system manager can be always set. It would be better to reject
   them when parsing config.
 
+* busctl --user call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager GetUnitProcesses "s" run-rbff1b85427b34ba3adf864281aeda8e7.service
+Failed to set address: No such file or directory
+
+  → improve error message
+
 External:
 
 * Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.
@@ -19,6 +24,9 @@ Janitorial Clean-ups:
 
 Features:
 
+* when killing due to service watchdog timeout maybe detect whether target
+  process is under ptracing and then log loudly and continue instead.
+
 * tweak journald context caching. In addition to caching per-process attributes
   keyed by PID, cache per-cgroup attributes (i.e. the various xattrs we read)
   keyed by cgroup path, and guarded by ctime changes. This should provide us
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644 (file)
index 0000000..9a50e2e
--- /dev/null
@@ -0,0 +1,27 @@
+trigger:
+- master
+
+jobs:
+- job: FuzzBuzz
+  displayName: FuzzBuzz
+
+  pool:
+    vmImage: 'ubuntu-latest'
+
+  steps:
+  - script: |
+      set -e
+      ./travis-ci/managers/fuzzbuzz.sh
+    displayName: 'This is where it gets darker'
+
+- job: ASan_UBSan
+  displayName: ASan_UBSan
+
+  pool:
+    vmImage: 'ubuntu-latest'
+
+  steps:
+  - script: |
+      set -e
+      sudo ./travis-ci/managers/xenial.sh
+    displayName: 'This is where it gets darker'
index 8ce4fa5d9202328e7147c4ea8807a6e521101506..c1375cca3ef228049c32f83244bf4364315c5768 100644 (file)
@@ -1,9 +1,14 @@
 # SPDX-License-Identifier: LGPL-2.1+
 #
-#  Copyright © 2013 Daniele Medri
+#  Copyright © 2013-2019 Daniele Medri
 
 # Message catalog for systemd's own messages
+# Italian translation
 
+# Il formato dei messaggi di catalogo è descritto (in inglese) qui:
+# https://www.freedesktop.org/wiki/Software/systemd/catalog
+
+# Subject: The Journal has been started
 -- f77379a8490b408bbe5f6940505a777b
 Subject: Il registro è stato avviato
 Defined-By: systemd
@@ -12,6 +17,7 @@ Support: %SUPPORT_URL%
 Il processo relativo al registro di sistema è stato avviato, ha aperto i
 file in scrittura ed è ora pronto a gestire richieste.
 
+# Subject: The Journal has been stopped
 -- d93fb3c9c24d451a97cea615ce59c00b
 Subject: Il registro è stato terminato
 Defined-By: systemd
@@ -20,6 +26,7 @@ Support: %SUPPORT_URL%
 Il processo relativo al registro di sistema è stato terminato e ha chiuso
 tutti i file attivi.
 
+# Subject: Disk space used by the journal
 -- ec387f577b844b8fa948f33cad9a75e6
 Subject: Spazio disco utilizzato dal journal
 Defined-By: systemd
@@ -27,14 +34,15 @@ Support: %SUPPORT_URL%
 
 @JOURNAL_NAME@ (@JOURNAL_PATH@) sta attualmente utilizzando @CURRENT_USE_PRETTY@.
 L'utilizzo massimo consentito è impostato a @MAX_USE_PRETTY@.
-Lasciando liberi almeno @DISK_KEEP_FREE_PRETTY@ (dell'attuale @DISK_AVAILABLE_PRETTY@ di spazio libero).
-Il limite di utilizzo forzato è quindi @LIMIT_PRETTY@, del quale @AVAILABLE_PRETTY@ sono ancora disponibili.
+Si lasciano liberi almeno @DISK_KEEP_FREE_PRETTY@ (attuale spazio libero: @DISK_AVAILABLE_PRETTY@).
+Il limite di utilizzo forzato è quindi @LIMIT_PRETTY@, con @AVAILABLE_PRETTY@ ancora disponibili.
 
 I limiti di controllo dello spazio disco utilizzati dal Journal possono
 essere configurati con le impostazioni SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=,
 RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= nel file di configurazione
 /etc/systemd/journald.conf. Guardare journald.conf(5) per i dettagli.
 
+# Subject: Messages from a service have been suppressed
 -- a596d6fe7bfa4994828e72309e95d61e
 Subject: I messaggi di un servizio sono stati soppressi
 Defined-By: systemd
@@ -47,18 +55,20 @@ I messaggi del servizio sono stati eliminati.
 Solo i messaggi del servizio indicato sono stati
 eliminati, i messaggi degli altri servizi rimangono invariati.
 
-I limiti oltre i quali i messaggi si eliminano si configurano
+I limiti oltre i quali si eliminano i messaggi si configurano
 con RateLimitIntervalSec= e RateLimitBurst= in
 /etc/systemd/journald.conf. Vedi journald.conf(5) per maggiori informazioni.
 
+# Subject: Journal messages have been missed
 -- e9bf28e6e834481bb6f48f548ad13606
 Subject: I messaggi di un servizio sono stati perduti
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-I messaggi del kernel sono andati persi perché, il registro di sistema
+I messaggi del kernel sono andati persi perché il registro di sistema
 non è stato in grado di gestirli abbastanza velocemente.
 
+# Subject: Process @COREDUMP_PID@ (@COREDUMP_COMM@) dumped core
 -- fc2e22bc6ee647b6b90729ab34a250b1
 Subject: Il processo @COREDUMP_PID@ (@COREDUMP_COMM@) ha generato un dump.
 Defined-By: systemd
@@ -68,19 +78,21 @@ Documentation: man:core(5)
 Il processo @COREDUMP_PID@ (@COREDUMP_COMM@) si è bloccato generando un dump.
 
 Questo di solito capita per un errore di programmazione nell'applicazione e
-dovrebbe essere segnalato al vendor come un bug.
+dovrebbe essere segnalato come bug al vendor.
 
+# Subject: Core file was truncated to @SIZE_LIMIT@ bytes
 -- 5aadd8e954dc4b1a8c954d63fd9e1137
 Subject: Il Core file è stato troncato a @SIZE_LIMIT@ bytes.
 Defined-By: systemd
 Support: %SUPPORT_URL%
 Documentation: man:coredump.conf(5)
 
-Il processo più memoria mappata del limite massimo configurato da systemd-coredump(8) 
+Il processo ha più memoria mappata del limite massimo configurato da systemd-coredump(8) 
 per processare e memorizzare. Solo i primi @SIZE_LIMIT@ bytes sono stati salvati.
 Il file potrebbe essere ancora utile, ma strumenti come gdb(1) dovrebbero
 segnalare la troncatura.
 
+# Subject: A new session @SESSION_ID@ has been created for user @USER_ID@
 -- 8d45620c1a4348dbb17410da57c60c66
 Subject: La nuova sessione @SESSION_ID@ è stata creata per l'utente @USER_ID@
 Defined-By: systemd
@@ -91,6 +103,7 @@ Una nuova sessione con ID @SESSION_ID@ è stata creata per l'utente @USER_ID@.
 
 Il processo primario della sessione è @LEADER@.
 
+# Subject: A new seat @SEAT_ID@ has been terminated
 -- 3354939424b4456d9802ca8333ed424a
 Subject: La sessione @SESSION_ID@ è terminata
 Defined-By: systemd
@@ -99,6 +112,7 @@ Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
 
 La sessione con ID @SESSION_ID@ è terminata.
 
+# Subject: A new seat @SEAT_ID@ is now available
 -- fcbefc5da23d428093f97c82a9290f7b
 Subject: La nuova postazione @SEAT_ID@ è ora disponibile
 Defined-By: systemd
@@ -107,6 +121,7 @@ Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
 
 La nuova postazione @SEAT_ID@ è stata configurata ed è ora disponibile.
 
+# Subject: A seat @SEAT_ID@ has been removed
 -- e7852bfe46784ed0accde04bc864c2d5
 Subject: La postazione @SEAT_ID@ è stata rimossa
 Defined-By: systemd
@@ -115,6 +130,7 @@ Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
 
 La postazione @SEAT_ID@ è stata rimossa e non è più disponibile.
 
+# Subject: Time Change
 -- c7a787079b354eaaa9e77b371893cd27
 Subject: Cambio d'orario
 Defined-By: systemd
@@ -122,6 +138,7 @@ Support: %SUPPORT_URL%
 
 L'orologio di sistema è cambiato in @REALTIME@ microsecondi dal 1 gennaio, 1970.
 
+# Subject: Time zone change to @TIMEZONE@
 -- 45f82f4aef7a4bbf942ce861d1f20990
 Subject: Il fuso orario è cambiato in @TIMEZONE@
 Defined-By: systemd
@@ -129,14 +146,15 @@ Support: %SUPPORT_URL%
 
 Il fuso orario di sistema è cambiato in @TIMEZONE@.
 
+# Subject: System start-up is now complete
 -- b07a249cd024414a82dd00cd181378ff
 Subject: Avvio del sistema completato.
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
 Tutti i servizi di sistema richiesti per la fase di avvio sono stati eseguiti
-con successo. Nota che la macchina potrebbe non essere ancora pronta in quanto
-i servizi attivati sono in fase di completamento.
+con successo. La macchina potrebbe ancora attendere i servizi attivati sono
+in fase di completamento.
 
 L'avvio del kernel ha richiesto @KERNEL_USEC@ microsecondi.
 
@@ -144,17 +162,19 @@ L'avvio del disco RAM ha richiesto @INITRD_USEC@ microsecondi.
 
 L'avvio dello userspace ha richiesto @USERSPACE_USEC@ microsecondi.
 
+# Subject: User manager start-up is now complete
 -- eed00a68ffd84e31882105fd973abdd1
-Subject: User manager start-up is now complete
+Subject: L'istanza di gestione per l'utente è completata
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
 L'istanza di gestione per l'utente @_UID@ è stata avviata. Tutti i servizi
-interrogati sono stati avviati. Da notare che altri servizi potrebbero essere
-ancora in fase di avvio o in attesa di essere avviati.
+interrogati sono stati avviati. Altri servizi potrebbero essere ancora in 
+fase di avvio o in attesa di essere avviati.
 
 L'avvio dell'istanza ha impiegato @USERSPACE_USEC@ microsecondi.
 
+# Subject: System sleep state @SLEEP@ entered
 -- 6bbd95ee977941e497c48be27c254128
 Subject: Il sistema è entrato in fase di pausa @SLEEP@
 Defined-By: systemd
@@ -162,6 +182,7 @@ Support: %SUPPORT_URL%
 
 Il sistema è entrato nello stato di pausa @SLEEP@.
 
+# Subject: System sleep state @SLEEP@ left
 -- 8811e6df2a8e40f58a94cea26f8ebf14
 Subject: Il sistema è uscito dalla fase di pausa @SLEEP@
 Defined-By: systemd
@@ -169,6 +190,7 @@ Support: %SUPPORT_URL%
 
 Il sistema è uscito dallo stato di pausa @SLEEP@.
 
+# Subject: System shutdown initiated
 -- 98268866d1d54a499c4e98921d93bc40
 Subject: Il sistema è in fase di spegnimento
 Defined-By: systemd
@@ -177,6 +199,7 @@ Support: %SUPPORT_URL%
 Systemd è in fase di spegnimento. Tutti i servizi di sistema
 saranno terminati e tutti i file systems smontati.
 
+# Subject: Unit @UNIT@ has begun with start-up
 -- 7d4958e842da4a758f6c1cdc7b36dcc5
 Subject: L'unità @UNIT@ inizia la fase di avvio
 Defined-By: systemd
@@ -184,8 +207,9 @@ Support: %SUPPORT_URL%
 
 L'unità @UNIT@ ha iniziato la fase di avvio.
 
+# Subject: Unit @UNIT@ has finished start-up
 -- 39f53479d3a045ac8e11786248231fbf
-Subject: L'unità @UNIT@ termina la fase di avvio
+Subject: L'unità @UNIT@ ha terminato la fase di avvio
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
@@ -193,20 +217,23 @@ L'unità @UNIT@ ha terminato la fase di avvio.
 
 La fase di avvio è @JOB_RESULT@.
 
+# Subject: Unit @UNIT@ has begun shutting down
 -- de5b426a63be47a7b6ac3eaac82e2f6f
-Subject: L'unità @UNIT@ inizia la fase di spegnimento
+Subject: L'unità @UNIT@ ha iniziato la fase di spegnimento
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
 L'unità @UNIT@ ha iniziato la fase di spegnimento.
 
+# Subject Unit @UNIT@ has finished shutting down
 -- 9d1aaa27d60140bd96365438aad20286
-Subject: L'unità @UNIT@ termina la fase di spegnimento
+Subject: L'unità @UNIT@ ha terminato la fase di spegnimento
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
 L'unità @UNIT@ ha terminato la fase di spegnimento.
 
+# Subject: Unit @UNIT@ has failed
 -- be02cf6855d2428ba40df7e9d022f03d
 Subject: L'unità @UNIT@ è fallita
 Defined-By: systemd
@@ -216,22 +243,25 @@ L'unità @UNIT@ è fallita.
 
 Il risultato è @JOB_RESULT@.
 
+# Subject: Unit @UNIT@ has begun with reloading its configuration
 -- d34d037fff1847e6ae669a370e694725
-Subject: L'unità @UNIT@ inizia a caricare la propria configurazione
+Subject: L'unità @UNIT@ è iniziata con il ricaricamento della propria configurazione
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-L'unità @UNIT@ è iniziata ricaricando la propria configurazione
+L'unità @UNIT@ è iniziata con il ricaricamento della propria configurazione
 
+# Subject: Unit @UNIT@ has finished reloading its configuration
 -- 7b05ebc668384222baa8881179cfda54
-Subject: L'unità @UNIT@ termina il caricamento della propria configurazione
+Subject: L'unità @UNIT@ è terminata con il ricaricamento della propria configurazione
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-L'unità @UNIT@ è terminata ricaricando la propria configurazione
+L'unità @UNIT@ è terminata con il ricaricamento della propria configurazione
 
 Il risultato è @JOB_RESULT@.
 
+# Subject: Process @EXECUTABLE@ could not be executed
 -- 641257651c1b4ec9a8624d7a40a9e1e7
 Subject: Il processo @EXECUTABLE@ non può essere eseguito
 Defined-By: systemd
@@ -241,6 +271,7 @@ Il processo @EXECUTABLE@ non può essere eseguito e termina.
 
 Il numero di errore restituito durante l'esecuzione del processo è @ERRNO@.
 
+# Subject: One or more messages could not be forwarded to syslog
 -- 0027229ca0644181a76c4e92458afa2e
 Subject: Uno o più messaggi non possono essere inoltrati a syslog
 Defined-By: systemd
@@ -251,6 +282,7 @@ eseguito in parallelo a journald. Questo di solito capita perché,
 l'implementazione di syslog non sta al passo con la
 velocità dei messaggi accodati.
 
+# Subject: Mount point is not empty
 -- 1dee0369c7fc4736b7099b38ecb46ee7
 Subject: Il punto di montaggio non è vuoto
 Defined-By: systemd
@@ -262,6 +294,7 @@ Questo non interferisce con il montaggio, ma i file pre-esistenti in questa
 directory diventano inaccessibili. Per visualizzare i file, si suggerisce
 di montare manualmente il file system indicato in una posizione secondaria.
 
+# Subject: A virtual machine or container has been started
 -- 24d8d4452573402496068381a6312df2
 Subject: Avviata macchina virtuale o container
 Defined-By: systemd
@@ -270,13 +303,15 @@ Support: %SUPPORT_URL%
 La macchina virtuale @NAME@ con PID primario @LEADER@ è stata
 avviata ed è pronta all'uso.
 
+# Subject: A virtual machine or container has been terminated
 -- 58432bd3bace477cb514b56381b8a758
 Subject: Terminata macchina virtuale o container
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-La macchina virtuale @NAME@ con PID primario @LEADER@ è stata spenta.
+La macchina virtuale @NAME@ con PID primario @LEADER@ è stata terminata.
 
+# Subject: DNSSEC mode has been turned off, as server doesn't support it
 -- 36db2dfa5a9045e1bd4af5f93e1cf057
 Subject: La modalità DNSSEC è stata spenta, il server non la supporta
 Defined-By: systemd
@@ -284,18 +319,19 @@ Support: %SUPPORT_URL%
 Documentation: man:systemd-resolved.service(8) resolved.conf(5)
 
 Il servizio di risoluzione (systemd-resolved.service) ha rilevato che il
-server DNS indicato non supporta DNSSEC e la validazione DNSSEC è stata
-conseguentemente disabilitata.
+server DNS indicato non supporta DNSSEC e la validazione di quest'ultimo tipo
+è stata conseguentemente disabilitata.
 
 Ciò avverrà se DNSSEC=allow-downgrade è configurato nel file
-resolved.conf e il server DNS indicato è incompatibile con DNSSEC. Da notare
-che in questo modo ci si espone ad attacchi DNSSEC downgrade, e un aggressore
+resolved.conf e il server DNS indicato è incompatibile con DNSSEC. 
+In questo modo ci si espone ad attacchi "DNSSEC downgrade", e un aggressore
 potrebbe disabilitare la validazione DNSSEC sul sistema inserendo risposte
 DNS nel canale di comunicazione.
 
-Questo evento potrebbe essere indice che il DNS server è forse incompatibile
-con DNSSEC o che un aggressore è riuscito nel suo intento malevolo.
+Questo evento potrebbe indicare un'incompatibilità del DNS Server con DNSSEC o
+che un aggressore è riuscito nel suo intento malevolo.
 
+# Subject: DNSSEC validation failed
 -- 1675d7f172174098b1108bf8c7dc8f5d
 Subject: La validazione DNSSEC è fallita
 Defined-By: systemd
@@ -306,6 +342,7 @@ Una query DNS o un dato hanno fatto fallire la validazione DNSSEC. Questo è
 usualmente un segnale che il canale di comunicazione utilizzato è stato
 manomesso.
 
+# Subject: A DNSSEC trust anchor has been revoked
 -- 4d4408cfd0d144859184d1e65d7c8a65
 Subject: Un trust anchor DNSSEC è stato revocato
 Defined-By: systemd
@@ -315,3 +352,76 @@ Documentation: man:systemd-resolved.service(8)
 Un trust anchor DNSSEC è stato revocato. Un nuovo punto di fiducia è stato
 riconfigurato o il sistema operativo deve essere aggiornato per fornire un
 nuovo ancoraggio.
+
+# Subject: Automatic restarting of a unit has been scheduled
+-- 5eb03494b6584870a536b337290809b3
+Subject: Il riavvio automatico di un'unità è stato schedulato
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Il riavvio automatico dell'unità @UNIT@ è stato schedulato, come risultato
+delle impostazioni configurate in Restart=.
+
+# Subject: Resources consumed by unit runtime
+-- ae8f7b866b0347b9af31fe1c80b127c0
+Subject: Risorse utilizzate dall'unità in esecuzione
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Unità @UNIT@ terminata consumando le indicate risorse.
+
+# Subject: Unit succeeded
+-- 7ad2d189f7e94e70a38c781354912448
+Subject: Unità terminata
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Unità @UNIT@ entrata con successo nello stato 'dead' (morto).
+
+# Subject: Unit failed
+-- d9b373ed55a64feb8242e02dbe79a49c
+Subject: Unit fallita
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Unità @UNIT@ entrata nello stato 'failed' (fallito) con risultato '@UNIT_RESULT@'.
+
+# Subject: Unit process exited
+-- 98e322203f7a4ed290d09fe03c09fe15
+Subject: Uscito processo unità
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Un processo @COMMAND@ appartenente all'unità @UNIT@ è uscito.
+
+Il codice di uscita del processo è '@EXIT_CODE@' ed è uscito con @EXIT_STATUS@.
+
+# Subject: The system is configured in a way that might cause problems
+-- 50876a9db00f4c40bde1a2ad381c3a1b
+Subject: Il sistema è configurato in un modo che potrebbe causare problemi
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+I seguenti "tags" sono possibili:
+- "split-usr" — /usr è un file system separato e non è stato montato all'avvio di systemd
+- "cgroups-missing" — il kernel era compilato senza supporto cgroup o l'accesso ai
+  file attesi è ristretto.
+- "var-run-bad" — /var/run non è un link simbolico (symlink) a /run
+- "overflowuid-not-65534" — l'ID usato dal kernel per gli utenti "unknown" (tipo
+  NFS o user namespace) non è 65534
+- "overflowgid-not-65534" — l'ID usato dal kernel per il gruppo "unknown" (tipo
+  NFS o user namespace) non è 65534
+L'attuale sistema è taggato come @TAINT@.
+
+# Subject: A process of @UNIT@ unit has been killed by the OOM killer.
+-- fe6faa94e7774663a0da52717891d8ef
+Subject: Un processo dell'unità @UNIT@ è stato terminato da un OOM killer.
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Un processo dell'unità @UNIT@ è stato terminato dalla logica del kernel Linux per
+gestire gli eventi out-of-memory (OOM). In altri termini, il sistema ha
+poca memoria e dovrebbe essere liberata. Un processo associato con @UNIT@ è
+stato identificato come il processo ideale da terminare e così è stato.
+
+La pressione sulla memoira potrebbe o meno essere causata da @UNIT@.
similarity index 80%
rename from coccinelle/const-strlen.cocci
rename to coccinelle/const-strlen.disabled
index 38bf9b118fd5d01117edb2046ee0eaf1d49742cd..30a6e5a88ed80308e9a4ffcb27e310a0dbdb6310 100644 (file)
@@ -1,8 +1,12 @@
 @@
 constant s;
 @@
+(
+#define STRLEN
+&
 - sizeof(s)-1
 + STRLEN(s)
+)
 @@
 constant s;
 @@
index 9084cf773bf685af625e7861aed76305899c97a0..a679dab01150a38b212c61b1c53d38177cc2e694 100644 (file)
@@ -1,8 +1,16 @@
 @@
 @@
+(
+#define DEBUG_LOGGING
+&
 - _unlikely_(log_get_max_level() >= LOG_DEBUG)
 + DEBUG_LOGGING
+)
 @@
 @@
+(
+#define DEBUG_LOGGING
+&
 - log_get_max_level() >= LOG_DEBUG
 + DEBUG_LOGGING
+)
index ef1356428223aaf2d8378cd86f0dc2305613214b..8b133b3a24f6547062dd1c0d803dace33c94cd6a 100644 (file)
@@ -1,5 +1,7 @@
 @@
+/* We want to stick with dup() in test-fd-util.c */
+position p : script:python() { p[0].file != "src/test/test-fd-util.c" };
 expression fd;
 @@
-- dup(fd)
+- dup@p(fd)
 + fcntl(fd, F_DUPFD, 3)
index fbc75b9c343ca49688435e34e9cef32c35d81ff5..bc6c656e798a22cfde36457facb9c85042740f64 100644 (file)
@@ -1,5 +1,8 @@
 @@
+/* Avoid running this transformation on the empty_to_null function itself */
+position p : script:python() { p[0].current_element != "empty_to_null" };
 expression s;
 @@
-- isempty(s) ? NULL : s
+
+- isempty@p(s) ? NULL : s
 + empty_to_null(s)
index 1a70717e76cb855ba75db28be584496c53e6f627..73966b02e5d27861900299f0a5adecd4f1fa0db2 100644 (file)
@@ -1,15 +1,16 @@
 @@
+/* Disable this transformation for the securebits-util.h, as it makes
+ * the expression there confusing. */
+position p : script:python() { p[0].file != "src/shared/securebits-util.h" };
 expression x, y;
 @@
-- ((x) & (y)) == (y)
+(
+- ((x@p) & (y)) == (y)
 + FLAGS_SET(x, y)
-@@
-expression x, y;
-@@
-- (x & (y)) == (y)
+|
+- (x@p & (y)) == (y)
 + FLAGS_SET(x, y)
-@@
-expression x, y;
-@@
-- ((x) & y) == y
+|
+- ((x@p) & y) == y
 + FLAGS_SET(x, y)
+)
index 12d5475fd91617d76883bcfe6e27db793c49027b..2c9b94ceb67438418efdbc5e42604a598dc1caa6 100644 (file)
@@ -1,54 +1,37 @@
 @@
 expression e;
-constant n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
-@@
+/* Exclude JsonVariant * from the transformation, as it can't work with the
+ * current version of the IN_SET macro */
+typedef JsonVariant;
+type T != JsonVariant*;
+constant T n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
+@@
+
+(
 - e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8 || e == n9
 + IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5, n6, n7, n8;
-@@
+|
 - e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8
 + IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5, n6, n7;
-@@
+|
 - e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7
 + IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5, n6;
-@@
+|
 - e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6
 + IN_SET(e, n0, n1, n2, n3, n4, n5, n6)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5;
-@@
+|
 - e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5
 + IN_SET(e, n0, n1, n2, n3, n4, n5)
-@@
-expression e;
-constant n0, n1, n2, n3, n4;
-@@
+|
 - e == n0 || e == n1 || e == n2 || e == n3 || e == n4
 + IN_SET(e, n0, n1, n2, n3, n4)
-@@
-expression e;
-constant n0, n1, n2, n3;
-@@
+|
 - e == n0 || e == n1 || e == n2 || e == n3
 + IN_SET(e, n0, n1, n2, n3)
-@@
-expression e;
-constant n0, n1, n2;
-@@
+|
 - e == n0 || e == n1 || e == n2
 + IN_SET(e, n0, n1, n2)
-@@
-expression e;
-constant n0, n1;
-@@
+|
 - e == n0 || e == n1
 + IN_SET(e, n0, n1)
+)
index d8d52758892e8e0735d256bc3ae30ccec906b6e3..e0a9f07ca6d0107524d41afb445d3c5f4f82bb9d 100644 (file)
@@ -1,60 +1,42 @@
 @@
+/* Disable this transformation for the test-string-util.c */
+position p : script:python() { p[0].file != "src/test/test-string-util.c" };
 expression s;
 @@
-- strv_length(s) == 0
+(
+- strv_length@p(s) == 0
 + strv_isempty(s)
-@@
-expression s;
-@@
-- strv_length(s) <= 0
+|
+- strv_length@p(s) <= 0
 + strv_isempty(s)
-@@
-expression s;
-@@
-- strv_length(s) > 0
+|
+- strv_length@p(s) > 0
 + !strv_isempty(s)
-@@
-expression s;
-@@
-- strv_length(s) != 0
+|
+- strv_length@p(s) != 0
 + !strv_isempty(s)
-@@
-expression s;
-@@
-- strlen(s) == 0
+|
+- strlen@p(s) == 0
 + isempty(s)
-@@
-expression s;
-@@
-- strlen(s) <= 0
+|
+- strlen@p(s) <= 0
 + isempty(s)
-@@
-expression s;
-@@
-- strlen(s) > 0
+|
+- strlen@p(s) > 0
 + !isempty(s)
-@@
-expression s;
-@@
-- strlen(s) != 0
+|
+- strlen@p(s) != 0
 + !isempty(s)
-@@
-expression s;
-@@
-- strlen_ptr(s) == 0
+|
+- strlen_ptr@p(s) == 0
 + isempty(s)
-@@
-expression s;
-@@
-- strlen_ptr(s) <= 0
+|
+- strlen_ptr@p(s) <= 0
 + isempty(s)
-@@
-expression s;
-@@
-- strlen_ptr(s) > 0
+|
+- strlen_ptr@p(s) > 0
 + !isempty(s)
-@@
-expression s;
-@@
-- strlen_ptr(s) != 0
+|
+- strlen_ptr@p(s) != 0
 + !isempty(s)
+)
index ebdc3f6a2a9493440fc66cc080a80a74ecaa7439..8198cc84b4cd4ad854f72ef25c0b82c2a6ced964 100644 (file)
@@ -21,10 +21,18 @@ expression s;
 @@
 expression a, b;
 @@
+(
+#define memzero
+&
 - memset(a, 0, b)
 + memzero(a, b)
+)
 @@
 expression a, b;
 @@
+(
+#define memzero
+&
 - bzero(a, b)
 + memzero(a, b)
+)
index 8119fe07f29f738f9749f8f46e63212fca054681..15e6c7d566bd08281e841892b3383500871da64f 100644 (file)
@@ -1,6 +1,8 @@
 @@
-expression p;
+/* Avoid running this transformation on the mfree function itself */
+position p : script:python() { p[0].current_element != "mfree" };
+expression e;
 @@
-- free(p);
+- free@p(e);
 - return NULL;
-+ return mfree(p);
++ return mfree(e);
index 7cf98500cd425369f6035ab259ffc49a5d37271e..aed2c3490c4f75485c2d5672058b285073322a3a 100644 (file)
@@ -1,54 +1,34 @@
 @@
 expression e;
-constant n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
+typedef JsonVariant;
+type T != JsonVariant*;
+constant T n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
 @@
+(
 - e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9
 + !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5, n6, n7, n8;
-@@
+|
 - e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8
 + !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5, n6, n7;
-@@
+|
 - e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7
 + !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5, n6;
-@@
+|
 - e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6
 + !IN_SET(e, n0, n1, n2, n3, n4, n5, n6)
-@@
-expression e;
-constant n0, n1, n2, n3, n4, n5;
-@@
+|
 - e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5
 + !IN_SET(e, n0, n1, n2, n3, n4, n5)
-@@
-expression e;
-constant n0, n1, n2, n3, n4;
-@@
+|
 - e != n0 && e != n1 && e != n2 && e != n3 && e != n4
 + !IN_SET(e, n0, n1, n2, n3, n4)
-@@
-expression e;
-constant n0, n1, n2, n3;
-@@
+|
 - e != n0 && e != n1 && e != n2 && e != n3
 + !IN_SET(e, n0, n1, n2, n3)
-@@
-expression e;
-constant n0, n1, n2;
-@@
+|
 - e != n0 && e != n1 && e != n2
 + !IN_SET(e, n0, n1, n2)
-@@
-expression e;
-constant n0, n1;
-@@
+|
 - e != n0 && e != n1
 + !IN_SET(e, n0, n1)
+)
index 520de0ac4215f012f644cefc78687133621d4b2e..be80a76a5f3b50cb0c60dd96e8d5bd3176541d4c 100755 (executable)
@@ -1,9 +1,25 @@
 #!/bin/bash -e
 
+# Exclude following paths from the Coccinelle transformations
+EXCLUDED_PATHS=(
+    "src/boot/efi/*"
+    "src/shared/linux/*"
+    "src/basic/linux/*"
+    # Symlinked to test-bus-vtable-cc.cc, which causes issues with the IN_SET macro
+    "src/libsystemd/sd-bus/test-bus-vtable.c"
+)
+
 top="$(git rev-parse --show-toplevel)"
-files="$(git ls-files ':/*.[ch]')"
+iso_defs="$top/coccinelle/systemd-definitions.iso"
 args=
 
+# Create an array from files tracked by git...
+mapfile -t files < <(git ls-files ':/*.[ch]')
+# ...and filter everything that matches patterns from EXCLUDED_PATHS
+for excl in "${EXCLUDED_PATHS[@]}"; do
+    files=(${files[@]//$excl})
+done
+
 case "$1" in
     -i)
         args="$args --in-place"
@@ -21,7 +37,7 @@ for SCRIPT in ${@-$top/coccinelle/*.cocci} ; do
     TMPFILE=`mktemp`
     echo "+ spatch --sp-file $SCRIPT $args ..."
     parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \
-             spatch --sp-file $SCRIPT $args ::: $files \
+             spatch --iso-file $iso_defs --sp-file $SCRIPT $args ::: "${files[@]}" \
              2>"$TMPFILE" || cat "$TMPFILE"
     echo -e "--x-- Processed $SCRIPT --x--\n"
 done
diff --git a/coccinelle/sd_event_source_disable_unref.cocci b/coccinelle/sd_event_source_disable_unref.cocci
new file mode 100644 (file)
index 0000000..2763fef
--- /dev/null
@@ -0,0 +1,36 @@
+@@
+expression p;
+@@
+- if (p) {
+-         (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+-         p = sd_event_source_unref(p);
+- }
++ p = sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- if (p) {
+-         sd_event_source_set_enabled(p, SD_EVENT_OFF);
+-         sd_event_source_unref(p);
+- }
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- if (p) {
+-         (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+-         sd_event_source_unref(p);
+- }
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
++ sd_event_source_disable_unref(p);
index 13ceb338f199dad900efa29f5f94d97db762a5e3..7901da3652ce7bb4c9d023e2ffaf7cb84b15ac5d 100644 (file)
@@ -1,48 +1,60 @@
 @@
+/* Avoid running this transformation on the strempty function itself */
+position p : script:python() { p[0].current_element != "strempty" };
 expression s;
 @@
-- s ?: ""
+(
+- s@p ?: ""
 + strempty(s)
-@@
-expression s;
-@@
-- s ? s : ""
+|
+- s@p ? s : ""
 + strempty(s)
+)
+
 @@
+position p : script:python() { p[0].current_element != "strempty" };
 expression s;
 @@
-- if (!s)
+- if (!s@p)
 -         s = "";
 + s = strempty(s);
+
 @@
+position p : script:python() { p[0].current_element != "strnull" };
 expression s;
 @@
-- s ?: "(null)"
+(
+- s@p ?: "(null)"
 + strnull(s)
-@@
-expression s;
-@@
-- s ? s : "(null)"
+|
+- s@p ? s : "(null)"
 + strnull(s)
+)
+
 @@
+position p : script:python() { p[0].current_element != "strnull" };
 expression s;
 @@
-- if (!s)
+- if (!s@p)
 -         s = "(null)";
 + s = strnull(s);
+
 @@
+position p : script:python() { p[0].current_element != "strna" };
 expression s;
 @@
-- s ?: "n/a"
+(
+- s@p ?: "n/a"
 + strna(s)
-@@
-expression s;
-@@
-- s ? s : "n/a"
+|
+- s@p ? s : "n/a"
 + strna(s)
+)
+
 @@
+position p : script:python() { p[0].current_element != "strna" };
 expression s;
 @@
-- if (!s)
+- if (!s@p)
 -         s = "n/a";
 + s = strna(s);
index 645bfc945f4b4b0e426ec72b72aca8529fb0a347..3ddb69cb4cff498ab310f6ffd9eba2504eef6192 100644 (file)
@@ -2,9 +2,15 @@
 expression e;
 expression list args;
 @@
+(
+/* Ignore one specific case in src/shared/bootspec.c where we want to stick
+ * with the log_debug() + return pattern */
+log_debug("Found no default boot entry :(");
+|
 - log_debug(args);
 - return -e;
 + return log_debug_errno(SYNTHETIC_ERRNO(e), args);
+)
 @@
 expression e;
 expression list args;
diff --git a/coccinelle/systemd-definitions.iso b/coccinelle/systemd-definitions.iso
new file mode 100644 (file)
index 0000000..92db763
--- /dev/null
@@ -0,0 +1,20 @@
+/* Statement isomorphisms - replace explicit checks against NULL with a
+ * shorter variant, which relies on C's downgrade-to-bool feature.
+ * The expression metavariables should be declared as pointers, however,
+ * that doesn't work well with complex expressions like:
+ * if (UNIT(p)->default_dependencies != NULL)
+ */
+
+Statement
+@@
+expression X;
+statement S;
+@@
+if (X == NULL) S => if (!X) S
+
+Statement
+@@
+expression X;
+statement S;
+@@
+if (X != NULL) S => if (X) S
index ba242483cd50c7d9f30081fb46fb85af02187303..f7124e789651cfe6db9571c63527cf11839bb8d7 100644 (file)
@@ -6,8 +6,15 @@ expression q;
 - q = -1;
 - return p;
 + return TAKE_FD(q);
+
+/* The ideal solution would use 'local idexpression' to avoid matching errno,
+ * which is a global variable. However, 'idexpression' nor 'identifier'
+ * would match, for example, "x->fd", which is considered 'expression' in
+ * the SmPL grammar
+ */
 @@
-expression p, q;
+expression p != errno;
+expression q;
 @@
 - p = q;
 - q = -1;
index 18363f0f1bba1bac8b9d3d3bef84ba287337b9bd..a3bdfaad8e16c4cce650cf9663252d34eb424b0e 100644 (file)
@@ -64,5 +64,10 @@ available functionality:
     of active alerts can be found
     [here](https://lgtm.com/projects/g/systemd/systemd/alerts/?mode=list).
 
+15. Each PR is automatically tested with [Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
+    and [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
+    See [Testing systemd using sanitizers](https://systemd.io/TESTING_WITH_SANITIZERS)
+    for more information.
+
 Access to Coverity and oss-fuzz reports is limited. Please reach out to the
 maintainers if you need access.
index 620e47e823c8ead9243313b98eab0f8d6505a32c..d14bf131ba7735e27deeb3611b808c6b8693d698 100644 (file)
@@ -15,7 +15,6 @@ distribution:
    * `-Dsysvinit-path=`
    * `-Dsysvrcnd-path=`
    * `-Drc-local=`
-   * `-Dhalt-local=`
    * `-Dloadkeys-path=`
    * `-Dsetfont-path=`
    * `-Dtty-gid=`
diff --git a/docs/TESTING_WITH_SANITIZERS.md b/docs/TESTING_WITH_SANITIZERS.md
new file mode 100644 (file)
index 0000000..7cb879a
--- /dev/null
@@ -0,0 +1,88 @@
+---
+title: Testing systemd using sanitizers
+---
+
+# Testing systemd using sanitizers
+
+To catch the *nastier* kind of bugs, you can run your code with [Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
+and [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
+This is mostly done automagically by various CI systems for each PR, but you may
+want to do it locally as well. The process slightly varies depending on the
+compiler you want to use and which part of the test suite you want to run.
+
+## gcc
+gcc compiles in sanitizer libraries dynamically by default, so you need to get
+the shared libraries first - on Fedora these are shipped as a separate packages
+(`libasan` for Address Sanitizer and `libubsan` for Undefined Behavior Sanitizer).
+
+The compilation itself is then a matter of simply adding `-Db_sanitize=address,undefined`
+to `meson`. That's it - following executions of `meson test` and integrations tests
+under `test/` subdirectory will run with sanitizers enabled. However, to get
+truly useful results, you should tweak the runtime configuration of respective
+sanitizers; e.g. in systemd we set the following environment variables:
+
+```bash
+ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
+UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
+```
+## clang
+In case of clang things are somewhat different - the sanitizer libraries are
+compiled in statically by default. This is not an issue if you plan to run
+only the unit tests, but for integration tests you'll need to convince clang
+to use the dynamic versions of sanitizer libraries.
+
+First of all, pass `-shared-libsan` to both `clang` and `clang++`:
+
+```bash
+CFLAGS=-shared-libasan
+CXXFLAGS=-shared-libasan
+```
+
+The `CXXFLAGS` are necessary for `src/libsystemd/sd-bus/test-bus-vtable-cc.c`. Compilation
+is then the same as in case of gcc, simply add `-Db_sanitize=address,undefined`
+to the `meson` call and use the same environment variables for runtime configuration.
+
+```bash
+ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
+UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
+```
+
+After this, you'll probably notice that all compiled binaries complain about
+missing `libclang_rt.asan*` library. To fix this, you have to install clang's
+runtime libraries, usually shipped in the `compiler-rt` package. As these libraries
+are installed in a non-standard location (non-standard for `ldconfig`), you'll
+need to manually direct binaries to the respective runtime libraries.
+
+```
+# Optionally locate the respective runtime DSO
+$ ldd build/systemd | grep libclang_rt.asan
+        libclang_rt.asan-x86_64.so => not found
+        libclang_rt.asan-x86_64.so => not found
+$ find /usr/lib* /usr/local/lib* -type f -name libclang_rt.asan-x86_64.so 2>/dev/null
+/usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so
+
+# Set the LD_LIBRARY_PATH accordingly
+export LD_LIBRARY_PATH=/usr/lib64/clang/7.0.1/lib/
+
+# If the path is correct, the "not found" message should change to an actual path
+$ ldd build/systemd | grep libclang_rt.asan
+        libclang_rt.asan-x86_64.so => /usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so (0x00007fa9752fc000)
+```
+
+This should help binaries to correctly find necessary sanitizer DSOs.
+
+Also, to make the reports useful, `llvm-symbolizer` tool is required (usually
+part of the `llvm` package).
+
+## Background notes
+The reason why you need to force dynamic linking in case of `clang` is that some
+applications make use of `libsystemd`, which is compiled with sanitizers as well.
+However, if a *standard* (uninstrumented) application loads an instrumented library,
+it will immediately fail due to unresolved symbols. To fix/workaround this, you
+need to pre-load the ASan DSO using `LD_PRELOAD=/path/to/asan/dso`, which will
+make things work as expected in most cases. This will, obviously, not work with
+statically linked sanitizer libraries.
+
+These shenanigans are performed automatically when running the integration test
+suite (i.e. `test/TEST-??-*`) and are located in `test/test-functions` (mainly,
+but not only, in the `create_asan_wrapper` function).
index 3aa68c0a2629d18766547f5d33545f4f06601294..469ef7ce31563c9e160ac34ff327fe31bd412a90 100644 (file)
@@ -227,6 +227,7 @@ All cgroup/resource control settings are available for transient units
 ✓ CPUQuota=
 ✓ CPUQuotaPeriodSec=
 ✓ MemoryAccounting=
+✓ DefaultMemoryMin=
 ✓ MemoryMin=
 ✓ DefaultMemoryLow=
 ✓ MemoryLow=
index 25345a918f65a733a3e6750889e3810b8e022eda..480ee231e74319e1cc331133965a62cc49a6094b 100644 (file)
@@ -237,7 +237,8 @@ the artifacts the container manager persistently leaves in the system.
 |                 65535 | 16bit `(uid_t) -1`    | Linux         |                               |
 |          65536…524287 | Unused                |               |                               |
 |     524288…1879048191 | Container UID ranges  | `systemd`     | `nss-mymachines`              |
-| 1879048192…4294967294 | Unused                |               |                               |
+| 1879048191…2147483647 | Unused                |               |                               |
+| 2147483648…4294967294 | HIC SVNT LEONES       |               |                               |
 |            4294967295 | 32bit `(uid_t) -1`    | Linux         |                               |
 
 Note that "Unused" in the table above doesn't meant that these ranges are
@@ -246,6 +247,13 @@ pre-defined purposes between Linux, generic low-level distributions and
 `systemd`. There might very well be other packages that allocate from these
 ranges.
 
+Note that the range 2147483648…4294967294 (i.e. 2^31…2^32-2) should be handled
+with care. Various programs (including kernel file systems, see `devpts`) have
+trouble with UIDs outside of the signed 32bit range, i.e any UIDs equal to or
+above 2147483648. It is thus strongly recommended to stay away from this range
+in order to avoid complications. This range should be considered reserved for
+future, special purposes.
+
 ## Notes on resolvability of user and group names
 
 User names, UIDs, group names and GIDs don't have to be resolvable using NSS
diff --git a/fuzz.yaml b/fuzz.yaml
new file mode 100644 (file)
index 0000000..f64af60
--- /dev/null
+++ b/fuzz.yaml
@@ -0,0 +1,32 @@
+base: ubuntu:16.04
+language: c
+setup:
+- sudo bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
+- sudo apt-get update -y
+- sudo apt-get build-dep -y systemd
+- sudo apt-get install -y python3-pip
+- pip3 install meson ninja
+- export PATH="$HOME/.local/bin/:$PATH"
+- CC=$FUZZ_CC CXX=$FUZZ_CXX meson -Dfuzzbuzz=true -Dfuzzbuzz-engine-dir=$(dirname "$FUZZ_ENGINE") -Dfuzzbuzz-engine=$(cut -d. -f1 <(basename "$FUZZ_ENGINE")) -Db_lundef=false ./build
+- ninja -v -C ./build fuzzers
+environment:
+targets:
+- name: fuzz-compress
+  harness:
+    binary: ./build/fuzz-compress
+- name: fuzz-unit-file
+  harness:
+    binary: ./build/fuzz-unit-file
+  corpus: ./test/fuzz/fuzz-unit-file
+- name: fuzz-journald-syslog
+  harness:
+    binary: ./build/fuzz-journald-syslog
+  corpus: ./test/fuzz/fuzz-journald-syslog
+- name: fuzz-netdev-parser
+  harness:
+    binary: ./build/fuzz-netdev-parser
+  corpus: ./test/fuzz/fuzz-netdev-parser
+- name: fuzz-network-parser
+  harness:
+    binary: ./build/fuzz-network-parser
+  corpus: ./test/fuzz/fuzz-network-parser
index 4762c68a1b2e65c83ec7f331fcb79622263ed3db..62957d27250712a5007ea7ddf2bcbe93befb0b57 100644 (file)
@@ -98,8 +98,7 @@
 
 # common keys
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pn*
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr*
  KEYBOARD_KEY_86=wlan                                   # Fn+F3 or Fn+Q for comunication key
  KEYBOARD_KEY_a5=help                                   # Fn+F1
@@ -183,6 +182,11 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1640:*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:pvr*
  KEYBOARD_KEY_a9=!switchvideomode                       # Fn+F5
 
+# Packard Bell and Gateway models
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pn*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pn*
+ KEYBOARD_KEY_86=wlan                                   # Fn+F3 or Fn+Q for comunication key
+
 ###########################################################
 # Alienware
 ###########################################################
@@ -837,6 +841,168 @@ evdev:input:b0003v04B3p301B*
 # Logitech
 ###########################################################
 
+# 27MHz wireless keyboards, these all have a PID of 00?? and all send c10xx
+# logitech custom consumer usage-page codes. The mappings below are the most
+# common, but some mapping may differ, especially the Fn F1-F12 mappings
+evdev:input:b0003v046Dp00*
+ KEYBOARD_KEY_c0183=media           # HUT:config, kbd:Media/Music player button
+ KEYBOARD_KEY_c1001=chat            # Messenger button
+ KEYBOARD_KEY_c1002=camera          # Webcam button
+ KEYBOARD_KEY_c1003=audio           # Music Browser button
+ KEYBOARD_KEY_c1004=video           # Video Browser button
+ KEYBOARD_KEY_c1005=images          # Image Browser button
+ KEYBOARD_KEY_c100a=documents       # Document Browser button
+ KEYBOARD_KEY_c100b=rewind          # Rewind button
+ KEYBOARD_KEY_c100c=fastforward     # Fast Forward button
+ KEYBOARD_KEY_c100f=f14             # Track 1 button → f14 → XF86Launch5
+ KEYBOARD_KEY_c1010=f15             # Track 2 button → f15 → XF86Launch6
+ KEYBOARD_KEY_c1011=channeldown     # Playlist back button
+ KEYBOARD_KEY_c1012=channelup       # Playlist advance button
+ KEYBOARD_KEY_c1013=camera          # Webcam button
+ KEYBOARD_KEY_c1014=coffee          # Status button
+ KEYBOARD_KEY_c1015=record          # Record symbol button
+ KEYBOARD_KEY_c1016=sound           # Flame/CD burning → sound → XF86AudioPreset
+ KEYBOARD_KEY_c1017=ejectcd         # Eject button
+ KEYBOARD_KEY_c1018=config          # Remote-control ico
+ KEYBOARD_KEY_c1019=f14             # Preset 1 → f14 → XF86Launch5
+ KEYBOARD_KEY_c101a=f15             # Preset 2 → f15 → XF86Launch6
+ KEYBOARD_KEY_c101b=f16             # Preset 3 → f16 → XF86Launch7
+ KEYBOARD_KEY_c101c=cyclewindows    # 2 overlapping windows icon
+ KEYBOARD_KEY_c101f=zoomout         # zoom - button / - side of zoomrocker
+ KEYBOARD_KEY_c1020=zoomin          # zoom + button / + side off zoom rocker
+ KEYBOARD_KEY_c1021=zoomreset       # 100% symbol on kbd left side
+ KEYBOARD_KEY_c1023=close           # [x] symbol on kbd left side
+ KEYBOARD_KEY_c1027=menu            # Hamburger menu icon
+ KEYBOARD_KEY_c1028=angle           # Rotate button
+ KEYBOARD_KEY_c1029=shuffle         # Shuffle button
+ KEYBOARD_KEY_c102a=back            # Back button
+ KEYBOARD_KEY_c102b=cyclewindows    # Empty window icon
+ KEYBOARD_KEY_c102d=www             # www text + magnifierglass icon
+ KEYBOARD_KEY_c1031=connect         # Pickup phone button → connect → XF86Go
+ KEYBOARD_KEY_c1032=cancel          # Hangup phone button → cancel → Cancel
+ KEYBOARD_KEY_c1041=help            # Help text or icon (Fn + F1)
+ KEYBOARD_KEY_c1042=wordprocessor   # Word icon (Fn + F2)
+ KEYBOARD_KEY_c1043=spreadsheet     # Excel icon (Fn + F3)
+ KEYBOARD_KEY_c1044=presentation    # Presentation icon (Fn + F4)
+ KEYBOARD_KEY_c1045=undo            # Undo Icon (Fn + F5)
+ KEYBOARD_KEY_c1046=redo            # Redo Icon (Fn + F6)
+ KEYBOARD_KEY_c1047=print           # Printer Icon (Fn + F7)
+ KEYBOARD_KEY_c1048=save            # Floppy Icon (Fn + F8)
+ KEYBOARD_KEY_c1049=prog1           # Smartkey A (Fn + F9)  → XF86Launch1
+ KEYBOARD_KEY_c104a=prog2           # Smartkey B (Fn + F10) → XF86Launch2
+ KEYBOARD_KEY_c104b=prog3           # Smartkey C (Fn + F11) → XF86Launch3
+ KEYBOARD_KEY_c104c=prog4           # Smartkey D (Fn + F12) → XF86Launch4
+
+# Cordless Access Keyboard (27 MHz, modelnumber Y-RH35)
+evdev:input:b0003v046Dp0042*
+ KEYBOARD_KEY_c1041=new
+ KEYBOARD_KEY_c1042=reply
+ KEYBOARD_KEY_c1043=forward
+ KEYBOARD_KEY_c1044=send
+ KEYBOARD_KEY_c1045=previoussong
+ KEYBOARD_KEY_c1046=nextsong
+ KEYBOARD_KEY_c1047=playpause
+ KEYBOARD_KEY_c1048=stopcd
+ KEYBOARD_KEY_c1049=file
+ KEYBOARD_KEY_c104a=documents
+ KEYBOARD_KEY_c104b=images
+ KEYBOARD_KEY_c104c=audio
+
+# "Cordless Rechargeable Desktop" keyboard (27 MHz, modelnumber Y-RK49)
+evdev:input:b0003v046Dp0045*
+ KEYBOARD_KEY_c1041=new
+ KEYBOARD_KEY_c1042=reply
+ KEYBOARD_KEY_c1043=forward
+ KEYBOARD_KEY_c1044=send
+ KEYBOARD_KEY_c1049=file
+ KEYBOARD_KEY_c104a=documents
+ KEYBOARD_KEY_c104b=images
+ KEYBOARD_KEY_c104c=audio
+
+# S510 keyboard (27 MHz, modelnumber Y-RAK73)
+evdev:input:b0003v046Dp0056*
+ KEYBOARD_KEY_c1041=battery      # Battery icon (Fn + F1)
+
+# MX3000 keyboard (27 MHz, modelnumber Y-RAM74)
+# We ignore the scroll up / down keypress events since these buttons also
+# generate scroll-wheel events and we do not want to generate duplicate events
+# Note if the "Special Button Function" in the HID++ features register gets
+# cleared then the scroll-wheel events for these buttons go away and then
+# tilting the scrollwheel left/right starts sending c1022 / c1024 events
+evdev:input:b0003v046Dp0057*
+ KEYBOARD_KEY_c1041=battery      # Battery icon (Fn + F1)
+
+#KEYBOARD_KEY_c101d=scrolldown   # Button below scrollwheel (see note above)
+#KEYBOARD_KEY_c101e=scrollup     # Button above scrollwheel (see note above)
+#KEYBOARD_KEY_c1022=scrollleft   # Left click on scroll-wheel (see note above)
+#KEYBOARD_KEY_c1024=scrollright  # Right click on scroll-wheel (see note above)
+
+# MX3200 keyboard (27 MHz, modelnumber Y-RAV80)
+evdev:input:b0003v046Dp005C*
+ KEYBOARD_KEY_c1001=phone           # VOIP button
+ KEYBOARD_KEY_c1016=record          # Record button
+ KEYBOARD_KEY_c1041=wordprocessor   # Word icon (Fn + F1)
+ KEYBOARD_KEY_c1042=spreadsheet     # Excel icon (Fn + F2)
+ KEYBOARD_KEY_c1043=calendar        # Calendar icon (Fn + F3)
+ KEYBOARD_KEY_c1044=documents       # My Documents icon (Fn + F4)
+ KEYBOARD_KEY_c1045=prog1           # Smartkey A (Fn + F5) → XF86Launch1
+ KEYBOARD_KEY_c1046=prog2           # Smartkey B (Fn + F6) → XF86Launch2
+ KEYBOARD_KEY_c1047=prog3           # Smartkey C (Fn + F7) → XF86Launch3
+ KEYBOARD_KEY_c1048=prog4           # Smartkey D (Fn + F8) → XF86Launch4
+
+# EX100 keyboard (27 MHz, modelnumber Y-RBH94)
+evdev:input:b0003v046Dp0065*
+ KEYBOARD_KEY_c104b=battery         # Battery icon (Fn + F11)
+ KEYBOARD_KEY_c104c=ejectcd         # Eject icon (Fn + F12)
+
+# S520 keyboard (27 MHz, modelnumber Y-RBA97)
+# Note this one uses non-standard codes for FN + F9 - Fn + F12?
+evdev:input:b0003v046Dp0066*
+ KEYBOARD_KEY_c100e=prog4           # Smartkey D (Fn + F12) → XF86Launch4
+ KEYBOARD_KEY_c1019=prog1           # Smartkey A (Fn + F9)  → XF86Launch1
+ KEYBOARD_KEY_c101a=prog2           # Smartkey B (Fn + F10) → XF86Launch2
+ KEYBOARD_KEY_c101b=prog3           # Smartkey C (Fn + F11) → XF86Launch3
+ KEYBOARD_KEY_c1041=wordprocessor   # Word icon (Fn + F1)
+ KEYBOARD_KEY_c1042=spreadsheet     # Excel icon (Fn + F2)
+ KEYBOARD_KEY_c1043=presentation    # Presentation icon (Fn + F3)
+ KEYBOARD_KEY_c1044=calendar        # Calendar icon (Fn + F4)
+ KEYBOARD_KEY_c1045=homepage        # Home icon (Fn + F5)
+ KEYBOARD_KEY_c1046=email           # Letter icon (Fn + F6)
+ KEYBOARD_KEY_c1047=search          # Magnifying glass icon (Fn + F7)
+ KEYBOARD_KEY_c1048=config          # Window with gear icon (Fn + F8)
+ KEYBOARD_KEY_c106f=battery         # Battery icon
+
+# S510 remote control (27 MHz)
+evdev:input:b0003v046Dp00FE*
+ KEYBOARD_KEY_c1018=media           # Media button
+
+# MX5000 keyboard (HID proxy mode and bluetooth matches)
+# The 4 buttons below the LCD send codes 0xc100c - 0xc100f. They only send
+# these codes when the LCD is displaying text send to it. These codes are
+# directly consumed by recent versions of lcdproc when it is driving the LCD,
+# so these codes should not be mapped
+evdev:input:b0003v046DpB305*
+evdev:input:b0005v046DpB305*
+ KEYBOARD_KEY_c0230=zoomreset  # HUT says fullscreen, kbd says 100%
+ KEYBOARD_KEY_c1004=send       # Send and receive / sync button
+ KEYBOARD_KEY_c1006=coffee     # Status (online/away) button
+ KEYBOARD_KEY_c1007=camera     # Webcam button
+ KEYBOARD_KEY_c1038=prog1      # Smartkey A → XF86Launch1
+ KEYBOARD_KEY_c1039=prog2      # Smartkey B → XF86Launch2
+ KEYBOARD_KEY_c103a=prog3      # Smartkey C → XF86Launch3
+ KEYBOARD_KEY_c103b=prog4      # Smartkey D → XF86Launch4
+
+# MX5500 keyboard (HID proxy mode and bluetooth matches)
+evdev:input:b0003v046DpB30B*
+evdev:input:b0005v046DpB30B*
+ KEYBOARD_KEY_c0183=media      # HUT says consumer control configuration, kbd says Media Center
+ KEYBOARD_KEY_c100e=images      # Camera icon, "Photo Gallery"
+ KEYBOARD_KEY_c100f=config      # Window with gear icon
+ KEYBOARD_KEY_c1038=prog1      # Smartkey A → XF86Launch1
+ KEYBOARD_KEY_c1039=prog2      # Smartkey B → XF86Launch2
+ KEYBOARD_KEY_c103a=prog3      # Smartkey C → XF86Launch3
+ KEYBOARD_KEY_c103b=prog4      # Smartkey D → XF86Launch4
+
 # iTouch
 evdev:input:b0003v046DpC308*
  KEYBOARD_KEY_90001=shop                                # Shopping
@@ -923,8 +1089,8 @@ evdev:input:b0003v046DpC309*
  KEYBOARD_KEY_c0207=save         # Save (F8)
  KEYBOARD_KEY_c0194=file         # My Computer (F9)
  KEYBOARD_KEY_c01a7=documents    # My Documents (F10)
- KEYBOARD_KEY_c01b6=images       # My Pictures (F11) ??
- KEYBOARD_KEY_c01b7=sound        # My Music (F12) ??
+ KEYBOARD_KEY_c01b6=images       # My Pictures (F11)
+ KEYBOARD_KEY_c01b7=audio        # My Music (F12)
 
 
 ###########################################################
index 02bae3e765e898a2b6b3dcac3b4f90f8eba5e82b..4bfab4d4c76c3331343d67c787345e0f8fc8b5d7 100644 (file)
@@ -166,7 +166,7 @@ sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo:pnP02BD6_HI-122LP:*
  ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
 
 # Chuwi Hi13
-sensor:modalias:acpi:KIOX000A*:dmi:svnChuwi*:pnHi13
+sensor:modalias:acpi:KIOX000A*:dmi:*:svnChuwi*:pnHi13:*
  ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
 
 # Chuwi HiBook
@@ -363,8 +363,8 @@ sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80U1:*
 sensor:modalias:acpi:BOSC0200*:dmi:*:svnLINX*:pnLINX1010B:*
  ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, -1
 
-# Linx 12X64
-sensor:modalias:acpi:KIOX000A*:dmi:*:svnLINX*:pnLINX12X64:*
+# Linx 12X64 and 12V64
+sensor:modalias:acpi:KIOX000A*:dmi:*:svnLINX*:pnLINX12*64:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
 #########################################
@@ -377,6 +377,10 @@ sensor:modalias:acpi:SMO8500*:dmi:*:svnMEDION:pnAkoyaE2212TMD99720:*
 sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION*:pnE3216*:*
  ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
 
+# Medion Akoya E3222 MD62450
+sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION*:pnE3222*:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
 #########################################
 # MSI
 #########################################
index a80a37309c9f0022661238986afbf52ee67b684d..46b9738b148acc4a9a08752c8c2373b0a1340df5 100644 (file)
       <varlistentry>
         <term><option>-p</option></term>
         <term><option>--print-esp-path</option></term>
-        <listitem><para>This option modifies the behaviour of <command>status</command>.  Prints only the
-        path to the EFI System Partition (ESP) to standard output and exits.</para></listitem>
+        <listitem><para>This option modifies the behaviour of <command>status</command>. Only prints the path
+        to the EFI System Partition (ESP) to standard output and exits.</para></listitem>
       </varlistentry>
 
       <varlistentry>
+        <term><option>-x</option></term>
         <term><option>--print-boot-path</option></term>
-        <listitem><para>This option modifies the behaviour of <command>status</command>.  Prints only the
-        path to the Extended Boot Loader partition if it exists, and the path to the ESP otherwise to
-        standard output and exit. This command is useful to determine where to place boot loader entries, as
-        they are preferably placed in the Extended Boot Loader partition if it exists and in the ESP
-        otherwise.</para></listitem>
+        <listitem><para>This option modifies the behaviour of <command>status</command>. Only prints the path
+        to the Extended Boot Loader partition if it exists, and the path to the ESP otherwise to standard
+        output and exit. This command is useful to determine where to place boot loader entries, as they are
+        preferably placed in the Extended Boot Loader partition if it exists and in the ESP otherwise.
+        </para></listitem>
       </varlistentry>
 
       <varlistentry>
diff --git a/man/html.in b/man/html.in
new file mode 100755 (executable)
index 0000000..d4debcc
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -e
+
+if [ -z "$1" ]; then
+    echo "Use: $0 page-name (with no section suffix)"
+    exit 1
+fi
+
+target="man/$1.html"
+ninja -C "@BUILD_ROOT@" "$target"
+set -x
+exec xdg-open build/"$target"
index a3c67f5e82d1335fced6908f36d6209eaf2fdbf9..0ecab521fa0aae8f18f6e16db126ed7e1a217465 100644 (file)
       <varlistentry>
         <term><option>--flush</option></term>
 
-        <listitem><para>Asks the journal daemon to flush any log data
-        stored in <filename>/run/log/journal</filename> into
-        <filename>/var/log/journal</filename>, if persistent storage
-        is enabled. This call does not return until the operation is
-        complete. Note that this call is idempotent: the data is only
-        flushed from <filename>/run/log/journal</filename> into
-        <filename>/var/log/journal</filename> once during system
-        runtime, and this command exits cleanly without executing any
-        operation if this has already happened. This command
-        effectively guarantees that all data is flushed to
-        <filename>/var/log/journal</filename> at the time it
-        returns.</para></listitem>
+        <listitem><para>Asks the journal daemon to flush any log data stored in
+        <filename>/run/log/journal/</filename> into <filename>/var/log/journal/</filename>, if persistent
+        storage is enabled. This call does not return until the operation is complete. Note that this call is
+        idempotent: the data is only flushed from <filename>/run/log/journal/</filename> into
+        <filename>/var/log/journal</filename> once during system runtime (but see
+        <option>--relinquish-var</option> below), and this command exits cleanly without executing any
+        operation if this has already happened. This command effectively guarantees that all data is flushed
+        to <filename>/var/log/journal</filename> at the time it returns.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--relinquish-var</option></term>
+
+        <listitem><para>Asks the journal daemon for the reverse operation to <option>--flush</option>: if
+        requested the daemon will write further log data to <filename>/run/log/journal/</filename> and stops
+        writing to <filename>/var/log/journal/</filename>. A subsequent call to <option>--flush</option>
+        causes the log output to switch back to <filename>/var/log/journal/</filename>, see
+        above.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--smart-relinquish-var</option></term>
+
+        <listitem><para>Similar to <option>--relinquish-var</option> but executes no operation if the root file
+        system and <filename>/var/lib/journal/</filename> reside on the same mount point. This operation is
+        used during system shutdown in order to make the journal daemon stop writing data to
+        <filename>/var/log/journal/</filename> in case that directory is located on a mount point that needs
+        to be unmounted.</para></listitem>
       </varlistentry>
 
       <varlistentry>
diff --git a/man/man.in b/man/man.in
new file mode 100755 (executable)
index 0000000..5700a64
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+
+if [ -z "$1" ]; then
+    echo "Use: $0 page-name (with no section suffix)"
+    exit 1
+fi
+
+target=$(ninja -C "@BUILD_ROOT@" -t query man/man | grep -E -m1 "man/$1\.[0-9]$" | awk '{print $2}')
+if [ -z "$target" ]; then
+    echo "Cannot find page $1"
+    exit 1
+fi
+ninja -C "@BUILD_ROOT@" "$target"
+exec man build/"$target"
index ae9c941fcdafe54b42286c4e4068f1dcf71204b0..f3992b28341698418be576efbaae07608be6174b 100644 (file)
@@ -204,3 +204,15 @@ if git.found()
                            'mv t @0@/rules/meson.build'.format(meson.current_source_dir())],
                 depend_files : custom_entities_ent)
 endif
+
+############################################################
+
+configure_file(
+        input : 'man.in',
+        output : 'man',
+        configuration : substs)
+
+configure_file(
+        input : 'html.in',
+        output : 'html',
+        configuration : substs)
index 689415846642c523fbbec7e014d13bde84095da4..6d47f09f48f9ee302520f941eaaeda3c8a6fa660 100644 (file)
@@ -445,7 +445,10 @@ manpages = [
  ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''],
  ['sd_event_source_unref',
   '3',
-  ['sd_event_source_ref', 'sd_event_source_unrefp'],
+  ['sd_event_source_disable_unref',
+   'sd_event_source_disable_unrefp',
+   'sd_event_source_ref',
+   'sd_event_source_unrefp'],
   ''],
  ['sd_event_wait',
   '3',
@@ -824,6 +827,7 @@ manpages = [
  ['systemd.kill', '5', [], ''],
  ['systemd.link', '5', [], ''],
  ['systemd.mount', '5', [], ''],
+ ['systemd.net-naming-scheme', '7', [], ''],
  ['systemd.netdev', '5', [], 'ENABLE_NETWORKD'],
  ['systemd.network', '5', [], 'ENABLE_NETWORKD'],
  ['systemd.nspawn', '5', [], ''],
index 0f6a4ec3137b3ac87ccb2f0340032004cfa3afc3..7229ef517a577051b5bfeaf78e107de75b6f1117 100644 (file)
@@ -65,9 +65,9 @@
   <refsect1>
     <title>Description</title>
 
-    <para><function>sd_bus_request_name()</function> requests a well-known service name on a bus. It takes a bus
-    connection, a valid bus name and a flags parameter. The flags parameter is a combination of the following
-    flags:</para>
+    <para><function>sd_bus_request_name()</function> requests a well-known service name on a bus. It takes a
+    bus connection, a valid bus name, and a flags parameter. The flags parameter is a combination of zero or
+    more of the following flags:</para>
 
     <variablelist>
       <varlistentry>
@@ -82,8 +82,9 @@
       <varlistentry>
         <term><constant>SD_BUS_NAME_REPLACE_EXISTING</constant></term>
 
-        <listitem><para>Take over the name if it is already acquired by another peer, and that other peer has permitted
-        takeover by setting <constant>SD_BUS_NAME_ALLOW_REPLACEMENT</constant> while acquiring it.</para></listitem>
+        <listitem><para>Take over the name if it was already acquired by another peer, and that other peer
+        has permitted takeover by setting <constant>SD_BUS_NAME_ALLOW_REPLACEMENT</constant> while acquiring
+        it.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index cfcebdfb29eb79472d38b209c432b15120078adb..3c5580e27cace84a2c879154dbbfaef9220b9404 100644 (file)
 
           <listitem><para>An argument is invalid.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENOPKG</constant></term>
 
           <listitem><para>The bus cannot be resolved.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-EPERM</constant></term>
 
           <listitem><para>The bus has already been started.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
           <listitem><para>The bus was created in a different process.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENOMEM</constant></term>
 
index 13dd6f8815820cb943de540e624f3b1fc0294f92..9bc2ba859257299903542697b3889ca16b6fa820 100644 (file)
 
           <listitem><para>An required argument is <constant>NULL</constant>.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENXIO</constant></term>
 
           <listitem><para>The bus slot object has no description.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENOMEM</constant></term>
 
index 01e3008eed4a94e87bc95216f72d0035a3bcfc53..81131fa737f373b8f85612dc75d0b8212a5bbbad 100644 (file)
@@ -19,6 +19,8 @@
     <refname>sd_event_source_unref</refname>
     <refname>sd_event_source_unrefp</refname>
     <refname>sd_event_source_ref</refname>
+    <refname>sd_event_source_disable_unref</refname>
+    <refname>sd_event_source_disable_unrefp</refname>
 
     <refpurpose>Increase or decrease event source reference counters</refpurpose>
   </refnamediv>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
       </funcprototype>
 
+      <funcprototype>
+        <funcdef>sd_event_source* <function>sd_event_source_disable_unref</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_event_source_disable_unrefp</function></funcdef>
+        <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+      </funcprototype>
     </funcsynopsis>
   </refsynopsisdiv>
 
     the passed event source object is
     <constant>NULL</constant>.</para>
 
-    <para>Note that event source objects stay alive and may be
-    dispatched as long as they have a reference counter greater than
-    zero. In order to drop a reference of an event source and make
-    sure the associated event source handler function is not called
-    anymore it is recommended to combine a call of
+    <para>Note that event source objects stay alive and may be dispatched as long as they have a reference
+    counter greater than zero. In order to drop a reference of an event source and make sure the associated
+    event source handler function is not called anymore it is recommended to combine a call of
     <function>sd_event_source_unref()</function> with a prior call to
-    <function>sd_event_source_set_enabled()</function> with
-    <constant>SD_EVENT_OFF</constant>.</para>
+    <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> or call
+    <function>sd_event_source_disable_unref()</function>, see below.</para>
+
+    <para><function>sd_event_source_disable_unref()</function> combines a call to
+    <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> with
+    <function>sd_event_source_unref()</function>. This ensures that the source is disabled before the local
+    reference to it is lost. The <parameter>source</parameter> parameter is allowed to be
+    <constant>NULL</constant>.</para>
+
+    <para><function>sd_event_source_disable_unrefp()</function> is similar to
+    <function>sd_event_source_unrefp()</function>, but in addition disables the source first. This call is
+    useful in conjunction with GCC's and LLVM's
+    <ulink url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up Variable
+    Attribute</ulink>. Note that this function is defined as inline function.</para>
   </refsect1>
 
   <refsect1>
     <title>Return Value</title>
 
-    <para><function>sd_event_source_unref()</function> always returns
-    <constant>NULL</constant>.
-    <function>sd_event_source_ref()</function> always returns the
-    event source object passed in.</para>
+    <para><function>sd_event_source_unref()</function> and
+    <function>sd_event_source_disable_unref()</function> always return <constant>NULL</constant>.
+    <function>sd_event_source_ref()</function> always returns the event source object passed in.</para>
   </refsect1>
 
   <xi:include href="libsystemd-pkgconfig.xml" />
index abc05e93033f1e51454f9bdaf1dc026d214858d1..651a73848ee983f74b65e8902ee27564ee07d42b 100644 (file)
       <command>systemd-analyze</command>
       <arg choice="opt" rep="repeat">OPTIONS</arg>
       <arg choice="plain">calendar</arg>
-      <arg choice="plain" rep="repeat"><replaceable>SPECS</replaceable></arg>
+      <arg choice="plain" rep="repeat"><replaceable>SPEC</replaceable></arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>systemd-analyze</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="plain">timestamp</arg>
+      <arg choice="plain" rep="repeat"><replaceable>TIMESTAMP</replaceable></arg>
     </cmdsynopsis>
     <cmdsynopsis>
       <command>systemd-analyze</command>
@@ -360,7 +366,8 @@ $ eog targets.svg</programlisting>
       <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>. By
       default, only the next time the calendar expression will elapse is shown; use
       <option>--iterations=</option> to show the specified number of next times the expression
-      elapses.</para>
+      elapses. Each time the expression elapses forms a timestamp, see the <command>timestamp</command>
+      verb below.</para>
 
       <example>
         <title>Show leap days in the near future</title>
@@ -382,13 +389,47 @@ Normalized form: *-02-29 00:00:00
       </example>
     </refsect2>
 
+    <refsect2>
+      <title><command>systemd-analyze timestamp <replaceable>TIMESTAMP</replaceable>...</command></title>
+
+      <para>This command parses a timestamp (i.e. a single point in time) and outputs the normalized form and
+      the difference between this timestamp and now. The timestamp should adhere to the syntax documented in
+      <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      section "PARSING TIMESTAMPS".</para>
+
+      <example>
+        <title>Show parsing of timestamps</title>
+
+        <programlisting>$ systemd-analyze timestamp yesterday now tomorrow
+  Original form: yesterday
+Normalized form: Mon 2019-05-20 00:00:00 CEST
+       (in UTC): Sun 2019-05-19 22:00:00 UTC
+   UNIX seconds: @15583032000
+       From now: 1 day 9h ago
+
+  Original form: now
+Normalized form: Tue 2019-05-21 09:48:39 CEST
+       (in UTC): Tue 2019-05-21 07:48:39 UTC
+   UNIX seconds: @1558424919.659757
+       From now: 43us ago
+
+  Original form: tomorrow
+Normalized form: Wed 2019-05-22 00:00:00 CEST
+       (in UTC): Tue 2019-05-21 22:00:00 UTC
+   UNIX seconds: @15584760000
+       From now: 14h left
+</programlisting>
+      </example>
+    </refsect2>
+
     <refsect2>
       <title><command>systemd-analyze timespan <replaceable>EXPRESSION</replaceable>...</command></title>
 
-      <para>This command parses a time span and outputs the normalized form and the equivalent value in
-      microseconds. The time span should adhere to the same syntax documented in
-      <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
-      Values without associated magnitudes are parsed as seconds.</para>
+      <para>This command parses a time span (i.e. a difference between two timestamps) and outputs the
+      normalized form and the equivalent value in microseconds. The time span should adhere to the syntax
+      documented in
+      <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      section "PARSING TIME SPANS". Values without units are parsed as seconds.</para>
 
       <example>
         <title>Show parsing of timespans</title>
index e557ee80a177f71decc96699e13cae623fd284b0..4a7c33f5584244261e9de09cc7f9fe25ab09849e 100644 (file)
       </varlistentry>
 
       <varlistentry>
-        <term><option>--bind-device=</option></term>
+        <term><option>--bind-device</option></term>
 
-        <listitem><para>Takes a boolean argument, defaults to off. This option only has an effect in automount mode,
-        and controls whether the automount unit shall be bound to the backing device's lifetime. If enabled, the
-        automount point will be removed automatically when the backing device vanishes. If disabled the automount point
+        <listitem><para>This option only has an effect in automount mode,
+        and controls whether the automount unit shall be bound to the backing device's lifetime. If set, the
+        automount point will be removed automatically when the backing device vanishes. By default the automount point
         stays around, and subsequent accesses will block until backing device is replugged. This option has no effect
         in case of non-device mounts, such as network or virtual file system mounts.</para>
 
index 5ba162b93cadf2fa3a252ddbb19b5b30315fa9d8..f1d6f14812519b6765078d71fcdb17853e4f85c1 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version='1.0'?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
-<!ENTITY fedora_latest_version "28">
-<!ENTITY fedora_cloud_release "1.1">
+<!ENTITY fedora_latest_version "30">
+<!ENTITY fedora_cloud_release "1.2">
 ]>
 <!-- SPDX-License-Identifier: LGPL-2.1+ -->
 
 
       <programlisting># machinectl pull-raw --verify=no \
       https://download.fedoraproject.org/pub/fedora/linux/releases/&fedora_latest_version;/Cloud/x86_64/images/Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw.xz
-# systemd-nspawn -M Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw</programlisting>
+# systemd-nspawn -M Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64</programlisting>
 
       <para>This downloads an image using
       <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
index 514d1021d6ddecf8b3daeaffc1544c50492384cd..81744c2025dc60b65869df83c6f4e6ec5e33cce3 100644 (file)
@@ -17,7 +17,7 @@
 
   <refnamediv>
     <refname>systemd-rc-local-generator</refname>
-    <refpurpose>Compatibility generator for starting <filename>/etc/rc.local</filename> and <filename>/usr/sbin/halt.local</filename> during boot and shutdown</refpurpose>
+    <refpurpose>Compatibility generator for starting <filename>/etc/rc.local</filename> during boot</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     script is run after <filename>network.target</filename>, but in parallel with most other regular system
     services.</para>
 
-    <para><filename>systemd-rc-local-generator</filename> also checks whether <filename>/usr/sbin/halt.local</filename>
-    exists and is executable, and if it is pulls the <filename>halt-local.service</filename> unit into the shutdown
-    process. This unit is responsible for running this script during later shutdown.</para>
-
-    <para>Support for both <filename>/etc/rc.local</filename> and <filename>/usr/sbin/halt.local</filename> is provided
+    <para>Support for <filename>/etc/rc.local</filename> is provided
     for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of
-    these scripts today, and instead provide proper unit files with appropriate dependencies for any scripts to run
-    during the boot or shutdown processes.</para>
+    this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run
+    during the boot process.</para>
 
     <para><filename>systemd-rc-local-generator</filename> implements
     <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
index f05e5ea2e535304d28c764c949098d3131ca231f..7720ef53fa19fb2ba73dbb83299d365faeb6b56b 100644 (file)
     <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     are searched for a matching file and the file found that has the highest priority is
     executed.</para>
+
+    <para>System services (<filename>systemd-tmpfiles-setup.service</filename>,
+    <filename>systemd-tmpfiles-setup-dev.service</filename>,
+    <filename>systemd-tmpfiles-clean.service</filename>) invoke <command>systemd-tmpfiles</command> to create
+    system files and to perform system wide cleanup. Those services read administrator-controlled
+    configuration files in <filename>tmpfiles.d/</filename> directories. User services
+    (<filename>systemd-tmpfiles-setup.service</filename>,
+    <filename>systemd-tmpfiles-clean.service</filename>) also invoke <command>systemd-tmpfiles</command>, but
+    it reads a separate set of files, which includes user-controlled files under
+    <filename>~/.config/user-tmpfiles.d/</filename> and <filename>~/.local/share/user-tmpfiles.d/</filename>,
+    and administrator-controller files under <filename>/usr/share/user-tmpfiles.d/</filename>. Users may use
+    this to create and clean up files under their control, but the system instance performs global cleanup
+    and is not influenced by user configuration. Note that this means a time-based cleanup configured in the
+    system instance, such as the one typically configured for <filename>/tmp</filename>, will thus also
+    affect files created by the user instance if they are placed in <filename>/tmp</filename>, even if the
+    user instance's time-based cleanup is turned off.</para>
   </refsect1>
 
   <refsect1>
     </variablelist>
 
     <para>It is possible to combine <option>--create</option>, <option>--clean</option>, and <option>--remove</option>
-    in one invocation (in which case removal and clean-up are executed before creation of new files). For example,
+    in one invocation (in which case removal and cleanup are executed before creation of new files). For example,
     during boot the following command line is executed to ensure that all temporary and volatile directories are
     removed and created according to the configuration file:</para>
 
index cf8087ccb3189e094a9a83067312cb604d771010..c267bb2b114b3da1f5154fbb06bf3bf46b286693 100644 (file)
         <term><varname>net.naming-scheme=</varname></term>
         <listitem>
           <para>Network interfaces are renamed to give them predictable names when possible (unless
-          <varname>net.ifnames=0</varname> is specified, see above). The names are derived from various
-          device metadata fields. Newer versions of <filename>systemd-udevd.service</filename> take more of
-          these fields into account, improving (and thus possibly changing) the names used for the same
-          devices. With this kernel command line option it is possible to pick a specific version of this
-          algorithm. It expects a naming scheme identifier as argument. Currently the following identifiers
-          are known: <literal>v238</literal>, <literal>v239</literal>, <literal>v240</literal> which each
-          implement the naming scheme that was the default in the indicated systemd version. In addition,
-          <literal>latest</literal> may be used to designate the latest scheme known (to this particular
-          version of <filename>systemd-udevd.service</filename>).</para>
+          <varname>net.ifnames=0</varname> is specified, see above). With this kernel command line option it
+          is possible to pick a specific version of this algorithm and override the default chosen at
+          compilation time. Expects one of the naming scheme identifiers listed in
+          <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+          or <literal>latest</literal> to select the latest scheme known (to this particular version of
+          <filename>systemd-udevd.service</filename>).</para>
 
           <para>Note that selecting a specific scheme is not sufficient to fully stabilize interface naming:
           the naming is generally derived from driver attributes exposed by the kernel. As the kernel is
         </listitem>
       </varlistentry>
     </variablelist>
-    <!-- when adding entries here, consider also adding them
-         in kernel-command-line.xml -->
- </refsect1>
+    <!-- when adding entries here, consider also adding them in kernel-command-line.xml -->
+  </refsect1>
 
   <refsect1>
     <title>See Also</title>
index 960b2ec6336c576c6c02fc95982f89d1561e262e..fa374bf0f804d1cdc487a8fed111cd00e5c9e274 100644 (file)
           usually derived from glibc's
           <varname>program_invocation_short_name</varname> variable, see
           <citerefentry project='die-net'><refentrytitle>program_invocation_short_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.)</para>
+          <para>Note that the journal service does not validate the values of any structured
+          journal fields whose name is not prefixed with an underscore, and this includes any
+          syslog related fields such as these. Hence, applications that supply a facility, PID,
+          or log level are expected to do so properly formatted, i.e. as numeric integers formatted
+          as decimal strings.</para>
         </listitem>
       </varlistentry>
 
index ea744bd2517a7d3f829a402a1658f2dfb0aec2cd..b1be32955e5f8aeb5e2688f4c09e38378617484d 100644 (file)
                 <para>The name is set based on information given by
                 the firmware for on-board devices, as exported by the
                 udev property <varname>ID_NET_NAME_ONBOARD</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
                 </para>
               </listitem>
             </varlistentry>
                 <para>The name is set based on information given by
                 the firmware for hot-plug devices, as exported by the
                 udev property <varname>ID_NET_NAME_SLOT</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
                 </para>
               </listitem>
             </varlistentry>
               <listitem>
                 <para>The name is set based on the device's physical
                 location, as exported by the udev property
-                <varname>ID_NET_NAME_PATH</varname>.</para>
+                <varname>ID_NET_NAME_PATH</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+                </para>
               </listitem>
             </varlistentry>
             <varlistentry>
               <listitem>
                 <para>The name is set based on the device's persistent
                 MAC address, as exported by the udev property
-                <varname>ID_NET_NAME_MAC</varname>.</para>
+                <varname>ID_NET_NAME_MAC</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+                </para>
               </listitem>
             </varlistentry>
             <varlistentry>
index 022e227e837ec81d054742b489b0213f1dbf62f6..178dc188a5a2a35ea096cc96b2d0027e398834d0 100644 (file)
     mount options are understood by systemd which influence how
     dependencies are created for mount points. systemd will create a
     dependency of type <varname>Wants=</varname> or
-    <option>Requires</option> (see option <option>nofail</option>
+    <option>Requires=</option> (see option <option>nofail</option>
     below), from either <filename>local-fs.target</filename> or
     <filename>remote-fs.target</filename>, depending whether the file
     system is local or remote.</para>
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
new file mode 100644 (file)
index 0000000..eb8faad
--- /dev/null
@@ -0,0 +1,420 @@
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="systemd.net-naming-scheme">
+  <refentryinfo>
+    <title>systemd.net-naming-scheme</title>
+    <productname>systemd</productname>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>systemd.net-naming-scheme</refentrytitle>
+    <manvolnum>7</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>systemd.net-naming-scheme</refname>
+    <refpurpose>Network device naming schemes</refpurpose>
+  </refnamediv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Network interfaces may be renamed to give them predictable names when there's enough information to
+    generate appropriate names and the use of certain types of names is configured. This page describes the
+    first part, i.e. what possible names may be generated. Those names are generated by the
+    <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    builtin <command>net_id</command> and exported as udev properties
+    (<varname>ID_NET_NAME_ONBOARD=</varname>, <varname>ID_NET_LABEL_ONBOARD=</varname>,
+    <varname>ID_NET_NAME_PATH=</varname>, <varname>ID_NET_NAME_SLOT=</varname>).</para>
+
+    <para>Names are derived from various device metadata attributes. Newer versions of udev take more of
+    these attributes into account, improving (and thus possibly changing) the names used for the same
+    devices. Differents version of the naming rules are called "naming schemes". The default naming scheme is
+    chosen at compilation time. Usually this will be the latest implemented version, but it is also possible
+    to set one of the older versions to preserve compatibility. This may be useful for example for
+    distributions, which may introduce new versions of systemd in stable releases without changing the naming
+    scheme. The naming scheme may also be overriden using the <varname>net.naming-scheme=</varname> kernel
+    command line switch, see
+    <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+    Available naming schemes are described below.</para>
+
+    <para>After the udev proprties have been generated, appropriate udev rules may be used to actually rename
+    devices based on those properties. See the description of <varname>NamePolicy=</varname> in
+    <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Naming</title>
+
+    <para>All names start with a two-character prefix that signifies the interface type.</para>
+
+    <table>
+      <title>Two character prefixes based on the type of interface</title>
+
+      <tgroup cols='2'>
+        <thead>
+          <row>
+            <entry>Prefix</entry>
+            <entry>Description</entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry><constant>en</constant></entry>
+            <entry>Ethernet</entry>
+          </row>
+          <row>
+            <entry><constant>ib</constant></entry>
+            <entry>InfiniBand</entry>
+          </row>
+          <row>
+            <entry><constant>sl</constant></entry>
+            <entry>serial line IP (slip)</entry>
+          </row>
+          <row>
+            <entry><constant>wl</constant></entry>
+            <entry>Wireless local area network (WLAN)</entry>
+          </row>
+          <row>
+            <entry><constant>ww</constant></entry>
+            <entry>Wireless wide area network (WWAN)</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+
+    <para>The udev <command>net_id</command> builtin exports the following udev device properties:</para>
+
+    <variablelist>
+        <varlistentry>
+          <term><varname>ID_NET_NAME_ONBOARD=<replaceable>prefix</replaceable><constant>o</constant><replaceable>number</replaceable></varname></term>
+
+          <listitem><para>This name is set based on the ordering information given by the firmware for
+          on-board devices. The name consists of the prefix, letter <constant>o</constant>, and a number
+          specified by the firmware. This is only available for PCI devices.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_LABEL_ONBOARD=<replaceable>prefix</replaceable> <replaceable>label</replaceable></varname></term>
+
+          <listitem><para>This property is set based on label given by the firmware for on-board devices. The
+          name consists of the prefix concatenated with the label. This is only available for PCI devices.
+          </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_NAME_MAC=<replaceable>prefix</replaceable><constant>x</constant><replaceable>AABBCCDDEEFF</replaceable></varname></term>
+
+          <listitem><para>This name consists of the prefix, letter <constant>x</constant>, and 12 hexadecimal
+          digits of the MAC address. It is available if the device has a fixed MAC address. Because this name
+          is based on an attribute of the card itself, it remains "stable" when the device is moved (even
+          between machines), but will change when the hardware is replaced.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]</varname></term>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>v</constant><replaceable>slot</replaceable></varname></term>
+
+          <listitem><para>This property describes the slot position. Different schemes are used depending on
+          the bus type, as described in the table below. In all cases, PCI slot information must be known. In
+          case of USB, BCMA, and SR-VIO devices, the full name consists of the prefix, PCI slot identifier,
+          and USB or BCMA or SR-VIO slot identifier. The first two parts are denoted as "…" in the table
+          below.</para>
+
+          <table>
+            <title>Slot naming schemes</title>
+
+            <tgroup cols='2'>
+              <thead>
+                <row>
+                  <entry>Format</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+
+              <tbody>
+                <row>
+                  <entry><replaceable>prefix</replaceable> [<constant>P</constant><replaceable>domain</replaceable>] <constant>s</constant><replaceable>slot</replaceable> [<constant>f</constant><replaceable>function</replaceable>] [<constant>n</constant><replaceable>port_name</replaceable> | <constant>d</constant><replaceable>dev_port</replaceable>]</entry>
+                  <entry>PCI slot number</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>b</constant><replaceable>number</replaceable></entry>
+                  <entry>Broadcom bus (BCMA) core number</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>u</constant><replaceable>port</replaceable>… [<constant>c</constant><replaceable>config</replaceable>] [<constant>i</constant><replaceable>interface</replaceable>]</entry>
+                  <entry>USB port number chain</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>v</constant><replaceable>slot</replaceable></entry>
+                  <entry>SR-VIO slot number</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </table>
+
+          <para>The PCI domain is only prepended when it is not 0. All multi-function PCI devices will carry
+          the <constant>f<replaceable>function</replaceable></constant> number in the device name, including
+          the function 0 device. For non-multi-function devices, the number is suppressed if 0. The port name
+          <replaceable>port_name</replaceable> is used, or the port number
+          <constant>d</constant><replaceable>dev_port</replaceable> if the name is not known.</para>
+
+          <para>For BCMA devices, the core number is suppressed when 0.</para>
+
+          <para>For USB devices the full chain of port numbers of hubs is composed. If the name gets longer
+          than the maximum number of 15 characters, the name is not exported. The usual USB configuration
+          number 1 and interface number 0 values are suppressed.</para>
+          </listitem>
+
+          <para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
+          <constant>v</constant> and the virtual device number, with any leading zeros removed. The bus
+          number is ignored. This device type is found in IBM PowerVMs.</para>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>c</constant><replaceable>bus_id</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>a</constant><replaceable>vendor</replaceable><replaceable>model</replaceable><constant>i</constant><replaceable>instance</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>i</constant><replaceable>address</replaceable><constant>n</constant><replaceable>port_name</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]</varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
+
+          <listitem><para>This property describes the device installation location. Different schemes are
+          used depending on the bus type, as described in the table below. For BCMA and USB devices, PCI path
+          information must known, and the full name consists of the prefix, PCI slot identifier, and USB or
+          BCMA location. The first two parts are denoted as "…" in the table below.</para>
+
+          <table>
+            <title>Path naming schemes</title>
+
+            <tgroup cols='2'>
+              <thead>
+                <row>
+                  <entry>Format</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+
+              <tbody>
+                <row>
+                  <entry><replaceable>prefix</replaceable> <constant>c</constant><replaceable>bus_id</replaceable></entry>
+                  <entry>CCW or grouped CCW device identifier</entry>
+                </row>
+
+                <row>
+                  <entry><replaceable>prefix</replaceable> <constant>a</constant><replaceable>vendor</replaceable> <replaceable>model</replaceable> <constant>i</constant><replaceable>instance</replaceable></entry>
+                  <entry>ACPI path names for ARM64 platform devices</entry>
+                </row>
+
+                <row>
+                  <entry><replaceable>prefix</replaceable> <constant>i</constant><replaceable>address</replaceable> <constant>n</constant><replaceable>port_name</replaceable></entry>
+                  <entry>Netdevsim (simulated networking device) device number and port name</entry>
+                </row>
+
+                <row>
+                  <entry><replaceable>prefix</replaceable> [<constant>P</constant><replaceable>domain</replaceable>] <constant>p</constant><replaceable>bus</replaceable> <constant>s</constant><replaceable>slot</replaceable> [<constant>f</constant><replaceable>function</replaceable>] [<constant>n</constant><replaceable>phys_port_name</replaceable> | <constant>d</constant><replaceable>dev_port</replaceable>]</entry>
+                  <entry>PCI geographical location</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>b</constant><replaceable>number</replaceable></entry>
+                  <entry>Broadcom bus (BCMA) core number</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>u</constant><replaceable>port</replaceable>… [<constant>c</constant><replaceable>config</replaceable>] [<constant>i</constant><replaceable>interface</replaceable>]</entry>
+                  <entry>USB port number chain</entry>
+                </row>
+
+              </tbody>
+            </tgroup>
+          </table>
+
+          <para>CCW and grouped CCW devices are found in IBM System Z mainframes. Any leading zeros and
+          dots are suppressed.</para>
+
+          <para>For PCI, BCMA, and USB devices, the same rules as described above for slot naming are
+          used.</para>
+          </listitem>
+        </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>History</title>
+
+    <para>The following "naming schemes" have been defined:</para>
+
+    <variablelist>
+        <varlistentry>
+          <term><constant>v238</constant></term>
+
+          <listitem><para>This is the naming naming that was implemented in systemd 238.</para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>v239</constant></term>
+
+          <listitem><para>Naming was changed for virtual network interfaces created with SR-IOV and NPAR and
+          for devices where the PCI network controller device does not have a slot number associated.</para>
+
+          <para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
+          <literal>v<replaceable>port</replaceable></literal>, where <replaceable>port</replaceable> is the
+          virtual device number. Previously those virtual devices were named as if completely independent.
+          </para>
+
+          <para>The ninth and later NPAR virtual devices are named following the scheme used for the first
+          eight NPAR partitions. Previously those devices were not renamed and the kernel default
+          ("eth<replaceable>N</replaceable>") was used.</para>
+
+          <para>Names are also generated for PCI devices where the PCI network controller device does not
+          have an associated slot number itself, but one of its parents does. Previously those devices were
+          not renamed and the kernel default was used.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>v240</constant></term>
+
+          <para>The <literal>ib</literal> prefix and stable names for infiniband devices are
+          introduced. Previously those devices were not renamed.</para>
+
+          <para>The ACPI index field (used in <varname>ID_NET_NAME_ONBOARD=</varname>) is now also used when
+          0.</para>
+
+          <para>A new naming policy <varname>NamePolicy=keep</varname> was introduced. With this policy, if
+          the network device name was already set by userspace, the device will not be renamed
+          again. Previously, this naming policy applied implicitly, and now it must be explicitly
+          requested. Effectively, this means that network devices will be renamed according to the
+          configuration, even if they have been renamed already, if <constant>keep</constant> is not
+          specified as the naming policy in the <filename noindex='true'>.link</filename> file. See
+          <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for a description of <varname>NamePolicy=</varname>.</para>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>v243</constant></term>
+
+          <para>Support for netdevsim (simulated networking devices) was added. Previously those devices were
+          not renamed.</para>
+
+          <para>Previously two-letter interface type prefix was prepended to
+          <varname>ID_NET_LABEL_ONBOARD=</varname>. This is not done anymore.</para>
+        </varlistentry>
+
+        <para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
+        particular version of systemd.</para>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Examples</title>
+
+    <example>
+      <title>Using <command>udevadm test-builtin</command> to display device properties</title>
+
+      <programlisting>$ udevadm test-builtin net_id /sys/class/net/enp0s31f6
+...
+Using default interface naming scheme 'v243'.
+ID_NET_NAMING_SCHEME=v243
+ID_NET_NAME_MAC=enx54ee75cb1dc0
+ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
+ID_NET_NAME_PATH=enp0s31f6
+...</programlisting>
+    </example>
+
+    <example>
+      <title>PCI Ethernet card with firmware index "1"</title>
+
+      <programlisting>ID_NET_NAME_ONBOARD=eno1
+ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
+      </programlisting>
+    </example>
+
+    <example>
+      <title>PCI Ethernet card in hotplug slot with firmware index number</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
+ID_NET_NAME_MAC=enx000000000466
+ID_NET_NAME_PATH=enp5s0
+ID_NET_NAME_SLOT=ens1</programlisting>
+    </example>
+
+    <example>
+      <title>PCI Ethernet multi-function card with 2 ports</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
+ID_NET_NAME_MAC=enx78e7d1ea46da
+ID_NET_NAME_PATH=enp2s0f0
+
+# /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
+ID_NET_NAME_MAC=enx78e7d1ea46dc
+ID_NET_NAME_PATH=enp2s0f1</programlisting>
+    </example>
+
+    <example>
+      <title>PCI WLAN card</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
+ID_NET_NAME_MAC=wlx0024d7e31130
+ID_NET_NAME_PATH=wlp3s0</programlisting>
+    </example>
+
+    <example>
+      <title>PCI IB host adapter with 2 ports</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/net/ibp21s0f0
+ID_NET_NAME_PATH=ibp21s0f0
+
+# /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.1/net/ibp21s0f1
+ID_NET_NAME_PATH=ibp21s0f1</programlisting>
+    </example>
+
+    <example>
+      <title>USB built-in 3G modem</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
+ID_NET_NAME_MAC=wwx028037ec0200
+ID_NET_NAME_PATH=wwp0s29u1u4i6</programlisting>
+    </example>
+
+    <example>
+      <title>USB Android phone</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
+ID_NET_NAME_MAC=enxd626b3450fb5
+ID_NET_NAME_PATH=enp0s29u1u2</programlisting>
+    </example>
+
+    <example>
+      <title>s390 grouped CCW interface</title>
+
+      <programlisting># /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0
+ID_NET_NAME_MAC=enx026d3c00000a
+ID_NET_NAME_PATH=encf5f0</programlisting>
+    </example>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <ulink url="https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames">the
+      original page describing stable interface names</ulink>
+    </para>
+  </refsect1>
+
+</refentry>
index b71320e20d91b3a0fcdf7a6fc16287ed89fde322..26a5dbbd1e1d437f2c09879bf9bb0b703592b48e 100644 (file)
           <row><entry><varname>ipvlan</varname></entry>
           <entry>An ipvlan device is a stacked device which receives packets from its underlying device based on IP address filtering.</entry></row>
 
+          <row><entry><varname>ipvtap</varname></entry>
+          <entry>An ipvtap device is a stacked device which receives packets from its underlying device based on IP address filtering and can be accessed using the tap user space interface.</entry></row>
+
           <row><entry><varname>macvlan</varname></entry>
           <entry>A macvlan device is a stacked device which receives packets from its underlying device based on MAC address filtering.</entry></row>
 
 
   </refsect1>
 
+  <refsect1>
+    <title>[IPVTAP] Section Options</title>
+
+    <para>The <literal>[IPVTAP]</literal> section only applies for
+    netdevs of kind <literal>ipvtap</literal> and accepts the
+    same key as <literal>[IPVLAN]</literal>.</para>
+
+  </refsect1>
+
   <refsect1>
     <title>[VXLAN] Section Options</title>
     <para>The <literal>[VXLAN]</literal> section only applies for
 
     <variablelist class='network-directives'>
       <varlistentry>
-        <term><varname>Id=</varname></term>
+        <term><varname>VNI=</varname></term>
         <listitem>
-          <para>The VXLAN ID to use.</para>
+          <para>The VXLAN Network Identifier (or VXLAN Segment ID). Takes a number in the range 1-16777215.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <listitem>
           <para>Configures local IP address.</para>
         </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Group=</varname></term>
+        <listitem>
+          <para>Configures VXLAN multicast group IP address. All members of a VXLAN must use the same multicast group address.</para>
+        </listitem>
       </varlistentry>
         <varlistentry>
         <term><varname>TOS=</varname></term>
       <varlistentry>
         <term><varname>TTL=</varname></term>
         <listitem>
-          <para>A fixed Time To Live N on Virtual eXtensible Local
-          Area Network packets. N is a number in the range 1–255. 0
-          is a special value meaning that packets inherit the TTL
-          value.</para>
+          <para>A fixed Time To Live N on Virtual eXtensible Local Area Network packets.
+          Takes <literal>inherit</literal> or a number in the range 0–255. 0 is a special
+          value meaning inherit the inner protocol's TTL value. <literal>inherit</literal>
+          means that it will inherit the outer protocol's TTL value.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         VXLAN Group Policy </ulink> document. Defaults to false.</para>
       </listitem>
     </varlistentry>
+    <varlistentry>
+       <term><varname>GenericProtocolExtension=</varname></term>
+       <listitem>
+         <para>Takes a boolean. When true, Generic Protocol Extension extends the existing VXLAN protocol
+         to provide protocol typing, OAM, and versioning capabilities. For details about the VXLAN GPE
+         Header, see the <ulink url="https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-07">
+         Generic Protocol Extension for VXLAN </ulink> document. If destination port is not specified and
+         Generic Protocol Extension is set then default port of 4790 is used. Defaults to false.</para>
+       </listitem>
+    </varlistentry>
     <varlistentry>
       <term><varname>DestinationPort=</varname></term>
       <listitem>
           The valid range is 0-1048575.
           </para>
         </listitem>
+    </varlistentry>
+      <varlistentry>
+        <term><varname>IPDoNotFragment=</varname></term>
+        <listitem>
+          <para>Allows to set the IPv4 Do not Fragment (DF) bit in outgoing packets, or to inherit its
+          value from the IPv4 inner header. Takes a boolean value, or <literal>inherit</literal>. Set
+          to <literal>inherit</literal> if the encapsulated protocol is IPv6. When unset, the kernel's
+          default will be used.</para>
+        </listitem>
       </varlistentry>
     </variablelist>
   </refsect1>
       <varlistentry>
         <term><varname>Id=</varname></term>
         <listitem>
-          <para>Specifies the Virtual Network Identifier (VNI) to use. Ranges [0-16777215].</para>
+          <para>Specifies the Virtual Network Identifier (VNI) to use. Ranges [0-16777215]. This field is mandatory.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
       <varlistentry>
         <term><varname>TTL=</varname></term>
         <listitem>
-          <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255].</para>
+          <para>Accepts the same key in <literal>[VXLAN]</literal> section except when unset or
+          set to 0, the kernel's default will be used meaning that packets TTL will be set from
+          <filename>/proc/sys/net/ipv4/ip_default_ttl</filename>.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <listitem>
           <para>Specifies the flow label to use in outgoing packets.</para>
         </listitem>
-      </varlistentry>
+    </varlistentry>
+    <varlistentry>
+      <term><varname>IPDoNotFragment=</varname></term>
+        <listitem>
+          <para>Accepts the same key in <literal>[VXLAN]</literal> section.</para>
+        </listitem>
+    </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
           for delivery to the real destination. This option is mandatory.</para>
         </listitem>
         </varlistentry>
+      <varlistentry>
+        <term><varname>PeerPort=</varname></term>
+        <listitem>
+          <para>Specifies the peer port number. Defaults to unset. Note that when peer port is set <literal>Peer=</literal> address is mandotory.</para>
+        </listitem>
+        </varlistentry>
       <varlistentry>
         <term><varname>Protocol=</varname></term>
         <listitem>
           <varname>Encapsulation=GenericUDPEncapsulation</varname>, this must not be specified.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Peer=</varname></term>
+        <listitem>
+          <para>Configures peer IP address. Note that when peer address is set <literal>PeerPort=</literal> is mandotory.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Local=</varname></term>
+        <listitem>
+          <para>Configures local IP address.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
     keys:</para>
 
     <variablelist class='network-directives'>
-      <varlistentry>
-        <term><varname>OneQueue=</varname></term>
-        <listitem><para>Takes a boolean. Configures whether
-        all packets are queued at the device (enabled), or a fixed
-        number of packets are queued at the device and the rest at the
-        <literal>qdisc</literal>. Defaults to
-        <literal>no</literal>.</para>
-        </listitem>
-      </varlistentry>
       <varlistentry>
         <term><varname>MultiQueue=</varname></term>
         <listitem><para>Takes a boolean. Configures whether
       <varlistentry>
         <term><varname>VNetHeader=</varname></term>
         <listitem><para>Takes a boolean. Configures
-        IFF_VNET_HDR flag for a tap device. It allows sending
+        IFF_VNET_HDR flag for a tun or tap device. It allows sending
         and receiving larger Generic Segmentation Offload (GSO)
         packets. This may increase throughput significantly.
         Defaults to
         </listitem>
       </varlistentry>
       <varlistentry>
-        <term><varname>FwMark=</varname></term>
+        <term><varname>FirewallMark=</varname></term>
         <listitem>
-          <para>Sets a firewall mark on outgoing WireGuard packets from this interface.</para>
+          <para>Sets a firewall mark on outgoing WireGuard packets from this interface. Takes a number between 1 and 4294967295.</para>
         </listitem>
       </varlistentry>
     </variablelist>
index 4381090d34eef8495f480110baa965facdbf117a..695bcaa0a47020475e8056457cff8d6891e7cb25 100644 (file)
           <term><varname>LinkLocalAddressing=</varname></term>
           <listitem>
             <para>Enables link-local address autoconfiguration. Accepts <literal>yes</literal>,
-            <literal>no</literal>, <literal>ipv4</literal>, or <literal>ipv6</literal>. If
-            <varname>Bridge=</varname> is set, defaults to <literal>no</literal>, and if not,
-            defaults to <literal>ipv6</literal>.</para>
+            <literal>no</literal>, <literal>ipv4</literal>, <literal>ipv6</literal>,
+            <literal>fallback</literal>, or <literal>ipv4-fallback</literal>. If
+            <literal>fallback</literal> or <literal>ipv4-fallback</literal> is specified, then an IPv4
+            link-local address is configured only when DHCPv4 fails. If <literal>fallback</literal>,
+            an IPv6 link-local address is always configured, and if <literal>ipv4-fallback</literal>,
+            the address is not configured. Note that, the fallback mechanism works only when DHCPv4
+            client is enabled, that is, it requires <literal>DHCP=yes</literal> or
+            <literal>DHCP=ipv4</literal>. If <varname>Bridge=</varname> is set, defaults to
+            <literal>no</literal>, and if not, defaults to <literal>ipv6</literal>.
+            </para>
           </listitem>
         </varlistentry>
         <varlistentry>
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>DefaultRouteOnDevice=</varname></term>
+          <listitem>
+            <para>Takes a boolean. If set to true, sets up the default route bound to the interface.
+            Defaults to false. This is useful when creating routes on point-to-point interfaces.
+            This is equivalent to e.g. the following.
+            <programlisting>ip route add default dev veth99</programlisting></para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>IPv6Token=</varname></term>
           <listitem>
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>FastOpenNoCookie=</varname></term>
+          <listitem>
+            <para>Takes a boolean. When true enables TCP fastopen without a cookie on a per-route basis.
+            When unset, the kernel's default will be used.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>TTLPropagate=</varname></term>
+          <listitem>
+            <para>Takes a boolean. When true enables TTL propagation at Label Switched Path (LSP) egress.
+            When unset, the kernel's default will be used.
+            </para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
         <term><varname>MTUBytes=</varname></term>
         <listitem>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>MaxAttempts=</varname></term>
+          <listitem>
+            <para>Specifies how many times the DHCPv4 client configuration should be attempted. Takes a
+            number or <literal>infinity</literal>. Defaults to <literal>infinity</literal>.
+            Note that the time between retries is increased exponentially, so the network will not be
+            overloaded even if this number is high.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>DUIDType=</varname></term>
           <listitem>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>SendRelease=</varname></term>
+          <listitem>
+            <para>When true, the DHCPv4 client sends a DHCP release packet when it stops.
+            Defaults to false.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>RapidCommit=</varname></term>
           <listitem>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>BlackList=</varname></term>
+          <listitem>
+            <para>A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect1>
 
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>BlackList=</varname></term>
+          <listitem>
+            <para>A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router advertisements in the list are ignored.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
   </refsect1>
 
             When unset, the kernel's default will be used.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>ProxyARP=</varname></term>
+          <listitem>
+            <para>Takes a boolean. Configures whether proxy ARP to be enabled on this port.
+            When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>ProxyARPWiFi=</varname></term>
+          <listitem>
+            <para>Takes a boolean. Configures whether proxy ARP to be enabled on this port
+            which meets extended requirements by IEEE 802.11 and Hotspot 2.0 specifications.
+            When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>MulticastRouter=</varname></term>
+          <listitem>
+            <para>Configures this port for having multicast routers attached. A port with a multicast
+            router will receive all multicast traffic. Takes one of <literal>no</literal>
+            to disable multicast routers on this port, <literal>query</literal> to let the system detect
+            the presence of routers, <literal>permanent</literal> to permanently enable multicast traffic
+            forwarding on this port, or <literal>temporary</literal> to enable multicast routers temporarily
+            on this port, not depending on incoming queries. When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>Cost=</varname></term>
           <listitem>
             key is mandatory.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>Destination=</varname></term>
+          <listitem>
+            <para>Takes an IP address of the destination VXLAN tunnel endpoint.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>VLANId=</varname></term>
           <listitem>
             table entry.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>VNI=</varname></term>
+          <listitem>
+            <para>The VXLAN Network Identifier (or VXLAN Segment ID) to use to connect to
+            the remote VXLAN tunnel endpoint. Takes a number in the range 1-16777215.
+            Defaults to unset.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>AssociatedWith=</varname></term>
+          <listitem>
+            <para>Specifies where the address is associated with. Takes one of <literal>use</literal>,
+            <literal>self</literal>, <literal>master</literal> or <literal>router</literal>.
+            <literal>use</literal> means the address is in use. User space can use this option to
+            indicate to the kernel that the fdb entry is in use. <literal>self</literal> means
+            the address is associated with the port drivers fdb. Usually hardware. <literal>master</literal>
+            means the address is associated with master devices fdb. <literal>router</literal> means
+            the destination address is associated with a router. Note that it's valid if the referenced
+            device is a VXLAN type device and has route shortcircuit enabled. Defaults to <literal>self</literal>.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
   </refsect1>
 
index e7fb46873c3af24d3654e73b2ddd30aacad0ab90..95209a8a6aa39b1f1a1ce647d610a31f8bdc2132 100644 (file)
 
           <para>This setting is supported only if the unified control group hierarchy is used and disables
           <varname>MemoryLimit=</varname>.</para>
+
+          <para>Units may have their children use a default <literal>memory.min</literal> value by specifying
+          <varname>DefaultMemoryMin=</varname>, which has the same semantics as <varname>MemoryMin=</varname>. This setting
+          does not affect <literal>memory.min</literal> in the unit itself.</para>
         </listitem>
       </varlistentry>
 
           <para>This setting is supported only if the unified control group hierarchy is used and disables
           <varname>MemoryLimit=</varname>.</para>
 
-          <para>Units may can have their children use a default <literal>memory.low</literal> value by specifying
-          <varname>DefaultMemoryLow=</varname>, which has the same usage as <varname>MemoryLow=</varname>. This setting
+          <para>Units may have their children use a default <literal>memory.low</literal> value by specifying
+          <varname>DefaultMemoryLow=</varname>, which has the same semantics as <varname>MemoryLow=</varname>. This setting
           does not affect <literal>memory.low</literal> in the unit itself.</para>
         </listitem>
       </varlistentry>
index e29602b068114d5952391730ed0a5915d18f646e..84faf89c2e668162a2270c6a4eadaf81fc7b954b 100644 (file)
     which configure resource control settings for the processes of the
     socket.</para>
 
-    <para>For each socket file, a matching service file must exist,
+    <para>For each socket unit, a matching service unit must exist,
     describing the service to start on incoming traffic on the socket
     (see
     <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-    for more information about .service files). The name of the
+    for more information about .service units). The name of the
     .service unit is by default the same as the name of the .socket
     unit, but can be altered with the <option>Service=</option> option
     described below. Depending on the setting of the
@@ -66,7 +66,7 @@
     socket file <filename>foo.socket</filename> needs a matching
     service <filename>foo.service</filename> if
     <option>Accept=no</option> is set. If
-    <option>Accept=yes</option> is set, a service template file
+    <option>Accept=yes</option> is set, a service template
     <filename>foo@.service</filename> must exist from which services
     are instantiated for each incoming connection.</para>
 
index 4a6b808c02bce9871b608032acbe672a3ead0a4e..c7d5f24b3c236c951b4291a1c722bfa7e41a8a70 100644 (file)
@@ -173,6 +173,10 @@ tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00
     <programlisting>2 months 5 days ago</programlisting>
 
     <para>Note that a relative timestamp is also accepted where a timestamp is expected (see above).</para>
+
+    <para>Use the <command>timestamp</command> command of
+    <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry> to
+    validate and normalize timestamps for testing purposes.</para>
   </refsect1>
 
   <refsect1>
index 4b283880c3d31901d7a62f66a35ceb47cbc3a496..d13212ebcc51bda59bffb885a4055113aaf773a9 100644 (file)
         or runtime environment doesn't require their functionality. Use the various
         <varname>AssertArchitecture=</varname>, <varname>AssertVirtualization=</varname>, … options for a similar
         mechanism that causes the job to fail (instead of being skipped) and results in logging about the failed check
-        (instead of being silently processed). For details about assertion conditions see below.</para>
+        (instead of being silently processed). For details about assertion conditions see below. Units with failed
+        conditions are considered to be in a clean state and will be garbage collected if they are not referenced.
+        This means, that when queried, the condition failure may or may not show up in the state of the unit.</para>
 
         <para><varname>ConditionArchitecture=</varname> may be used to
         check whether the system is running on a specific
         "Forward" and "reverse" unit properties
       </title>
 
-      <tgroup cols='2'>
+      <tgroup cols='4'>
         <colspec colname='forward' />
         <colspec colname='reverse' />
-        <colspec colname='notes' />
+        <colspec colname='fuse' />
+        <colspec colname='ruse' />
         <thead>
           <row>
             <entry>"Forward" property</entry>
             <entry>"Reverse" property</entry>
-            <entry>Where used</entry>
+            <entry namest='fuse' nameend='ruse' valign='middle'>Where used</entry>
           </row>
         </thead>
         <tbody>
           <row>
             <entry><varname>Before=</varname></entry>
             <entry><varname>After=</varname></entry>
-            <entry morerows='1' valign='middle'>Both are unit file options</entry>
+            <entry morerows='1' namest='fuse' nameend='ruse' valign='middle'>[Unit] section</entry>
           </row>
           <row>
             <entry><varname>After=</varname></entry>
           <row>
             <entry><varname>Requires=</varname></entry>
             <entry><varname>RequiredBy=</varname></entry>
-            <entry>A unit file option; an option in the [Install] section</entry>
+            <entry>[Unit] section</entry>
+            <entry>[Install] section</entry>
           </row>
           <row>
             <entry><varname>Wants=</varname></entry>
             <entry><varname>WantedBy=</varname></entry>
-            <entry>A unit file option; an option in the [Install] section</entry>
+            <entry>[Unit] section</entry>
+            <entry>[Install] section</entry>
           </row>
           <row>
             <entry><varname>PartOf=</varname></entry>
             <entry><varname>ConsistsOf=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>BindsTo=</varname></entry>
             <entry><varname>BoundBy=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>Requisite=</varname></entry>
             <entry><varname>RequisiteOf=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>Triggers=</varname></entry>
             <entry><varname>TriggeredBy=</varname></entry>
-            <entry>Automatic properties, see notes below</entry>
+            <entry namest='fuse' nameend='ruse' valign='middle'>Automatic properties, see notes below</entry>
           </row>
           <row>
             <entry><varname>Conflicts=</varname></entry>
             <entry><varname>ConflictedBy=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>PropagatesReloadTo=</varname></entry>
             <entry><varname>ReloadPropagatedFrom=</varname></entry>
-            <entry morerows='1' valign='middle'>Both are unit file options</entry>
+            <entry morerows='1' namest='fuse' nameend='ruse' valign='middle'>[Unit] section</entry>
           </row>
           <row>
             <entry><varname>ReloadPropagatedFrom=</varname></entry>
           <row>
             <entry><literal>%h</literal></entry>
             <entry>User home directory</entry>
-            <entry>This is the home directory of the user running the service manager instance. In case of the system manager this resolves to <literal>/root</literal>.</entry>
+            <entry>This is the home directory of the <emphasis>user running the service manager instance</emphasis>. In case of the system manager this resolves to <literal>/root</literal>.
+
+Note that this setting is <emphasis>not</emphasis> influenced by the <varname>User=</varname> setting configurable in the [Service] section of the service unit.</entry>
           </row>
           <row>
             <entry><literal>%H</literal></entry>
           <row>
             <entry><literal>%u</literal></entry>
             <entry>User name</entry>
-            <entry>This is the name of the user running the service manager instance. In case of the system manager this resolves to <literal>root</literal>.</entry>
+            <entry>This is the name of the <emphasis>user running the service manager instance</emphasis>. In case of the system manager this resolves to <literal>root</literal>.
+
+Note that this setting is <emphasis>not</emphasis> influenced by the <varname>User=</varname> setting configurable in the [Service] section of the service unit.</entry>
           </row>
           <row>
             <entry><literal>%U</literal></entry>
             <entry>User UID</entry>
-            <entry>This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to <literal>0</literal>.</entry>
+            <entry>This is the numeric UID of the <emphasis>user running the service manager instance</emphasis>. In case of the system manager this resolves to <literal>0</literal>.
+
+Note that this setting is <emphasis>not</emphasis> influenced by the <varname>User=</varname> setting configurable in the [Service] section of the service unit.</entry>
           </row>
           <row>
             <entry><literal>%v</literal></entry>
index a2a6cd18d7527b057382320e719567678290fb43..98c20eec5227d191fe974a1728dc250725900493 100644 (file)
@@ -59,7 +59,7 @@ int main(int argc, char **argv) {
                                  vtable,
                                  &object));
 
-  while (true) {
+  for (;;) {
     check(sd_bus_wait(bus, UINT64_MAX));
     check(sd_bus_process(bus, NULL));
   }
index 33fff909b419018990d3528a9ed7f5bb9ccc7895..30e4743489814571f2ecbf5ba80eec4ef23d9ac5 100644 (file)
@@ -32,10 +32,13 @@ project_source_root = meson.current_source_dir()
 
 want_ossfuzz = get_option('oss-fuzz')
 want_libfuzzer = get_option('llvm-fuzz')
-if want_ossfuzz and want_libfuzzer
-        error('only one of oss-fuzz and llvm-fuzz can be specified')
+want_fuzzbuzz = get_option('fuzzbuzz')
+if want_ossfuzz + want_libfuzzer + want_fuzzbuzz > 1
+        error('only one of oss-fuzz, llvm-fuzz or fuzzbuzz can be specified')
 endif
-fuzzer_build = want_ossfuzz or want_libfuzzer
+
+skip_deps = want_ossfuzz or want_libfuzzer
+fuzzer_build = want_ossfuzz or want_libfuzzer or want_fuzzbuzz
 
 #####################################################################
 
@@ -190,7 +193,6 @@ conf.set_quoted('SYSTEM_DATA_UNIT_PATH',                      systemunitdir)
 conf.set_quoted('SYSTEM_SYSVINIT_PATH',                       sysvinit_path)
 conf.set_quoted('SYSTEM_SYSVRCND_PATH',                       sysvrcnd_path)
 conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START',                 get_option('rc-local'))
-conf.set_quoted('RC_LOCAL_SCRIPT_PATH_STOP',                  get_option('halt-local'))
 
 conf.set('ANSI_OK_COLOR',                                     'ANSI_' + get_option('ok-color').underscorify().to_upper())
 
@@ -277,9 +279,9 @@ substs.set('RANDOM_SEED',                                     join_paths(randoms
 substs.set('SYSTEM_SYSVINIT_PATH',                            sysvinit_path)
 substs.set('SYSTEM_SYSVRCND_PATH',                            sysvrcnd_path)
 substs.set('RC_LOCAL_SCRIPT_PATH_START',                      get_option('rc-local'))
-substs.set('RC_LOCAL_SCRIPT_PATH_STOP',                       get_option('halt-local'))
 substs.set('MEMORY_ACCOUNTING_DEFAULT',                       memory_accounting_default ? 'yes' : 'no')
 substs.set('HIGH_RLIMIT_NOFILE',                              conf.get('HIGH_RLIMIT_NOFILE'))
+substs.set('BUILD_ROOT',                                      meson.current_build_dir())
 
 #####################################################################
 
@@ -300,9 +302,18 @@ else
 endif
 
 if want_libfuzzer
-        fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer')
+        fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer', required : false)
+        if fuzzing_engine.found()
+                add_project_arguments('-fsanitize-coverage=trace-pc-guard,trace-cmp', language : 'c')
+        elif cc.has_argument('-fsanitize=fuzzer-no-link')
+                add_project_arguments('-fsanitize=fuzzer-no-link', language : 'c')
+        else
+                error('Looks like neither libFuzzer nor -fsanitize=fuzzer-no-link is supported')
+        endif
 elif want_ossfuzz
         fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
+elif want_fuzzbuzz
+        fuzzing_engine = meson.get_compiler('cpp').find_library(get_option('fuzzbuzz-engine'), dirs: get_option('fuzzbuzz-engine-dir'))
 endif
 
 possible_cc_flags = [
@@ -411,11 +422,14 @@ endif
 
 cpp = ' '.join(cc.cmd_array()) + ' -E'
 
+has_wstringop_truncation = cc.has_argument('-Wstringop-truncation')
+
 #####################################################################
 # compilation result tests
 
 conf.set('_GNU_SOURCE', true)
 conf.set('__SANE_USERSPACE_TYPES__', true)
+conf.set10('HAVE_WSTRINGOP_TRUNCATION', has_wstringop_truncation)
 
 conf.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include <sys/types.h>'))
 conf.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include <sys/types.h>'))
@@ -815,7 +829,7 @@ libmount = dependency('mount',
                       version : fuzzer_build ? '>= 0' : '>= 2.30')
 
 want_seccomp = get_option('seccomp')
-if want_seccomp != 'false' and not fuzzer_build
+if want_seccomp != 'false' and not skip_deps
         libseccomp = dependency('libseccomp',
                                 version : '>= 2.3.1',
                                 required : want_seccomp == 'true')
@@ -827,7 +841,7 @@ endif
 conf.set10('HAVE_SECCOMP', have)
 
 want_selinux = get_option('selinux')
-if want_selinux != 'false' and not fuzzer_build
+if want_selinux != 'false' and not skip_deps
         libselinux = dependency('libselinux',
                                 version : '>= 2.1.9',
                                 required : want_selinux == 'true')
@@ -839,7 +853,7 @@ endif
 conf.set10('HAVE_SELINUX', have)
 
 want_apparmor = get_option('apparmor')
-if want_apparmor != 'false' and not fuzzer_build
+if want_apparmor != 'false' and not skip_deps
         libapparmor = dependency('libapparmor',
                                  required : want_apparmor == 'true')
         have = libapparmor.found()
@@ -857,7 +871,7 @@ endif
 want_polkit = get_option('polkit')
 install_polkit = false
 install_polkit_pkla = false
-if want_polkit != 'false' and not fuzzer_build
+if want_polkit != 'false' and not skip_deps
         install_polkit = true
 
         libpolkit = dependency('polkit-gobject-1',
@@ -870,7 +884,7 @@ endif
 conf.set10('ENABLE_POLKIT', install_polkit)
 
 want_acl = get_option('acl')
-if want_acl != 'false' and not fuzzer_build
+if want_acl != 'false' and not skip_deps
         libacl = cc.find_library('acl', required : want_acl == 'true')
         have = libacl.found()
 else
@@ -880,7 +894,7 @@ endif
 conf.set10('HAVE_ACL', have)
 
 want_audit = get_option('audit')
-if want_audit != 'false' and not fuzzer_build
+if want_audit != 'false' and not skip_deps
         libaudit = dependency('audit', required : want_audit == 'true')
         have = libaudit.found()
 else
@@ -890,7 +904,7 @@ endif
 conf.set10('HAVE_AUDIT', have)
 
 want_blkid = get_option('blkid')
-if want_blkid != 'false' and not fuzzer_build
+if want_blkid != 'false' and not skip_deps
         libblkid = dependency('blkid', required : want_blkid == 'true')
         have = libblkid.found()
 else
@@ -900,7 +914,7 @@ endif
 conf.set10('HAVE_BLKID', have)
 
 want_kmod = get_option('kmod')
-if want_kmod != 'false' and not fuzzer_build
+if want_kmod != 'false' and not skip_deps
         libkmod = dependency('libkmod',
                              version : '>= 15',
                              required : want_kmod == 'true')
@@ -912,7 +926,7 @@ endif
 conf.set10('HAVE_KMOD', have)
 
 want_pam = get_option('pam')
-if want_pam != 'false' and not fuzzer_build
+if want_pam != 'false' and not skip_deps
         libpam = cc.find_library('pam', required : want_pam == 'true')
         libpam_misc = cc.find_library('pam_misc', required : want_pam == 'true')
         have = libpam.found() and libpam_misc.found()
@@ -924,7 +938,7 @@ endif
 conf.set10('HAVE_PAM', have)
 
 want_microhttpd = get_option('microhttpd')
-if want_microhttpd != 'false' and not fuzzer_build
+if want_microhttpd != 'false' and not skip_deps
         libmicrohttpd = dependency('libmicrohttpd',
                                    version : '>= 0.9.33',
                                    required : want_microhttpd == 'true')
@@ -936,7 +950,7 @@ endif
 conf.set10('HAVE_MICROHTTPD', have)
 
 want_libcryptsetup = get_option('libcryptsetup')
-if want_libcryptsetup != 'false' and not fuzzer_build
+if want_libcryptsetup != 'false' and not skip_deps
         libcryptsetup = dependency('libcryptsetup',
                                    version : '>= 1.6.0',
                                    required : want_libcryptsetup == 'true')
@@ -954,7 +968,7 @@ conf.set10('HAVE_LIBCRYPTSETUP', have)
 conf.set10('HAVE_LIBCRYPTSETUP_SECTOR_SIZE', have_sector)
 
 want_libcurl = get_option('libcurl')
-if want_libcurl != 'false' and not fuzzer_build
+if want_libcurl != 'false' and not skip_deps
         libcurl = dependency('libcurl',
                              version : '>= 7.32.0',
                              required : want_libcurl == 'true')
@@ -971,7 +985,7 @@ if want_libidn == 'true' and want_libidn2 == 'true'
         error('libidn and libidn2 cannot be requested simultaneously')
 endif
 
-if want_libidn != 'false' and want_libidn2 != 'true' and not fuzzer_build
+if want_libidn != 'false' and want_libidn2 != 'true' and not skip_deps
         libidn = dependency('libidn',
                             required : want_libidn == 'true')
         have = libidn.found()
@@ -980,7 +994,7 @@ else
         libidn = []
 endif
 conf.set10('HAVE_LIBIDN', have)
-if not have and want_libidn2 != 'false' and not fuzzer_build
+if not have and want_libidn2 != 'false' and not skip_deps
         # libidn is used for both libidn and libidn2 objects
         libidn = dependency('libidn2',
                             required : want_libidn2 == 'true')
@@ -991,7 +1005,7 @@ endif
 conf.set10('HAVE_LIBIDN2', have)
 
 want_libiptc = get_option('libiptc')
-if want_libiptc != 'false' and not fuzzer_build
+if want_libiptc != 'false' and not skip_deps
         libiptc = dependency('libiptc',
                              required : want_libiptc == 'true')
         have = libiptc.found()
@@ -1002,7 +1016,7 @@ endif
 conf.set10('HAVE_LIBIPTC', have)
 
 want_qrencode = get_option('qrencode')
-if want_qrencode != 'false' and not fuzzer_build
+if want_qrencode != 'false' and not skip_deps
         libqrencode = dependency('libqrencode',
                                  required : want_qrencode == 'true')
         have = libqrencode.found()
@@ -1013,7 +1027,7 @@ endif
 conf.set10('HAVE_QRENCODE', have)
 
 want_gcrypt = get_option('gcrypt')
-if want_gcrypt != 'false' and not fuzzer_build
+if want_gcrypt != 'false' and not skip_deps
         libgcrypt = cc.find_library('gcrypt', required : want_gcrypt == 'true')
         libgpg_error = cc.find_library('gpg-error', required : want_gcrypt == 'true')
         have = libgcrypt.found() and libgpg_error.found()
@@ -1028,7 +1042,7 @@ endif
 conf.set10('HAVE_GCRYPT', have)
 
 want_gnutls = get_option('gnutls')
-if want_gnutls != 'false' and not fuzzer_build
+if want_gnutls != 'false' and not skip_deps
         libgnutls = dependency('gnutls',
                                version : '>= 3.1.4',
                                required : want_gnutls == 'true')
@@ -1040,7 +1054,7 @@ endif
 conf.set10('HAVE_GNUTLS', have)
 
 want_openssl = get_option('openssl')
-if want_openssl != 'false' and not fuzzer_build
+if want_openssl != 'false' and not skip_deps
         libopenssl = dependency('openssl',
                                 version : '>= 1.1.0',
                                 required : want_openssl == 'true')
@@ -1052,7 +1066,7 @@ endif
 conf.set10('HAVE_OPENSSL', have)
 
 want_elfutils = get_option('elfutils')
-if want_elfutils != 'false' and not fuzzer_build
+if want_elfutils != 'false' and not skip_deps
         libdw = dependency('libdw',
                            required : want_elfutils == 'true')
         have = libdw.found()
@@ -1063,7 +1077,7 @@ endif
 conf.set10('HAVE_ELFUTILS', have)
 
 want_zlib = get_option('zlib')
-if want_zlib != 'false' and not fuzzer_build
+if want_zlib != 'false' and not skip_deps
         libz = dependency('zlib',
                           required : want_zlib == 'true')
         have = libz.found()
@@ -1074,7 +1088,7 @@ endif
 conf.set10('HAVE_ZLIB', have)
 
 want_bzip2 = get_option('bzip2')
-if want_bzip2 != 'false' and not fuzzer_build
+if want_bzip2 != 'false' and not skip_deps
         libbzip2 = cc.find_library('bz2',
                                    required : want_bzip2 == 'true')
         have = libbzip2.found()
@@ -1085,7 +1099,7 @@ endif
 conf.set10('HAVE_BZIP2', have)
 
 want_xz = get_option('xz')
-if want_xz != 'false' and not fuzzer_build
+if want_xz != 'false' and not skip_deps
         libxz = dependency('liblzma',
                            required : want_xz == 'true')
         have = libxz.found()
@@ -1096,7 +1110,7 @@ endif
 conf.set10('HAVE_XZ', have)
 
 want_lz4 = get_option('lz4')
-if want_lz4 != 'false' and not fuzzer_build
+if want_lz4 != 'false' and not skip_deps
         liblz4 = dependency('liblz4',
                             version : '>= 1.3.0',
                             required : want_lz4 == 'true')
@@ -1108,7 +1122,7 @@ endif
 conf.set10('HAVE_LZ4', have)
 
 want_xkbcommon = get_option('xkbcommon')
-if want_xkbcommon != 'false' and not fuzzer_build
+if want_xkbcommon != 'false' and not skip_deps
         libxkbcommon = dependency('xkbcommon',
                                   version : '>= 0.3.0',
                                   required : want_xkbcommon == 'true')
@@ -1131,7 +1145,7 @@ endif
 conf.set10('HAVE_PCRE2', have)
 
 want_glib = get_option('glib')
-if want_glib != 'false' and not fuzzer_build
+if want_glib != 'false' and not skip_deps
         libglib =    dependency('glib-2.0',
                                 version : '>= 2.22.0',
                                 required : want_glib == 'true')
@@ -1150,7 +1164,7 @@ endif
 conf.set10('HAVE_GLIB', have)
 
 want_dbus = get_option('dbus')
-if want_dbus != 'false' and not fuzzer_build
+if want_dbus != 'false' and not skip_deps
         libdbus = dependency('dbus-1',
                              version : '>= 1.3.2',
                              required : want_dbus == 'true')
@@ -1162,7 +1176,7 @@ endif
 conf.set10('HAVE_DBUS', have)
 
 default_dnssec = get_option('default-dnssec')
-if fuzzer_build
+if skip_deps
         default_dnssec = 'no'
 endif
 if default_dnssec != 'no' and conf.get('HAVE_GCRYPT') == 0
@@ -1203,7 +1217,7 @@ conf.set10('DNS_OVER_TLS_USE_GNUTLS', have_gnutls)
 conf.set10('DNS_OVER_TLS_USE_OPENSSL', have_openssl)
 
 default_dns_over_tls = get_option('default-dns-over-tls')
-if fuzzer_build
+if skip_deps
         default_dns_over_tls = 'no'
 endif
 if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
@@ -2470,6 +2484,7 @@ exe = executable('systemd-mount',
                  'src/mount/mount-tool.c',
                  include_directories : includes,
                  link_with : [libshared],
+                 dependencies: [libmount],
                  install_rpath : rootlibexecdir,
                  install : true)
 public_programs += exe
@@ -2816,13 +2831,24 @@ foreach tuple : fuzzers
         dependencies = tuple[2]
         defs = tuple.length() >= 4 ? tuple[3] : []
         incs = tuple.length() >= 5 ? tuple[4] : includes
+        link_args = []
 
-        if fuzzer_build
+        if want_ossfuzz or want_fuzzbuzz
                 dependencies += fuzzing_engine
+        elif want_libfuzzer
+                if fuzzing_engine.found()
+                        dependencies += fuzzing_engine
+                else
+                        link_args += ['-fsanitize=fuzzer']
+                endif
         else
                 sources += 'src/fuzz/fuzz-main.c'
         endif
 
+        if want_fuzzbuzz
+                sources += 'src/fuzz/fuzzer-entry-point.c'
+        endif
+
         name = sources[0].split('/')[-1].split('.')[0]
 
         fuzzer_exes += executable(
@@ -2832,6 +2858,7 @@ foreach tuple : fuzzers
                 link_with : link_with,
                 dependencies : dependencies,
                 c_args : defs,
+                link_args: link_args,
                 install : false)
 endforeach
 endif
@@ -2899,6 +2926,16 @@ endforeach
 
 ############################################################
 
+check_directives_sh = find_program('tools/check-directives.sh')
+
+if want_tests != 'false'
+        test('check-directives',
+             check_directives_sh,
+             args : project_source_root)
+endif
+
+############################################################
+
 # Enable tests for all supported sanitizers
 foreach tuple : sanitizers
         sanitizer = tuple[0]
@@ -3019,7 +3056,6 @@ status = [
         'bash completions directory:        @0@'.format(bashcompletiondir),
         'zsh completions directory:         @0@'.format(zshcompletiondir),
         'extra start script:                @0@'.format(get_option('rc-local')),
-        'extra stop script:                 @0@'.format(get_option('halt-local')),
         'debug shell:                       @0@ @ @1@'.format(get_option('debug-shell'),
                                                               get_option('debug-tty')),
         'TTY GID:                           @0@'.format(tty_gid),
index d4ec37dda2c160d69fa3a71eca6d331f42f07aed..494a8de43c487ec17f145ea0a6a411f549267473 100644 (file)
@@ -31,8 +31,6 @@ option('telinit-path', type : 'string', value : '/lib/sysvinit/telinit',
        description : 'path to telinit')
 option('rc-local', type : 'string',
        value : '/etc/rc.local')
-option('halt-local', type : 'string',
-       value : '/usr/sbin/halt.local')
 
 option('quotaon-path', type : 'string', description : 'path to quotaon')
 option('quotacheck-path', type : 'string', description : 'path to quotacheck')
@@ -126,6 +124,7 @@ option('hwdb', type : 'boolean',
 option('rfkill', type : 'boolean',
        description : 'support for the rfkill tools')
 option('man', type : 'combo', choices : ['auto', 'true', 'false'],
+       value : 'false',
        description : 'build and install man pages')
 option('html', type : 'combo', choices : ['auto', 'true', 'false'],
        value : 'false',
@@ -157,7 +156,7 @@ option('fallback-hostname', type : 'string', value : 'localhost',
 option('compat-gateway-hostname', type : 'boolean', value : 'false',
        description : 'allow "gateway" as the symbolic name for default gateway')
 option('default-hierarchy', type : 'combo',
-       choices : ['legacy', 'hybrid', 'unified'], value : 'hybrid',
+       choices : ['legacy', 'hybrid', 'unified'], value : 'unified',
        description : 'default cgroup hierarchy')
 option('default-net-naming-scheme', type : 'combo',
        choices : ['latest', 'v238', 'v239', 'v240'],
@@ -329,3 +328,9 @@ option('oss-fuzz', type : 'boolean', value : 'false',
        description : 'build against oss-fuzz')
 option('llvm-fuzz', type : 'boolean', value : 'false',
        description : 'build against LLVM libFuzzer')
+option('fuzzbuzz', type : 'boolean', value : 'false',
+       description : 'build against FuzzBuzz')
+option('fuzzbuzz-engine', type : 'string',
+       description : 'the name of the FuzzBuzz fuzzing engine')
+option('fuzzbuzz-engine-dir', type : 'string',
+       description : 'the directory where the FuzzBuzz fuzzing engine is')
index 3c1213d8f7e41f2c2be45789018e455eab23a449..1eafe5a6586275d3d2be6f7d778bef075a4a5e2c 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -8,8 +8,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2019-01-02 13:27+0100\n"
-"PO-Revision-Date: 2019-01-02 13:35+0100\n"
+"POT-Creation-Date: 2019-05-05 17:02+0200\n"
+"PO-Revision-Date: 2019-05-05 17:13+0200\n"
 "Last-Translator: Daniele Medri <dmedri@gmail.com>\n"
 "Language-Team: Italian\n"
 "Language: it\n"
@@ -17,7 +17,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.2\n"
+"X-Generator: Poedit 2.2.1\n"
 
 #: src/core/org.freedesktop.systemd1.policy.in:22
 msgid "Send passphrase back to system"
@@ -102,11 +102,11 @@ msgstr ""
 
 #: src/hostname/org.freedesktop.hostname1.policy:51
 msgid "Get product UUID"
-msgstr "Ottieni UUID prodotto"
+msgstr "Ottieni UUID del prodotto"
 
 #: src/hostname/org.freedesktop.hostname1.policy:52
 msgid "Authentication is required to get product UUID."
-msgstr "Autenticazione richiesta per ottenere UUID prodotto."
+msgstr "Autenticazione richiesta per ottenere UUID del prodotto."
 
 #: src/import/org.freedesktop.import1.policy:22
 msgid "Import a VM or container image"
@@ -168,7 +168,7 @@ msgstr "Consenti alle applicazioni di ritardare lo spegnimento del sistema"
 #: src/login/org.freedesktop.login1.policy:34
 msgid "Authentication is required for an application to delay system shutdown."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per ritardare lo spegnimento "
+"Autenticazione richiesta ad un'applicazione per ritardare lo spegnimento "
 "del sistema."
 
 #: src/login/org.freedesktop.login1.policy:44
@@ -178,7 +178,7 @@ msgstr "Consenti alle applicazioni di inibire il sistema in pausa"
 #: src/login/org.freedesktop.login1.policy:45
 msgid "Authentication is required for an application to inhibit system sleep."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire il sistema in pausa."
+"Autenticazione richiesta ad un'applicazione per inibire il sistema in pausa."
 
 #: src/login/org.freedesktop.login1.policy:55
 msgid "Allow applications to delay system sleep"
@@ -187,7 +187,7 @@ msgstr "Consenti alle applicazioni di ritardare il sistema in pausa"
 #: src/login/org.freedesktop.login1.policy:56
 msgid "Authentication is required for an application to delay system sleep."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per ritardare il sistema in "
+"Autenticazione richiesta ad un'applicazione per ritardare il sistema in "
 "pausa."
 
 #: src/login/org.freedesktop.login1.policy:65
@@ -200,13 +200,13 @@ msgid ""
 "Authentication is required for an application to inhibit automatic system "
 "suspend."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire la sospensione "
+"Autenticazione richiesta ad un'applicazione per inibire la sospensione "
 "automatica del sistema."
 
 #: src/login/org.freedesktop.login1.policy:75
 msgid "Allow applications to inhibit system handling of the power key"
 msgstr ""
-"Consenti alle applicazioni di inibire la gestione di sistema del tasto di "
+"Consenti alle applicazioni di inibire la gestione di sistema del tasto"
 "accensione"
 
 #: src/login/org.freedesktop.login1.policy:76
@@ -215,7 +215,7 @@ msgid ""
 "the power key."
 msgstr ""
 "Autenticazione richiesta per un'applicazione per inibire la gestione di "
-"sistema del tasto di accensione."
+"sistema del tasto accensione."
 
 #: src/login/org.freedesktop.login1.policy:86
 msgid "Allow applications to inhibit system handling of the suspend key"
@@ -228,7 +228,7 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the suspend key."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire la gestione di "
+"Autenticazione richiesta ad un'applicazione per inibire la gestione di "
 "sistema del tasto di sospensione."
 
 #: src/login/org.freedesktop.login1.policy:97
@@ -242,7 +242,7 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the hibernate key."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire la gestione di "
+"Autenticazione richiesta ad un'applicazione per inibire la gestione di "
 "sistema del tasto di ibernazione."
 
 #: src/login/org.freedesktop.login1.policy:107
@@ -479,33 +479,66 @@ msgid "Authentication is required to lock or unlock active sessions."
 msgstr "Autenticazione richiesta per bloccare o sbloccare le sessioni attive."
 
 #: src/login/org.freedesktop.login1.policy:341
-msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
-"Permette indicazioni al firmware per avviare l'interfaccia di configurazione"
+msgid "Set the reboot \"reason\" in the kernel"
+msgstr "Indica il \"motivo\" del riavvio nel kernel"
 
 #: src/login/org.freedesktop.login1.policy:342
+msgid "Authentication is required to set the reboot \"reason\" in the kernel."
+msgstr ""
+"Autenticazione richiesta per configurare il \"motivo\" del riavvio nel "
+"kernel."
+
+#: src/login/org.freedesktop.login1.policy:352
+msgid "Indicate to the firmware to boot to setup interface"
+msgstr "Indicate al firmware di avviare un'interfaccia di configurazione"
+
+#: src/login/org.freedesktop.login1.policy:353
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
 msgstr ""
-"Autenticazione richiesta per indicare al firmware di avviare l'interfaccia "
+"Autenticazione richiesta per indicare al firmware l'avvio di un'interfaccia "
 "di configurazione."
 
-#: src/login/org.freedesktop.login1.policy:352
+#: src/login/org.freedesktop.login1.policy:363
+msgid "Indicate to the boot loader to boot to the boot loader menu"
+msgstr "Indicate al boot loader di avviare un menu"
+
+#: src/login/org.freedesktop.login1.policy:364
+msgid ""
+"Authentication is required to indicate to the boot loader to boot to the "
+"boot loader menu."
+msgstr ""
+"Autenticazione richiesta per indicate al boot loader l'avvio di uno "
+"specifico menu."
+
+#: src/login/org.freedesktop.login1.policy:374
+msgid "Indicate to the boot loader to boot a specific entry"
+msgstr "Indicare al boot loader di avviare una voce specifica"
+
+#: src/login/org.freedesktop.login1.policy:375
+msgid ""
+"Authentication is required to indicate to the boot loader to boot into a "
+"specific boot loader entry."
+msgstr ""
+"Autenticazione richiesta per indicare al boot loader l'avvio di una "
+"specifica voce in elenco."
+
+#: src/login/org.freedesktop.login1.policy:385
 msgid "Set a wall message"
 msgstr "Configura un messaggio per gli utenti"
 
-#: src/login/org.freedesktop.login1.policy:353
+#: src/login/org.freedesktop.login1.policy:386
 msgid "Authentication is required to set a wall message"
 msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
 
 #: src/machine/org.freedesktop.machine1.policy:22
 msgid "Log into a local container"
-msgstr "Accedi in un container locale"
+msgstr "Accedi ad un container locale"
 
 #: src/machine/org.freedesktop.machine1.policy:23
 msgid "Authentication is required to log into a local container."
-msgstr "Autenticazione richiesta per accedere in un container locale."
+msgstr "Autenticazione richiesta per accedere ad un container locale."
 
 #: src/machine/org.freedesktop.machine1.policy:32
 msgid "Log into the local host"
@@ -513,7 +546,7 @@ msgstr "Accedi in un host locale"
 
 #: src/machine/org.freedesktop.machine1.policy:33
 msgid "Authentication is required to log into the local host."
-msgstr "Autenticazione richiesta per accedere in un host locale."
+msgstr "Autenticazione richiesta per accedere ad un host locale."
 
 #: src/machine/org.freedesktop.machine1.policy:42
 msgid "Acquire a shell in a local container"
@@ -617,7 +650,7 @@ msgstr "Annulla la registrazione di un servizio DNS-SD"
 #: src/resolve/org.freedesktop.resolve1.policy:34
 msgid "Authentication is required to unregister a DNS-SD service"
 msgstr ""
-"Autenticazione richiesta per annullare la registrare di un servizio DNS-SD"
+"Autenticazione richiesta per annullare la registrazione di un servizio DNS-SD"
 
 #: src/timedate/org.freedesktop.timedate1.policy:22
 msgid "Set system time"
@@ -659,25 +692,25 @@ msgid ""
 "shall be enabled."
 msgstr ""
 "Autenticazione richiesta per verificare se la sincronizzazione dell'orario "
-"in rete possa essere attivata."
+"in rete deve essere attivata."
 
-#: src/core/dbus-unit.c:326
+#: src/core/dbus-unit.c:317
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Autenticazione richiesta per avviare '$(unit)'."
 
-#: src/core/dbus-unit.c:327
+#: src/core/dbus-unit.c:318
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "Autenticazione richiesta per fermare '$(unit)'."
 
-#: src/core/dbus-unit.c:328
+#: src/core/dbus-unit.c:319
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "Autenticazione richiesta per ricaricare '$(unit)'."
 
-#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330
+#: src/core/dbus-unit.c:320 src/core/dbus-unit.c:321
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "Autenticazione richiesta per riavviare '$(unit)'."
 
-#: src/core/dbus-unit.c:437
+#: src/core/dbus-unit.c:493
 msgid ""
 "Authentication is required to send a UNIX signal to the processes of "
 "'$(unit)'."
@@ -685,11 +718,11 @@ msgstr ""
 "Autenticazione richiesta per inviare un segnale UNIX ai processi di "
 "'$(unit)'."
 
-#: src/core/dbus-unit.c:468
+#: src/core/dbus-unit.c:524
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
 "Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'."
 
-#: src/core/dbus-unit.c:501
+#: src/core/dbus-unit.c:557
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'."
index 1f2fb3dd4e5d5e47dfc39114697e458cacc9d60a..4f37f99bdc0c26707e6f2cfc182ebbf077150f14 100644 (file)
@@ -2,22 +2,23 @@
 #
 # Brazilian Portuguese translation for systemd.
 # Enrico Nicoletto <liverig@gmail.com>, 2014.
-# Rafael Fontenelle <rafaelff@gnome.org>, 2015, 2017.
 # Filipe Brandenburger <filbranden@gmail.com>, 2018.
+# Rafael Fontenelle <rafaelff@gnome.org>, 2015-2019.
+#
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-09-06 20:10-0700\n"
-"PO-Revision-Date: 2018-02-19 10:36-0500\n"
-"Last-Translator: Filipe Brandenburger <filbranden@gmail.com>\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2019-05-04 03:28+0000\n"
+"PO-Revision-Date: 2019-05-04 11:12-0300\n"
+"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
 "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
-"Language: pt-BR\n"
+"Language: pt_BR\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Zanata 3.9.6\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"X-Generator: Gtranslator 3.32.0\n"
 
 #: src/core/org.freedesktop.systemd1.policy.in:22
 msgid "Send passphrase back to system"
@@ -47,7 +48,7 @@ msgstr "Gerenciar arquivos de unidades e serviços do sistema"
 #: src/core/org.freedesktop.systemd1.policy.in:44
 msgid "Authentication is required to manage system service or unit files."
 msgstr ""
-"É necessária autenticação para gerenciar arquivos \"unit\" e \"service\" do "
+"É necessária autenticação para gerenciar arquivos “unit” e “service” do "
 "sistema."
 
 #: src/core/org.freedesktop.systemd1.policy.in:54
@@ -477,12 +478,20 @@ msgid "Authentication is required to lock or unlock active sessions."
 msgstr "É necessária autenticação para travar ou destravar sessões ativas."
 
 #: src/login/org.freedesktop.login1.policy:341
-msgid "Allow indication to the firmware to boot to setup interface"
-msgstr ""
-"Permitir indicação para o firmware inicializar para a interface de "
-"configuração"
+msgid "Set the reboot \"reason\" in the kernel"
+msgstr "Definir o “motivo” de reinicialização no kernel"
 
 #: src/login/org.freedesktop.login1.policy:342
+msgid "Authentication is required to set the reboot \"reason\" in the kernel."
+msgstr ""
+"É necessária autenticação para definir o “motivo” de reinicialização no "
+"kernel."
+
+#: src/login/org.freedesktop.login1.policy:352
+msgid "Indicate to the firmware to boot to setup interface"
+msgstr "Indicar para o firmware inicializar para a interface de configuração"
+
+#: src/login/org.freedesktop.login1.policy:353
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -490,11 +499,36 @@ msgstr ""
 "É necessária autenticação para indicar para o firmware inicializar para a "
 "interface de configuração."
 
-#: src/login/org.freedesktop.login1.policy:351
+#: src/login/org.freedesktop.login1.policy:363
+msgid "Indicate to the boot loader to boot to the boot loader menu"
+msgstr "Indicar para o carregador de inicialização iniciar seu menu"
+
+#: src/login/org.freedesktop.login1.policy:364
+msgid ""
+"Authentication is required to indicate to the boot loader to boot to the "
+"boot loader menu."
+msgstr ""
+"É necessária autenticação para indicar para o carregador de inicialização "
+"iniciar seu menu"
+
+#: src/login/org.freedesktop.login1.policy:374
+msgid "Indicate to the boot loader to boot a specific entry"
+msgstr ""
+"Indicar para o carregador de inicializar iniciar uma entrada específica"
+
+#: src/login/org.freedesktop.login1.policy:375
+msgid ""
+"Authentication is required to indicate to the boot loader to boot into a "
+"specific boot loader entry."
+msgstr ""
+"É necessária autenticação para indicar para o carregador de inicializar "
+"iniciar uma entrada específica"
+
+#: src/login/org.freedesktop.login1.policy:385
 msgid "Set a wall message"
 msgstr "Definir uma mensagem de parede"
 
-#: src/login/org.freedesktop.login1.policy:352
+#: src/login/org.freedesktop.login1.policy:386
 msgid "Authentication is required to set a wall message"
 msgstr "É necessária autenticação para definir uma mensagem de parede"
 
@@ -661,31 +695,38 @@ msgstr ""
 "É necessária autenticação para controlar se deve ser habilitada, ou não, a "
 "sincronização de horário através de rede."
 
-#: src/core/dbus-unit.c:326
+#: src/core/dbus-unit.c:317
 msgid "Authentication is required to start '$(unit)'."
-msgstr "É necessária autenticação para iniciar '$(unit)'."
+msgstr "É necessária autenticação para iniciar “$(unit)”."
 
-#: src/core/dbus-unit.c:327
+#: src/core/dbus-unit.c:318
 msgid "Authentication is required to stop '$(unit)'."
-msgstr "É necessária autenticação para parar '$(unit)'."
+msgstr "É necessária autenticação para parar “$(unit)”."
 
-#: src/core/dbus-unit.c:328
+#: src/core/dbus-unit.c:319
 msgid "Authentication is required to reload '$(unit)'."
-msgstr "É necessária autenticação para recarregar '$(unit)'."
+msgstr "É necessária autenticação para recarregar “$(unit)”."
 
-#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330
+#: src/core/dbus-unit.c:320 src/core/dbus-unit.c:321
 msgid "Authentication is required to restart '$(unit)'."
-msgstr "É necessária autenticação para reiniciar '$(unit)'."
+msgstr "É necessária autenticação para reiniciar “$(unit)”."
 
-#: src/core/dbus-unit.c:437
-msgid "Authentication is required to kill '$(unit)'."
-msgstr "É necessária autenticação para matar '$(unit)'."
+#: src/core/dbus-unit.c:493
+msgid ""
+"Authentication is required to send a UNIX signal to the processes of "
+"'$(unit)'."
+msgstr ""
+"É necessária autenticação para enviar um sinal UNIX para os processos de "
+"“$(unit)”."
 
-#: src/core/dbus-unit.c:468
+#: src/core/dbus-unit.c:524
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
-"É necessária autenticação para reiniciar o estado \"failed\" de '$(unit)'."
+"É necessária autenticação para reiniciar o estado “failed” de “$(unit)”."
 
-#: src/core/dbus-unit.c:501
+#: src/core/dbus-unit.c:557
 msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "É necessária autenticação para definir propriedades em '$(unit)'."
+msgstr "É necessária autenticação para definir propriedades em “$(unit)”."
+
+#~ msgid "Authentication is required to kill '$(unit)'."
+#~ msgstr "É necessária autenticação para matar “$(unit)”."
index 361c80e5c9bdfe45166b0e9c94a479bc88bd08f4..809ab60051bb5d340be3fe95608b64e7332b8770 100644 (file)
--- a/po/uk.po
+++ b/po/uk.po
@@ -2,21 +2,22 @@
 # Ukrainian translation for systemd.
 # Eugene Melnik <jeka7js@gmail.com>, 2014.
 # Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018.
+# Yuri Chornoivan <yurchor@ukr.net>, 2019.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
 "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2018-03-27 03:26+0000\n"
-"PO-Revision-Date: 2018-05-11 23:16+0300\n"
-"Last-Translator: Daniel Korostil <ted.korostiled@gmail.com>\n"
-"Language-Team: linux.org.ua\n"
+"POT-Creation-Date: 2019-03-26 15:29+0000\n"
+"PO-Revision-Date: 2019-04-29 19:03+0300\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
 "Language: uk\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-"X-Generator: Virtaal 0.7.1\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<"
+"=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Lokalize 19.03.70\n"
 
 #: src/core/org.freedesktop.systemd1.policy.in:22
 msgid "Send passphrase back to system"
@@ -25,7 +26,8 @@ msgstr "Надіслати пароль назад у систему"
 #: src/core/org.freedesktop.systemd1.policy.in:23
 msgid ""
 "Authentication is required to send the entered passphrase back to the system."
-msgstr "Потрібна автентифікація, щоб надіслати введений пароль назад у систему."
+msgstr ""
+"Потрібна автентифікація, щоб надіслати введений пароль назад у систему."
 
 #: src/core/org.freedesktop.systemd1.policy.in:33
 msgid "Manage system services or other units"
@@ -34,7 +36,8 @@ msgstr "Керувати системними службами й іншими 
 #: src/core/org.freedesktop.systemd1.policy.in:34
 msgid "Authentication is required to manage system services or other units."
 msgstr ""
-"Потрібна автентифікація, щоб керувати системними службами й іншими одиницями systemd."
+"Потрібна автентифікація, щоб керувати системними службами й іншими одиницями "
+"systemd."
 
 #: src/core/org.freedesktop.systemd1.policy.in:43
 msgid "Manage system service or unit files"
@@ -43,14 +46,15 @@ msgstr "Керувати системними службами й одиниця
 #: src/core/org.freedesktop.systemd1.policy.in:44
 msgid "Authentication is required to manage system service or unit files."
 msgstr ""
-"Потрібна автентифікація, щоб керувати системними службами й одиницями systemd."
+"Потрібна автентифікація, щоб керувати системними службами й одиницями "
+"systemd."
 
-#: src/core/org.freedesktop.systemd1.policy.in:53
+#: src/core/org.freedesktop.systemd1.policy.in:54
 msgid "Set or unset system and service manager environment variables"
 msgstr ""
 "Встановити або забрати змінну середовища з керування службами і системою"
 
-#: src/core/org.freedesktop.systemd1.policy.in:54
+#: src/core/org.freedesktop.systemd1.policy.in:55
 msgid ""
 "Authentication is required to set or unset system and service manager "
 "environment variables."
@@ -58,27 +62,27 @@ msgstr ""
 "Потрібна автентифікація, щоб установити або забрати змінні середовища з "
 "керування службами і системою."
 
-#: src/core/org.freedesktop.systemd1.policy.in:63
+#: src/core/org.freedesktop.systemd1.policy.in:64
 msgid "Reload the systemd state"
 msgstr "Перезапустити стан системи"
 
-#: src/core/org.freedesktop.systemd1.policy.in:64
+#: src/core/org.freedesktop.systemd1.policy.in:65
 msgid "Authentication is required to reload the systemd state."
 msgstr "Потрібна автентифікація, щоб перезапустити стан системи."
 
-#: src/hostname/org.freedesktop.hostname1.policy:22
+#: src/hostname/org.freedesktop.hostname1.policy:20
 msgid "Set host name"
 msgstr "Встановити назву вузла"
 
-#: src/hostname/org.freedesktop.hostname1.policy:23
+#: src/hostname/org.freedesktop.hostname1.policy:21
 msgid "Authentication is required to set the local host name."
 msgstr "Потрібна автентифікація, щоб встановити назву локального вузла."
 
-#: src/hostname/org.freedesktop.hostname1.policy:32
+#: src/hostname/org.freedesktop.hostname1.policy:30
 msgid "Set static host name"
 msgstr "Встановити статичну назву вузла"
 
-#: src/hostname/org.freedesktop.hostname1.policy:33
+#: src/hostname/org.freedesktop.hostname1.policy:31
 msgid ""
 "Authentication is required to set the statically configured local host name, "
 "as well as the pretty host name."
@@ -86,14 +90,22 @@ msgstr ""
 "Потрібна автентифікація, щоб вказати статично налаштовану назву локального "
 "вузла, так само й форматовану."
 
-#: src/hostname/org.freedesktop.hostname1.policy:43
+#: src/hostname/org.freedesktop.hostname1.policy:41
 msgid "Set machine information"
 msgstr "Встановити інформацію про машину"
 
-#: src/hostname/org.freedesktop.hostname1.policy:44
+#: src/hostname/org.freedesktop.hostname1.policy:42
 msgid "Authentication is required to set local machine information."
 msgstr "Потрібна автентифікація, щоб вказати локальну інформацію про машини."
 
+#: src/hostname/org.freedesktop.hostname1.policy:51
+msgid "Get product UUID"
+msgstr "Отримання UUID продукту"
+
+#: src/hostname/org.freedesktop.hostname1.policy:52
+msgid "Authentication is required to get product UUID."
+msgstr "Потрібна автентифікація, щоб отримати UUID продукту."
+
 #: src/import/org.freedesktop.import1.policy:22
 msgid "Import a VM or container image"
 msgstr "Імпортувати образ контейнера або віртуальної машини"
@@ -101,7 +113,8 @@ msgstr "Імпортувати образ контейнера або вірту
 #: src/import/org.freedesktop.import1.policy:23
 msgid "Authentication is required to import a VM or container image"
 msgstr ""
-"Потрібна автентифікація, щоб імпортувати образ контейнера або віртуальної машини"
+"Потрібна автентифікація, щоб імпортувати образ контейнера або віртуальної "
+"машини"
 
 #: src/import/org.freedesktop.import1.policy:32
 msgid "Export a VM or container image"
@@ -120,7 +133,8 @@ msgstr "Звантажити образ контейнера або віртуа
 #: src/import/org.freedesktop.import1.policy:43
 msgid "Authentication is required to download a VM or container image"
 msgstr ""
-"Потрібна автентифікація, щоб звантажити образ контейнера або віртуальної машини"
+"Потрібна автентифікація, щоб звантажити образ контейнера або віртуальної "
+"машини"
 
 #: src/locale/org.freedesktop.locale1.policy:22
 msgid "Set system locale"
@@ -136,7 +150,8 @@ msgstr "Вказати налаштування системної клавіа
 
 #: src/locale/org.freedesktop.locale1.policy:34
 msgid "Authentication is required to set the system keyboard settings."
-msgstr "Потрібна автентифікація, щоб вказати налаштування системної клавіатури."
+msgstr ""
+"Потрібна автентифікація, щоб вказати налаштування системної клавіатури."
 
 #: src/login/org.freedesktop.login1.policy:22
 msgid "Allow applications to inhibit system shutdown"
@@ -146,7 +161,8 @@ msgstr "Дозволити програмам перешкоджати вимк
 msgid ""
 "Authentication is required for an application to inhibit system shutdown."
 msgstr ""
-"Потрібна автентифікація, щоб дозволити програмам перешкоджати вимкненню системи."
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати вимкненню "
+"системи."
 
 #: src/login/org.freedesktop.login1.policy:33
 msgid "Allow applications to delay system shutdown"
@@ -155,7 +171,8 @@ msgstr "Дозволити програмам затримувати вимкн
 #: src/login/org.freedesktop.login1.policy:34
 msgid "Authentication is required for an application to delay system shutdown."
 msgstr ""
-"Потрібна автентифікація, щоб дозволити програмам затримувати вимкнення системи."
+"Потрібна автентифікація, щоб дозволити програмам затримувати вимкнення "
+"системи."
 
 #: src/login/org.freedesktop.login1.policy:44
 msgid "Allow applications to inhibit system sleep"
@@ -164,7 +181,8 @@ msgstr "Дозволити програмам перешкоджати заси
 #: src/login/org.freedesktop.login1.policy:45
 msgid "Authentication is required for an application to inhibit system sleep."
 msgstr ""
-"Потрібна автентифікація, щоб дозволити програмам перешкоджати засинанню системи."
+"Потрібна автентифікація, щоб дозволити програмам перешкоджати засинанню "
+"системи."
 
 #: src/login/org.freedesktop.login1.policy:55
 msgid "Allow applications to delay system sleep"
@@ -173,7 +191,8 @@ msgstr "Дозволити програмами затримувати заси
 #: src/login/org.freedesktop.login1.policy:56
 msgid "Authentication is required for an application to delay system sleep."
 msgstr ""
-"Потрібна автентифікація, щоб дозволити програмам затримувати засинання системи."
+"Потрібна автентифікація, щоб дозволити програмам затримувати засинання "
+"системи."
 
 #: src/login/org.freedesktop.login1.policy:65
 msgid "Allow applications to inhibit automatic system suspend"
@@ -240,16 +259,14 @@ msgstr ""
 "системою клавіші перемикання кришки."
 
 #: src/login/org.freedesktop.login1.policy:117
-#| msgid "Allow non-logged-in users to run programs"
 msgid "Allow non-logged-in user to run programs"
 msgstr "Дозволити незареєстрованим користувачам запускати програми"
 
 #: src/login/org.freedesktop.login1.policy:118
-#| msgid "Authentication is required to run programs as a non-logged-in user."
 msgid "Explicit request is required to run programs as a non-logged-in user."
 msgstr ""
-"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам запускати "
-"програми."
+"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам "
+"запÑ\83Ñ\81каÑ\82и Ð¿Ñ\80огÑ\80ами."
 
 #: src/login/org.freedesktop.login1.policy:127
 msgid "Allow non-logged-in users to run programs"
@@ -258,8 +275,8 @@ msgstr "Дозволити незареєстрованим користувач
 #: src/login/org.freedesktop.login1.policy:128
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
-"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам запускати "
-"програми."
+"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам "
+"запÑ\83Ñ\81каÑ\82и Ð¿Ñ\80огÑ\80ами."
 
 #: src/login/org.freedesktop.login1.policy:137
 msgid "Allow attaching devices to seats"
@@ -276,7 +293,8 @@ msgstr "Очисний пристрій для під'єднань до місц
 #: src/login/org.freedesktop.login1.policy:149
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
-msgstr "Потрібна автентифікація, щоб перезапустити спосіб під'єднання до місць."
+msgstr ""
+"Потрібна автентифікація, щоб перезапустити спосіб під'єднання до місць."
 
 #: src/login/org.freedesktop.login1.policy:158
 msgid "Power off the system"
@@ -326,7 +344,8 @@ msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
 msgstr ""
-"Потрібна автентифікація, щоб перезапустити систему, коли інші користувачі в ній."
+"Потрібна автентифікація, щоб перезапустити систему, коли інші користувачі в "
+"ній."
 
 #: src/login/org.freedesktop.login1.policy:213
 msgid "Reboot the system while an application asked to inhibit it"
@@ -337,28 +356,22 @@ msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
 msgstr ""
-"Потрібна автентифікація, щоб перезапустити систему, коли програми намагаються "
-"перешкодити цьому."
+"Потрібна автентифікація, щоб перезапустити систему, коли програми "
+"намагаÑ\8eÑ\82Ñ\8cÑ\81Ñ\8f Ð¿ÐµÑ\80еÑ\88кодиÑ\82и Ñ\86Ñ\8cомÑ\83."
 
 #: src/login/org.freedesktop.login1.policy:224
-#| msgid "Hibernate the system"
 msgid "Halt the system"
 msgstr "Зупинити систему"
 
 #: src/login/org.freedesktop.login1.policy:225
-#| msgid "Authentication is required for hibernating the system."
 msgid "Authentication is required for halting the system."
 msgstr "Потрібна автентифікація, щоб зупинити систему."
 
 #: src/login/org.freedesktop.login1.policy:235
-#| msgid "Hibernate the system while other users are logged in"
 msgid "Halt the system while other users are logged in"
 msgstr "Зупинити систему, коли інші користувачі в ній"
 
 #: src/login/org.freedesktop.login1.policy:236
-#| msgid ""
-#| "Authentication is required for hibernating the system while other users "
-#| "are logged in."
 msgid ""
 "Authentication is required for halting the system while other users are "
 "logged in."
@@ -366,14 +379,10 @@ msgstr ""
 "Потрібна автентифікація, щоб зупинити систему, коли інші користувачі в ній."
 
 #: src/login/org.freedesktop.login1.policy:246
-#| msgid "Hibernate the system while an application asked to inhibit it"
 msgid "Halt the system while an application asked to inhibit it"
 msgstr "Зупинити систему, коли програми намагаються перешкодити цьому"
 
 #: src/login/org.freedesktop.login1.policy:247
-#| msgid ""
-#| "Authentication is required for hibernating the system while an "
-#| "application asked to inhibit it."
 msgid ""
 "Authentication is required for halting the system while an application asked "
 "to inhibit it."
@@ -398,7 +407,8 @@ msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
 msgstr ""
-"Потрібна автентифікація, щоб призупинити систему, коли інші користувачі в ній."
+"Потрібна автентифікація, щоб призупинити систему, коли інші користувачі в "
+"ній."
 
 #: src/login/org.freedesktop.login1.policy:278
 msgid "Suspend the system while an application asked to inhibit it"
@@ -463,10 +473,19 @@ msgid "Authentication is required to lock or unlock active sessions."
 msgstr "Потрібна автентифікація, щоб заблокувати або розблокувати сеанси."
 
 #: src/login/org.freedesktop.login1.policy:341
-msgid "Allow indication to the firmware to boot to setup interface"
-msgstr "Ð\94озволиÑ\82и Ð¼Ñ\96кÑ\80окодÑ\83 Ð²Ð¸Ð·Ð½Ð°Ñ\87аÑ\82и, Ñ\87и Ð·Ð°Ð²Ð°Ð½Ñ\82ажÑ\83ваÑ\82и Ñ\96нÑ\82еÑ\80Ñ\84ейÑ\81 Ð²Ñ\81Ñ\82ановленнÑ\8f"
+msgid "Set the reboot \"reason\" in the kernel"
+msgstr "Ð\92Ñ\81Ñ\82ановленнÑ\8f Â«Ð¿Ñ\80иÑ\87ини» Ð¿ÐµÑ\80езаванÑ\82аженнÑ\8f Ñ\83 Ñ\8fдÑ\80Ñ\96"
 
 #: src/login/org.freedesktop.login1.policy:342
+msgid "Authentication is required to set the reboot \"reason\" in the kernel."
+msgstr ""
+"Потрібна автентифікація, щоб встановити «причину» перезавантаження у ядрі."
+
+#: src/login/org.freedesktop.login1.policy:352
+msgid "Indicate to the firmware to boot to setup interface"
+msgstr "Визначення для мікрокоду завантаження інтерфейсу встановлення"
+
+#: src/login/org.freedesktop.login1.policy:353
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -474,11 +493,35 @@ msgstr ""
 "Потрібна автентифікація, щоб дозволити мікрокоду визначати, чи завантажувати "
 "інтерфейс встановлення."
 
-#: src/login/org.freedesktop.login1.policy:351
+#: src/login/org.freedesktop.login1.policy:363
+msgid "Indicate to the boot loader to boot to the boot loader menu"
+msgstr "Визначення для завантажувача завантаження до меню завантажувача"
+
+#: src/login/org.freedesktop.login1.policy:364
+msgid ""
+"Authentication is required to indicate to the boot loader to boot to the "
+"boot loader menu."
+msgstr ""
+"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажитися до"
+" меню завантажувача."
+
+#: src/login/org.freedesktop.login1.policy:374
+msgid "Indicate to the boot loader to boot a specific entry"
+msgstr "Визначення для завантажувача певного пункту для завантаження"
+
+#: src/login/org.freedesktop.login1.policy:375
+msgid ""
+"Authentication is required to indicate to the boot loader to boot into a "
+"specific boot loader entry."
+msgstr ""
+"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажити"
+" певний пункт меню завантаження."
+
+#: src/login/org.freedesktop.login1.policy:385
 msgid "Set a wall message"
 msgstr "Вказати повідомлення на стіні"
 
-#: src/login/org.freedesktop.login1.policy:352
+#: src/login/org.freedesktop.login1.policy:386
 msgid "Authentication is required to set a wall message"
 msgstr "Потрібна автентифікація, щоб вказати повідомлення на стіні"
 
@@ -504,7 +547,8 @@ msgstr "Перейняти оболонку в локальному контей
 
 #: src/machine/org.freedesktop.machine1.policy:43
 msgid "Authentication is required to acquire a shell in a local container."
-msgstr "Потрібна автентифікація, щоб перейняти оболонку в локальному контейнері."
+msgstr ""
+"Потрібна автентифікація, щоб перейняти оболонку в локальному контейнері."
 
 #: src/machine/org.freedesktop.machine1.policy:53
 msgid "Acquire a shell on the local host"
@@ -552,15 +596,43 @@ msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
 msgstr ""
-"Потрібна автентифікація, щоб керувати локальними образами віртуальних машин і "
-"контейнерів."
+"Потрібна автентифікація, щоб керувати локальними образами віртуальних машин "
+"і контейнерів."
+
+#: src/portable/org.freedesktop.portable1.policy:13
+msgid "Inspect a portable service image"
+msgstr "Інспектування образу портативної служби"
+
+#: src/portable/org.freedesktop.portable1.policy:14
+msgid "Authentication is required to inspect a portable service image."
+msgstr "Потрібна автентифікація, щоб інспектувати образ портативної служби."
+
+#: src/portable/org.freedesktop.portable1.policy:23
+msgid "Attach or detach a portable service image"
+msgstr "Долучення або вилучення образу портативної служби"
+
+#: src/portable/org.freedesktop.portable1.policy:24
+msgid ""
+"Authentication is required to attach or detach a portable service image."
+msgstr ""
+"Потрібна автентифікація, щоб долучити або вилучити образ портативної служби."
+
+#: src/portable/org.freedesktop.portable1.policy:34
+msgid "Delete or modify portable service image"
+msgstr "Вилучення або внесення змін до образу портативної служби"
+
+#: src/portable/org.freedesktop.portable1.policy:35
+msgid ""
+"Authentication is required to delete or modify a portable service image."
+msgstr ""
+"Потрібна автентифікація, щоб вилучити образ портативної служби або внести до"
+" нього зміни."
 
 #: src/resolve/org.freedesktop.resolve1.policy:22
 msgid "Register a DNS-SD service"
 msgstr "Зареєструвати службу DNS-SD"
 
 #: src/resolve/org.freedesktop.resolve1.policy:23
-#| msgid "Authentication is required to set a wall message"
 msgid "Authentication is required to register a DNS-SD service"
 msgstr "Потрібна автентифікація, щоб зареєструвати службу DNS-SD"
 
@@ -569,7 +641,6 @@ msgid "Unregister a DNS-SD service"
 msgstr "Зняти з реєстрації службу DNS-SD"
 
 #: src/resolve/org.freedesktop.resolve1.policy:34
-#| msgid "Authentication is required to set a wall message"
 msgid "Authentication is required to unregister a DNS-SD service"
 msgstr "Потрібна автентифікація, щоб зняти з реєстрації службу DNS-SD"
 
@@ -597,44 +668,50 @@ msgstr "Вкажіть RTC для локального часового пояс
 msgid ""
 "Authentication is required to control whether the RTC stores the local or "
 "UTC time."
-msgstr "Потрібна автентифікація, щоб контролювати, чи зберігає RTC локальний час або UTC."
+msgstr ""
+"Потрібна автентифікація, щоб контролювати, чи зберігає RTC локальний час або "
+"UTC."
 
-#: src/timedate/org.freedesktop.timedate1.policy:54
+#: src/timedate/org.freedesktop.timedate1.policy:53
 msgid "Turn network time synchronization on or off"
 msgstr "Увімкнути або вимкнути синхронізування часу через мережу"
 
-#: src/timedate/org.freedesktop.timedate1.policy:55
+#: src/timedate/org.freedesktop.timedate1.policy:54
 msgid ""
 "Authentication is required to control whether network time synchronization "
 "shall be enabled."
 msgstr ""
-"Потрібна автентифікація, щоб контролювати, чи синхронізування часу через мережу "
-"запущено."
+"Потрібна автентифікація, щоб контролювати, чи синхронізування часу через "
+"меÑ\80ежÑ\83 Ð·Ð°Ð¿Ñ\83Ñ\89ено."
 
-#: src/core/dbus-unit.c:496
+#: src/core/dbus-unit.c:325
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Потрібна автентифікація, щоб запустити «$(unit)»."
 
-#: src/core/dbus-unit.c:497
+#: src/core/dbus-unit.c:326
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "Потрібна автентифікація, щоб зупинити «$(unit)»."
 
-#: src/core/dbus-unit.c:498
+#: src/core/dbus-unit.c:327
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "Потрібна автентифікація, щоб перезавантажити «$(unit)»."
 
-#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
+#: src/core/dbus-unit.c:328 src/core/dbus-unit.c:329
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "Потрібна автентифікація, щоб перезапустити «$(unit)»."
 
-#: src/core/dbus-unit.c:607
-msgid "Authentication is required to kill '$(unit)'."
-msgstr "Потрібна автентифікація, щоб вбити «$(unit)»."
+#: src/core/dbus-unit.c:434
+msgid ""
+"Authentication is required to send a UNIX signal to the processes of "
+"'$(unit)'."
+msgstr ""
+"Потрібна автентифікація, щоб надіслати сигнал UNIX до процесів «$(unit)»."
 
-#: src/core/dbus-unit.c:638
+#: src/core/dbus-unit.c:465
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr "Потрібна автентифікація, щоб скинути «пошкоджений» стан з «$(unit)»."
 
-#: src/core/dbus-unit.c:671
+#: src/core/dbus-unit.c:498
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr "Потрібна автентифікація, щоб вказати властивості на «$(unit)»."
+
index d284955776991d0c01cd310f01b27bcc4679bff7..4bef0eb95480bde5109a19f4d1bd2d436f0717c0 100644 (file)
@@ -6,510 +6,628 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-11-22 16:37+0100\n"
-"PO-Revision-Date: 2016-02-12 11:46+0800\n"
-"Last-Translator: Jeff Huang <s8321414@chakraos.org>\n"
+"POT-Creation-Date: 2019-05-24 23:59+0800\n"
+"PO-Revision-Date: 2019-05-25 00:38+0800\n"
+"Last-Translator: pan93412 <pan93412@gmail.com>\n"
 "Language-Team: chinese-l10n <chinese-l10n@googlegroups.com>\n"
 "Language: zh_TW\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Lokalize 2.0\n"
+"X-Generator: Poedit 2.2.1\n"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+#: src/core/org.freedesktop.systemd1.policy.in:22
 msgid "Send passphrase back to system"
-msgstr "å\82³å\9b\9eå¯\86碼ç\89\87èª\9eå\88°系統"
+msgstr "å°\87å¯\86碼ç\89\87èª\9eå\82³å\9b\9e系統"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+#: src/core/org.freedesktop.systemd1.policy.in:23
 msgid ""
 "Authentication is required to send the entered passphrase back to the system."
-msgstr "å\82³å\9b\9e已輸å\85¥ç\9a\84å¯\86碼ç\89\87èª\9eå\88°系統需要驗證。"
+msgstr "å°\87已輸å\85¥ç\9a\84å¯\86碼ç\89\87èª\9eå\82³å\9b\9e系統需要驗證。"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+#: src/core/org.freedesktop.systemd1.policy.in:33
 msgid "Manage system services or other units"
 msgstr "管理系統服務或其他單位"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+#: src/core/org.freedesktop.systemd1.policy.in:34
 msgid "Authentication is required to manage system services or other units."
 msgstr "管理系統服務或其他單位需要驗證。"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+#: src/core/org.freedesktop.systemd1.policy.in:43
 msgid "Manage system service or unit files"
 msgstr "管理系統服務或單位檔案"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+#: src/core/org.freedesktop.systemd1.policy.in:44
 msgid "Authentication is required to manage system service or unit files."
 msgstr "管理系統服務或單位檔案需要驗證。"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+#: src/core/org.freedesktop.systemd1.policy.in:54
 msgid "Set or unset system and service manager environment variables"
-msgstr "設定或取消設定系統及服務管理員環境變"
+msgstr "設定或取消設定系統及服務管理員環境變"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+#: src/core/org.freedesktop.systemd1.policy.in:55
 msgid ""
 "Authentication is required to set or unset system and service manager "
 "environment variables."
-msgstr "設定或取消設定系統及服務管理員環境變量時需要驗證"
+msgstr "需要身份驗證,才能設定或取消設定系統及服務管理員的環境變數。"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+#: src/core/org.freedesktop.systemd1.policy.in:64
 msgid "Reload the systemd state"
 msgstr "重新載入 systemd 狀態"
 
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+#: src/core/org.freedesktop.systemd1.policy.in:65
 msgid "Authentication is required to reload the systemd state."
 msgstr "重新載入 systemd 狀態需要驗證。"
 
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+#: src/hostname/org.freedesktop.hostname1.policy:20
 msgid "Set host name"
 msgstr "設定主機名稱"
 
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+#: src/hostname/org.freedesktop.hostname1.policy:21
 msgid "Authentication is required to set the local host name."
 msgstr "設定主機名稱需要驗證。"
 
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+#: src/hostname/org.freedesktop.hostname1.policy:30
 msgid "Set static host name"
 msgstr "設定靜態主機名稱"
 
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+#: src/hostname/org.freedesktop.hostname1.policy:31
 msgid ""
 "Authentication is required to set the statically configured local host name, "
 "as well as the pretty host name."
-msgstr "設定靜態設定的本機主機名稱時需要驗證,同時也需要漂亮的主機名稱"
+msgstr "需要身份驗證,才能設定靜態預先設定或 pretty 本地主機名稱。"
 
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+#: src/hostname/org.freedesktop.hostname1.policy:41
 msgid "Set machine information"
 msgstr "設定機器資訊"
 
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+#: src/hostname/org.freedesktop.hostname1.policy:42
 msgid "Authentication is required to set local machine information."
-msgstr "設定機器資訊需要驗證"
+msgstr "需要身份驗證,才能設定本地機器資訊。"
 
-#: ../src/import/org.freedesktop.import1.policy.in.h:1
+#: src/hostname/org.freedesktop.hostname1.policy:51
+msgid "Get product UUID"
+msgstr "取得產品的 UUID"
+
+#: src/hostname/org.freedesktop.hostname1.policy:52
+msgid "Authentication is required to get product UUID."
+msgstr "取得產品 UUID 需要身份驗證。"
+
+#: src/import/org.freedesktop.import1.policy:22
 msgid "Import a VM or container image"
 msgstr "匯入虛擬機器或容器映像"
 
-#: ../src/import/org.freedesktop.import1.policy.in.h:2
+#: src/import/org.freedesktop.import1.policy:23
 msgid "Authentication is required to import a VM or container image"
 msgstr "匯入虛擬機器或容器映像需要驗證"
 
-#: ../src/import/org.freedesktop.import1.policy.in.h:3
+#: src/import/org.freedesktop.import1.policy:32
 msgid "Export a VM or container image"
 msgstr "匯出虛擬機器或容器映像"
 
-#: ../src/import/org.freedesktop.import1.policy.in.h:4
+#: src/import/org.freedesktop.import1.policy:33
 msgid "Authentication is required to export a VM or container image"
 msgstr "匯出虛擬機器或容器映像需要驗證"
 
-#: ../src/import/org.freedesktop.import1.policy.in.h:5
+#: src/import/org.freedesktop.import1.policy:42
 msgid "Download a VM or container image"
 msgstr "下載虛擬機器或容器映像"
 
-#: ../src/import/org.freedesktop.import1.policy.in.h:6
+#: src/import/org.freedesktop.import1.policy:43
 msgid "Authentication is required to download a VM or container image"
 msgstr "下載虛擬機器或容器映像需要驗證"
 
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+#: src/locale/org.freedesktop.locale1.policy:22
 msgid "Set system locale"
 msgstr "設定系統語系"
 
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+#: src/locale/org.freedesktop.locale1.policy:23
 msgid "Authentication is required to set the system locale."
 msgstr "設定系統語系需要驗證。"
 
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+#: src/locale/org.freedesktop.locale1.policy:33
 msgid "Set system keyboard settings"
 msgstr "設定系統鍵盤設定"
 
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+#: src/locale/org.freedesktop.locale1.policy:34
 msgid "Authentication is required to set the system keyboard settings."
 msgstr "設定系統鍵盤設定需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:1
+#: src/login/org.freedesktop.login1.policy:22
 msgid "Allow applications to inhibit system shutdown"
 msgstr "允許應用程式阻止系統關機"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:2
+#: src/login/org.freedesktop.login1.policy:23
 msgid ""
 "Authentication is required for an application to inhibit system shutdown."
 msgstr "要讓應用程式阻止系統關機需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:3
+#: src/login/org.freedesktop.login1.policy:33
 msgid "Allow applications to delay system shutdown"
 msgstr "允許應用程式延遲系統關機"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:4
+#: src/login/org.freedesktop.login1.policy:34
 msgid "Authentication is required for an application to delay system shutdown."
 msgstr "要讓應用程式延遲系統關機需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:5
+#: src/login/org.freedesktop.login1.policy:44
 msgid "Allow applications to inhibit system sleep"
 msgstr "允許應用程式阻止系統睡眠"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:6
+#: src/login/org.freedesktop.login1.policy:45
 msgid "Authentication is required for an application to inhibit system sleep."
 msgstr "要讓應用程式阻止系統睡眠需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:7
+#: src/login/org.freedesktop.login1.policy:55
 msgid "Allow applications to delay system sleep"
 msgstr "允許應用程式延遲系統睡眠"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:8
+#: src/login/org.freedesktop.login1.policy:56
 msgid "Authentication is required for an application to delay system sleep."
 msgstr "要讓應用程式延遲系統睡眠需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:9
+#: src/login/org.freedesktop.login1.policy:65
 msgid "Allow applications to inhibit automatic system suspend"
 msgstr "允許應用程式阻止自動系統暫停"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:10
+#: src/login/org.freedesktop.login1.policy:66
 msgid ""
 "Authentication is required for an application to inhibit automatic system "
 "suspend."
 msgstr "要讓應用程式阻止自動系統暫停需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:11
+#: src/login/org.freedesktop.login1.policy:75
 msgid "Allow applications to inhibit system handling of the power key"
 msgstr "允許應用程式阻止系統處理電源鍵"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:12
+#: src/login/org.freedesktop.login1.policy:76
 msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the power key."
 msgstr "要讓應用程式阻止系統處理電源鍵需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:13
+#: src/login/org.freedesktop.login1.policy:86
 msgid "Allow applications to inhibit system handling of the suspend key"
 msgstr "允許應用程式阻止系統處理暫停鍵"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:14
+#: src/login/org.freedesktop.login1.policy:87
 msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the suspend key."
 msgstr "要讓應用程式阻止系統處理暫停鍵需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:15
+#: src/login/org.freedesktop.login1.policy:97
 msgid "Allow applications to inhibit system handling of the hibernate key"
 msgstr "允許應用程式阻止系統處理冬眠鍵"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:16
+#: src/login/org.freedesktop.login1.policy:98
 msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the hibernate key."
 msgstr "要讓應用程式阻止系統處理冬眠鍵需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:17
+#: src/login/org.freedesktop.login1.policy:107
 msgid "Allow applications to inhibit system handling of the lid switch"
 msgstr "允許應用程式阻止系統處理上蓋開關"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:18
+#: src/login/org.freedesktop.login1.policy:108
 msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the lid switch."
 msgstr "要讓應用程式阻止系統處理上蓋開關需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:19
+#: src/login/org.freedesktop.login1.policy:117
+msgid "Allow non-logged-in user to run programs"
+msgstr "允許未登入的使用者執行程式"
+
+#: src/login/org.freedesktop.login1.policy:118
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr "需要明確請求,才能以未登入使用者身份執行程式。"
+
+#: src/login/org.freedesktop.login1.policy:127
 msgid "Allow non-logged-in users to run programs"
 msgstr "允許未登入的使用者執行程式"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: src/login/org.freedesktop.login1.policy:128
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr "要讓未登入的使用者執行程式需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: src/login/org.freedesktop.login1.policy:137
 msgid "Allow attaching devices to seats"
 msgstr "允許將設備連接到座位"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: src/login/org.freedesktop.login1.policy:138
 msgid "Authentication is required for attaching a device to a seat."
 msgstr "將設備連接到座位需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: src/login/org.freedesktop.login1.policy:148
 msgid "Flush device to seat attachments"
 msgstr "暴露裝置以安裝附件"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: src/login/org.freedesktop.login1.policy:149
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr "要重置裝置如何連接到座位需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: src/login/org.freedesktop.login1.policy:158
 msgid "Power off the system"
 msgstr "關閉系統電源"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: src/login/org.freedesktop.login1.policy:159
 msgid "Authentication is required for powering off the system."
-msgstr "關閉系統電源需要驗證"
+msgstr "關閉系統電源需要身份驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: src/login/org.freedesktop.login1.policy:169
 msgid "Power off the system while other users are logged in"
 msgstr "在有其他使用者登入時關閉系統電源"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: src/login/org.freedesktop.login1.policy:170
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
 msgstr "在有其他使用者登入時關閉系統電源需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: src/login/org.freedesktop.login1.policy:180
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "當應用程式阻止系統電源關閉時將其關閉"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: src/login/org.freedesktop.login1.policy:181
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
 msgstr "當應用程式阻止系統電源關閉時將系統電源關閉需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: src/login/org.freedesktop.login1.policy:191
 msgid "Reboot the system"
 msgstr "重新啟動系統"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: src/login/org.freedesktop.login1.policy:192
 msgid "Authentication is required for rebooting the system."
 msgstr "重新啟動系統需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: src/login/org.freedesktop.login1.policy:202
 msgid "Reboot the system while other users are logged in"
 msgstr "在有其他使用者登入時重新啟動系統"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: src/login/org.freedesktop.login1.policy:203
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
 msgstr "在有其他使用者登入時重新啟動系統需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: src/login/org.freedesktop.login1.policy:213
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "當應用程式阻止重新啟動系統時將系統重新啟動"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: src/login/org.freedesktop.login1.policy:214
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
 msgstr "當應用程式阻止系統重新啟動時將系統重新啟動需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: src/login/org.freedesktop.login1.policy:224
+msgid "Halt the system"
+msgstr "停止系統"
+
+#: src/login/org.freedesktop.login1.policy:225
+msgid "Authentication is required for halting the system."
+msgstr "停止系統需要身份驗證。"
+
+#: src/login/org.freedesktop.login1.policy:235
+msgid "Halt the system while other users are logged in"
+msgstr "在其他使用者登入時停止系統"
+
+#: src/login/org.freedesktop.login1.policy:236
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr "在其他使用者登入時停止系統需要身份驗證。"
+
+#: src/login/org.freedesktop.login1.policy:246
+msgid "Halt the system while an application asked to inhibit it"
+msgstr "在應用程式阻止時停止系統"
+
+#: src/login/org.freedesktop.login1.policy:247
+msgid ""
+"Authentication is required for halting the system while an application asked "
+"to inhibit it."
+msgstr "需要身份驗證,才能在應用程式阻止時停止系統。"
+
+#: src/login/org.freedesktop.login1.policy:257
 msgid "Suspend the system"
 msgstr "暫停系統"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: src/login/org.freedesktop.login1.policy:258
 msgid "Authentication is required for suspending the system."
 msgstr "暫停系統需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: src/login/org.freedesktop.login1.policy:267
 msgid "Suspend the system while other users are logged in"
 msgstr "在有其他使用者登入時暫停系統"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: src/login/org.freedesktop.login1.policy:268
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
 msgstr "在有其他使用者登入時暫停系統需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: src/login/org.freedesktop.login1.policy:278
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "當應用程式阻止暫停系統時將系統暫停"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: src/login/org.freedesktop.login1.policy:279
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
 msgstr "當應用程式阻止系統暫停時將系統暫停需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: src/login/org.freedesktop.login1.policy:289
 msgid "Hibernate the system"
 msgstr "系統冬眠"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: src/login/org.freedesktop.login1.policy:290
 msgid "Authentication is required for hibernating the system."
 msgstr "系統冬眠需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: src/login/org.freedesktop.login1.policy:299
 msgid "Hibernate the system while other users are logged in"
 msgstr "在有其他使用者登入時冬眠系統"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: src/login/org.freedesktop.login1.policy:300
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
 msgstr "在有其他使用者登入時冬眠系統需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: src/login/org.freedesktop.login1.policy:310
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "當應用程式阻止冬眠系統時將系統冬眠"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: src/login/org.freedesktop.login1.policy:311
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
 msgstr "當應用程式阻止系統冬眠時將系統冬眠需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: src/login/org.freedesktop.login1.policy:321
 msgid "Manage active sessions, users and seats"
 msgstr "管理活躍的工作階段、使用者與座位"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: src/login/org.freedesktop.login1.policy:322
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr "管理活躍的工作階段、使用者與座位需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: src/login/org.freedesktop.login1.policy:331
 msgid "Lock or unlock active sessions"
 msgstr "鎖定或解鎖活躍的工作階段"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: src/login/org.freedesktop.login1.policy:332
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr "鎖定或解鎖活躍的工作階段需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
-msgid "Allow indication to the firmware to boot to setup interface"
-msgstr "允許對韌體的指示以開始設定介面"
+#: src/login/org.freedesktop.login1.policy:341
+msgid "Set the reboot \"reason\" in the kernel"
+msgstr "設定內核中的重新啟動 \"reason (原因)\""
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: src/login/org.freedesktop.login1.policy:342
+msgid "Authentication is required to set the reboot \"reason\" in the kernel."
+msgstr "需要身份驗證,才能設定內核中的重新啟動 \"reason (原因)\"。"
+
+#: src/login/org.freedesktop.login1.policy:352
+msgid "Indicate to the firmware to boot to setup interface"
+msgstr "引導韌體啟動設定畫面"
+
+#: src/login/org.freedesktop.login1.policy:353
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
 msgstr "對韌體的指示以開始設定介面需要驗證。"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: src/login/org.freedesktop.login1.policy:363
+msgid "Indicate to the boot loader to boot to the boot loader menu"
+msgstr "引導開機載入器啟動開機載入選單"
+
+#: src/login/org.freedesktop.login1.policy:364
+msgid ""
+"Authentication is required to indicate to the boot loader to boot to the "
+"boot loader menu."
+msgstr "需要身份驗證,才能引導開機載入器啟動開機載入器選單。"
+
+#: src/login/org.freedesktop.login1.policy:374
+msgid "Indicate to the boot loader to boot a specific entry"
+msgstr "引導開機載入器啟動指定項目"
+
+#: src/login/org.freedesktop.login1.policy:375
+msgid ""
+"Authentication is required to indicate to the boot loader to boot into a "
+"specific boot loader entry."
+msgstr "需要身份驗證,才能引導開機載入器啟動指定的開機載入器項目。"
+
+#: src/login/org.freedesktop.login1.policy:385
 msgid "Set a wall message"
 msgstr "設定 wall 訊息"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: src/login/org.freedesktop.login1.policy:386
 msgid "Authentication is required to set a wall message"
-msgstr "設定 wall 訊息需要驗證。"
+msgstr "需要身份驗證,才能設定 wall 訊息"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+#: src/machine/org.freedesktop.machine1.policy:22
 msgid "Log into a local container"
 msgstr "登入到本機容器"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+#: src/machine/org.freedesktop.machine1.policy:23
 msgid "Authentication is required to log into a local container."
 msgstr "登入到本機容器需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#: src/machine/org.freedesktop.machine1.policy:32
 msgid "Log into the local host"
 msgstr "登入到本機主機"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: src/machine/org.freedesktop.machine1.policy:33
 msgid "Authentication is required to log into the local host."
 msgstr "登入到本機主機需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: src/machine/org.freedesktop.machine1.policy:42
 msgid "Acquire a shell in a local container"
 msgstr "在本機容器中取得一個 shell"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: src/machine/org.freedesktop.machine1.policy:43
 msgid "Authentication is required to acquire a shell in a local container."
 msgstr "在本機容器中取得一個 shell 需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+#: src/machine/org.freedesktop.machine1.policy:53
 msgid "Acquire a shell on the local host"
 msgstr "在本機主機中取得一個 shell"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#: src/machine/org.freedesktop.machine1.policy:54
 msgid "Authentication is required to acquire a shell on the local host."
 msgstr "在本機主機中取得一個 shell 需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#: src/machine/org.freedesktop.machine1.policy:64
 msgid "Acquire a pseudo TTY in a local container"
 msgstr "取得在本機容器中的偽 TTY"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#: src/machine/org.freedesktop.machine1.policy:65
 msgid ""
 "Authentication is required to acquire a pseudo TTY in a local container."
 msgstr "取得在本機容器中的偽 TTY 需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+#: src/machine/org.freedesktop.machine1.policy:74
 msgid "Acquire a pseudo TTY on the local host"
 msgstr "取得在本機主機中的偽 TTY"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#: src/machine/org.freedesktop.machine1.policy:75
 msgid "Authentication is required to acquire a pseudo TTY on the local host."
 msgstr "取得在本機主機中的偽 TTY 需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+#: src/machine/org.freedesktop.machine1.policy:84
 msgid "Manage local virtual machines and containers"
 msgstr "管理本機虛擬機器及容器"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+#: src/machine/org.freedesktop.machine1.policy:85
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
 msgstr "管理本機虛擬機器及容器需要驗證。"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+#: src/machine/org.freedesktop.machine1.policy:95
 msgid "Manage local virtual machine and container images"
 msgstr "管理本機虛擬機器及容器映像"
 
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+#: src/machine/org.freedesktop.machine1.policy:96
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
 msgstr "管理本機虛擬機器及容器映像需要驗證。"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+#: src/portable/org.freedesktop.portable1.policy:13
+msgid "Inspect a portable service image"
+msgstr "檢查可攜式服務映像"
+
+#: src/portable/org.freedesktop.portable1.policy:14
+msgid "Authentication is required to inspect a portable service image."
+msgstr "需要身份驗證,才能檢查可攜式服務映像。"
+
+#: src/portable/org.freedesktop.portable1.policy:23
+msgid "Attach or detach a portable service image"
+msgstr "連結或取消連結可攜式服務映像"
+
+#: src/portable/org.freedesktop.portable1.policy:24
+msgid ""
+"Authentication is required to attach or detach a portable service image."
+msgstr "需要身份驗證,才能連結或取消連結可攜式服務映像。"
+
+#: src/portable/org.freedesktop.portable1.policy:34
+msgid "Delete or modify portable service image"
+msgstr "刪除或修改可攜式服務映像"
+
+#: src/portable/org.freedesktop.portable1.policy:35
+msgid ""
+"Authentication is required to delete or modify a portable service image."
+msgstr "需要身份驗證,才能刪除或修改可攜式服務映像。"
+
+#: src/resolve/org.freedesktop.resolve1.policy:22
+msgid "Register a DNS-SD service"
+msgstr "註冊 DNS-SD 服務"
+
+#: src/resolve/org.freedesktop.resolve1.policy:23
+msgid "Authentication is required to register a DNS-SD service"
+msgstr "需要身份驗證,才能註冊 DNS-SD 服務"
+
+#: src/resolve/org.freedesktop.resolve1.policy:33
+msgid "Unregister a DNS-SD service"
+msgstr "取消註冊 DNS-SD 服務"
+
+#: src/resolve/org.freedesktop.resolve1.policy:34
+msgid "Authentication is required to unregister a DNS-SD service"
+msgstr "需要身份驗證,才能取消註冊 DNS-SD 服務"
+
+#: src/timedate/org.freedesktop.timedate1.policy:22
 msgid "Set system time"
 msgstr "設定系統時間"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+#: src/timedate/org.freedesktop.timedate1.policy:23
 msgid "Authentication is required to set the system time."
 msgstr "設定系統時間需要驗證。"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+#: src/timedate/org.freedesktop.timedate1.policy:33
 msgid "Set system timezone"
 msgstr "設定系統時區"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+#: src/timedate/org.freedesktop.timedate1.policy:34
 msgid "Authentication is required to set the system timezone."
 msgstr "設定系統時區需要驗證。"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+#: src/timedate/org.freedesktop.timedate1.policy:43
 msgid "Set RTC to local timezone or UTC"
 msgstr "將 RTC 設定為本地時區或 UTC"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+#: src/timedate/org.freedesktop.timedate1.policy:44
 msgid ""
 "Authentication is required to control whether the RTC stores the local or "
 "UTC time."
 msgstr "控制 RTC 儲存本地或 UTC 時間需要驗證。"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+#: src/timedate/org.freedesktop.timedate1.policy:53
 msgid "Turn network time synchronization on or off"
 msgstr "打開或關閉網路時間同步"
 
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+#: src/timedate/org.freedesktop.timedate1.policy:54
 msgid ""
 "Authentication is required to control whether network time synchronization "
 "shall be enabled."
 msgstr "控制網路時間同步是否啟用需要驗證。"
 
-#: ../src/core/dbus-unit.c:428
+#: src/core/dbus-unit.c:317
 msgid "Authentication is required to start '$(unit)'."
 msgstr "啟動 '$(unit)' 需要驗證。"
 
-#: ../src/core/dbus-unit.c:429
+#: src/core/dbus-unit.c:318
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "停止 '$(unit)' 需要驗證。"
 
-#: ../src/core/dbus-unit.c:430
+#: src/core/dbus-unit.c:319
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "重新載入 '$(unit)' 需要驗證。"
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: src/core/dbus-unit.c:320 src/core/dbus-unit.c:321
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "重新啟動 '$(unit)' 需要驗證。"
 
-#: ../src/core/dbus-unit.c:535
-msgid "Authentication is required to kill '$(unit)'."
-msgstr "砍除 '$(unit)' 需要驗證。"
+#: src/core/dbus-unit.c:493
+msgid ""
+"Authentication is required to send a UNIX signal to the processes of "
+"'$(unit)'."
+msgstr "需要身份驗證,才能傳送 UNIX 信號至「$(unit)」的程序。"
 
-#: ../src/core/dbus-unit.c:565
+#: src/core/dbus-unit.c:524
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr "重置 '$(unit)' 的「失敗」狀態需要驗證。"
 
-#: ../src/core/dbus-unit.c:597
+#: src/core/dbus-unit.c:557
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr "在 '$(unit)' 上設定屬性需要驗證。"
 
+#~ msgid "Authentication is required to kill '$(unit)'."
+#~ msgstr "砍除 '$(unit)' 需要驗證。"
index f982631766b1c9d25c4687256aeffa1a588e5bb7..c34b60621683831271b5342b0eb1f0dbd1628d83 100644 (file)
@@ -48,13 +48,13 @@ SUBSYSTEM=="block", KERNEL=="nbd*", ENV{DEVTYPE}=="disk", TEST!="pid", ENV{SYSTE
 SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name"
 SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k"
 
-SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target"
-ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target"
-SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target"
+SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target", ENV{SYSTEMD_USER_WANTS}+="bluetooth.target"
+ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target", ENV{SYSTEMD_USER_WANTS}+="smartcard.target"
+SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target", ENV{SYSTEMD_USER_WANTS}+="sound.target"
 
-SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target"
-SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target"
-SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target"
+SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target"
+SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target"
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target"
 
 SUBSYSTEM=="udc", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="usb-gadget.target"
 
index 5117bb48617d55003d19468db652748d8231b454..1951dcbbada6a8e9fe6bdf33025ac99e8b8fb4ea 100755 (executable)
@@ -5,6 +5,7 @@ set -eux
 # default to Debian testing
 DISTRO=${DISTRO:-debian}
 RELEASE=${RELEASE:-buster}
+BRANCH=${BRANCH:-experimental}
 ARCH=${ARCH:-amd64}
 CONTAINER=${RELEASE}-${ARCH}
 MAX_CACHE_AGE=604800  # one week
@@ -66,7 +67,7 @@ for phase in "${PHASES[@]}"; do
         ;;
         RUN)
             # add current debian/ packaging
-            git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git master
+            git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git $BRANCH
             git checkout FETCH_HEAD debian
 
             # craft changelog
@@ -87,7 +88,7 @@ EOF
             # disable autopkgtests which are not for upstream
             sed -i '/# NOUPSTREAM/ q' debian/tests/control
             # enable more unit tests
-            sed -i '/^CONFFLAGS =/ s/=/= -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true /' debian/rules
+            sed -i '/^CONFFLAGS =/ s/=/= -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true -Dman=true /' debian/rules
             # no orig tarball
             echo '1.0' > debian/source/format
 
index 7e568dc3bd7965faa022443ef29c83417548f5d9..27b73900f736d1b6701ee4b797790fde523a6037 100644 (file)
@@ -31,13 +31,13 @@ _bootctl() {
     local i verb comps
     local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
     local -A OPTS=(
-        [STANDALONE]='-h --help --no-variables -p --print-path --version --no-pager'
-        [ARG]='--path'
+        [STANDALONE]='-h --help --no-variables -p --print-esp-path -x --print-boot-path --version --no-pager'
+        [ARG]='--esp-path --boot-path'
     )
 
     if __contains_word "$prev" ${OPTS[ARG]}; then
         case $prev in
-            --path)
+            --esp-path|--boot-path)
                 if [[ -z $cur ]]; then
                     comps=$(compgen -A directory -- "/" )
                 else
index c51c48516704fa4802b8f28cd2d8a85ae2e83201..4536f9bd2e5745c252becdc262e56870c1a1daac 100644 (file)
@@ -28,7 +28,7 @@ _systemd-inhibit_what() {
 _arguments \
     {-h,--help}'[Show this help]' \
     '--version[Show package version]' \
-    '--what=[Operations to inhibit]:options:_inhibit_what' \
+    '--what=[Operations to inhibit]:options:_systemd-inhibit_what' \
     '--who=[A descriptive string who is inhibiting]:who is inhibiting:' \
     '--why=[A descriptive string why is being inhibited]:reason for the lock:' \
     '--mode=[One of block or delay]:lock mode:( block delay )' \
index 48aa617e784209a7a1a062d4f3bdd6e5ce6d0f63..8bdf2e50aae43f1c71dc559e056e9ccf424cca77 100644 (file)
@@ -474,6 +474,7 @@ int main(int argc, char **argv, char **envp) {
         int r, n;
         int epoll_fd = -1;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 97d94516c87c2f57f9fb18aa3bb89f56d38eaddd..5217a92b438583fb2148c7d3b83b7161d9c963e9 100644 (file)
@@ -1673,6 +1673,18 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
 }
 #endif
 
+static void parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan) {
+        if (calendar && calendar_spec_from_string(p, NULL) >= 0)
+                log_notice("Hint: this expression is a valid calendar specification. "
+                           "Use 'systemd-analyze calendar \"%s\"' instead?", p);
+        if (timestamp && parse_timestamp(p, NULL) >= 0)
+                log_notice("Hint: this expression is a valid timestamp. "
+                           "Use 'systemd-analyze timestamp \"%s\"' instead?", p);
+        if (timespan && parse_time(p, NULL, USEC_PER_SEC) >= 0)
+                log_notice("Hint: this expression is a valid timespan. "
+                           "Use 'systemd-analyze timespan \"%s\"' instead?", p);
+}
+
 static int dump_timespan(int argc, char *argv[], void *userdata) {
         char **input_timespan;
 
@@ -1682,12 +1694,18 @@ static int dump_timespan(int argc, char *argv[], void *userdata) {
                 char ft_buf[FORMAT_TIMESPAN_MAX];
 
                 r = parse_time(*input_timespan, &output_usecs, USEC_PER_SEC);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse time span '%s': %m", *input_timespan);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to parse time span '%s': %m", *input_timespan);
+                        parsing_hint(*input_timespan, true, true, false);
+                        return r;
+                }
 
                 printf("Original: %s\n", *input_timespan);
                 printf("      %ss: %" PRIu64 "\n", special_glyph(SPECIAL_GLYPH_MU), output_usecs);
-                printf("   Human: %s\n", format_timespan(ft_buf, sizeof(ft_buf), output_usecs, usec_magnitude));
+                printf("   Human: %s%s%s\n",
+                       ansi_highlight(),
+                       format_timespan(ft_buf, sizeof(ft_buf), output_usecs, usec_magnitude),
+                       ansi_normal());
 
                 if (input_timespan[1])
                         putchar('\n');
@@ -1696,18 +1714,65 @@ static int dump_timespan(int argc, char *argv[], void *userdata) {
         return EXIT_SUCCESS;
 }
 
+static int test_timestamp_one(const char *p) {
+        usec_t usec;
+        char buf[FORMAT_TIMESTAMP_MAX];
+        int r;
+
+        r = parse_timestamp(p, &usec);
+        if (r < 0) {
+                log_error_errno(r, "Failed to parse \"%s\": %m", p);
+                parsing_hint(p, true, false, true);
+                return r;
+        }
+
+        printf("  Original form: %s\n", p);
+        printf("Normalized form: %s%s%s\n",
+               ansi_highlight_blue(),
+               format_timestamp(buf, sizeof buf, usec),
+               ansi_normal());
+
+        if (!in_utc_timezone())
+                printf("       (in UTC): %s\n", format_timestamp_utc(buf, sizeof buf, usec));
+
+        printf("   UNIX seconds: @%"PRI_USEC"%s%0*"PRI_USEC"\n",
+               usec / USEC_PER_SEC,
+               usec % USEC_PER_SEC ? "." : "",
+               usec % USEC_PER_SEC ? 6 : 0,
+               usec % USEC_PER_SEC);
+
+        printf("       From now: %s\n", format_timestamp_relative(buf, sizeof buf, usec));
+
+        return 0;
+}
+
+static int test_timestamp(int argc, char *argv[], void *userdata) {
+        int ret = 0, r;
+        char **p;
+
+        STRV_FOREACH(p, strv_skip(argv, 1)) {
+                r = test_timestamp_one(*p);
+                if (ret == 0 && r < 0)
+                        ret = r;
+
+                if (*(p + 1))
+                        putchar('\n');
+        }
+
+        return ret;
+}
+
 static int test_calendar_one(usec_t n, const char *p) {
         _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL;
         _cleanup_free_ char *t = NULL;
         int r;
 
         r = calendar_spec_from_string(p, &spec);
-        if (r < 0)
-                return log_error_errno(r, "Failed to parse calendar specification '%s': %m", p);
-
-        r = calendar_spec_normalize(spec);
-        if (r < 0)
-                return log_error_errno(r, "Failed to normalize calendar specification '%s': %m", p);
+        if (r < 0) {
+                log_error_errno(r, "Failed to parse calendar specification '%s': %m", p);
+                parsing_hint(p, false, true, true);
+                return r;
+        }
 
         r = calendar_spec_to_string(spec, &t);
         if (r < 0)
@@ -1873,8 +1938,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --require             Show only requirement in the graph\n"
                "     --from-pattern=GLOB   Show only origins in the graph\n"
                "     --to-pattern=GLOB     Show only destinations in the graph\n"
-               "     --fuzz=SECONDS        Also print also services which finished SECONDS\n"
-               "                           earlier than the latest in the branch\n"
+               "     --fuzz=SECONDS        Also print services which finished SECONDS earlier\n"
+               "                           than the latest in the branch\n"
                "     --man[=BOOL]          Do [not] check for existence of man pages\n"
                "     --generators[=BOOL]   Do [not] run unit generators (requires privileges)\n"
                "     --iterations=N        Show the specified number of iterations\n"
@@ -1891,8 +1956,9 @@ static int help(int argc, char *argv[], void *userdata) {
                "  unit-paths               List load directories for units\n"
                "  syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
                "  verify FILE...           Check unit files for correctness\n"
-               "  calendar SPEC...         Validate repetitive calendar time events\n"
                "  service-watchdogs [BOOL] Get/set service watchdog state\n"
+               "  calendar SPEC...         Validate repetitive calendar time events\n"
+               "  timestamp TIMESTAMP...   Validate a timestamp\n"
                "  timespan SPAN...         Validate a time span\n"
                "  security [UNIT...]       Analyze security of unit\n"
                "\nSee the %s for details.\n"
@@ -2093,8 +2159,9 @@ static int run(int argc, char *argv[]) {
                 { "syscall-filter",    VERB_ANY, VERB_ANY, 0,            dump_syscall_filters   },
                 { "verify",            2,        VERB_ANY, 0,            do_verify              },
                 { "calendar",          2,        VERB_ANY, 0,            test_calendar          },
-                { "service-watchdogs", VERB_ANY, 2,        0,            service_watchdogs      },
+                { "timestamp",         2,        VERB_ANY, 0,            test_timestamp         },
                 { "timespan",          2,        VERB_ANY, 0,            dump_timespan          },
+                { "service-watchdogs", VERB_ANY, 2,        0,            service_watchdogs      },
                 { "security",          VERB_ANY, VERB_ANY, 0,            do_security            },
                 {}
         };
@@ -2104,6 +2171,7 @@ static int run(int argc, char *argv[]) {
         setlocale(LC_ALL, "");
         setlocale(LC_NUMERIC, "C"); /* we want to format/parse floats in C style */
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 4637c3281931a4261d6dabf19183d98adbbad607..ca6da40bbc96763ce987844a0ab9eb81437e254b 100644 (file)
@@ -158,6 +158,7 @@ static int run(int argc, char *argv[]) {
         char **p;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 1e4ee722f204c4748ae916aa485f8e102c245570..a16db6824fe84f2299e290f0b8d961aee165d234 100644 (file)
@@ -64,8 +64,31 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
         if (!q)
                 return NULL;
 
+        if (size > 0) {
+                size_t bn;
+
+                /* Adjust for the 64 byte minimum */
+                newalloc = a / size;
+
+                bn = malloc_usable_size(q) / size;
+                if (bn > newalloc) {
+                        void *qq;
+
+                        /* The actual size allocated is larger than what we asked for. Let's call realloc() again to
+                         * take possession of the extra space. This should be cheap, since libc doesn't have to move
+                         * the memory for this. */
+
+                        qq = realloc(q, bn * size);
+                        if (_likely_(qq)) {
+                                *p = qq;
+                                *allocated = bn;
+                                return qq;
+                        }
+                }
+        }
+
         *p = q;
-        *allocated = _unlikely_(size == 0) ? newalloc : malloc_usable_size(q) / size;
+        *allocated = newalloc;
         return q;
 }
 
index 0035352954a8452c96c4e1cfc0d03052ef2ef57f..2a9c3b80f8150a7bc31adc36f5d3a18e9356f63b 100644 (file)
@@ -238,23 +238,20 @@ static int drop_from_file(const char *fn, uint64_t keep) {
         if (r < 0)
                 return r;
 
-        assert_cc(sizeof(hi) == sizeof(unsigned));
-        assert_cc(sizeof(lo) == sizeof(unsigned));
-
-        k = sscanf(p, "%u %u", &lo, &hi);
+        k = sscanf(p, "%" PRIu32 " %" PRIu32, &lo, &hi);
         if (k != 2)
                 return -EIO;
 
-        current = (uint64_t) lo | ((uint64_t) hi << 32ULL);
+        current = (uint64_t) lo | ((uint64_t) hi << 32);
         after = current & keep;
 
         if (current == after)
                 return 0;
 
-        lo = (unsigned) (after & 0xFFFFFFFFULL);
-        hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL);
+        lo = after & UINT32_C(0xFFFFFFFF);
+        hi = (after >> 32) & UINT32_C(0xFFFFFFFF);
 
-        return write_string_filef(fn, WRITE_STRING_FILE_CREATE, "%u %u", lo, hi);
+        return write_string_filef(fn, 0, "%" PRIu32 " %" PRIu32, lo, hi);
 }
 
 int capability_bounding_set_drop_usermode(uint64_t keep) {
index fd449dcce07d1c0badf7f5b614646b04751c66a1..896eec58356a0673ec7feb1a951e0b0839123bea 100644 (file)
@@ -72,7 +72,7 @@ bool env_value_is_valid(const char *e) {
          * either. Discounting the shortest possible variable name of
          * length 1, the equal sign and trailing NUL this hence leaves
          * ARG_MAX-3 as longest possible variable value. */
-        if (strlen(e) > (size_t) sysconf(_SC_ARG_MAX) - 3)
+        if (strlen(e) > sc_arg_max() - 3)
                 return false;
 
         return true;
@@ -95,7 +95,7 @@ bool env_assignment_is_valid(const char *e) {
          * be > ARG_MAX, hence the individual variable assignments
          * cannot be either, but let's leave room for one trailing NUL
          * byte. */
-        if (strlen(e) > (size_t) sysconf(_SC_ARG_MAX) - 1)
+        if (strlen(e) > sc_arg_max() - 1)
                 return false;
 
         return true;
index d54f99658bddaebdcaa54437629ba6126e483c13..92802ed774448ef867ef289c54ecc280cfea368e 100644 (file)
@@ -4,10 +4,17 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #include "macro.h"
 #include "string.h"
 
+static inline size_t sc_arg_max(void) {
+        long l = sysconf(_SC_ARG_MAX);
+        assert(l > 0);
+        return (size_t) l;
+}
+
 bool env_name_is_valid(const char *e);
 bool env_value_is_valid(const char *e);
 bool env_assignment_is_valid(const char *e);
index 5f715156fbf407e6c03d1a1839147ac7e76dbc96..33a6f204f55f5efb92e673c752cfac3f72a27d91 100644 (file)
@@ -368,33 +368,78 @@ int cunescape(const char *s, UnescapeFlags flags, char **ret) {
         return cunescape_length(s, strlen(s), flags, ret);
 }
 
-char *xescape(const char *s, const char *bad) {
-        char *r, *t;
+char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) {
+        char *ans, *t, *prev, *prev2;
         const char *f;
 
-        /* Escapes all chars in bad, in addition to \ and all special
-         * chars, in \xFF style escaping. May be reversed with
-         * cunescape(). */
+        /* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be
+         * reversed with cunescape(). If eight_bits is true, characters >= 127 are let through unchanged.
+         * This corresponds to non-ASCII printable characters in pre-unicode encodings.
+         *
+         * If console_width is reached, output is truncated and "..." is appended. */
 
-        r = new(char, strlen(s) * 4 + 1);
-        if (!r)
+        if (console_width == 0)
+                return strdup("");
+
+        ans = new(char, MIN(strlen(s), console_width) * 4 + 1);
+        if (!ans)
                 return NULL;
 
-        for (f = s, t = r; *f; f++) {
+        memset(ans, '_', MIN(strlen(s), console_width) * 4);
+        ans[MIN(strlen(s), console_width) * 4] = 0;
+
+        for (f = s, t = prev = prev2 = ans; ; f++) {
+                char *tmp_t = t;
+
+                if (!*f) {
+                        *t = 0;
+                        return ans;
+                }
+
+                if ((unsigned char) *f < ' ' || (!eight_bits && (unsigned char) *f >= 127) ||
+                    *f == '\\' || strchr(bad, *f)) {
+                        if ((size_t) (t - ans) + 4 > console_width)
+                                break;
 
-                if ((*f < ' ') || (*f >= 127) ||
-                    (*f == '\\') || strchr(bad, *f)) {
                         *(t++) = '\\';
                         *(t++) = 'x';
                         *(t++) = hexchar(*f >> 4);
                         *(t++) = hexchar(*f);
-                } else
+                } else {
+                        if ((size_t) (t - ans) + 1 > console_width)
+                                break;
+
                         *(t++) = *f;
+                }
+
+                /* We might need to go back two cycles to fit three dots, so remember two positions */
+                prev2 = prev;
+                prev = tmp_t;
         }
 
-        *t = 0;
+        /* We can just write where we want, since chars are one-byte */
+        size_t c = MIN(console_width, 3u); /* If the console is too narrow, write fewer dots */
+        size_t off;
+        if (console_width - c >= (size_t) (t - ans))
+                off = (size_t) (t - ans);
+        else if (console_width - c >= (size_t) (prev - ans))
+                off = (size_t) (prev - ans);
+        else if (console_width - c >= (size_t) (prev2 - ans))
+                off = (size_t) (prev2 - ans);
+        else
+                off = console_width - c;
+        assert(off <= (size_t) (t - ans));
 
-        return r;
+        memcpy(ans + off, "...", c);
+        ans[off + c] = '\0';
+        return ans;
+}
+
+char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) {
+        if (eight_bit)
+                return xescape_full(str, "", console_width, true);
+        else
+                return utf8_escape_non_printable_full(str, console_width);
 }
 
 char *octescape(const char *s, size_t len) {
index 515620993d051b4df03074acf3f5736937053ee0..b26054c5df8abb765e7c68163c3c47ca41906c22 100644 (file)
@@ -46,8 +46,12 @@ int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **r
 int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
 int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
 
-char *xescape(const char *s, const char *bad);
+char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits);
+static inline char *xescape(const char *s, const char *bad) {
+        return xescape_full(s, bad, SIZE_MAX, false);
+}
 char *octescape(const char *s, size_t len);
+char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit);
 
 char *shell_escape(const char *s, const char *bad);
 char* shell_maybe_quote(const char *s, EscapeStyle style);
index b9651205e60818661ebf97af4e8cfc38f0e9c8bb..c153bc4448da61ccae1f5beabfaa7dd1d29e7b0f 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/inotify.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
index 1d5c6412b5ba50bcd587a3e2dba92acb6b84abb9..c1fab51b5e43db651d29dce01077d269bb98d862 100644 (file)
@@ -738,3 +738,15 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
 }
 
 DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
+
+static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
+        assert(addr);
+
+        siphash24_compress(addr, sizeof(*addr), state);
+}
+
+static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
+        return memcmp(a, b, sizeof(*a));
+}
+
+DEFINE_HASH_OPS(in6_addr_hash_ops, struct in6_addr, in6_addr_hash_func, in6_addr_compare_func);
index a6a685b9188b5084e1b699a0afbb535cf77a1c41..2ca7f4b32fc88b5d8a9ecd2674661839821f4015 100644 (file)
@@ -72,3 +72,4 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
 #define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} })
 
 extern const struct hash_ops in_addr_data_hash_ops;
+extern const struct hash_ops in6_addr_hash_ops;
index f849f34951281300e64c49974cc54c350e9e805c..2bb70fdaadb812a6ea231ab8b9428f7708722983 100644 (file)
@@ -1,3 +1,6 @@
-The files in this directory are copied from kernel-5.0, and the following modifications are applied:
+The files in this directory are copied from current kernel master
+(b06ed1e7a2fa9b636f368a9e97c3c8877623f8b2) or WireGuard master
+(8416093498ac2c754536dad4757c5d86c9ba8809), and the following
+modifications are applied:
 - btrfs.h: drop '__user' attributes
 - if.h: drop '#include <linux/compiler.h>' and '__user' attributes
index f477008fef0876827c0fa35670bf6e2cc49b527f..b960b45d674290fdb32a2ce6ff0a46afcad973d0 100644 (file)
@@ -135,7 +135,7 @@ struct btrfs_scrub_progress {
        __u64 tree_bytes_scrubbed;      /* # of tree bytes scrubbed */
        __u64 read_errors;              /* # of read errors encountered (EIO) */
        __u64 csum_errors;              /* # of failed csum checks */
-       __u64 verify_errors;            /* # of occurrences, where the metadata
+       __u64 verify_errors;            /* # of occurences, where the metadata
                                         * of a tree block did not match the
                                         * expected values, like generation or
                                         * logical */
@@ -155,7 +155,7 @@ struct btrfs_scrub_progress {
        __u64 last_physical;            /* last physical address scrubbed. In
                                         * case a scrub was aborted, this can
                                         * be used to restart the scrub */
-       __u64 unverified_errors;        /* # of occurrences where a read for a
+       __u64 unverified_errors;        /* # of occurences where a read for a
                                         * full (64k) bio failed, but the re-
                                         * check succeeded for each 4k piece.
                                         * Intermittent error. */
@@ -837,6 +837,8 @@ enum btrfs_err_code {
                                   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
                                   struct btrfs_ioctl_vol_args)
+#define BTRFS_IOC_FORGET_DEV _IOW(BTRFS_IOCTL_MAGIC, 5, \
+                                  struct btrfs_ioctl_vol_args)
 /* trans start and trans end are dangerous, and only for
  * use by applications that know how to avoid the
  * resulting deadlocks
index 0d933ba3a12ef3206b764785fb18af3ce7cfb038..421239b98db2c79e9a9e3fe57c5013716af43603 100644 (file)
@@ -54,7 +54,7 @@
 /* for storing balance parameters in the root tree */
 #define BTRFS_BALANCE_OBJECTID -4ULL
 
-/* orphan objectid for tracking unlinked/truncated files */
+/* orhpan objectid for tracking unlinked/truncated files */
 #define BTRFS_ORPHAN_OBJECTID -5ULL
 
 /* does write ahead logging to speed up fsyncs */
 #define BTRFS_PERSISTENT_ITEM_KEY      249
 
 /*
- * Persistently stores the device replace state in the device tree.
+ * Persistantly stores the device replace state in the device tree.
  * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0).
  */
 #define BTRFS_DEV_REPLACE_KEY  250
  *
  * Used by:
  * struct btrfs_dir_item.type
+ *
+ * Values 0..7 must match common file type values in fs_types.h.
  */
 #define BTRFS_FT_UNKNOWN       0
 #define BTRFS_FT_REG_FILE      1
index f2ea833a2812561d7b10517a39e695589e8b236b..87c2c9f0880304e20202350ea164b9293e085d50 100644 (file)
@@ -16,6 +16,12 @@ enum {
        FOU_ATTR_IPPROTO,                       /* u8 */
        FOU_ATTR_TYPE,                          /* u8 */
        FOU_ATTR_REMCSUM_NOPARTIAL,             /* flag */
+       FOU_ATTR_LOCAL_V4,                      /* u32 */
+       FOU_ATTR_LOCAL_V6,                      /* in6_addr */
+       FOU_ATTR_PEER_V4,                       /* u32 */
+       FOU_ATTR_PEER_V6,                       /* in6_addr */
+       FOU_ATTR_PEER_PORT,                     /* u16 */
+       FOU_ATTR_IFINDEX,                       /* s32 */
 
        __FOU_ATTR_MAX,
 };
index cbabdde8f9da5163391c53d59c4ef67c16f42727..4c6f030afc14e71048aa73da2b6f99c9388d6d47 100644 (file)
@@ -179,7 +179,7 @@ enum {
 };
 
 /*
- *     Device mapping structure. I'd just gone off and designed a
+ *     Device mapping structure. I'd just gone off and designed a 
  *     beautiful scheme using only loadable modules with arguments
  *     for driver options and along come the PCMCIA people 8)
  *
@@ -193,7 +193,7 @@ enum {
 struct ifmap {
        unsigned long mem_start;
        unsigned long mem_end;
-       unsigned short base_addr;
+       unsigned short base_addr; 
        unsigned char irq;
        unsigned char dma;
        unsigned char port;
@@ -233,7 +233,7 @@ struct ifreq {
        {
                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
        } ifr_ifrn;
-
+       
        union {
                struct  sockaddr ifru_addr;
                struct  sockaddr ifru_dstaddr;
index 61a1bf6e865e8b41aa1f5bd8ce188f513f58e143..790585f0e61b5b252a03bd558694dc4c8921246b 100644 (file)
@@ -117,6 +117,30 @@ struct ad_info {
        __u8 partner_system[ETH_ALEN];
 };
 
+/* Embedded inside LINK_XSTATS_TYPE_BOND */
+enum {
+       BOND_XSTATS_UNSPEC,
+       BOND_XSTATS_3AD,
+       __BOND_XSTATS_MAX
+};
+#define BOND_XSTATS_MAX (__BOND_XSTATS_MAX - 1)
+
+/* Embedded inside BOND_XSTATS_3AD */
+enum {
+       BOND_3AD_STAT_LACPDU_RX,
+       BOND_3AD_STAT_LACPDU_TX,
+       BOND_3AD_STAT_LACPDU_UNKNOWN_RX,
+       BOND_3AD_STAT_LACPDU_ILLEGAL_RX,
+       BOND_3AD_STAT_MARKER_RX,
+       BOND_3AD_STAT_MARKER_TX,
+       BOND_3AD_STAT_MARKER_RESP_RX,
+       BOND_3AD_STAT_MARKER_RESP_TX,
+       BOND_3AD_STAT_MARKER_UNKNOWN_RX,
+       BOND_3AD_STAT_PAD,
+       __BOND_3AD_STAT_MAX
+};
+#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1)
+
 #endif /* _LINUX_IF_BONDING_H */
 
 /*
index 3a45b4ad71a3083a16085d69e2891e31dddcdaa8..3158ba672b72ba24b97a5e7f341389c629202c11 100644 (file)
 #define ETH_P_QINQ2    0x9200          /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ3    0x9300          /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_EDSA     0xDADA          /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DSA_8021Q        0xDADB          /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IFE      0xED3E          /* ForCES inter-FE LFB type */
 #define ETH_P_AF_IUCV   0xFBFB         /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
 
index d6533828123a6728958d2127ab81c2b5fa30f07f..5b225ff63b483145878e977cf0a1be7d1fe53cd9 100644 (file)
@@ -925,6 +925,7 @@ enum {
 enum {
        LINK_XSTATS_TYPE_UNSPEC,
        LINK_XSTATS_TYPE_BRIDGE,
+       LINK_XSTATS_TYPE_BOND,
        __LINK_XSTATS_TYPE_MAX
 };
 #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
index 23a6753b37df3a0a241c2986aa932301bef02b1f..454ae31b93c7a4b4aeedddf7ceb5274377b39a58 100644 (file)
@@ -60,6 +60,7 @@
 #define TUNSETSTEERINGEBPF _IOR('T', 224, int)
 #define TUNSETFILTEREBPF _IOR('T', 225, int)
 #define TUNSETCARRIER _IOW('T', 226, int)
+#define TUNGETDEVNETNS _IO('T', 227)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN                0x0001
index a55cb8b10165abcf8a07d8228b590bbc1d8a0c08..e7ad9d350a283d81e89696e1bc42438030accc90 100644 (file)
@@ -292,10 +292,11 @@ struct sockaddr_in {
 #define        IN_LOOPBACK(a)          ((((long int) (a)) & 0xff000000) == 0x7f000000)
 
 /* Defines for Multicast INADDR */
-#define INADDR_UNSPEC_GROUP    0xe0000000U     /* 224.0.0.0   */
-#define INADDR_ALLHOSTS_GROUP  0xe0000001U     /* 224.0.0.1   */
-#define INADDR_ALLRTRS_GROUP    0xe0000002U    /* 224.0.0.2 */
-#define INADDR_MAX_LOCAL_GROUP  0xe00000ffU    /* 224.0.0.255 */
+#define INADDR_UNSPEC_GROUP            0xe0000000U     /* 224.0.0.0   */
+#define INADDR_ALLHOSTS_GROUP          0xe0000001U     /* 224.0.0.1   */
+#define INADDR_ALLRTRS_GROUP           0xe0000002U     /* 224.0.0.2 */
+#define INADDR_ALLSNOOPERS_GROUP       0xe000006aU     /* 224.0.0.106 */
+#define INADDR_MAX_LOCAL_GROUP         0xe00000ffU     /* 224.0.0.255 */
 #endif
 
 /* <asm/byteorder.h> contains the htonl type stuff.. */
index 9fa75591c5662d5b84d08d35dbe595bc052062b5..9f2273a0835642b243a7c10903ac24b79ecb9f99 100644 (file)
@@ -178,13 +178,14 @@ struct in6_flowlabel_req {
 #define IPV6_JOIN_ANYCAST      27
 #define IPV6_LEAVE_ANYCAST     28
 #define IPV6_MULTICAST_ALL     29
+#define IPV6_ROUTER_ALERT_ISOLATE      30
 
 /* IPV6_MTU_DISCOVER values */
 #define IPV6_PMTUDISC_DONT             0
 #define IPV6_PMTUDISC_WANT             1
 #define IPV6_PMTUDISC_DO               2
 #define IPV6_PMTUDISC_PROBE            3
-/* same as IPV6_PMTUDISC_PROBE, provided for symmetry with IPv4
+/* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4
  * also see comments on IP_PMTUDISC_INTERFACE
  */
 #define IPV6_PMTUDISC_INTERFACE                4
diff --git a/src/basic/linux/update.sh b/src/basic/linux/update.sh
new file mode 100755 (executable)
index 0000000..b232070
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -eu
+
+for i in *.h */*.h; do
+    if [[ $i == 'wireguard.h' ]]; then
+        curl https://raw.githubusercontent.com/WireGuard/WireGuard/master/src/uapi/$i -o $i
+    else
+        curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
+    fi
+
+    sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
+done
index ea252c41302fb6fd9d0b29d9853a3c9f9a760f2d..a81c350ab4d3ca1945920b426c4b64aeb9af20f9 100644 (file)
@@ -336,7 +336,7 @@ static int write_to_console(
 
         char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
         struct iovec iovec[6] = {};
-        bool highlight;
+        const char *on = NULL, *off = NULL;
         size_t n = 0;
 
         if (console_fd < 0)
@@ -347,18 +347,19 @@ static int write_to_console(
                 iovec[n++] = IOVEC_MAKE_STRING(prefix);
         }
 
-        highlight = LOG_PRI(level) <= LOG_ERR && show_color;
+        if (show_color)
+                get_log_colors(LOG_PRI(level), &on, &off, NULL);
 
         if (show_location) {
                 (void) snprintf(location, sizeof location, "(%s:%i) ", file, line);
                 iovec[n++] = IOVEC_MAKE_STRING(location);
         }
 
-        if (highlight)
-                iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
+        if (on)
+                iovec[n++] = IOVEC_MAKE_STRING(on);
         iovec[n++] = IOVEC_MAKE_STRING(buffer);
-        if (highlight)
-                iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
+        if (off)
+                iovec[n++] = IOVEC_MAKE_STRING(off);
         iovec[n++] = IOVEC_MAKE_STRING("\n");
 
         if (writev(console_fd, iovec, n) < 0) {
index 1971e912db4f497e676af561733f98286397e4ad..ae8907db04bc719ecd13c16cbe64d2a570c77dc6 100644 (file)
         _Pragma("GCC diagnostic push");                                 \
         _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"")
 
+#if HAVE_WSTRINGOP_TRUNCATION
+#  define DISABLE_WARNING_STRINGOP_TRUNCATION                           \
+        _Pragma("GCC diagnostic push");                                 \
+        _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"")
+#else
+#  define DISABLE_WARNING_STRINGOP_TRUNCATION                           \
+        _Pragma("GCC diagnostic push")
+#endif
+
 #define REENABLE_WARNING                                                \
         _Pragma("GCC diagnostic pop")
 
index 5ac9293167153824722093e9dcb3a38f023e803e..cb8ddccecde63304d55f9bf4b8a040002651977b 100644 (file)
@@ -359,6 +359,7 @@ bool fstype_can_uid_gid(const char *fstype) {
 
         return STR_IN_SET(fstype,
                           "adfs",
+                          "exfat",
                           "fat",
                           "hfs",
                           "hpfs",
index 16700013641ccc47c83c115fc22d0387f3989457..b82ca4b21b2e5131d9e6d8c94eded1431449c55c 100644 (file)
@@ -34,7 +34,7 @@ int proc_cmdline(char **ret) {
         }
 
         if (detect_container() > 0)
-                return get_process_cmdline(1, 0, false, ret);
+                return get_process_cmdline(1, SIZE_MAX, 0, ret);
         else
                 return read_one_line_file("/proc/cmdline", ret);
 }
index 3dc3534e1ab21556b2bc81918345ed93c3876ad5..b50537908cc75362861a665cb4beeaa8c0233847 100644 (file)
 #include "alloc-util.h"
 #include "architecture.h"
 #include "escape.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "ioprio.h"
+#include "locale-util.h"
 #include "log.h"
 #include "macro.h"
 #include "memory-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
 #include "user-util.h"
+#include "utf8.h"
 
-int get_process_state(pid_t pid) {
+/* The kernel limits userspace processes to TASK_COMM_LEN (16 bytes), but allows higher values for its own
+ * workers, e.g. "kworker/u9:3-kcryptd/253:0". Let's pick a fixed smallish limit that will work for the kernel.
+ */
+#define COMM_MAX_LEN 128
+
+static int get_process_state(pid_t pid) {
         const char *p;
         char state;
         int r;
@@ -80,7 +88,7 @@ int get_process_comm(pid_t pid, char **ret) {
         assert(ret);
         assert(pid >= 0);
 
-        escaped = new(char, TASK_COMM_LEN);
+        escaped = new(char, COMM_MAX_LEN);
         if (!escaped)
                 return -ENOMEM;
 
@@ -93,28 +101,31 @@ int get_process_comm(pid_t pid, char **ret) {
                 return r;
 
         /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */
-        cellescape(escaped, TASK_COMM_LEN, comm);
+        cellescape(escaped, COMM_MAX_LEN, comm);
 
         *ret = TAKE_PTR(escaped);
         return 0;
 }
 
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
+int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) {
         _cleanup_fclose_ FILE *f = NULL;
-        bool space = false;
-        char *k;
-        _cleanup_free_ char *ans = NULL;
+        _cleanup_free_ char *t = NULL, *ans = NULL;
         const char *p;
-        int c, r;
+        int r;
+        size_t k;
+
+        /* This is supposed to be a safety guard against runaway command lines. */
+        size_t max_length = sc_arg_max();
 
         assert(line);
         assert(pid >= 0);
 
-        /* Retrieves a process' command line. Replaces unprintable characters while doing so by whitespace (coalescing
-         * multiple sequential ones into one). If max_length is != 0 will return a string of the specified size at most
-         * (the trailing NUL byte does count towards the length here!), abbreviated with a "..." ellipsis. If
-         * comm_fallback is true and the process has no command line set (the case for kernel threads), or has a
-         * command line that resolves to the empty string will return the "comm" name of the process instead.
+        /* Retrieves a process' command line. Replaces non-utf8 bytes by replacement character (�). If
+         * max_columns is != -1 will return a string of the specified console width at most, abbreviated with
+         * an ellipsis. If PROCESS_CMDLINE_COMM_FALLBACK is specified in flags and the process has no command
+         * line set (the case for kernel threads), or has a command line that resolves to the empty string
+         * will return the "comm" name of the process instead. This will use at most _SC_ARG_MAX bytes of
+         * input data.
          *
          * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
          * comm_fallback is false). Returns 0 and sets *line otherwise. */
@@ -126,130 +137,56 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
         if (r < 0)
                 return r;
 
-        if (max_length == 0) {
-                /* This is supposed to be a safety guard against runaway command lines. */
-                long l = sysconf(_SC_ARG_MAX);
-                assert(l > 0);
-                max_length = l;
-        }
-
-        if (max_length == 1) {
+        /* We assume that each four-byte character uses one or two columns. If we ever check for combining
+         * characters, this assumption will need to be adjusted. */
+        if ((size_t) 4 * max_columns + 1 < max_columns)
+                max_length = MIN(max_length, (size_t) 4 * max_columns + 1);
 
-                /* If there's only room for one byte, return the empty string */
-                ans = new0(char, 1);
-                if (!ans)
-                        return -ENOMEM;
+        t = new(char, max_length);
+        if (!t)
+                return -ENOMEM;
 
-                *line = TAKE_PTR(ans);
-                return 0;
+        k = fread(t, 1, max_length, f);
+        if (k > 0) {
+                /* Arguments are separated by NULs. Let's replace those with spaces. */
+                for (size_t i = 0; i < k - 1; i++)
+                        if (t[i] == '\0')
+                                t[i] = ' ';
 
+                t[k] = '\0'; /* Normally, t[k] is already NUL, so this is just a guard in case of short read */
         } else {
-                bool dotdotdot = false;
-                size_t left;
-
-                ans = new(char, max_length);
-                if (!ans)
-                        return -ENOMEM;
-
-                k = ans;
-                left = max_length;
-                while ((c = getc(f)) != EOF) {
-
-                        if (isprint(c)) {
-
-                                if (space) {
-                                        if (left <= 2) {
-                                                dotdotdot = true;
-                                                break;
-                                        }
-
-                                        *(k++) = ' ';
-                                        left--;
-                                        space = false;
-                                }
-
-                                if (left <= 1) {
-                                        dotdotdot = true;
-                                        break;
-                                }
-
-                                *(k++) = (char) c;
-                                left--;
-                        } else if (k > ans)
-                                space = true;
-                }
-
-                if (dotdotdot) {
-                        if (max_length <= 4) {
-                                k = ans;
-                                left = max_length;
-                        } else {
-                                k = ans + max_length - 4;
-                                left = 4;
-
-                                /* Eat up final spaces */
-                                while (k > ans && isspace(k[-1])) {
-                                        k--;
-                                        left++;
-                                }
-                        }
-
-                        strncpy(k, "...", left-1);
-                        k[left-1] = 0;
-                } else
-                        *k = 0;
-        }
-
-        /* Kernel threads have no argv[] */
-        if (isempty(ans)) {
-                _cleanup_free_ char *t = NULL;
-                int h;
-
-                ans = mfree(ans);
+                /* We only treat getting nothing as an error. We *could* also get an error after reading some
+                 * data, but we ignore that case, as such an error is rather unlikely and we prefer to get
+                 * some data rather than none. */
+                if (ferror(f))
+                        return -errno;
 
-                if (!comm_fallback)
+                if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK))
                         return -ENOENT;
 
-                h = get_process_comm(pid, &t);
-                if (h < 0)
-                        return h;
-
-                size_t l = strlen(t);
-
-                if (l + 3 <= max_length) {
-                        ans = strjoin("[", t, "]");
-                        if (!ans)
-                                return -ENOMEM;
-
-                } else if (max_length <= 6) {
-                        ans = new(char, max_length);
-                        if (!ans)
-                                return -ENOMEM;
+                /* Kernel threads have no argv[] */
+                _cleanup_free_ char *t2 = NULL;
 
-                        memcpy(ans, "[...]", max_length-1);
-                        ans[max_length-1] = 0;
-                } else {
-                        t[max_length - 6] = 0;
+                r = get_process_comm(pid, &t2);
+                if (r < 0)
+                        return r;
 
-                        /* Chop off final spaces */
-                        delete_trailing_chars(t, WHITESPACE);
+                mfree(t);
+                t = strjoin("[", t2, "]");
+                if (!t)
+                        return -ENOMEM;
+        }
 
-                        ans = strjoin("[", t, "...]");
-                        if (!ans)
-                                return -ENOMEM;
-                }
+        delete_trailing_chars(t, WHITESPACE);
 
-                *line = TAKE_PTR(ans);
-                return 0;
-        }
+        bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8();
 
-        k = realloc(ans, strlen(ans) + 1);
-        if (!k)
+        ans = escape_non_printable_full(t, max_columns, eight_bit);
+        if (!ans)
                 return -ENOMEM;
 
-        ans = NULL;
-        *line = k;
-
+        (void) str_realloc(&ans);
+        *line = TAKE_PTR(ans);
         return 0;
 }
 
@@ -281,7 +218,7 @@ int rename_process(const char name[]) {
          * can use PR_SET_NAME, which sets the thread name for the calling thread. */
         if (prctl(PR_SET_NAME, name) < 0)
                 log_debug_errno(errno, "PR_SET_NAME failed: %m");
-        if (l >= TASK_COMM_LEN) /* Linux process names can be 15 chars at max */
+        if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
                 truncated = true;
 
         /* Second step, change glibc's ID of the process name. */
index 7e1d65a7bf1b3c52c9b7c8d3e982d72be127308d..2e3bd7250545406d818635ecfd6ca290ed16c173 100644 (file)
                 _r_;                                                    \
         })
 
-int get_process_state(pid_t pid);
+typedef enum ProcessCmdlineFlags {
+        PROCESS_CMDLINE_COMM_FALLBACK = 1 << 0,
+        PROCESS_CMDLINE_USE_LOCALE    = 1 << 1,
+} ProcessCmdlineFlags;
+
 int get_process_comm(pid_t pid, char **name);
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
+int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line);
 int get_process_exe(pid_t pid, char **name);
 int get_process_uid(pid_t pid, uid_t *uid);
 int get_process_gid(pid_t pid, gid_t *gid);
index ca25fd2420c4de14d1c47e43eebe06b3889cd1d5..3af6f271f0e38eba268378052ee965c5828778d4 100644 (file)
 #include "io-util.h"
 #include "missing.h"
 #include "random-util.h"
+#include "siphash24.h"
 #include "time-util.h"
 
 int rdrand(unsigned long *ret) {
 
+        /* So, you are a "security researcher", and you wonder why we bother with using raw RDRAND here,
+         * instead of sticking to /dev/urandom or getrandom()?
+         *
+         * Here's why: early boot. On Linux, during early boot the random pool that backs /dev/urandom and
+         * getrandom() is generally not initialized yet. It is very common that initialization of the random
+         * pool takes a longer time (up to many minutes), in particular on embedded devices that have no
+         * explicit hardware random generator, as well as in virtualized environments such as major cloud
+         * installations that do not provide virtio-rng or a similar mechanism.
+         *
+         * In such an environment using getrandom() synchronously means we'd block the entire system boot-up
+         * until the pool is initialized, i.e. *very* long. Using getrandom() asynchronously (GRND_NONBLOCK)
+         * would mean acquiring randomness during early boot would simply fail. Using /dev/urandom would mean
+         * generating many kmsg log messages about our use of it before the random pool is properly
+         * initialized. Neither of these outcomes is desirable.
+         *
+         * Thus, for very specific purposes we use RDRAND instead of either of these three options. RDRAND
+         * provides us quickly and relatively reliably with random values, without having to delay boot,
+         * without triggering warning messages in kmsg.
+         *
+         * Note that we use RDRAND only under very specific circumstances, when the requirements on the
+         * quality of the returned entropy permit it. Specifically, here are some cases where we *do* use
+         * RDRAND:
+         *
+         *         • UUID generation: UUIDs are supposed to be universally unique but are not cryptographic
+         *           key material. The quality and trust level of RDRAND should hence be OK: UUIDs should be
+         *           generated in a way that is reliably unique, but they do not require ultimate trust into
+         *           the entropy generator. systemd generates a number of UUIDs during early boot, including
+         *           'invocation IDs' for every unit spawned that identify the specific invocation of the
+         *           service globally, and a number of others. Other alternatives for generating these UUIDs
+         *           have been considered, but don't really work: for example, hashing uuids from a local
+         *           system identifier combined with a counter falls flat because during early boot disk
+         *           storage is not yet available (think: initrd) and thus a system-specific ID cannot be
+         *           stored or retrieved yet.
+         *
+         *         • Hash table seed generation: systemd uses many hash tables internally. Hash tables are
+         *           generally assumed to have O(1) access complexity, but can deteriorate to prohibitive
+         *           O(n) access complexity if an attacker manages to trigger a large number of hash
+         *           collisions. Thus, systemd (as any software employing hash tables should) uses seeded
+         *           hash functions for its hash tables, with a seed generated randomly. The hash tables
+         *           systemd employs watch the fill level closely and reseed if necessary. This allows use of
+         *           a low quality RNG initially, as long as it improves should a hash table be under attack:
+         *           the attacker after all needs to to trigger many collisions to exploit it for the purpose
+         *           of DoS, but if doing so improves the seed the attack surface is reduced as the attack
+         *           takes place.
+         *
+         * Some cases where we do NOT use RDRAND are:
+         *
+         *         • Generation of cryptographic key material 🔑
+         *
+         *         • Generation of cryptographic salt values 🧂
+         *
+         * This function returns:
+         *
+         *         -EOPNOTSUPP → RDRAND is not available on this system 😔
+         *         -EAGAIN     → The operation failed this time, but is likely to work if you try again a few
+         *                       times ♻
+         *         -EUCLEAN    → We got some random value, but it looked strange, so we refused using it.
+         *                       This failure might or might not be temporary. 😕
+         */
+
 #if defined(__i386__) || defined(__x86_64__)
         static int have_rdrand = -1;
-        unsigned char err;
+        unsigned long v;
+        uint8_t success;
 
         if (have_rdrand < 0) {
                 uint32_t eax, ebx, ecx, edx;
@@ -45,7 +107,12 @@ int rdrand(unsigned long *ret) {
                         return -EOPNOTSUPP;
                 }
 
-                have_rdrand = !!(ecx & (1U << 30));
+/* Compat with old gcc where bit_RDRND didn't exist yet */
+#ifndef bit_RDRND
+#define bit_RDRND (1U << 30)
+#endif
+
+                have_rdrand = !!(ecx & bit_RDRND);
         }
 
         if (have_rdrand == 0)
@@ -53,12 +120,24 @@ int rdrand(unsigned long *ret) {
 
         asm volatile("rdrand %0;"
                      "setc %1"
-                     : "=r" (*ret),
-                       "=qm" (err));
-        msan_unpoison(&err, sizeof(err));
-        if (!err)
+                     : "=r" (v),
+                       "=qm" (success));
+        msan_unpoison(&success, sizeof(success));
+        if (!success)
                 return -EAGAIN;
 
+        /* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success
+         * via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be
+         * a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking
+         * for this special value (and also 0, just to be sure) and filtering it out. This is a work-around
+         * only however and something AMD really should fix properly. The Linux kernel should probably work
+         * around this issue by turning off RDRAND altogether on those CPUs. See:
+         * https://github.com/systemd/systemd/issues/11810 */
+        if (v == 0 || v == ULONG_MAX)
+                return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
+                                       "RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v);
+
+        *ret = v;
         return 0;
 #else
         return -EOPNOTSUPP;
@@ -71,21 +150,32 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
         bool got_some = false;
         int r;
 
-        /* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't
-         * block, unless the RANDOM_BLOCK flag is set. If RANDOM_DONT_DRAIN is set, an error is returned if the random
-         * pool is not initialized. Otherwise it will always return some data from the kernel, regardless of whether
-         * the random pool is fully initialized or not. */
+        /* Gathers some high-quality randomness from the kernel (or potentially mid-quality randomness from
+         * the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't block, unless the RANDOM_BLOCK
+         * flag is set. If RANDOM_MAY_FAIL is set, an error is returned if the random pool is not
+         * initialized. Otherwise it will always return some data from the kernel, regardless of whether the
+         * random pool is fully initialized or not. If RANDOM_EXTEND_WITH_PSEUDO is set, and some but not
+         * enough better quality randomness could be acquired, the rest is filled up with low quality
+         * randomness.
+         *
+         * Of course, when creating cryptographic key material you really shouldn't use RANDOM_ALLOW_DRDRAND
+         * or even RANDOM_EXTEND_WITH_PSEUDO.
+         *
+         * When generating UUIDs it's fine to use RANDOM_ALLOW_RDRAND but not OK to use
+         * RANDOM_EXTEND_WITH_PSEUDO. In fact RANDOM_EXTEND_WITH_PSEUDO is only really fine when invoked via
+         * an "all bets are off" wrapper, such as random_bytes(), see below. */
 
         if (n == 0)
                 return 0;
 
         if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND))
-                /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is not
-                 * required, as we don't trust it (who does?). Note that we only do a single iteration of RDRAND here,
-                 * even though the Intel docs suggest calling this in a tight loop of 10 invocations or so. That's
-                 * because we don't really care about the quality here. We generally prefer using RDRAND if the caller
-                 * allows us too, since this way we won't drain the kernel randomness pool if we don't need it, as the
-                 * pool's entropy is scarce. */
+                /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
+                 * not required, as we don't trust it (who does?). Note that we only do a single iteration of
+                 * RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
+                 * invocations or so. That's because we don't really care about the quality here. We
+                 * generally prefer using RDRAND if the caller allows us to, since this way we won't upset
+                 * the kernel's random subsystem by accessing it before the pool is initialized (after all it
+                 * will kmsg log about every attempt to do so)..*/
                 for (;;) {
                         unsigned long u;
                         size_t m;
@@ -153,12 +243,13 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
                                 break;
 
                         } else if (errno == EAGAIN) {
-                                /* The kernel has no entropy whatsoever. Let's remember to use the syscall the next
-                                 * time again though.
+                                /* The kernel has no entropy whatsoever. Let's remember to use the syscall
+                                 * the next time again though.
                                  *
-                                 * If RANDOM_DONT_DRAIN is set, return an error so that random_bytes() can produce some
-                                 * pseudo-random bytes instead. Otherwise, fall back to /dev/urandom, which we know is empty,
-                                 * but the kernel will produce some bytes for us on a best-effort basis. */
+                                 * If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can
+                                 * produce some pseudo-random bytes instead. Otherwise, fall back to
+                                 * /dev/urandom, which we know is empty, but the kernel will produce some
+                                 * bytes for us on a best-effort basis. */
                                 have_syscall = true;
 
                                 if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
@@ -167,7 +258,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
                                         return 0;
                                 }
 
-                                if (FLAGS_SET(flags, RANDOM_DONT_DRAIN))
+                                if (FLAGS_SET(flags, RANDOM_MAY_FAIL))
                                         return -ENODATA;
 
                                 /* Use /dev/urandom instead */
@@ -196,14 +287,19 @@ void initialize_srand(void) {
                 return;
 
 #if HAVE_SYS_AUXV_H
-        /* The kernel provides us with 16 bytes of entropy in auxv, so let's
-         * try to make use of that to seed the pseudo-random generator. It's
-         * better than nothing... */
+        /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed
+         * the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder
+         * to recover the original value by watching any pseudo-random bits we generate. After all the
+         * AT_RANDOM data might be used by other stuff too (in particular: ASLR), and we probably shouldn't
+         * leak the seed for that. */
 
-        auxv = (const void*) getauxval(AT_RANDOM);
+        auxv = ULONG_TO_PTR(getauxval(AT_RANDOM));
         if (auxv) {
-                assert_cc(sizeof(x) <= 16);
-                memcpy(&x, auxv, sizeof(x));
+                static const uint8_t auxval_hash_key[16] = {
+                        0x92, 0x6e, 0xfe, 0x1b, 0xcf, 0x00, 0x52, 0x9c, 0xcc, 0x42, 0xcf, 0xdc, 0x94, 0x1f, 0x81, 0x0f
+                };
+
+                x = (unsigned) siphash24(auxv, 16, auxval_hash_key);
         } else
 #endif
                 x = 0;
@@ -229,6 +325,11 @@ void initialize_srand(void) {
 void pseudo_random_bytes(void *p, size_t n) {
         uint8_t *q;
 
+        /* This returns pseudo-random data using libc's rand() function. You probably never want to call this
+         * directly, because why would you use this if you can get better stuff cheaply? Use random_bytes()
+         * instead, see below: it will fall back to this function if there's nothing better to get, but only
+         * then. */
+
         initialize_srand();
 
         for (q = p; q < (uint8_t*) p + n; q += RAND_STEP) {
@@ -250,7 +351,39 @@ void pseudo_random_bytes(void *p, size_t n) {
 
 void random_bytes(void *p, size_t n) {
 
-        if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN|RANDOM_ALLOW_RDRAND) >= 0)
+        /* This returns high quality randomness if we can get it cheaply. If we can't because for some reason
+         * it is not available we'll try some crappy fallbacks.
+         *
+         * What this function will do:
+         *
+         *         • This function will preferably use the CPU's RDRAND operation, if it is available, in
+         *           order to return "mid-quality" random values cheaply.
+         *
+         *         • Use getrandom() with GRND_NONBLOCK, to return high-quality random values if they are
+         *           cheaply available.
+         *
+         *         • This function will return pseudo-random data, generated via libc rand() if nothing
+         *           better is available.
+         *
+         *         • This function will work fine in early boot
+         *
+         *         • This function will always succeed
+         *
+         * What this function won't do:
+         *
+         *         • This function will never fail: it will give you randomness no matter what. It might not
+         *           be high quality, but it will return some, possibly generated via libc's rand() call.
+         *
+         *         • This function will never block: if the only way to get good randomness is a blocking,
+         *           synchronous getrandom() we'll instead provide you with pseudo-random data.
+         *
+         * This function is hence great for things like seeding hash tables, generating random numeric UNIX
+         * user IDs (that are checked for collisions before use) and such.
+         *
+         * This function is hence not useful for generating UUIDs or cryptographic key material.
+         */
+
+        if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
                 return;
 
         /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
index 3e8c288d3d00f38c077bb205b6218d93f33cecb6..148b6c7813ddd7ae845917f6f8dc9dc95ec50605 100644 (file)
@@ -8,11 +8,11 @@
 typedef enum RandomFlags {
         RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */
         RANDOM_BLOCK              = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
-        RANDOM_DONT_DRAIN         = 1 << 2, /* If we can't get any randomness at all, return early with -EAGAIN */
+        RANDOM_MAY_FAIL           = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
         RANDOM_ALLOW_RDRAND       = 1 << 3, /* Allow usage of the CPU RNG */
 } RandomFlags;
 
-int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled upwith pseudo random, if not enough is available */
+int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
 void pseudo_random_bytes(void *p, size_t n);                    /* returns only pseudo-randommess (but possibly seeded from something better) */
 void random_bytes(void *p, size_t n);                           /* returns genuine randomness if cheaply available, and pseudo randomness if not. */
 
index acc0f88cd24a6918e369db701717b5c8db86d18e..b751933c83b4c9974d807d9059a19b9278b3a813 100644 (file)
@@ -33,8 +33,8 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
 
         assert(fd >= 0);
 
-        /* This returns the first error we run into, but nevertheless
-         * tries to go on. This closes the passed fd. */
+        /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed
+         * fd, in all cases, including on failure.. */
 
         if (!(flags & REMOVE_PHYSICAL)) {
 
@@ -85,7 +85,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
                         is_dir = de->d_type == DT_DIR;
 
                 if (is_dir) {
-                        int subdir_fd;
+                        _cleanup_close_ int subdir_fd = -1;
 
                         /* if root_dev is set, remove subdirectories only if device is same */
                         if (root_dev && st.st_dev != root_dev->st_dev)
@@ -104,13 +104,10 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
                                 if (ret == 0 && r != -ENOENT)
                                         ret = r;
 
-                                safe_close(subdir_fd);
                                 continue;
                         }
-                        if (r) {
-                                safe_close(subdir_fd);
+                        if (r > 0)
                                 continue;
-                        }
 
                         if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
 
@@ -122,24 +119,18 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
                                                 if (ret == 0)
                                                         ret = r;
 
-                                                safe_close(subdir_fd);
                                                 continue;
                                         }
 
-                                        /* ENOTTY, then it wasn't a
-                                         * btrfs subvolume, continue
-                                         * below. */
-                                } else {
+                                        /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */
+                                } else
                                         /* It was a subvolume, continue. */
-                                        safe_close(subdir_fd);
                                         continue;
-                                }
                         }
 
-                        /* We pass REMOVE_PHYSICAL here, to avoid
-                         * doing the fstatfs() to check the file
+                        /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file
                          * system type again for each directory */
-                        r = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev);
+                        r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
                         if (r < 0 && ret == 0)
                                 ret = r;
 
index 6920fd99ba5d4ac27a67eae8ebeb607777e42a38..36ec422f2c09103d458e7fc6d1f09fe5425b66f6 100644 (file)
@@ -9,6 +9,7 @@
 #include <netinet/in.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
index b23f4c834140978b0e6f953721cf72917ebad5a4..47b17c9d3e7c07f30ff3687ab8a27580c0973b1c 100644 (file)
@@ -212,6 +212,12 @@ static inline size_t strlen_ptr(const char *s) {
         return strlen(s);
 }
 
+DISABLE_WARNING_STRINGOP_TRUNCATION;
+static inline void strncpy_exact(char *buf, const char *src, size_t buf_len) {
+        strncpy(buf, src, buf_len);
+}
+REENABLE_WARNING;
+
 /* Like startswith(), but operates on arbitrary memory blocks */
 static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
         size_t n;
@@ -251,3 +257,16 @@ static inline void *memory_startswith_no_case(const void *p, size_t sz, const ch
 
         return (uint8_t*) p + n;
 }
+
+static inline char* str_realloc(char **p) {
+        /* Reallocate *p to actual size */
+
+        if (!*p)
+                return NULL;
+
+        char *t = realloc(*p, strlen(*p) + 1);
+        if (!t)
+                return NULL;
+
+        return (*p = t);
+}
index a2ea3212431549cad1dfc03fe9b8602a3072ffbc..71238ac9c43579079f9182be18f62f1e97c47513 100644 (file)
@@ -1249,12 +1249,36 @@ int vt_default_utf8(void) {
         return parse_boolean(b);
 }
 
+int vt_verify_kbmode(int fd) {
+        int curr_mode;
+
+        /*
+         * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
+         * Otherwise we would (likely) interfere with X11's processing of the
+         * key events.
+         *
+         * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
+         */
+
+        if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
+                return -errno;
+
+        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
+}
+
 int vt_reset_keyboard(int fd) {
-        int kb;
+        int kb, r;
 
         /* If we can't read the default, then default to unicode. It's 2017 after all. */
         kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE;
 
+        r = vt_verify_kbmode(fd);
+        if (r == -EBUSY) {
+                log_debug_errno(r, "Keyboard is not in XLATE or UNICODE mode, not resetting: %m");
+                return 0;
+        } else if (r < 0)
+                return r;
+
         if (ioctl(fd, KDSKBMODE, kb) < 0)
                 return -errno;
 
@@ -1310,3 +1334,41 @@ int vt_release(int fd, bool restore) {
 
         return 0;
 }
+
+void get_log_colors(int priority, const char **on, const char **off, const char **highlight) {
+        /* Note that this will initialize output variables only when there's something to output.
+         * The caller must pre-initalize to "" or NULL as appropriate. */
+
+        if (priority <= LOG_ERR) {
+                if (on)
+                        *on = ANSI_HIGHLIGHT_RED;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT;
+
+        } else if (priority <= LOG_WARNING) {
+                if (on)
+                        *on = ANSI_HIGHLIGHT_YELLOW;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT;
+
+        } else if (priority <= LOG_NOTICE) {
+                if (on)
+                        *on = ANSI_HIGHLIGHT;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT_RED;
+
+        } else if (priority >= LOG_DEBUG) {
+                if (on)
+                        *on = ANSI_GREY;
+                if (off)
+                        *off = ANSI_NORMAL;
+                if (highlight)
+                        *highlight = ANSI_HIGHLIGHT_RED;
+        }
+}
index c885e0a2d1a014dea069f46cf5e5e1d1537999e4..90adc14d176fcf2ec805e96a7661da59a28e9e40 100644 (file)
@@ -4,41 +4,35 @@
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <syslog.h>
 #include <sys/types.h>
 
 #include "macro.h"
 #include "time-util.h"
 
 /* Regular colors */
-#define ANSI_BLACK   "\x1B[0;30m"
 #define ANSI_RED     "\x1B[0;31m"
 #define ANSI_GREEN   "\x1B[0;32m"
 #define ANSI_YELLOW  "\x1B[0;33m"
 #define ANSI_BLUE    "\x1B[0;34m"
 #define ANSI_MAGENTA "\x1B[0;35m"
-#define ANSI_CYAN    "\x1B[0;36m"
-#define ANSI_WHITE   "\x1B[0;37m"
-#define ANSI_GREY    "\x1B[0;2;37m"
+#define ANSI_GREY    "\x1B[0;38;5;245m"
 
 /* Bold/highlighted */
-#define ANSI_HIGHLIGHT_BLACK   "\x1B[0;1;30m"
 #define ANSI_HIGHLIGHT_RED     "\x1B[0;1;31m"
 #define ANSI_HIGHLIGHT_GREEN   "\x1B[0;1;32m"
-#define ANSI_HIGHLIGHT_YELLOW  "\x1B[0;1;33m"
+#define ANSI_HIGHLIGHT_YELLOW  "\x1B[0;1;38;5;185m"
 #define ANSI_HIGHLIGHT_BLUE    "\x1B[0;1;34m"
 #define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
-#define ANSI_HIGHLIGHT_CYAN    "\x1B[0;1;36m"
-#define ANSI_HIGHLIGHT_WHITE   "\x1B[0;1;37m"
+#define ANSI_HIGHLIGHT_GREY    "\x1B[0;1;38;5;245m"
 
 /* Underlined */
-#define ANSI_HIGHLIGHT_BLACK_UNDERLINE   "\x1B[0;1;4;30m"
 #define ANSI_HIGHLIGHT_RED_UNDERLINE     "\x1B[0;1;4;31m"
 #define ANSI_HIGHLIGHT_GREEN_UNDERLINE   "\x1B[0;1;4;32m"
 #define ANSI_HIGHLIGHT_YELLOW_UNDERLINE  "\x1B[0;1;4;33m"
 #define ANSI_HIGHLIGHT_BLUE_UNDERLINE    "\x1B[0;1;4;34m"
 #define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
-#define ANSI_HIGHLIGHT_CYAN_UNDERLINE    "\x1B[0;1;4;36m"
-#define ANSI_HIGHLIGHT_WHITE_UNDERLINE   "\x1B[0;1;4;37m"
+#define ANSI_HIGHLIGHT_GREY_UNDERLINE    "\x1B[0;1;4;38;5;245m"
 
 /* Other ANSI codes */
 #define ANSI_UNDERLINE "\x1B[0;4m"
@@ -126,21 +120,29 @@ bool dev_console_colors_enabled(void);
                         colors_enabled() ? ANSI_##REPLACEMENT : "";     \
         }
 
-DEFINE_ANSI_FUNC(highlight,                  HIGHLIGHT);
-DEFINE_ANSI_FUNC(highlight_red,              HIGHLIGHT_RED);
-DEFINE_ANSI_FUNC(highlight_green,            HIGHLIGHT_GREEN);
-DEFINE_ANSI_FUNC(highlight_yellow,           HIGHLIGHT_YELLOW);
-DEFINE_ANSI_FUNC(highlight_blue,             HIGHLIGHT_BLUE);
-DEFINE_ANSI_FUNC(highlight_magenta,          HIGHLIGHT_MAGENTA);
-DEFINE_ANSI_FUNC(normal,                     NORMAL);
-DEFINE_ANSI_FUNC(grey,                       GREY);
-
-DEFINE_ANSI_FUNC_UNDERLINE(underline,                  UNDERLINE, NORMAL);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline,        HIGHLIGHT_UNDERLINE, HIGHLIGHT);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline,    HIGHLIGHT_RED_UNDERLINE, HIGHLIGHT_RED);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline,  HIGHLIGHT_GREEN_UNDERLINE, HIGHLIGHT_GREEN);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE, HIGHLIGHT_YELLOW);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline,   HIGHLIGHT_BLUE_UNDERLINE, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(normal,            NORMAL);
+DEFINE_ANSI_FUNC(highlight,         HIGHLIGHT);
+DEFINE_ANSI_FUNC(red,               RED);
+DEFINE_ANSI_FUNC(green,             GREEN);
+DEFINE_ANSI_FUNC(yellow,            YELLOW);
+DEFINE_ANSI_FUNC(blue,              BLUE);
+DEFINE_ANSI_FUNC(magenta,           MAGENTA);
+DEFINE_ANSI_FUNC(grey,              GREY);
+DEFINE_ANSI_FUNC(highlight_red,     HIGHLIGHT_RED);
+DEFINE_ANSI_FUNC(highlight_green,   HIGHLIGHT_GREEN);
+DEFINE_ANSI_FUNC(highlight_yellow,  HIGHLIGHT_YELLOW);
+DEFINE_ANSI_FUNC(highlight_blue,    HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
+DEFINE_ANSI_FUNC(highlight_grey,    HIGHLIGHT_GREY);
+
+DEFINE_ANSI_FUNC_UNDERLINE(underline,                   UNDERLINE, NORMAL);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline,         HIGHLIGHT_UNDERLINE, HIGHLIGHT);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline,     HIGHLIGHT_RED_UNDERLINE, HIGHLIGHT_RED);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline,   HIGHLIGHT_GREEN_UNDERLINE, HIGHLIGHT_GREEN);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_yellow_underline,  HIGHLIGHT_YELLOW_UNDERLINE, HIGHLIGHT_YELLOW);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline,    HIGHLIGHT_BLUE_UNDERLINE, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_magenta_underline, HIGHLIGHT_MAGENTA_UNDERLINE, HIGHLIGHT_MAGENTA);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_grey_underline,    HIGHLIGHT_GREY_UNDERLINE, HIGHLIGHT_GREY);
 
 int get_ctty_devnr(pid_t pid, dev_t *d);
 int get_ctty(pid_t, dev_t *_devnr, char **r);
@@ -155,6 +157,9 @@ int openpt_in_namespace(pid_t pid, int flags);
 int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
 
 int vt_default_utf8(void);
+int vt_verify_kbmode(int fd);
 int vt_reset_keyboard(int fd);
 int vt_restore(int fd);
 int vt_release(int fd, bool restore_vt);
+
+void get_log_colors(int priority, const char **on, const char **off, const char **highlight);
index daf952baa117906b93ddbec87ebe3bb02f6ad729..8ccb4a941a7467a5dac5cf7c2bb5e6cf0cfc1f54 100644 (file)
@@ -575,7 +575,6 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
          */
 
         assert(t);
-        assert(usec);
 
         if (t[0] == '@' && !with_tz)
                 return parse_sec(t + 1, usec);
@@ -803,8 +802,8 @@ finish:
         else
                 return -EINVAL;
 
-        *usec = ret;
-
+        if (usec)
+                *usec = ret;
         return 0;
 }
 
@@ -861,7 +860,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
         if (munmap(shared, sizeof *shared) != 0)
                 return negative_errno();
 
-        if (tmp.return_value == 0)
+        if (tmp.return_value == 0 && usec)
                 *usec = tmp.usec;
 
         return tmp.return_value;
@@ -923,7 +922,6 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
         bool something = false;
 
         assert(t);
-        assert(usec);
         assert(default_unit > 0);
 
         p = t;
@@ -935,7 +933,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
                 if (*s != 0)
                         return -EINVAL;
 
-                *usec = USEC_INFINITY;
+                if (usec)
+                        *usec = USEC_INFINITY;
                 return 0;
         }
 
@@ -1007,8 +1006,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
                 }
         }
 
-        *usec = r;
-
+        if (usec)
+                *usec = r;
         return 0;
 }
 
index e964292eaf4813893ecb0f7937a5514a9dd912be..cad745170ebfb0d0eec652bb54dbfd97f215c2d1 100644 (file)
@@ -8,21 +8,19 @@
 #include "macro.h"
 
 static inline void umaskp(mode_t *u) {
-        umask(*u);
+        umask(*u & 0777);
 }
 
 #define _cleanup_umask_ _cleanup_(umaskp)
 
-struct _umask_struct_ {
-        mode_t mask;
-        bool quit;
-};
+/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although
+ * mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to
+ * distinguish the first and the second iteration of the RUN_WITH_UMASK() loop, so that we can run the first
+ * one, and exit on the second. */
 
-static inline void _reset_umask_(struct _umask_struct_ *s) {
-        umask(s->mask);
-};
+assert_cc((S_IFMT & 0777) == 0);
 
 #define RUN_WITH_UMASK(mask)                                            \
-        for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
-             !_saved_umask_.quit ;                                      \
-             _saved_umask_.quit = true)
+        for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \
+             FLAGS_SET(_saved_umask_, S_IFMT);                          \
+             _saved_umask_ &= 0777)
index 090c69d1400bad8bd43b33ddcd7df536e131a2d3..afc24700dd77a786d8cf9392916dece1b3785c3a 100644 (file)
@@ -32,6 +32,7 @@
 #include "gunicode.h"
 #include "hexdecoct.h"
 #include "macro.h"
+#include "string-util.h"
 #include "utf8.h"
 
 bool unichar_is_valid(char32_t ch) {
@@ -192,46 +193,93 @@ char *utf8_escape_invalid(const char *str) {
         }
 
         *s = '\0';
-
+        (void) str_realloc(&p);
         return p;
 }
 
-char *utf8_escape_non_printable(const char *str) {
-        char *p, *s;
+static int utf8_char_console_width(const char *str) {
+        char32_t c;
+        int r;
+
+        r = utf8_encoded_to_unichar(str, &c);
+        if (r < 0)
+                return r;
+
+        /* TODO: we should detect combining characters */
+
+        return unichar_iswide(c) ? 2 : 1;
+}
+
+char *utf8_escape_non_printable_full(const char *str, size_t console_width) {
+        char *p, *s, *prev_s;
+        size_t n = 0; /* estimated print width */
 
         assert(str);
 
-        p = s = malloc(strlen(str) * 4 + 1);
+        if (console_width == 0)
+                return strdup("");
+
+        p = s = prev_s = malloc(strlen(str) * 4 + 1);
         if (!p)
                 return NULL;
 
-        while (*str) {
+        for (;;) {
                 int len;
+                char *saved_s = s;
+
+                if (!*str) /* done! */
+                        goto finish;
 
                 len = utf8_encoded_valid_unichar(str, (size_t) -1);
                 if (len > 0) {
                         if (utf8_is_printable(str, len)) {
+                                int w;
+
+                                w = utf8_char_console_width(str);
+                                assert(w >= 0);
+                                if (n + w > console_width)
+                                        goto truncation;
+
                                 s = mempcpy(s, str, len);
                                 str += len;
+                                n += w;
+
                         } else {
-                                while (len > 0) {
+                                for (; len > 0; len--) {
+                                        if (n + 4 > console_width)
+                                                goto truncation;
+
                                         *(s++) = '\\';
                                         *(s++) = 'x';
                                         *(s++) = hexchar((int) *str >> 4);
                                         *(s++) = hexchar((int) *str);
 
                                         str += 1;
-                                        len--;
+                                        n += 4;
                                 }
                         }
                 } else {
-                        s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER);
+                        if (n + 1 > console_width)
+                                goto truncation;
+
+                        s = mempcpy(s, UTF8_REPLACEMENT_CHARACTER, strlen(UTF8_REPLACEMENT_CHARACTER));
                         str += 1;
+                        n += 1;
                 }
+
+                prev_s = saved_s;
         }
 
-        *s = '\0';
+ truncation:
+        /* Try to go back one if we don't have enough space for the ellipsis */
+        if (n + 1 >= console_width)
+                s = prev_s;
+
+        s = mempcpy(s, "…", strlen("…"));
 
+ finish:
+        *s = '\0';
+        (void) str_realloc(&p);
         return p;
 }
 
@@ -519,15 +567,15 @@ size_t utf8_console_width(const char *str) {
         /* Returns the approximate width a string will take on screen when printed on a character cell
          * terminal/console. */
 
-        while (*str != 0) {
-                char32_t c;
+        while (*str) {
+                int w;
 
-                if (utf8_encoded_to_unichar(str, &c) < 0)
+                w = utf8_char_console_width(str);
+                if (w < 0)
                         return (size_t) -1;
 
+                n += w;
                 str = utf8_next_char(str);
-
-                n += unichar_iswide(c) ? 2 : 1;
         }
 
         return n;
index 6df70921dbd9050c6292622d8f29ab0be57960ae..62e99b72802d0bae2b2c2bc3457dfabdb5813661 100644 (file)
@@ -22,7 +22,10 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pu
 #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
 
 char *utf8_escape_invalid(const char *s);
-char *utf8_escape_non_printable(const char *str);
+char *utf8_escape_non_printable_full(const char *str, size_t console_width);
+static inline char *utf8_escape_non_printable(const char *str) {
+        return utf8_escape_non_printable_full(str, (size_t) -1);
+}
 
 size_t utf8_encode_unichar(char *out_utf8, char32_t g);
 size_t utf16_encode_unichar(char16_t *out, char32_t c);
index 9df181a10c957860d1b5dbc8b771f168455b61e2..55924adf069cdd0daf10c3d38b62d4e61a9a8e0f 100644 (file)
@@ -326,7 +326,7 @@ static int boot_entry_file_check(const char *root, const char *p) {
 static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) {
         int status = boot_entry_file_check(root, p);
 
-        printf("%13s%s", strempty(field), field ? ":" : " ");
+        printf("%13s%s ", strempty(field), field ? ":" : " ");
         if (status < 0) {
                 errno = -status;
                 printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal());
@@ -997,7 +997,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --esp-path=PATH   Path to the EFI System Partition (ESP)\n"
                "     --boot-path=PATH  Path to the $BOOT partition\n"
                "  -p --print-esp-path  Print path to the EFI System Partition\n"
-               "     --print-boot-path Print path to the $BOOT partition\n"
+               "  -x --print-boot-path Print path to the $BOOT partition\n"
                "     --no-variables    Don't touch EFI variables\n"
                "     --no-pager        Do not pipe output into a pager\n"
                "\nBoot Loader Commands:\n"
@@ -1020,7 +1020,6 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_ESP_PATH = 0x100,
                 ARG_BOOT_PATH,
-                ARG_PRINT_BOOT_PATH,
                 ARG_VERSION,
                 ARG_NO_VARIABLES,
                 ARG_NO_PAGER,
@@ -1034,7 +1033,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "boot-path",       required_argument, NULL, ARG_BOOT_PATH       },
                 { "print-esp-path",  no_argument,       NULL, 'p'                 },
                 { "print-path",      no_argument,       NULL, 'p'                 }, /* Compatibility alias */
-                { "print-boot-path", no_argument,       NULL, ARG_PRINT_BOOT_PATH },
+                { "print-boot-path", no_argument,       NULL, 'x'                 },
                 { "no-variables",    no_argument,       NULL, ARG_NO_VARIABLES    },
                 { "no-pager",        no_argument,       NULL, ARG_NO_PAGER        },
                 {}
@@ -1045,7 +1044,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hp", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hpx", options, NULL)) >= 0)
                 switch (c) {
 
                 case 'h':
@@ -1068,10 +1067,16 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'p':
+                        if (arg_print_dollar_boot_path)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "--print-boot-path/-x cannot be combined with --print-esp-path/-p");
                         arg_print_esp_path = true;
                         break;
 
-                case ARG_PRINT_BOOT_PATH:
+                case 'x':
+                        if (arg_print_esp_path)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "--print-boot-path/-x cannot be combined with --print-esp-path/-p");
                         arg_print_dollar_boot_path = true;
                         break;
 
index 86efc02bd8c32da09721c9d44001c2d8aff9915c..e702f9366a9fa032baafa9ada4332722f3261ca5 100644 (file)
@@ -2508,6 +2508,7 @@ static int busctl_main(int argc, char *argv[]) {
 static int run(int argc, char *argv[]) {
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 09ee0e86a24f6d8a735e27d42bd2213d28726014..adc028bc8e655418b1ea1983ee1d42c554b8a8dc 100644 (file)
@@ -165,6 +165,7 @@ static void show_cg_info(const char *controller, const char *path) {
 static int run(int argc, char *argv[]) {
         int r, output_flags;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index bde58f47a806e93ce6348a122e5671ca031393c1..fff6b505cc36fe3ba6c04284ea95eb96e4ca760d 100644 (file)
@@ -909,6 +909,7 @@ static int run(int argc, char *argv[]) {
         CGroupMask mask;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
@@ -929,7 +930,7 @@ static int run(int argc, char *argv[]) {
         r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root);
         if (r < 0)
                 return log_error_errno(r, "Failed to get root control group path: %m");
-        log_debug("Cgroup path: %s", root);
+        log_debug("CGroup path: %s", root);
 
         a = hashmap_new(&group_hash_ops);
         b = hashmap_new(&group_hash_ops);
index 6cab4b5ee050b6a3aba076ec1fa998b7cdef3bae..042a742fa9b4b7132545adc2858a200da90e3a61 100644 (file)
@@ -2607,7 +2607,7 @@ void unit_add_to_cgroup_empty_queue(Unit *u) {
                 log_debug_errno(r, "Failed to enable cgroup empty event source: %m");
 }
 
-static int unit_check_oom(Unit *u) {
+int unit_check_oom(Unit *u) {
         _cleanup_free_ char *oom_kill = NULL;
         bool increased;
         uint64_t c;
index be8be1b7e7650beea75d16feefa310dfa0a5f1f4..fe347ea11453303ba24b448628295ab7aec848cc 100644 (file)
@@ -197,6 +197,7 @@ int unit_watch_cgroup(Unit *u);
 int unit_watch_cgroup_memory(Unit *u);
 
 void unit_add_to_cgroup_empty_queue(Unit *u);
+int unit_check_oom(Unit *u);
 
 int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path);
 
index c427c3cafe060f15098a5b1de57160c2f7ba6703..d75628c663b6623dfa6eb5773dbed3e0c92d092c 100644 (file)
@@ -348,6 +348,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
         SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
         SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
         SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0),
+        SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0),
         SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
         SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
         SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
@@ -612,6 +613,7 @@ BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_O
 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
 BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
+BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
 BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
 BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale, 1);
 #pragma GCC diagnostic pop
@@ -671,16 +673,16 @@ int bus_cgroup_set_property(
                 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
 
         if (streq(name, "MemoryMin"))
-                return bus_cgroup_set_memory(u, name, &c->memory_min, message, flags, error);
+                return bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, error);
 
         if (streq(name, "MemoryLow"))
-                return bus_cgroup_set_memory(u, name, &c->memory_low, message, flags, error);
+                return bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, error);
 
         if (streq(name, "DefaultMemoryMin"))
-                return bus_cgroup_set_memory(u, name, &c->default_memory_min, message, flags, error);
+                return bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, error);
 
         if (streq(name, "DefaultMemoryLow"))
-                return bus_cgroup_set_memory(u, name, &c->default_memory_low, message, flags, error);
+                return bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, error);
 
         if (streq(name, "MemoryHigh"))
                 return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
@@ -695,16 +697,16 @@ int bus_cgroup_set_property(
                 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
 
         if (streq(name, "MemoryMinScale"))
-                return bus_cgroup_set_memory_scale(u, name, &c->memory_min, message, flags, error);
+                return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, error);
 
         if (streq(name, "MemoryLowScale"))
-                return bus_cgroup_set_memory_scale(u, name, &c->memory_low, message, flags, error);
+                return bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, error);
 
         if (streq(name, "DefaultMemoryMinScale"))
-                return bus_cgroup_set_memory_scale(u, name, &c->default_memory_min, message, flags, error);
+                return bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, error);
 
         if (streq(name, "DefaultMemoryLowScale"))
-                return bus_cgroup_set_memory_scale(u, name, &c->default_memory_low, message, flags, error);
+                return bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, error);
 
         if (streq(name, "MemoryHighScale"))
                 return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
index 83ac7ad1107874df565c4bee528953f2ddafda46..0aadc98c9b59193dc4c6c351b3d3a2a2dddbba80 100644 (file)
@@ -303,8 +303,12 @@ static int bus_socket_set_transient_property(
         if (streq(name, "SocketProtocol"))
                 return bus_set_transient_socket_protocol(u, name, &s->socket_protocol, message, flags, error);
 
-        if ((ci = socket_exec_command_from_string(name)) >= 0)
-                return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
+        ci = socket_exec_command_from_string(name);
+        if (ci >= 0)
+                return bus_set_transient_exec_command(u, name,
+                                                      &s->exec_command[ci],
+                                                      message, flags, error);
+
 
         if (streq(name, "Symlinks")) {
                 _cleanup_strv_free_ char **l = NULL;
index 16b4a6b133267d244db69c8413bcc75d6aabd0a1..a60362fff65c56cc98eef39f89c44af6f5281a54 100644 (file)
@@ -901,7 +901,7 @@ static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *
                 p = buf;
         }
 
-        (void) get_process_cmdline(pid, 0, true, &cmdline);
+        (void) get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &cmdline);
 
         return sd_bus_message_append(reply,
                                      "(sus)",
index a8b6c9287357df41ef9001d8c49aa2cb65eda5ff..e90c3ac4f38942fb9051e1c5a5a1c0ad205b41bd 100644 (file)
@@ -1439,7 +1439,7 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_
         if (skip_seccomp_unavailable(u, "SystemCallFilter="))
                 return 0;
 
-        negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
+        negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno);
 
         if (c->syscall_whitelist) {
                 default_action = negative_action;
@@ -2406,7 +2406,8 @@ static int apply_mount_namespace(
                 const ExecCommand *command,
                 const ExecContext *context,
                 const ExecParameters *params,
-                const ExecRuntime *runtime) {
+                const ExecRuntime *runtime,
+                char **error_path) {
 
         _cleanup_strv_free_ char **empty_directories = NULL;
         char *tmp = NULL, *var = NULL;
@@ -2482,7 +2483,8 @@ static int apply_mount_namespace(
                             needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
                             needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
                             context->mount_flags,
-                            DISSECT_IMAGE_DISCARD_ON_LOOP);
+                            DISSECT_IMAGE_DISCARD_ON_LOOP,
+                            error_path);
 
         bind_mount_free_many(bind_mounts, n_bind_mounts);
 
@@ -3319,10 +3321,13 @@ static int exec_child(
 
         needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
         if (needs_mount_namespace) {
-                r = apply_mount_namespace(unit, command, context, params, runtime);
+                _cleanup_free_ char *error_path = NULL;
+
+                r = apply_mount_namespace(unit, command, context, params, runtime, &error_path);
                 if (r < 0) {
                         *exit_status = EXIT_NAMESPACE;
-                        return log_unit_error_errno(unit, r, "Failed to set up mount namespacing: %m");
+                        return log_unit_error_errno(unit, r, "Failed to set up mount namespacing%s%s: %m",
+                                                    error_path ? ": " : "", strempty(error_path));
                 }
         }
 
index 13e9bbbfb1c1a6f951b829b7502c0176d6308def..b868a367f1ebd299ea6563f355f67c9c58a0d03b 100644 (file)
@@ -172,6 +172,7 @@ $1.CPUQuota,                     config_parse_cpu_quota,             0,
 $1.CPUQuotaPeriodSec,            config_parse_sec_def_infinity,      0,                             offsetof($1, cgroup_context.cpu_quota_period_usec)
 $1.MemoryAccounting,             config_parse_bool,                  0,                             offsetof($1, cgroup_context.memory_accounting)
 $1.MemoryMin,                    config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
+$1.DefaultMemoryMin,             config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
 $1.DefaultMemoryLow,             config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
 $1.MemoryLow,                    config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
 $1.MemoryHigh,                   config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
index bb302fb46b85a442aca1bb3762cbebc25fc1ed7e..11a9a7bdebb62fc6372328b90184c3bef76f5464 100644 (file)
@@ -3137,7 +3137,7 @@ int config_parse_memory_limit(
                         bytes = physical_memory_scale(r, 1000U);
 
                 if (bytes >= UINT64_MAX ||
-                    (bytes <= 0 && !streq(lvalue, "MemorySwapMax"))) {
+                    (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) {
                         log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue);
                         return 0;
                 }
index e34da119846cbcb8a6f07bab14cf1163033be7cc..d65455c6c06cb52c380f9af56f60b88765f8c986 100644 (file)
@@ -1546,6 +1546,11 @@ static int fixup_environment(void) {
         if (setenv("TERM", t, 1) < 0)
                 return -errno;
 
+        /* The kernels sets HOME=/ for init. Let's undo this. */
+        if (path_equal_ptr(getenv("HOME"), "/") &&
+            unsetenv("HOME") < 0)
+                log_warning_errno(errno, "Failed to unset $HOME: %m");
+
         return 0;
 }
 
index b7848648bebfd430ed0c86c161937feff3200e1d..a3dc5bb40ea29d117718e55abe3a6c8aa3ad331e 100644 (file)
@@ -2472,7 +2472,7 @@ static int manager_dispatch_sigchld(sd_event_source *source, void *userdata) {
         assert(source);
         assert(m);
 
-        /* First we call waitd() for a PID and do not reap the zombie. That way we can still access /proc/$PID for it
+        /* First we call waitid() for a PID and do not reap the zombie. That way we can still access /proc/$PID for it
          * while it is a zombie. */
 
         if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
@@ -2524,8 +2524,13 @@ static int manager_dispatch_sigchld(sd_event_source *source, void *userdata) {
                 /* Finally, execute them all. Note that u1, u2 and the array might contain duplicates, but
                  * that's fine, manager_invoke_sigchld_event() will ensure we only invoke the handlers once for
                  * each iteration. */
-                if (u1)
+                if (u1) {
+                        /* We check for oom condition, in case we got SIGCHLD before the oom notification.
+                         * We only do this for the cgroup the PID belonged to. */
+                        (void) unit_check_oom(u1);
+
                         manager_invoke_sigchld_event(m, u1, &si);
+                }
                 if (u2)
                         manager_invoke_sigchld_event(m, u2, &si);
                 if (array_copy)
index 86ab35d818d2c032cae4ff5da646d380d22bbc0f..f1df760a676cc69848e1313c2e793e956304ba45 100644 (file)
@@ -212,10 +212,6 @@ meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir))
 meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir))
 meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir))
 
-meson.add_install_script('sh', '-c',
-                         mkdir_p.format(join_paths(pkgsysconfdir, 'system/multi-user.target.wants')))
-meson.add_install_script('sh', '-c',
-                         mkdir_p.format(join_paths(pkgsysconfdir, 'system/getty.target.wants')))
 meson.add_install_script('sh', '-c',
                          mkdir_p.format(join_paths(pkgsysconfdir, 'user')))
 meson.add_install_script('sh', '-c',
index b7fd35fc678ca206fe46e07d48602fc60f6078e7..e32db2bf630a489b1a9823c40dbfbebbbf9989c8 100644 (file)
@@ -1597,31 +1597,25 @@ static int mount_setup_unit(
 }
 
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
-        _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
-        _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
+        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
         int r;
 
         assert(m);
 
-        t = mnt_new_table();
-        i = mnt_new_iter(MNT_ITER_FORWARD);
-        if (!t || !i)
-                return log_oom();
-
-        r = mnt_table_parse_mtab(t, NULL);
+        r = libmount_parse(NULL, NULL, &table, &iter);
         if (r < 0)
                 return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
         for (;;) {
                 struct libmnt_fs *fs;
                 const char *device, *path, *options, *fstype;
-                int k;
 
-                k = mnt_table_next_fs(t, i, &fs);
-                if (k == 1)
+                r = mnt_table_next_fs(table, iter, &fs);
+                if (r == 1)
                         break;
-                if (k < 0)
-                        return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m");
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
 
                 device = mnt_fs_get_source(fs);
                 path = mnt_fs_get_target(fs);
index 8475145f068b6ca3337cf741b5d5e9b0678436ea..ec7af3ab1c0204bb81dc8d9fdb0a1b6cd702a7cf 100644 (file)
@@ -1187,7 +1187,8 @@ int setup_namespace(
                 ProtectHome protect_home,
                 ProtectSystem protect_system,
                 unsigned long mount_flags,
-                DissectImageFlags dissect_image_flags) {
+                DissectImageFlags dissect_image_flags,
+                char **error_path) {
 
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
@@ -1440,6 +1441,8 @@ int setup_namespace(
                 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
                 if (!proc_self_mountinfo) {
                         r = log_debug_errno(errno, "Failed to open /proc/self/mountinfo: %m");
+                        if (error_path)
+                                *error_path = strdup("/proc/self/mountinfo");
                         goto finish;
                 }
 
@@ -1453,8 +1456,11 @@ int setup_namespace(
                                         continue;
 
                                 r = follow_symlink(root, m);
-                                if (r < 0)
+                                if (r < 0) {
+                                        if (error_path && mount_entry_path(m))
+                                                *error_path = strdup(mount_entry_path(m));
                                         goto finish;
+                                }
                                 if (r == 0) {
                                         /* We hit a symlinked mount point. The entry got rewritten and might point to a
                                          * very different place now. Let's normalize the changed list, and start from
@@ -1465,8 +1471,11 @@ int setup_namespace(
                                 }
 
                                 r = apply_mount(root, m);
-                                if (r < 0)
+                                if (r < 0) {
+                                        if (error_path && mount_entry_path(m))
+                                                *error_path = strdup(mount_entry_path(m));
                                         goto finish;
+                                }
 
                                 m->applied = true;
                         }
@@ -1490,8 +1499,11 @@ int setup_namespace(
                 /* Second round, flip the ro bits if necessary. */
                 for (m = mounts; m < mounts + n_mounts; ++m) {
                         r = make_read_only(m, blacklist, proc_self_mountinfo);
-                        if (r < 0)
+                        if (r < 0) {
+                                if (error_path && mount_entry_path(m))
+                                        *error_path = strdup(mount_entry_path(m));
                                 goto finish;
+                        }
                 }
         }
 
index 022bdb614211a4a2daaa7fe566126c0a5fbbea26..73fcb3fc82a3c5b6e4a8e8536c3c830fb0c7734c 100644 (file)
@@ -86,7 +86,8 @@ int setup_namespace(
                 ProtectHome protect_home,
                 ProtectSystem protect_system,
                 unsigned long mount_flags,
-                DissectImageFlags dissected_image_flags);
+                DissectImageFlags dissected_image_flags,
+                char **error_path);
 
 int setup_tmp_dirs(
                 const char *id,
index c83a748456e11e77709976391de1c4fbe69056a5..f16601a7288acc36353ac766cc85e9aa307a15f8 100644 (file)
@@ -320,10 +320,7 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
                 fs->service->n_fd_store--;
         }
 
-        if (fs->event_source) {
-                sd_event_source_set_enabled(fs->event_source, SD_EVENT_OFF);
-                sd_event_source_unref(fs->event_source);
-        }
+        sd_event_source_disable_unref(fs->event_source);
 
         free(fs->fdname);
         safe_close(fs->fd);
@@ -2050,9 +2047,10 @@ static int service_adverse_to_leftover_processes(Service *s) {
          * aren't as rigoriously written to protect aganst against multiple use. */
         if (unit_warn_leftover_processes(UNIT(s)) &&
             IN_SET(s->kill_context.kill_mode, KILL_MIXED, KILL_CONTROL_GROUP) &&
-            !s->kill_context.send_sigkill) {
-               return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY), "Will not start SendSIGKILL=no service of type KillMode=control-group or mixed while processes exist");
-        }
+            !s->kill_context.send_sigkill)
+               return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY),
+                                           "Will not start SendSIGKILL=no service of type KillMode=control-group or mixed while processes exist");
+
         return 0;
 }
 
index 8440bb27ba88dc90df120069ab37d2a51619ebd2..ba74dc7aea3ab06e3f17f9de0490241da0027c3a 100644 (file)
@@ -430,28 +430,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
 
                         case TIMER_UNIT_ACTIVE:
                                 leave_around = true;
-                                base = trigger->inactive_exit_timestamp.monotonic;
-
-                                if (base <= 0)
-                                        base = t->last_trigger.monotonic;
-
+                                base = MAX(trigger->inactive_exit_timestamp.monotonic, t->last_trigger.monotonic);
                                 if (base <= 0)
                                         continue;
-                                base = MAX(base, t->last_trigger.monotonic);
-
                                 break;
 
                         case TIMER_UNIT_INACTIVE:
                                 leave_around = true;
-                                base = trigger->inactive_enter_timestamp.monotonic;
-
-                                if (base <= 0)
-                                        base = t->last_trigger.monotonic;
-
+                                base = MAX(trigger->inactive_enter_timestamp.monotonic, t->last_trigger.monotonic);
                                 if (base <= 0)
                                         continue;
-                                base = MAX(base, t->last_trigger.monotonic);
-
                                 break;
 
                         default:
index bd353eda964e2483dbcfda6dce028c986f90de65..2cceb49f4b1aa05b51a210cb357f6dd81fa0d29a 100644 (file)
@@ -661,7 +661,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
         if (r < 0)
                 return r;
 
-        r = get_process_cmdline(container_pid, 0, false, cmdline);
+        r = get_process_cmdline(container_pid, SIZE_MAX, 0, cmdline);
         if (r < 0)
                 return r;
 
@@ -1036,10 +1036,7 @@ static int send_iovec(const struct iovec iovec[], size_t n_iovec, int input_fd)
                                          * (truncated) copy of what we want to send, and the second one
                                          * contains the trailing dots. */
                                         copy[0] = iovec[i];
-                                        copy[1] = (struct iovec) {
-                                                .iov_base = (char[]) { '.', '.', '.' },
-                                                .iov_len = 3,
-                                        };
+                                        copy[1] = IOVEC_MAKE(((char[]){'.', '.', '.'}), 3);
 
                                         mh.msg_iov = copy;
                                         mh.msg_iovlen = 2;
@@ -1157,7 +1154,7 @@ static int gather_pid_metadata(
         if (sd_pid_get_slice(pid, &t) >= 0)
                 set_iovec_field_free(iovec, n_iovec, "COREDUMP_SLICE=", t);
 
-        if (get_process_cmdline(pid, 0, false, &t) >= 0)
+        if (get_process_cmdline(pid, SIZE_MAX, 0, &t) >= 0)
                 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CMDLINE=", t);
 
         if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0)
index 70507d284b216b5f59e61add4b2ba81e452ab007..d62cbd0323df553ea08cd94b028f8144e21ab5c6 100644 (file)
@@ -904,7 +904,7 @@ static int dump_core(int argc, char **argv, void *userdata) {
 
 static int run_debug(int argc, char **argv, void *userdata) {
         _cleanup_(sd_journal_closep) sd_journal *j = NULL;
-        _cleanup_free_ char *exe = NULL, *path = NULL;
+        _cleanup_free_ char *exe = NULL, *path = NULL, *debugger = NULL;
         bool unlink_path = false;
         const char *data, *fork_name;
         size_t len;
@@ -921,6 +921,10 @@ static int run_debug(int argc, char **argv, void *userdata) {
                         arg_debugger = "gdb";
         }
 
+        debugger = strdup(arg_debugger);
+        if (!debugger)
+                return -ENOMEM;
+
         if (arg_field) {
                 log_error("Option --field/-F only makes sense with list");
                 return -EINVAL;
@@ -966,19 +970,19 @@ static int run_debug(int argc, char **argv, void *userdata) {
         /* Don't interfere with gdb and its handling of SIGINT. */
         (void) ignore_signals(SIGINT, -1);
 
-        fork_name = strjoina("(", arg_debugger, ")");
+        fork_name = strjoina("(", debugger, ")");
 
         r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 goto finish;
         if (r == 0) {
-                execlp(arg_debugger, arg_debugger, exe, "-c", path, NULL);
+                execlp(debugger, debugger, exe, "-c", path, NULL);
                 log_open();
-                log_error_errno(errno, "Failed to invoke %s: %m", arg_debugger);
+                log_error_errno(errno, "Failed to invoke %s: %m", debugger);
                 _exit(EXIT_FAILURE);
         }
 
-        r = wait_for_terminate_and_check(arg_debugger, pid, WAIT_LOG_ABNORMAL);
+        r = wait_for_terminate_and_check(debugger, pid, WAIT_LOG_ABNORMAL);
 
 finish:
         (void) default_signals(SIGINT, -1);
@@ -1069,6 +1073,7 @@ static int run(int argc, char *argv[]) {
         int r, units_active;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index c28a816d6774abee7090f40d1faab3f04ee2a6f7..63baa747949e590c8c55bf62a59bea834a4ad7bd 100644 (file)
@@ -639,6 +639,7 @@ static int parse_argv(int argc, char *argv[]) {
 static int run(int argc, char *argv[]) {
         int r, k, n_found = 0;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index f05f2279b35ef157dcecd1ffa842ed94a3882d0a..7fb80ca138abe6d68f97eb1e7506d7fd22c1080b 100644 (file)
@@ -128,6 +128,7 @@ static int run(int argc, char *argv[]) {
          * to detect whether we are being run in a virtualized
          * environment or not */
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 8b38d9f679581e0646010d4ff100824365123e05..9066c30853bc8bfd682d69c3e2d06a34551febb2 100644 (file)
@@ -159,6 +159,7 @@ static int run(int argc, char *argv[]) {
         char **i;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 28ae48d551a87f476a3848b59337c87350fbe700..76270aec17f22ca4c284f699c9764b5e7738de1c 100644 (file)
@@ -463,7 +463,7 @@ static int add_mount(
                 if (r < 0)
                         return log_error_errno(r, "Failed to generate unit name: %m");
 
-                fclose(f);
+                f = safe_fclose(f);
 
                 r = generator_open_unit_file(dest, "/etc/fstab", automount_name, &f);
                 if (r < 0)
diff --git a/src/fuzz/fuzz-varlink.c b/src/fuzz/fuzz-varlink.c
new file mode 100644 (file)
index 0000000..31c13e2
--- /dev/null
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+
+#include "errno-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "hexdecoct.h"
+#include "io-util.h"
+#include "varlink.h"
+#include "log.h"
+
+static FILE *null = NULL;
+
+static int method_something(Varlink *v, JsonVariant *p, VarlinkMethodFlags flags, void *userdata) {
+        json_variant_dump(p, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, null, NULL);
+        return 0;
+}
+
+static int reply_callback(Varlink *v, JsonVariant *p, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+        json_variant_dump(p, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, null, NULL);
+        return 0;
+}
+
+static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        struct iovec *iov = userdata;
+        bool write_eof = false, read_eof = false;
+
+        assert(s);
+        assert(fd >= 0);
+        assert(iov);
+
+        if ((revents & (EPOLLOUT|EPOLLHUP|EPOLLERR)) && iov->iov_len > 0) {
+                ssize_t n;
+
+                /* never write more than 143 bytes a time, to make broken up recv()s on the other side more
+                 * likely, and thus test some additional code paths. */
+                n = send(fd, iov->iov_base, MIN(iov->iov_len, 143U), MSG_NOSIGNAL|MSG_DONTWAIT);
+                if (n < 0) {
+                        if (ERRNO_IS_DISCONNECT(errno))
+                                write_eof = true;
+                        else
+                                assert_se(errno == EAGAIN);
+                } else
+                        IOVEC_INCREMENT(iov, 1, n);
+        }
+
+        if (revents & EPOLLIN) {
+                char c[137];
+                ssize_t n;
+
+                n = recv(fd, c, sizeof(c), MSG_DONTWAIT);
+                if (n < 0) {
+                        if (ERRNO_IS_DISCONNECT(errno))
+                                read_eof = true;
+                        else
+                                assert_se(errno == EAGAIN);
+                } else if (n == 0)
+                        read_eof = true;
+                else
+                        hexdump(null, c, (size_t) n);
+        }
+
+        /* After we wrote everything we could turn off EPOLLOUT. And if we reached read EOF too turn off the
+         * whole thing. */
+        if (write_eof || iov->iov_len == 0) {
+
+                if (read_eof)
+                        assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
+                else
+                        assert_se(sd_event_source_set_io_events(s, EPOLLIN) >= 0);
+        }
+
+        return 0;
+}
+
+static int idle_callback(sd_event_source *s, void *userdata) {
+        assert(s);
+
+        /* Called as idle callback when there's nothing else to do anymore */
+        sd_event_exit(sd_event_source_get_event(s), 0);
+        return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        struct iovec server_iov = IOVEC_MAKE((void*) data, size), client_iov = IOVEC_MAKE((void*) data, size);
+        /* Important: the declaration order matters here! we want that the fds are closed on return after the
+         * event sources, hence we declare the fds first, the event sources second */
+        _cleanup_close_pair_ int server_pair[2] = { -1, -1 }, client_pair[2] = { -1, -1 };
+        _cleanup_(sd_event_source_unrefp) sd_event_source *idle_event_source = NULL,
+                *server_event_source = NULL, *client_event_source = NULL;
+        _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+
+        log_set_max_level(LOG_CRIT);
+        log_parse_environment();
+
+        assert_se(null = fopen("/dev/null", "we"));
+
+        assert_se(sd_event_default(&e) >= 0);
+
+        /* Test one: write the data as method call to a server */
+        assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, server_pair) >= 0);
+        assert_se(varlink_server_new(&s, 0) >= 0);
+        assert_se(varlink_server_set_description(s, "myserver") >= 0);
+        assert_se(varlink_server_attach_event(s, e, 0) >= 0);
+        assert_se(varlink_server_add_connection(s, server_pair[0], NULL) >= 0);
+        TAKE_FD(server_pair[0]);
+        assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
+        assert_se(sd_event_add_io(e, &server_event_source, server_pair[1], EPOLLIN|EPOLLOUT, io_callback, &server_iov) >= 0);
+
+        /* Test two: write the data as method response to a client */
+        assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, client_pair) >= 0);
+        assert_se(varlink_connect_fd(&c, client_pair[0]) >= 0);
+        TAKE_FD(client_pair[0]);
+        assert_se(varlink_set_description(c, "myclient") >= 0);
+        assert_se(varlink_attach_event(c, e, 0) >= 0);
+        assert_se(varlink_bind_reply(c, reply_callback) >= 0);
+        assert_se(varlink_invoke(c, "io.test.DoSomething", NULL) >= 0);
+        assert_se(sd_event_add_io(e, &client_event_source, client_pair[1], EPOLLIN|EPOLLOUT, io_callback, &client_iov) >= 0);
+
+        assert_se(sd_event_add_defer(e, &idle_event_source, idle_callback, NULL) >= 0);
+        assert_se(sd_event_source_set_priority(idle_event_source, SD_EVENT_PRIORITY_IDLE) >= 0);
+
+        assert_se(sd_event_loop(e) >= 0);
+
+        null = safe_fclose(null);
+
+        return 0;
+}
index 1e56526259b20ff3fa48c019406c5e0352b0555f..83b1ac11ad182a00845b2b1afa2db568a4f94ee1 100644 (file)
@@ -6,3 +6,6 @@
 
 /* The entry point into the fuzzer */
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+/* https://docs.fuzzbuzz.io/developer-documentation/porting-targets-to-fuzzbuzz/libfuzzer-targets */
+int FuzzerEntrypoint(const uint8_t *data, size_t size);
diff --git a/src/fuzz/fuzzer-entry-point.c b/src/fuzz/fuzzer-entry-point.c
new file mode 100644 (file)
index 0000000..020c111
--- /dev/null
@@ -0,0 +1,5 @@
+#include "fuzz.h"
+
+int FuzzerEntrypoint(const uint8_t *data, size_t size) {
+        return LLVMFuzzerTestOneInput(data, size);
+}
index 0d1ad2b1e1a4db1624f952a9d228a8650a348761..c88812d1de9f7d83a26f7e9c52d19ac875179007 100644 (file)
@@ -51,6 +51,10 @@ fuzzers += [
          [libshared],
          []],
 
+        [['src/fuzz/fuzz-varlink.c'],
+         [libshared],
+         []],
+
         [['src/fuzz/fuzz-unit-file.c'],
          [libcore,
           libshared],
@@ -128,12 +132,12 @@ fuzzers += [
         [['src/fuzz/fuzz-nspawn-settings.c'],
          [libshared,
           libnspawn_core],
-         []],
+         [libseccomp]],
 
         [['src/fuzz/fuzz-nspawn-oci.c'],
          [libshared,
           libnspawn_core],
-         []],
+         [libseccomp]],
 
         [['src/fuzz/fuzz-calendarspec.c'],
          [libshared],
index 7f9bb49e0c900a2267794902c20903916acdcfd0..22de7350fe7f18abc2f5b3b0b4d7a315b9f06f19 100644 (file)
@@ -432,6 +432,7 @@ static int run(int argc, char *argv[]) {
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 60551ec22585499d5f1992d4d79305cfca6befca..4b370d700d51b7cb400bf23cc7db02294519a0bf 100644 (file)
@@ -155,6 +155,7 @@ static int id128_main(int argc, char *argv[]) {
 static int run(int argc, char *argv[]) {
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 83671cf99b04922fa03d2d611334d4214c41319c..febcc43ce87f224797f6a5fcac2f3a6209a90d5c 100644 (file)
@@ -70,8 +70,7 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
                         fd = sd_event_source_get_io_fd(io);
                         assert(fd >= 0);
 
-                        sd_event_source_set_enabled(io, SD_EVENT_OFF);
-                        sd_event_source_unref(io);
+                        sd_event_source_disable_unref(io);
 
                         hashmap_remove(g->ios, FD_TO_PTR(s));
                         hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
index 2426933558f3737e1192e9556b4d4da75f302b36..f4ca8f4f59438a80dbc5ecea341dd3e319cfdef3 100644 (file)
@@ -250,7 +250,7 @@ static void transfer_send_logs(Transfer *t, bool flush) {
                 n = strndup(t->log_message, e - t->log_message);
 
                 /* Skip over NUL and newlines */
-                while (e < t->log_message + t->log_message_size && (*e == 0 || *e == '\n'))
+                while (e < t->log_message + t->log_message_size && IN_SET(*e, 0, '\n'))
                         e++;
 
                 memmove(t->log_message, e, t->log_message + sizeof(t->log_message) - e);
index 2321a91e7bd57d0e1a6b0642ca5ab9b2ec9f284e..d32c51c3cec376411797033ce936d412626bdc46 100644 (file)
@@ -528,7 +528,7 @@ static int dispatch_http_event(sd_event_source *event,
                                void *userdata) {
         MHDDaemonWrapper *d = userdata;
         int r;
-        MHD_UNSIGNED_LONG_LONG timeout = ULONG_LONG_MAX;
+        MHD_UNSIGNED_LONG_LONG timeout = ULLONG_MAX;
 
         assert(d);
 
@@ -538,7 +538,7 @@ static int dispatch_http_event(sd_event_source *event,
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "MHD_run failed!");
         if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO)
-                timeout = ULONG_LONG_MAX;
+                timeout = ULLONG_MAX;
 
         r = sd_event_source_set_time(d->timer_event, timeout);
         if (r < 0) {
index 04c66a29ce802e34fb1cb5cf2ed40c96570e6c7a..35efe7002b030dfb3987711f402413d24b75b2dd 100644 (file)
@@ -181,7 +181,7 @@ static int get_source_for_fd(RemoteServer *s,
                 return log_warning_errno(r, "Failed to get writer for source %s: %m",
                                          name);
 
-        if (s->sources[fd] == NULL) {
+        if (!s->sources[fd]) {
                 s->sources[fd] = source_new(fd, false, name, writer);
                 if (!s->sources[fd]) {
                         writer_unref(writer);
index d8d72690d7278f5fed66ccef04a63c727556b45f..376b68ad546631eed443e4b20a9e9d6332c64f4c 100644 (file)
@@ -127,6 +127,7 @@ static int run(int argc, char *argv[]) {
         _cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 91d1c2921a3f1447ffbe1365d41be4e0dcbeaa38..c2dcf76deb86dd177594b1bbe9cccb3bc41e9fb2 100644 (file)
@@ -340,7 +340,8 @@ bool journal_file_is_offlining(JournalFile *f) {
 }
 
 JournalFile* journal_file_close(JournalFile *f) {
-        assert(f);
+        if (!f)
+                return NULL;
 
 #if HAVE_GCRYPT
         /* Write the final tag */
@@ -357,8 +358,7 @@ JournalFile* journal_file_close(JournalFile *f) {
                 if (sd_event_source_get_enabled(f->post_change_timer, NULL) > 0)
                         journal_file_post_change(f);
 
-                (void) sd_event_source_set_enabled(f->post_change_timer, SD_EVENT_OFF);
-                sd_event_source_unref(f->post_change_timer);
+                sd_event_source_disable_unref(f->post_change_timer);
         }
 
         journal_file_set_offline(f, true);
@@ -3324,6 +3324,13 @@ int journal_file_open(
         }
 
         r = mmap_cache_get(f->mmap, f->cache_fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h, NULL);
+        if (r == -EINVAL) {
+                /* Some file systems (jffs2 or p9fs) don't support mmap() properly (or only read-only
+                 * mmap()), and return EINVAL in that case. Let's propagate that as a more recognizable error
+                 * code. */
+                r = -EAFNOSUPPORT;
+                goto fail;
+        }
         if (r < 0)
                 goto fail;
 
index e1ea368999123c126f4966c9050d166cbad9342d..502f1f567d1e653aebce8bab10c91f61b88941d5 100644 (file)
@@ -145,6 +145,7 @@ int journal_file_open(
 int journal_file_set_offline(JournalFile *f, bool wait);
 bool journal_file_is_offlining(JournalFile *f);
 JournalFile* journal_file_close(JournalFile *j);
+DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close);
 
 int journal_file_open_reliably(
                 const char *fname,
index 0a06ce7b847d11e7807b06328a9891de1fe31fa9..344b7b019a57c3148bccf6c5e1cfa3305ebcb8a6 100644 (file)
@@ -46,7 +46,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
         for (i = 0; i < j; i++)
                 fputs("\xe2\x96\x88", stdout);
 
-        fputs(ANSI_NORMAL, stdout);
+        fputs(ansi_normal(), stdout);
 
         for (i = 0; i < k; i++)
                 fputs("\xe2\x96\x91", stdout);
index 62110495b37f7ade4ce5abf8772518b425cccd8f..91a21e407fcedab0595da0719d13b975c35c1468 100644 (file)
@@ -52,6 +52,7 @@
 #include "logs-show.h"
 #include "memory-util.h"
 #include "mkdir.h"
+#include "mountpoint-util.h"
 #include "nulstr-util.h"
 #include "pager.h"
 #include "parse-util.h"
@@ -67,6 +68,7 @@
 #include "tmpfile-util.h"
 #include "unit-name.h"
 #include "user-util.h"
+#include "varlink.h"
 
 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
 
@@ -167,6 +169,7 @@ static enum {
         ACTION_UPDATE_CATALOG,
         ACTION_LIST_BOOTS,
         ACTION_FLUSH,
+        ACTION_RELINQUISH_VAR,
         ACTION_SYNC,
         ACTION_ROTATE,
         ACTION_VACUUM,
@@ -368,6 +371,8 @@ static int help(void) {
                "     --vacuum-time=TIME      Remove journal files older than specified time\n"
                "     --verify                Verify journal file consistency\n"
                "     --sync                  Synchronize unwritten journal messages to disk\n"
+               "     --relinquish-var        Stop logging to disk, log to temporary file system\n"
+               "     --smart-relinquish-var  Similar, but NOP if log directory is on root mount\n"
                "     --flush                 Flush all journal data from /run into /var\n"
                "     --rotate                Request immediate rotation of the journal files\n"
                "     --header                Show journal header information\n"
@@ -415,6 +420,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_UTC,
                 ARG_SYNC,
                 ARG_FLUSH,
+                ARG_RELINQUISH_VAR,
+                ARG_SMART_RELINQUISH_VAR,
                 ARG_ROTATE,
                 ARG_VACUUM_SIZE,
                 ARG_VACUUM_FILES,
@@ -424,65 +431,67 @@ static int parse_argv(int argc, char *argv[]) {
         };
 
         static const struct option options[] = {
-                { "help",           no_argument,       NULL, 'h'                },
-                { "version" ,       no_argument,       NULL, ARG_VERSION        },
-                { "no-pager",       no_argument,       NULL, ARG_NO_PAGER       },
-                { "pager-end",      no_argument,       NULL, 'e'                },
-                { "follow",         no_argument,       NULL, 'f'                },
-                { "force",          no_argument,       NULL, ARG_FORCE          },
-                { "output",         required_argument, NULL, 'o'                },
-                { "all",            no_argument,       NULL, 'a'                },
-                { "full",           no_argument,       NULL, 'l'                },
-                { "no-full",        no_argument,       NULL, ARG_NO_FULL        },
-                { "lines",          optional_argument, NULL, 'n'                },
-                { "no-tail",        no_argument,       NULL, ARG_NO_TAIL        },
-                { "new-id128",      no_argument,       NULL, ARG_NEW_ID128      }, /* deprecated */
-                { "quiet",          no_argument,       NULL, 'q'                },
-                { "merge",          no_argument,       NULL, 'm'                },
-                { "this-boot",      no_argument,       NULL, ARG_THIS_BOOT      }, /* deprecated */
-                { "boot",           optional_argument, NULL, 'b'                },
-                { "list-boots",     no_argument,       NULL, ARG_LIST_BOOTS     },
-                { "dmesg",          no_argument,       NULL, 'k'                },
-                { "system",         no_argument,       NULL, ARG_SYSTEM         },
-                { "user",           no_argument,       NULL, ARG_USER           },
-                { "directory",      required_argument, NULL, 'D'                },
-                { "file",           required_argument, NULL, ARG_FILE           },
-                { "root",           required_argument, NULL, ARG_ROOT           },
-                { "header",         no_argument,       NULL, ARG_HEADER         },
-                { "identifier",     required_argument, NULL, 't'                },
-                { "priority",       required_argument, NULL, 'p'                },
-                { "grep",           required_argument, NULL, 'g'                },
-                { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
-                { "setup-keys",     no_argument,       NULL, ARG_SETUP_KEYS     },
-                { "interval",       required_argument, NULL, ARG_INTERVAL       },
-                { "verify",         no_argument,       NULL, ARG_VERIFY         },
-                { "verify-key",     required_argument, NULL, ARG_VERIFY_KEY     },
-                { "disk-usage",     no_argument,       NULL, ARG_DISK_USAGE     },
-                { "cursor",         required_argument, NULL, 'c'                },
-                { "cursor-file",    required_argument, NULL, ARG_CURSOR_FILE    },
-                { "after-cursor",   required_argument, NULL, ARG_AFTER_CURSOR   },
-                { "show-cursor",    no_argument,       NULL, ARG_SHOW_CURSOR    },
-                { "since",          required_argument, NULL, 'S'                },
-                { "until",          required_argument, NULL, 'U'                },
-                { "unit",           required_argument, NULL, 'u'                },
-                { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
-                { "field",          required_argument, NULL, 'F'                },
-                { "fields",         no_argument,       NULL, 'N'                },
-                { "catalog",        no_argument,       NULL, 'x'                },
-                { "list-catalog",   no_argument,       NULL, ARG_LIST_CATALOG   },
-                { "dump-catalog",   no_argument,       NULL, ARG_DUMP_CATALOG   },
-                { "update-catalog", no_argument,       NULL, ARG_UPDATE_CATALOG },
-                { "reverse",        no_argument,       NULL, 'r'                },
-                { "machine",        required_argument, NULL, 'M'                },
-                { "utc",            no_argument,       NULL, ARG_UTC            },
-                { "flush",          no_argument,       NULL, ARG_FLUSH          },
-                { "sync",           no_argument,       NULL, ARG_SYNC           },
-                { "rotate",         no_argument,       NULL, ARG_ROTATE         },
-                { "vacuum-size",    required_argument, NULL, ARG_VACUUM_SIZE    },
-                { "vacuum-files",   required_argument, NULL, ARG_VACUUM_FILES   },
-                { "vacuum-time",    required_argument, NULL, ARG_VACUUM_TIME    },
-                { "no-hostname",    no_argument,       NULL, ARG_NO_HOSTNAME    },
-                { "output-fields",  required_argument, NULL, ARG_OUTPUT_FIELDS  },
+                { "help",                 no_argument,       NULL, 'h'                      },
+                { "version" ,             no_argument,       NULL, ARG_VERSION              },
+                { "no-pager",             no_argument,       NULL, ARG_NO_PAGER             },
+                { "pager-end",            no_argument,       NULL, 'e'                      },
+                { "follow",               no_argument,       NULL, 'f'                      },
+                { "force",                no_argument,       NULL, ARG_FORCE                },
+                { "output",               required_argument, NULL, 'o'                      },
+                { "all",                  no_argument,       NULL, 'a'                      },
+                { "full",                 no_argument,       NULL, 'l'                      },
+                { "no-full",              no_argument,       NULL, ARG_NO_FULL              },
+                { "lines",                optional_argument, NULL, 'n'                      },
+                { "no-tail",              no_argument,       NULL, ARG_NO_TAIL              },
+                { "new-id128",            no_argument,       NULL, ARG_NEW_ID128            }, /* deprecated */
+                { "quiet",                no_argument,       NULL, 'q'                      },
+                { "merge",                no_argument,       NULL, 'm'                      },
+                { "this-boot",            no_argument,       NULL, ARG_THIS_BOOT            }, /* deprecated */
+                { "boot",                 optional_argument, NULL, 'b'                      },
+                { "list-boots",           no_argument,       NULL, ARG_LIST_BOOTS           },
+                { "dmesg",                no_argument,       NULL, 'k'                      },
+                { "system",               no_argument,       NULL, ARG_SYSTEM               },
+                { "user",                 no_argument,       NULL, ARG_USER                 },
+                { "directory",            required_argument, NULL, 'D'                      },
+                { "file",                 required_argument, NULL, ARG_FILE                 },
+                { "root",                 required_argument, NULL, ARG_ROOT                 },
+                { "header",               no_argument,       NULL, ARG_HEADER               },
+                { "identifier",           required_argument, NULL, 't'                      },
+                { "priority",             required_argument, NULL, 'p'                      },
+                { "grep",                 required_argument, NULL, 'g'                      },
+                { "case-sensitive",       optional_argument, NULL, ARG_CASE_SENSITIVE       },
+                { "setup-keys",           no_argument,       NULL, ARG_SETUP_KEYS           },
+                { "interval",             required_argument, NULL, ARG_INTERVAL             },
+                { "verify",               no_argument,       NULL, ARG_VERIFY               },
+                { "verify-key",           required_argument, NULL, ARG_VERIFY_KEY           },
+                { "disk-usage",           no_argument,       NULL, ARG_DISK_USAGE           },
+                { "cursor",               required_argument, NULL, 'c'                      },
+                { "cursor-file",          required_argument, NULL, ARG_CURSOR_FILE          },
+                { "after-cursor",         required_argument, NULL, ARG_AFTER_CURSOR         },
+                { "show-cursor",          no_argument,       NULL, ARG_SHOW_CURSOR          },
+                { "since",                required_argument, NULL, 'S'                      },
+                { "until",                required_argument, NULL, 'U'                      },
+                { "unit",                 required_argument, NULL, 'u'                      },
+                { "user-unit",            required_argument, NULL, ARG_USER_UNIT            },
+                { "field",                required_argument, NULL, 'F'                      },
+                { "fields",               no_argument,       NULL, 'N'                      },
+                { "catalog",              no_argument,       NULL, 'x'                      },
+                { "list-catalog",         no_argument,       NULL, ARG_LIST_CATALOG         },
+                { "dump-catalog",         no_argument,       NULL, ARG_DUMP_CATALOG         },
+                { "update-catalog",       no_argument,       NULL, ARG_UPDATE_CATALOG       },
+                { "reverse",              no_argument,       NULL, 'r'                      },
+                { "machine",              required_argument, NULL, 'M'                      },
+                { "utc",                  no_argument,       NULL, ARG_UTC                  },
+                { "flush",                no_argument,       NULL, ARG_FLUSH                },
+                { "relinquish-var",       no_argument,       NULL, ARG_RELINQUISH_VAR       },
+                { "smart-relinquish-var", no_argument,       NULL, ARG_SMART_RELINQUISH_VAR },
+                { "sync",                 no_argument,       NULL, ARG_SYNC                 },
+                { "rotate",               no_argument,       NULL, ARG_ROTATE               },
+                { "vacuum-size",          required_argument, NULL, ARG_VACUUM_SIZE          },
+                { "vacuum-files",         required_argument, NULL, ARG_VACUUM_FILES         },
+                { "vacuum-time",          required_argument, NULL, ARG_VACUUM_TIME          },
+                { "no-hostname",          no_argument,       NULL, ARG_NO_HOSTNAME          },
+                { "output-fields",        required_argument, NULL, ARG_OUTPUT_FIELDS        },
                 {}
         };
 
@@ -914,6 +923,35 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_FLUSH;
                         break;
 
+                case ARG_SMART_RELINQUISH_VAR: {
+                        int root_mnt_id, log_mnt_id;
+
+                        /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
+                         * if it's on the same mount as the root file system there's no point in
+                         * relinquishing access and we can leave journald write to it until the very last
+                         * moment. */
+
+                        r = path_get_mnt_id("/", &root_mnt_id);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to get root mount ID, ignoring: %m");
+                        else {
+                                r = path_get_mnt_id("/var/log/journal/", &log_mnt_id);
+                                if (r < 0)
+                                        log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m");
+                                else if (root_mnt_id == log_mnt_id) {
+                                        log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
+                                        return 0;
+                                } else
+                                        log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
+                        }
+
+                        _fallthrough_;
+                }
+
+                case ARG_RELINQUISH_VAR:
+                        arg_action = ACTION_RELINQUISH_VAR;
+                        break;
+
                 case ARG_ROTATE:
                         arg_action = arg_action == ACTION_VACUUM ? ACTION_ROTATE_AND_VACUUM : ACTION_ROTATE;
                         break;
@@ -1901,156 +1939,41 @@ static int verify(sd_journal *j) {
         return r;
 }
 
-static int watch_run_systemd_journal(uint32_t mask) {
-        _cleanup_close_ int watch_fd = -1;
-
-        (void) mkdir_p("/run/systemd/journal", 0755);
-
-        watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
-        if (watch_fd < 0)
-                return log_error_errno(errno, "Failed to create inotify object: %m");
-
-        if (inotify_add_watch(watch_fd, "/run/systemd/journal", mask) < 0)
-                return log_error_errno(errno, "Failed to watch \"/run/systemd/journal\": %m");
-
-        return TAKE_FD(watch_fd);
-}
-
-static int flush_to_var(void) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-        _cleanup_close_ int watch_fd = -1;
+static int simple_varlink_call(const char *option, const char *method) {
+        _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
+        const char *error;
         int r;
 
-        if (arg_machine) {
-                log_error("--flush is not supported in conjunction with --machine=.");
-                return -EOPNOTSUPP;
-        }
-
-        /* Quick exit */
-        if (access("/run/systemd/journal/flushed", F_OK) >= 0)
-                return 0;
+        if (arg_machine)
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not supported in conjunction with --machine=.", option);
 
-        /* OK, let's actually do the full logic, send SIGUSR1 to the
-         * daemon and set up inotify to wait for the flushed file to appear */
-        r = bus_connect_system_systemd(&bus);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get D-Bus connection: %m");
-
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "KillUnit",
-                        &error,
-                        NULL,
-                        "ssi", "systemd-journald.service", "main", SIGUSR1);
+        r = varlink_connect_address(&link, "/run/systemd/journal/io.systemd.journal");
         if (r < 0)
-                return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
-
-        watch_fd = watch_run_systemd_journal(IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR);
-        if (watch_fd < 0)
-                return watch_fd;
-
-        for (;;) {
-                if (access("/run/systemd/journal/flushed", F_OK) >= 0)
-                        return 0;
+                return log_error_errno(r, "Failed to connect to /run/systemd/journal/io.systemd.journal: %m");
 
-                if (errno != ENOENT)
-                        return log_error_errno(errno, "Failed to check for existence of /run/systemd/journal/flushed: %m");
+        (void) varlink_set_description(link, "journal");
 
-                r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to wait for event: %m");
+        r = varlink_call(link, method, NULL, NULL, &error, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to execute varlink call: %s", error);
 
-                r = flush_fd(watch_fd);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to flush inotify events: %m");
-        }
+        return 0;
 }
 
-static int send_signal_and_wait(int sig, const char *watch_path) {
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-        _cleanup_close_ int watch_fd = -1;
-        usec_t start;
-        int r;
-
-        if (arg_machine) {
-                log_error("--sync and --rotate are not supported in conjunction with --machine=.");
-                return -EOPNOTSUPP;
-        }
-
-        start = now(CLOCK_MONOTONIC);
-
-        /* This call sends the specified signal to journald, and waits
-         * for acknowledgment by watching the mtime of the specified
-         * flag file. This is used to trigger syncing or rotation and
-         * then wait for the operation to complete. */
-
-        for (;;) {
-                usec_t tstamp;
-
-                /* See if a sync happened by now. */
-                r = read_timestamp_file(watch_path, &tstamp);
-                if (r < 0 && r != -ENOENT)
-                        return log_error_errno(r, "Failed to read %s: %m", watch_path);
-                if (r >= 0 && tstamp >= start)
-                        return 0;
-
-                /* Let's ask for a sync, but only once. */
-                if (!bus) {
-                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
-                        r = bus_connect_system_systemd(&bus);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to get D-Bus connection: %m");
-
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.systemd1",
-                                        "/org/freedesktop/systemd1",
-                                        "org.freedesktop.systemd1.Manager",
-                                        "KillUnit",
-                                        &error,
-                                        NULL,
-                                        "ssi", "systemd-journald.service", "main", sig);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
-
-                        continue;
-                }
-
-                /* Let's install the inotify watch, if we didn't do that yet. */
-                if (watch_fd < 0) {
-                        watch_fd = watch_run_systemd_journal(IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR);
-                        if (watch_fd < 0)
-                                return watch_fd;
-
-                        /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
-                        continue;
-                }
-
-                /* OK, all preparatory steps done, let's wait until inotify reports an event. */
-
-                r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to wait for event: %m");
-
-                r = flush_fd(watch_fd);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to flush inotify events: %m");
-        }
+static int flush_to_var(void) {
+        return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
+}
 
-        return 0;
+static int relinquish_var(void) {
+        return simple_varlink_call("--relinquish-var", "io.systemd.Journal.RelinquishVar");
 }
 
 static int rotate(void) {
-        return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated");
+        return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
 }
 
 static int sync_journal(void) {
-        return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced");
+        return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
 }
 
 static int wait_for_change(sd_journal *j, int poll_fd) {
@@ -2100,6 +2023,7 @@ int main(int argc, char *argv[]) {
         int n_shown = 0, r, poll_fd = -1;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
@@ -2159,6 +2083,10 @@ int main(int argc, char *argv[]) {
                 r = flush_to_var();
                 goto finish;
 
+        case ACTION_RELINQUISH_VAR:
+                r = relinquish_var();
+                goto finish;
+
         case ACTION_SYNC:
                 r = sync_journal();
                 goto finish;
@@ -2750,8 +2678,16 @@ finish:
         free(arg_verify_key);
 
 #if HAVE_PCRE2
-        if (arg_compiled_pattern)
+        if (arg_compiled_pattern) {
                 pcre2_code_free(arg_compiled_pattern);
+
+                /* --grep was used, no error was thrown, but the pattern didn't
+                 * match anything. Let's mimic grep's behavior here and return
+                 * a non-zero exit code, so journalctl --grep can be used
+                 * in scripts and such */
+                if (r == 0 && n_shown == 0)
+                        r = -ENOENT;
+        }
 #endif
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
index e6aeb03b77974a7ffd2603843dfc474666244028..46edf24cd6500e8ab606189a619e084133cb91fe 100644 (file)
@@ -7,6 +7,7 @@
 #include "alloc-util.h"
 #include "audit-util.h"
 #include "cgroup-util.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
@@ -76,18 +77,14 @@ static size_t cache_max(void) {
                 if (r < 0) {
                         log_warning_errno(r, "Cannot query /proc/meminfo for MemTotal: %m");
                         cached = CACHE_MAX_FALLBACK;
-                } else {
+                } else
                         /* Cache entries are usually a few kB, but the process cmdline is controlled by the
                          * user and can be up to _SC_ARG_MAX, usually 2MB. Let's say that approximately up to
                          * 1/8th of memory may be used by the cache.
                          *
                          * In the common case, this formula gives 64 cache entries for each GB of RAM.
                          */
-                        long l = sysconf(_SC_ARG_MAX);
-                        assert(l > 0);
-
-                        cached = CLAMP(mem_total / 8 / (uint64_t) l, CACHE_MAX_MIN, CACHE_MAX_MAX);
-                }
+                        cached = CLAMP(mem_total / 8 / sc_arg_max(), CACHE_MAX_MIN, CACHE_MAX_MAX);
         }
 
         return cached;
@@ -233,7 +230,7 @@ static void client_context_read_basic(ClientContext *c) {
         if (get_process_exe(c->pid, &t) >= 0)
                 free_and_replace(c->exe, t);
 
-        if (get_process_cmdline(c->pid, 0, false, &t) >= 0)
+        if (get_process_cmdline(c->pid, SIZE_MAX, 0, &t) >= 0)
                 free_and_replace(c->cmdline, t);
 
         if (get_process_capeff(c->pid, &t) >= 0)
index ee6c25541cf6445c63a8a0026fa9f32a25564b44..2a4fc250c9190ea4e240af77ab4c891b8da4206b 100644 (file)
@@ -255,7 +255,7 @@ static int open_journal(
                 JournalMetrics *metrics,
                 JournalFile **ret) {
 
-        JournalFile *f;
+        _cleanup_(journal_file_closep) JournalFile *f = NULL;
         int r;
 
         assert(s);
@@ -273,12 +273,10 @@ static int open_journal(
                 return r;
 
         r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC);
-        if (r < 0) {
-                (void) journal_file_close(f);
+        if (r < 0)
                 return r;
-        }
 
-        *ret = f;
+        *ret = TAKE_PTR(f);
         return r;
 }
 
@@ -286,13 +284,14 @@ static bool flushed_flag_is_set(void) {
         return access("/run/systemd/journal/flushed", F_OK) >= 0;
 }
 
-static int system_journal_open(Server *s, bool flush_requested) {
+static int system_journal_open(Server *s, bool flush_requested, bool relinquish_requested) {
         const char *fn;
         int r = 0;
 
         if (!s->system_journal &&
             IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
-            (flush_requested || flushed_flag_is_set())) {
+            (flush_requested || flushed_flag_is_set()) &&
+            !relinquish_requested) {
 
                 /* If in auto mode: first try to create the machine
                  * path, but not the prefix.
@@ -334,7 +333,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
 
                 fn = strjoina(s->runtime_storage.path, "/system.journal");
 
-                if (s->system_journal) {
+                if (s->system_journal && !relinquish_requested) {
 
                         /* Try to open the runtime journal, but only
                          * if it already exists, so that we can flush
@@ -389,7 +388,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
          * else that's left the journals as NULL).
          *
          * Fixes https://github.com/systemd/systemd/issues/3968 */
-        (void) system_journal_open(s, false);
+        (void) system_journal_open(s, false, false);
 
         /* We split up user logs only on /var, not on /run. If the
          * runtime file is open, we write to it exclusively, in order
@@ -786,6 +785,10 @@ static bool shall_try_append_again(JournalFile *f, int r) {
                 log_warning("%s: Journal file is from the future, rotating.", f->path);
                 return true;
 
+        case -EAFNOSUPPORT:
+                log_warning("%s: underlying file system does not support memory mapping or another required file system feature.", f->path);
+                return false;
+
         default:
                 return false;
         }
@@ -1117,7 +1120,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
         char ts[FORMAT_TIMESPAN_MAX];
         usec_t start;
         unsigned n = 0;
-        int r;
+        int r, k;
 
         assert(s);
 
@@ -1130,7 +1133,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
         if (require_flag_file && !flushed_flag_is_set())
                 return 0;
 
-        (void) system_journal_open(s, true);
+        (void) system_journal_open(s, true, false);
 
         if (!s->system_journal)
                 return 0;
@@ -1209,9 +1212,36 @@ finish:
                                           n),
                               NULL);
 
+        k = touch("/run/systemd/journal/flushed");
+        if (k < 0)
+                log_warning_errno(k, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
+
         return r;
 }
 
+static int server_relinquish_var(Server *s) {
+        assert(s);
+
+        if (s->storage == STORAGE_NONE)
+                return 0;
+
+        if (s->runtime_journal && !s->system_journal)
+                return 0;
+
+        log_debug("Relinquishing /var...");
+
+        (void) system_journal_open(s, false, true);
+
+        s->system_journal = journal_file_close(s->system_journal);
+        ordered_hashmap_clear_with_destructor(s->user_journals, journal_file_close);
+        set_clear_with_destructor(s->deferred_closes, journal_file_close);
+
+        if (unlink("/run/systemd/journal/flushed") < 0 && errno != ENOENT)
+                log_warning_errno(errno, "Failed to unlink /run/systemd/journal/flushed, ignoring: %m");
+
+        return 0;
+}
+
 int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
         Server *s = userdata;
         struct ucred *ucred = NULL;
@@ -1330,33 +1360,32 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
         return 0;
 }
 
-static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
-        Server *s = userdata;
-        int r;
-
+static void server_full_flush(Server *s) {
         assert(s);
 
-        log_info("Received request to flush runtime journal from PID " PID_FMT, si->ssi_pid);
-
         (void) server_flush_to_var(s, false);
         server_sync(s);
         server_vacuum(s, false);
 
-        r = touch("/run/systemd/journal/flushed");
-        if (r < 0)
-                log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
-
         server_space_usage_message(s, NULL);
-        return 0;
 }
 
-static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
         Server *s = userdata;
+
+        assert(s);
+
+        log_info("Received SIGUSR1 signal from PID " PID_FMT ", as request to flush runtime journal.", si->ssi_pid);
+        server_full_flush(s);
+
+        return 0;
+}
+
+static void server_full_rotate(Server *s) {
         int r;
 
         assert(s);
 
-        log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid);
         server_rotate(s);
         server_vacuum(s, true);
 
@@ -1369,6 +1398,15 @@ static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *
         r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC));
         if (r < 0)
                 log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m");
+}
+
+static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+        Server *s = userdata;
+
+        assert(s);
+
+        log_info("Received SIGUSR2 signal from PID " PID_FMT ", as request to rotate journal.", si->ssi_pid);
+        server_full_rotate(s);
 
         return 0;
 }
@@ -1384,14 +1422,11 @@ static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *
         return 0;
 }
 
-static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
-        Server *s = userdata;
+static void server_full_sync(Server *s) {
         int r;
 
         assert(s);
 
-        log_debug("Received request to sync from PID " PID_FMT, si->ssi_pid);
-
         server_sync(s);
 
         /* Let clients know when the most recent sync happened. */
@@ -1399,6 +1434,17 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
         if (r < 0)
                 log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m");
 
+        return;
+}
+
+static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+        Server *s = userdata;
+
+        assert(s);
+
+        log_debug("Received SIGRTMIN1 signal from PID " PID_FMT ", as request to sync.", si->ssi_pid );
+        server_full_sync(s);
+
         return 0;
 }
 
@@ -1803,6 +1849,151 @@ static int server_connect_notify(Server *s) {
         return 0;
 }
 
+static int synchronize_second_half(sd_event_source *event_source, void *userdata) {
+        Varlink *link = userdata;
+        Server *s;
+        int r;
+
+        assert(link);
+        assert_se(s = varlink_get_userdata(link));
+
+        /* This is the "second half" of the Synchronize() varlink method. This function is called as deferred
+         * event source at a low priority to ensure the synchronization completes after all queued log
+         * messages are processed. */
+        server_full_sync(s);
+
+        /* Let's get rid of the event source now, by marking it as non-floating again. It then has no ref
+         * anymore and is immediately destroyed after we return from this function, i.e. from this event
+         * source handler at the end. */
+        r = sd_event_source_set_floating(event_source, false);
+        if (r < 0)
+                return log_error_errno(r, "Failed to mark event source as non-floating: %m");
+
+        return varlink_reply(link, NULL);
+}
+
+static void synchronize_destroy(void *userdata) {
+        varlink_unref(userdata);
+}
+
+static int vl_method_synchronize(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *event_source = NULL;
+        Server *s = userdata;
+        int r;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to rotate journal.");
+
+        /* We don't do the main work now, but instead enqueue a deferred event loop job which will do
+         * it. That job is scheduled at low priority, so that we return from this method call only after all
+         * queued but not processed log messages are written to disk, so that this method call returning can
+         * be used as nice synchronization point. */
+        r = sd_event_add_defer(s->event, &event_source, synchronize_second_half, link);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate defer event source: %m");
+
+        r = sd_event_source_set_destroy_callback(event_source, synchronize_destroy);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set event source destroy callback: %m");
+
+        varlink_ref(link); /* The varlink object is now left to the destroy callack to unref */
+
+        r = sd_event_source_set_priority(event_source, SD_EVENT_PRIORITY_NORMAL+15);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set defer event source priority: %m");
+
+        /* Give up ownership of this event source. It will now be destroyed along with event loop itself,
+         * unless it destroys itself earlier. */
+        r = sd_event_source_set_floating(event_source, true);
+        if (r < 0)
+                return log_error_errno(r, "Failed to mark event source as floating: %m");
+
+        (void) sd_event_source_set_description(event_source, "deferred-sync");
+
+        return 0;
+}
+
+static int vl_method_rotate(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Server *s = userdata;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to rotate journal.");
+        server_full_rotate(s);
+
+        return varlink_reply(link, NULL);
+}
+
+static int vl_method_flush_to_var(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Server *s = userdata;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to flush runtime journal.");
+        server_full_flush(s);
+
+        return varlink_reply(link, NULL);
+}
+
+static int vl_method_relinquish_var(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Server *s = userdata;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to relinquish /var access.");
+        server_relinquish_var(s);
+
+        return varlink_reply(link, NULL);
+}
+
+static int server_open_varlink(Server *s) {
+        int r;
+
+        assert(s);
+
+        r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY);
+        if (r < 0)
+                return r;
+
+        varlink_server_set_userdata(s->varlink_server, s);
+
+        r = varlink_server_bind_method_many(
+                        s->varlink_server,
+                        "io.systemd.Journal.Synchronize",   vl_method_synchronize,
+                        "io.systemd.Journal.Rotate",        vl_method_rotate,
+                        "io.systemd.Journal.FlushToVar",    vl_method_flush_to_var,
+                        "io.systemd.Journal.RelinquishVar", vl_method_relinquish_var);
+        if (r < 0)
+                return r;
+
+        r = varlink_server_listen_address(s->varlink_server, "/run/systemd/journal/io.systemd.journal", 0600);
+        if (r < 0)
+                return r;
+
+        r = varlink_server_attach_event(s->varlink_server, s->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int server_init(Server *s) {
         _cleanup_fdset_free_ FDSet *fds = NULL;
         int n, r, fd;
@@ -1973,6 +2164,10 @@ int server_init(Server *s) {
                         return r;
         }
 
+        r = server_open_varlink(s);
+        if (r < 0)
+                return r;
+
         r = server_open_kernel_seqnum(s);
         if (r < 0)
                 return r;
@@ -2006,7 +2201,7 @@ int server_init(Server *s) {
 
         (void) client_context_acquire_default(s);
 
-        return system_journal_open(s, false);
+        return system_journal_open(s, false, false);
 }
 
 void server_maybe_append_tags(Server *s) {
@@ -2035,14 +2230,13 @@ void server_done(Server *s) {
 
         client_context_flush_all(s);
 
-        if (s->system_journal)
-                (void) journal_file_close(s->system_journal);
-
-        if (s->runtime_journal)
-                (void) journal_file_close(s->runtime_journal);
+        (void) journal_file_close(s->system_journal);
+        (void) journal_file_close(s->runtime_journal);
 
         ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close);
 
+        varlink_server_unref(s->varlink_server);
+
         sd_event_source_unref(s->syslog_event_source);
         sd_event_source_unref(s->native_event_source);
         sd_event_source_unref(s->stdout_event_source);
index 5f0b3dd4ac2a8a98c745dab65ea3fc374841a441..6ce9f269ffc5b294567823337222faaf5bb391d1 100644 (file)
@@ -17,6 +17,7 @@ typedef struct Server Server;
 #include "list.h"
 #include "prioq.h"
 #include "time-util.h"
+#include "varlink.h"
 
 typedef enum Storage {
         STORAGE_AUTO,
@@ -166,6 +167,8 @@ struct Server {
 
         ClientContext *my_context; /* the context of journald itself */
         ClientContext *pid1_context; /* the context of PID 1 */
+
+        VarlinkServer *varlink_server;
 };
 
 #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + STRLEN("_MACHINE_ID="))
index 2154cf7eac4b1a6e426b1117ced511be9df79686..a112b9f70f98660a8234f165c9b29ef1e4d30202 100644 (file)
@@ -612,7 +612,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
         assert(data);
 
         hex_buf = hexmem(data, size);
-        if (hex_buf == NULL)
+        if (!hex_buf)
                 return -ENOMEM;
 
         fprintf(f, "%s=%s\n", key, hex_buf);
index 97e1dd3702352514d5e42e0c9f511d50654dd70c..6e077c0860c543857b918b7fd811ecc7b0fe701b 100644 (file)
@@ -88,7 +88,8 @@ struct sd_dhcp_client {
         uint32_t mtu;
         uint32_t xid;
         usec_t start_time;
-        unsigned attempt;
+        uint64_t attempt;
+        uint64_t max_attempts;
         usec_t request_sent;
         sd_event_source *timeout_t1;
         sd_event_source *timeout_t2;
@@ -520,10 +521,18 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
         return 0;
 }
 
+int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
+        assert_return(client, -EINVAL);
+
+        client->max_attempts = max_attempts;
+
+        return 0;
+}
+
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         assert_return(client, -EINVAL);
 
-        if (!IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
+        if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
                 return -EADDRNOTAVAIL;
 
         if (ret)
@@ -532,11 +541,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         return 0;
 }
 
-static void client_notify(sd_dhcp_client *client, int event) {
+static int client_notify(sd_dhcp_client *client, int event) {
         assert(client);
 
         if (client->callback)
-                client->callback(client, event, client->userdata);
+                return client->callback(client, event, client->userdata);
+
+        return 0;
 }
 
 static int client_initialize(sd_dhcp_client *client) {
@@ -551,7 +562,7 @@ static int client_initialize(sd_dhcp_client *client) {
         (void) event_source_disable(client->timeout_t2);
         (void) event_source_disable(client->timeout_expire);
 
-        client->attempt = 1;
+        client->attempt = 0;
 
         client->state = DHCP_STATE_INIT;
         client->xid = 0;
@@ -595,7 +606,7 @@ static int client_message_init(
         assert(ret);
         assert(_optlen);
         assert(_optoffset);
-        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
+        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE));
 
         optlen = DHCP_MIN_OPTIONS_SIZE;
         size = sizeof(DHCPPacket) + optlen;
@@ -686,7 +697,7 @@ static int client_message_init(
            MAY contain the Parameter Request List option. */
         /* NOTE: in case that there would be an option to do not send
          * any PRL at all, the size should be checked before sending */
-        if (client->req_opts_size > 0) {
+        if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
                 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
                                        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
                                        client->req_opts_size, client->req_opts);
@@ -718,7 +729,7 @@ static int client_message_init(
          */
         /* RFC7844 section 3:
            SHOULD NOT contain any other option. */
-        if (!client->anonymize) {
+        if (!client->anonymize && type != DHCP_RELEASE) {
                 max_size = htobe16(size);
                 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
                                        SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
@@ -850,6 +861,41 @@ static int client_send_discover(sd_dhcp_client *client) {
         return 0;
 }
 
+static int client_send_release(sd_dhcp_client *client) {
+        _cleanup_free_ DHCPPacket *release = NULL;
+        size_t optoffset, optlen;
+        int r;
+
+        assert(client);
+        assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
+
+        r = client_message_init(client, &release, DHCP_RELEASE,
+                                &optlen, &optoffset);
+        if (r < 0)
+                return r;
+
+        /* Fill up release IP and MAC */
+        release->dhcp.ciaddr = client->lease->address;
+        memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
+
+        r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
+                               SD_DHCP_OPTION_END, 0, NULL);
+        if (r < 0)
+                return r;
+
+        r = dhcp_network_send_udp_socket(client->fd,
+                                         client->lease->server_address,
+                                         DHCP_PORT_SERVER,
+                                         &release->dhcp,
+                                         sizeof(DHCPMessage) + optoffset);
+        if (r < 0)
+                return r;
+
+        log_dhcp_client(client, "RELEASE");
+
+        return 0;
+}
+
 static int client_send_request(sd_dhcp_client *client) {
         _cleanup_free_ DHCPPacket *request = NULL;
         size_t optoffset, optlen;
@@ -1050,10 +1096,12 @@ static int client_timeout_resend(
         case DHCP_STATE_REQUESTING:
         case DHCP_STATE_BOUND:
 
-                if (client->attempt < 64)
-                        client->attempt *= 2;
+                if (client->attempt < client->max_attempts)
+                        client->attempt++;
+                else
+                        goto error;
 
-                next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
+                next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
 
                 break;
 
@@ -1077,17 +1125,15 @@ static int client_timeout_resend(
                 r = client_send_discover(client);
                 if (r >= 0) {
                         client->state = DHCP_STATE_SELECTING;
-                        client->attempt = 1;
-                } else {
-                        if (client->attempt >= 64)
-                                goto error;
-                }
+                        client->attempt = 0;
+                } else if (client->attempt >= client->max_attempts)
+                        goto error;
 
                 break;
 
         case DHCP_STATE_SELECTING:
                 r = client_send_discover(client);
-                if (r < 0 && client->attempt >= 64)
+                if (r < 0 && client->attempt >= client->max_attempts)
                         goto error;
 
                 break;
@@ -1097,7 +1143,7 @@ static int client_timeout_resend(
         case DHCP_STATE_RENEWING:
         case DHCP_STATE_REBINDING:
                 r = client_send_request(client);
-                if (r < 0 && client->attempt >= 64)
+                if (r < 0 && client->attempt >= client->max_attempts)
                          goto error;
 
                 if (client->state == DHCP_STATE_INIT_REBOOT)
@@ -1249,7 +1295,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         client->fd = asynchronous_close(client->fd);
 
         client->state = DHCP_STATE_REBINDING;
-        client->attempt = 1;
+        client->attempt = 0;
 
         r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
                                          client->xid, client->mac_addr,
@@ -1269,7 +1315,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
         DHCP_CLIENT_DONT_DESTROY(client);
 
         client->state = DHCP_STATE_RENEWING;
-        client->attempt = 1;
+        client->attempt = 0;
 
         return client_initialize_time_events(client);
 }
@@ -1319,6 +1365,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
         sd_dhcp_lease_unref(client->lease);
         client->lease = TAKE_PTR(lease);
 
+        if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
+                return -ENOMSG;
+
         log_dhcp_client(client, "OFFER");
 
         return 0;
@@ -1553,7 +1602,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
                 if (r >= 0) {
 
                         client->state = DHCP_STATE_REQUESTING;
-                        client->attempt = 1;
+                        client->attempt = 0;
 
                         r = event_reset_time(client->event, &client->timeout_resend,
                                              clock_boottime_or_monotonic(),
@@ -1588,7 +1637,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
                                 notify_event = r;
 
                         client->state = DHCP_STATE_BOUND;
-                        client->attempt = 1;
+                        client->attempt = 0;
 
                         client->last_addr = client->lease->address;
 
@@ -1844,6 +1893,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
         return r;
 }
 
+int sd_dhcp_client_send_release(sd_dhcp_client *client) {
+        assert_return(client, -EINVAL);
+
+        client_send_release(client);
+
+        return 0;
+}
+
 int sd_dhcp_client_stop(sd_dhcp_client *client) {
         DHCP_CLIENT_DONT_DESTROY(client);
 
@@ -1927,10 +1984,10 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
                 .state = DHCP_STATE_INIT,
                 .ifindex = -1,
                 .fd = -1,
-                .attempt = 1,
                 .mtu = DHCP_DEFAULT_MIN_SIZE,
                 .port = DHCP_PORT_CLIENT,
                 .anonymize = !!anonymize,
+                .max_attempts = (uint64_t) -1,
         };
         /* NOTE: this could be moved to a function. */
         if (anonymize) {
index 08433adb25c911c5aa2ea63b5cdac3e1b5096fb7..185b55e1c56ca35754fa1d1f16cb27f24399e2b6 100644 (file)
@@ -598,6 +598,7 @@ _public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra,
 
                 LIST_REMOVE(prefix, ra->prefixes, cur);
                 ra->n_prefixes--;
+                sd_radv_prefix_unref(cur);
 
                 break;
         }
index 0431e2c3f568605ed2d3e12e8cdd2d6d154b74a1..5f31d24d20bd4d3e750d5bd88d02a9c835909746 100644 (file)
@@ -418,7 +418,7 @@ static uint8_t test_addr_acq_ack[] = {
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
-static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
+static int test_addr_acq_acquired(sd_dhcp_client *client, int event,
                                    void *userdata) {
         sd_event *e = userdata;
         sd_dhcp_lease *lease;
@@ -426,7 +426,7 @@ static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
         const struct in_addr *addrs;
 
         assert_se(client);
-        assert_se(event == SD_DHCP_CLIENT_EVENT_IP_ACQUIRE);
+        assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
 
         assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
         assert_se(lease);
@@ -447,6 +447,8 @@ static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
                 printf("  DHCP address acquired\n");
 
         sd_event_exit(e, 0);
+
+        return 0;
 }
 
 static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
index a9ab0605ce14427d8b0219e91d7b0014fd1b14a9..5ec42e0f1f826eb602ce121e2650012b3250f930 100644 (file)
@@ -680,4 +680,5 @@ global:
 LIBSYSTEMD_243 {
 global:
         sd_bus_object_vtable_format;
+        sd_event_source_disable_unref;
 } LIBSYSTEMD_241;
index 1759e13ca134ce79961e42fb007d92f647baebbf..774bf10219089ed4e8ffa74d72c743616c1411b4 100644 (file)
@@ -26,7 +26,7 @@ static int message_append_basic(sd_bus_message *m, char type, const void *p, con
 
 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
 
-        if (p == NULL)
+        if (!p)
                 return NULL;
 
         if (old_base == new_base)
index fe3b9feea6dfe1e83b5a309ef571577a5ce3d522..d18c5781775c762245347fe54747f70814cf9fc0 100644 (file)
@@ -638,8 +638,14 @@ static int property_get_set_callbacks_run(
                 if (r < 0)
                         return r;
 
-                if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature)))
-                        return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature));
+                if (type != 'v')
+                        return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_SIGNATURE,
+                                                          "Incorrect signature when setting property '%s', expected 'v', got '%c'.",
+                                                          c->member, type);
+                if (!streq(strempty(signature), strempty(c->vtable->x.property.signature)))
+                        return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS,
+                                                          "Incorrect parameters for property '%s', expected '%s', got '%s'.",
+                                                          c->member, strempty(c->vtable->x.property.signature), strempty(signature));
 
                 r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
                 if (r < 0)
index 50017a9517baac9ef06934413ac0c443e30ef521..09285c19d86b6d29047128a2be01e2ee3c0bc13b 100644 (file)
@@ -339,6 +339,12 @@ fail:
 
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
 
+_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
+        if (s)
+                (void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
+        return sd_event_source_unref(s);
+}
+
 static bool event_pid_changed(sd_event *e) {
         assert(e);
 
index 118f319a2082799ac17feb08c6609eb2a3825ed4..7fd3efbd35723a44b7b7d745d7d5191043937774 100644 (file)
@@ -170,6 +170,8 @@ static const NLType rtnl_link_info_data_vxlan_types[] = {
         [IFLA_VXLAN_COLLECT_METADATA]  = { .type = NETLINK_TYPE_U8 },
         [IFLA_VXLAN_LABEL]             = { .type = NETLINK_TYPE_U32 },
         [IFLA_VXLAN_GPE]               = { .type = NETLINK_TYPE_FLAG },
+        [IFLA_VXLAN_TTL_INHERIT]       = { .type = NETLINK_TYPE_FLAG },
+        [IFLA_VXLAN_DF]                = { .type = NETLINK_TYPE_U8 },
 };
 
 static const NLType rtnl_bond_arp_target_types[] = {
@@ -299,6 +301,8 @@ static const NLType rtnl_link_info_data_geneve_types[] = {
         [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
         [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
         [IFLA_GENEVE_LABEL]             = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GENEVE_TTL_INHERIT]       = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_DF]                = { .type = NETLINK_TYPE_U8 },
 };
 
 static const NLType rtnl_link_info_data_can_types[] = {
@@ -333,6 +337,7 @@ static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan",
         [NL_UNION_LINK_INFO_DATA_MACVTAP] = "macvtap",
         [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan",
+        [NL_UNION_LINK_INFO_DATA_IPVTAP] = "ipvtap",
         [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan",
         [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
         [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
@@ -371,6 +376,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
                                                        .types = rtnl_link_info_data_macvlan_types },
         [NL_UNION_LINK_INFO_DATA_IPVLAN] =           { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
                                                        .types = rtnl_link_info_data_ipvlan_types },
+        [NL_UNION_LINK_INFO_DATA_IPVTAP] =           { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
+                                                       .types = rtnl_link_info_data_ipvlan_types },
         [NL_UNION_LINK_INFO_DATA_VXLAN] =            { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
                                                        .types = rtnl_link_info_data_vxlan_types },
         [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] =      { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
@@ -553,6 +560,8 @@ static const NLType rtnl_link_types[] = {
 /*
         [IFLA_PHYS_PORT_ID]     = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
 */
+        [IFLA_MIN_MTU]              = { .type = NETLINK_TYPE_U32 },
+        [IFLA_MAX_MTU]              = { .type = NETLINK_TYPE_U32 },
 };
 
 static const NLTypeSystem rtnl_link_type_system = {
@@ -583,20 +592,22 @@ static const NLTypeSystem rtnl_address_type_system = {
 /* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
 
 static const NLType rtnl_route_metrics_types[] = {
-        [RTAX_MTU]               = { .type = NETLINK_TYPE_U32 },
-        [RTAX_WINDOW]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTT]               = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTTVAR]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_SSTHRESH]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_CWND]              = { .type = NETLINK_TYPE_U32 },
-        [RTAX_ADVMSS]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_REORDERING]        = { .type = NETLINK_TYPE_U32 },
-        [RTAX_HOPLIMIT]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_INITCWND]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_FEATURES]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTO_MIN]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_INITRWND]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_QUICKACK]          = { .type = NETLINK_TYPE_U32 },
+        [RTAX_MTU]                = { .type = NETLINK_TYPE_U32 },
+        [RTAX_WINDOW]             = { .type = NETLINK_TYPE_U32 },
+        [RTAX_RTT]                = { .type = NETLINK_TYPE_U32 },
+        [RTAX_RTTVAR]             = { .type = NETLINK_TYPE_U32 },
+        [RTAX_SSTHRESH]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_CWND]               = { .type = NETLINK_TYPE_U32 },
+        [RTAX_ADVMSS]             = { .type = NETLINK_TYPE_U32 },
+        [RTAX_REORDERING]         = { .type = NETLINK_TYPE_U32 },
+        [RTAX_HOPLIMIT]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_INITCWND]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_FEATURES]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_RTO_MIN]            = { .type = NETLINK_TYPE_U32 },
+        [RTAX_INITRWND]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_QUICKACK]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_CC_ALGO]            = { .type = NETLINK_TYPE_U32 },
+        [RTAX_FASTOPEN_NO_COOKIE] = { .type = NETLINK_TYPE_U32 },
 };
 
 static const NLTypeSystem rtnl_route_metrics_type_system = {
@@ -613,23 +624,23 @@ static const NLType rtnl_route_types[] = {
         [RTA_PRIORITY]          = { .type = NETLINK_TYPE_U32 },
         [RTA_PREFSRC]           = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
         [RTA_METRICS]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system},
-/*      [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
-*/
+        [RTA_MULTIPATH]         = { .size = sizeof(struct rtnexthop) },
         [RTA_FLOW]              = { .type = NETLINK_TYPE_U32 }, /* 6? */
-/*
-        RTA_CACHEINFO,
-        RTA_TABLE,
-        RTA_MARK,
-        RTA_MFC_STATS,
-        RTA_VIA,
-        RTA_NEWDST,
-*/
+        [RTA_CACHEINFO]         = { .size = sizeof(struct rta_cacheinfo) },
+        [RTA_TABLE]             = { .type = NETLINK_TYPE_U32 },
+        [RTA_MARK]              = { .type = NETLINK_TYPE_U32 },
+        [RTA_MFC_STATS]         = { .type = NETLINK_TYPE_U64 },
+        [RTA_VIA]               = { .type = NETLINK_TYPE_U32 },
+        [RTA_NEWDST]            = { .type = NETLINK_TYPE_U32 },
         [RTA_PREF]              = { .type = NETLINK_TYPE_U8 },
-/*
-        RTA_ENCAP_TYPE,
-        RTA_ENCAP,
- */
         [RTA_EXPIRES]           = { .type = NETLINK_TYPE_U32 },
+        [RTA_ENCAP_TYPE]        = { .type = NETLINK_TYPE_U16 },
+        [RTA_ENCAP]             = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
+        [RTA_UID]               = { .type = NETLINK_TYPE_U32 },
+        [RTA_TTL_PROPAGATE]     = { .type = NETLINK_TYPE_U8 },
+        [RTA_IP_PROTO]          = { .type = NETLINK_TYPE_U8 },
+        [RTA_SPORT]             = { .type = NETLINK_TYPE_U16 },
+        [RTA_DPORT]             = { .type = NETLINK_TYPE_U16 },
 };
 
 static const NLTypeSystem rtnl_route_type_system = {
@@ -794,6 +805,12 @@ static const NLType genl_fou_types[] = {
         [FOU_ATTR_IPPROTO]           = { .type = NETLINK_TYPE_U8 },
         [FOU_ATTR_TYPE]              = { .type = NETLINK_TYPE_U8 },
         [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
+        [FOU_ATTR_LOCAL_V4]          = { .type = NETLINK_TYPE_IN_ADDR },
+        [FOU_ATTR_PEER_V4]           = { .type = NETLINK_TYPE_IN_ADDR },
+        [FOU_ATTR_LOCAL_V6]          = { .type = NETLINK_TYPE_IN_ADDR },
+        [FOU_ATTR_PEER_V6]           = { .type = NETLINK_TYPE_IN_ADDR},
+        [FOU_ATTR_PEER_PORT]         = { .type = NETLINK_TYPE_U16},
+        [FOU_ATTR_IFINDEX]           = { .type = NETLINK_TYPE_U32},
 };
 
 static const NLTypeSystem genl_fou_type_system = {
index a2b3087d1596158dd748e56b55fe629724ff1c8a..8585280463a647bf22d3beca634d92a945c0adb0 100644 (file)
@@ -62,6 +62,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_MACVLAN,
         NL_UNION_LINK_INFO_DATA_MACVTAP,
         NL_UNION_LINK_INFO_DATA_IPVLAN,
+        NL_UNION_LINK_INFO_DATA_IPVTAP,
         NL_UNION_LINK_INFO_DATA_VXLAN,
         NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL,
index c8b195d9a6c0968c32856d7973af5505cd7e950e..9fb51521109ba81fb28f9c780caa9f0c2d6929ae 100644 (file)
@@ -510,6 +510,7 @@ static int run(int argc, char *argv[]) {
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 47fd9e874dab7f5f57492ae5fc7f58d9a04d333a..d96c8195a28a0611b43b649fdc10e629fccb4414 100644 (file)
@@ -270,6 +270,7 @@ static int run(int argc, char *argv[]) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 342ac56d90437e022179ab04ab9686c607b54525..687a534f7b85d0cbc4e1b69ef63f077450a6073b 100644 (file)
@@ -94,7 +94,7 @@ static int show_table(Table *table, const char *word) {
         assert(table);
         assert(word);
 
-        if (table_get_rows(table) > 1) {
+        if (table_get_rows(table) > 1 || OUTPUT_MODE_IS_JSON(arg_output)) {
                 r = table_set_sort(table, (size_t) 0, (size_t) -1);
                 if (r < 0)
                         return log_error_errno(r, "Failed to sort table: %m");
@@ -1529,6 +1529,7 @@ static int run(int argc, char *argv[]) {
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index daffbf0668cd397af469146e2a0ab388a69213f0..86c9121f270bdd90f40f57d141053cd07fbfe3ba 100644 (file)
@@ -224,19 +224,18 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
         return 0;
 }
 
-static int button_suitable(Button *b) {
+static int button_suitable(int fd) {
         unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1];
 
-        assert(b);
-        assert(b->fd);
+        assert(fd >= 0);
 
-        if (ioctl(b->fd, EVIOCGBIT(EV_SYN, sizeof(types)), types) < 0)
+        if (ioctl(fd, EVIOCGBIT(EV_SYN, sizeof types), types) < 0)
                 return -errno;
 
         if (bitset_get(types, EV_KEY)) {
                 unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1];
 
-                if (ioctl(b->fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys) < 0)
+                if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0)
                         return -errno;
 
                 if (bitset_get(keys, KEY_POWER) ||
@@ -249,7 +248,7 @@ static int button_suitable(Button *b) {
         if (bitset_get(types, EV_SW)) {
                 unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1];
 
-                if (ioctl(b->fd, EVIOCGBIT(EV_SW, sizeof(switches)), switches) < 0)
+                if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof switches), switches) < 0)
                         return -errno;
 
                 if (bitset_get(switches, SW_LID) ||
@@ -260,15 +259,15 @@ static int button_suitable(Button *b) {
         return false;
 }
 
-static int button_set_mask(Button *b) {
+static int button_set_mask(const char *name, int fd) {
         unsigned long
                 types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {},
                 keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {},
                 switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
         struct input_mask mask;
 
-        assert(b);
-        assert(b->fd >= 0);
+        assert(name);
+        assert(fd >= 0);
 
         bitset_put(types, EV_KEY);
         bitset_put(types, EV_SW);
@@ -279,10 +278,10 @@ static int button_set_mask(Button *b) {
                 .codes_ptr = PTR_TO_UINT64(types),
         };
 
-        if (ioctl(b->fd, EVIOCSMASK, &mask) < 0)
+        if (ioctl(fd, EVIOCSMASK, &mask) < 0)
                 /* Log only at debug level if the kernel doesn't do EVIOCSMASK yet */
                 return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING,
-                                      errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", b->name);
+                                      errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", name);
 
         bitset_put(keys, KEY_POWER);
         bitset_put(keys, KEY_POWER2);
@@ -295,8 +294,8 @@ static int button_set_mask(Button *b) {
                 .codes_ptr = PTR_TO_UINT64(keys),
         };
 
-        if (ioctl(b->fd, EVIOCSMASK, &mask) < 0)
-                return log_warning_errno(errno, "Failed to set EV_KEY event mask on /dev/input/%s: %m", b->name);
+        if (ioctl(fd, EVIOCSMASK, &mask) < 0)
+                return log_warning_errno(errno, "Failed to set EV_KEY event mask on /dev/input/%s: %m", name);
 
         bitset_put(switches, SW_LID);
         bitset_put(switches, SW_DOCK);
@@ -307,14 +306,16 @@ static int button_set_mask(Button *b) {
                 .codes_ptr = PTR_TO_UINT64(switches),
         };
 
-        if (ioctl(b->fd, EVIOCSMASK, &mask) < 0)
-                return log_warning_errno(errno, "Failed to set EV_SW event mask on /dev/input/%s: %m", b->name);
+        if (ioctl(fd, EVIOCSMASK, &mask) < 0)
+                return log_warning_errno(errno, "Failed to set EV_SW event mask on /dev/input/%s: %m", name);
 
         return 0;
 }
 
 int button_open(Button *b) {
-        char *p, name[256];
+        _cleanup_close_ int fd = -1;
+        const char *p;
+        char name[256];
         int r;
 
         assert(b);
@@ -323,38 +324,30 @@ int button_open(Button *b) {
 
         p = strjoina("/dev/input/", b->name);
 
-        b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
-        if (b->fd < 0)
+        fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
+        if (fd < 0)
                 return log_warning_errno(errno, "Failed to open %s: %m", p);
 
-        r = button_suitable(b);
+        r = button_suitable(fd);
         if (r < 0)
-                return log_warning_errno(r, "Failed to determine whether input device is relevant to us: %m");
+                return log_warning_errno(r, "Failed to determine whether input device %s is relevant to us: %m", p);
         if (r == 0)
                 return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL),
-                                       "Device %s does not expose keys or switches relevant to us, ignoring.",
-                                       p);
-
-        if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
-                r = log_error_errno(errno, "Failed to get input name: %m");
-                goto fail;
-        }
+                                       "Device %s does not expose keys or switches relevant to us, ignoring.", p);
 
-        (void) button_set_mask(b);
+        if (ioctl(fd, EVIOCGNAME(sizeof name), name) < 0)
+                return log_error_errno(errno, "Failed to get input name for %s: %m", p);
 
-        r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b);
-        if (r < 0) {
-                log_error_errno(r, "Failed to add button event: %m");
-                goto fail;
-        }
-
-        log_info("Watching system buttons on /dev/input/%s (%s)", b->name, name);
+        (void) button_set_mask(b->name, fd);
+        
+        b->io_event_source = sd_event_source_unref(b->io_event_source);
+        r = sd_event_add_io(b->manager->event, &b->io_event_source, fd, EPOLLIN, button_dispatch, b);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add button event for %s: %m", p);
 
+        b->fd = TAKE_FD(fd);
+        log_info("Watching system buttons on %s (%s)", p, name);
         return 0;
-
-fail:
-        b->fd = safe_close(b->fd);
-        return r;
 }
 
 int button_check_switches(Button *b) {
index 2467da18eea4a6caf8aa43eb7229397154c23771..dacd3b3d9c0c0ce1c0e70a83f8194f238cd2e616 100644 (file)
@@ -693,8 +693,7 @@ bool manager_all_buttons_ignored(Manager *m) {
                 return false;
         if (m->handle_lid_switch != HANDLE_IGNORE)
                 return false;
-        if (m->handle_lid_switch_ep != _HANDLE_ACTION_INVALID &&
-            m->handle_lid_switch_ep != HANDLE_IGNORE)
+        if (!IN_SET(m->handle_lid_switch_ep, _HANDLE_ACTION_INVALID, HANDLE_IGNORE))
                 return false;
         if (m->handle_lid_switch_docked != HANDLE_IGNORE)
                 return false;
index 0a19cf8abcd3cb5aa447751fdc3c8bc6e92be95e..c5d442865cc39ec102c305cc463fe37d181db83e 100644 (file)
@@ -754,7 +754,7 @@ void user_update_last_session_timer(User *u) {
 
         assert(!u->timer_event_source);
 
-        if (u->manager->user_stop_delay == 0 || u->manager->user_stop_delay == USEC_INFINITY)
+        if (IN_SET(u->manager->user_stop_delay, 0, USEC_INFINITY))
                 return;
 
         if (sd_event_get_state(u->manager->event) == SD_EVENT_FINISHED) {
index d98027a0ca5fdd63246f8498b960d1373743910d..12de188239d9e307b62de798d975cd3508c57a01 100644 (file)
@@ -255,7 +255,7 @@ static int show_table(Table *table, const char *word) {
         assert(table);
         assert(word);
 
-        if (table_get_rows(table) > 1) {
+        if (table_get_rows(table) > 1 || OUTPUT_MODE_IS_JSON(arg_output)) {
                 r = table_set_sort(table, (size_t) 0, (size_t) -1);
                 if (r < 0)
                         return log_error_errno(r, "Failed to sort table: %m");
@@ -3100,6 +3100,7 @@ static int run(int argc, char *argv[]) {
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index b290095b0e95385c7acc15cf570f9bab45f9c46f..43e216acad09f3a65546333f51a337ac000a6317 100644 (file)
@@ -17,6 +17,7 @@
 #include "format-util.h"
 #include "fs-util.h"
 #include "fstab-util.h"
+#include "libmount-util.h"
 #include "main-func.h"
 #include "mount-util.h"
 #include "mountpoint-util.h"
@@ -713,9 +714,11 @@ static int start_transient_automount(
 }
 
 static int find_mount_points(const char *what, char ***list) {
-        _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
         _cleanup_strv_free_ char **l = NULL;
         size_t bufsize = 0, n = 0;
+        int r;
 
         assert(what);
         assert(list);
@@ -723,55 +726,42 @@ static int find_mount_points(const char *what, char ***list) {
         /* Returns all mount points obtained from /proc/self/mountinfo in *list,
          * and the number of mount points as return value. */
 
-        proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
-        if (!proc_self_mountinfo)
-                return log_error_errno(errno, "Can't open /proc/self/mountinfo: %m");
+        r = libmount_parse(NULL, NULL, &table, &iter);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
         for (;;) {
-                _cleanup_free_ char *path = NULL, *where = NULL, *dev = NULL;
-                int r;
+                struct libmnt_fs *fs;
+                const char *source, *target;
 
-                r = fscanf(proc_self_mountinfo,
-                           "%*s "       /* (1) mount id */
-                           "%*s "       /* (2) parent id */
-                           "%*s "       /* (3) major:minor */
-                           "%*s "       /* (4) root */
-                           "%ms "       /* (5) mount point */
-                           "%*s"        /* (6) mount options */
-                           "%*[^-]"     /* (7) optional fields */
-                           "- "         /* (8) separator */
-                           "%*s "       /* (9) file system type */
-                           "%ms"        /* (10) mount source */
-                           "%*s"        /* (11) mount options 2 */
-                           "%*[^\n]",   /* some rubbish at the end */
-                           &path, &dev);
-                if (r != 2) {
-                        if (r == EOF)
-                                break;
-
-                        continue;
-                }
+                r = mnt_table_next_fs(table, iter, &fs);
+                if (r == 1)
+                        break;
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
 
-                if (!streq(what, dev))
+                source = mnt_fs_get_source(fs);
+                target = mnt_fs_get_target(fs);
+                if (!source || !target)
                         continue;
 
-                r = cunescape(path, UNESCAPE_RELAX, &where);
-                if (r < 0)
+                if (!path_equal(source, what))
                         continue;
 
                 /* one extra slot is needed for the terminating NULL */
-                if (!GREEDY_REALLOC(l, bufsize, n + 2))
+                if (!GREEDY_REALLOC0(l, bufsize, n + 2))
                         return log_oom();
 
-                l[n++] = TAKE_PTR(where);
+                l[n] = strdup(target);
+                if (!l[n])
+                        return log_oom();
+                n++;
         }
 
-        if (!GREEDY_REALLOC(l, bufsize, n + 1))
+        if (!GREEDY_REALLOC0(l, bufsize, n + 1))
                 return log_oom();
 
-        l[n] = NULL;
         *list = TAKE_PTR(l);
-
         return n;
 }
 
@@ -1525,6 +1515,7 @@ static int run(int argc, char* argv[]) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 2acbe858bb5a52b44937a4ad87af405c5c77893a..0bcf7f4a815d193f510c909931e67d33a34e963e 100644 (file)
@@ -49,6 +49,8 @@ sources = files('''
         networkd-address.h
         networkd-brvlan.c
         networkd-brvlan.h
+        networkd-can.c
+        networkd-can.h
         networkd-conf.c
         networkd-conf.h
         networkd-dhcp4.c
@@ -61,6 +63,8 @@ sources = files('''
         networkd-link-bus.c
         networkd-link.c
         networkd-link.h
+        networkd-lldp-rx.c
+        networkd-lldp-rx.h
         networkd-lldp-tx.c
         networkd-lldp-tx.h
         networkd-manager-bus.c
index 166aa37139fd6b6752011cd33ce80c872e985645..240cfe34e223e15569c3975323f1b249fd75019a 100644 (file)
@@ -7,6 +7,8 @@
 #include "conf-parser.h"
 #include "ether-addr-util.h"
 #include "extract-word.h"
+#include "netlink-util.h"
+#include "networkd-manager.h"
 #include "string-table.h"
 #include "string-util.h"
 
@@ -291,6 +293,78 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin
         return 0;
 }
 
+static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(m);
+        assert(link);
+        assert(link->ifname);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not set bonding interface: %m");
+                return 1;
+        }
+
+        return 1;
+}
+
+int link_set_bond(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+        r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+        r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        if (link->network->active_slave) {
+                r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
+        }
+
+        if (link->network->primary_slave) {
+                r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r,  "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return r;
+}
+
 int config_parse_arp_ip_target_address(
                 const char *unit,
                 const char *filename,
index 12f59cd94695c57c883dd1e2ebf53e716af63eea..28796a3a8be1d40ff75893c64c4a2b9442830b49 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/if_bonding.h>
 
 #include "in-addr-util.h"
@@ -119,6 +120,8 @@ typedef struct Bond {
 DEFINE_NETDEV_CAST(BOND, Bond);
 extern const NetDevVTable bond_vtable;
 
+int link_set_bond(Link *link);
+
 const char *bond_mode_to_string(BondMode d) _const_;
 BondMode bond_mode_from_string(const char *d) _pure_;
 
index cbbf11220be523a17d8f5aca457aa20336786a50..f20130d26441f813496561e611d0ad52ed4703c5 100644 (file)
@@ -5,9 +5,22 @@
 #include "missing.h"
 #include "netlink-util.h"
 #include "netdev/bridge.h"
+#include "network-internal.h"
 #include "networkd-manager.h"
+#include "string-table.h"
 #include "vlan-util.h"
 
+static const char* const multicast_router_table[_MULTICAST_ROUTER_MAX] = {
+        [MULTICAST_ROUTER_NONE] = "no",
+        [MULTICAST_ROUTER_TEMPORARY_QUERY] = "query",
+        [MULTICAST_ROUTER_PERMANENT] = "permanent",
+        [MULTICAST_ROUTER_TEMPORARY] = "temporary",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router, MulticastRouter, _MULTICAST_ROUTER_INVALID);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router, multicast_router, MulticastRouter,
+                         "Failed to parse bridge multicast router setting");
+
 /* callback for bridge netdev's parameter set */
 static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
         int r;
@@ -138,6 +151,142 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
         return r;
 }
 
+static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(m);
+        assert(link);
+        assert(link->ifname);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not set bridge interface: %m");
+                return 1;
+        }
+
+        return 1;
+}
+
+int link_set_bridge(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set message family: %m");
+
+        r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+        if (link->network->use_bpdu >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
+        }
+
+        if (link->network->hairpin >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
+        }
+
+        if (link->network->fast_leave >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
+        }
+
+        if (link->network->allow_port_to_be_root >=  0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
+        }
+
+        if (link->network->unicast_flood >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+        }
+
+        if (link->network->multicast_flood >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
+        }
+
+        if (link->network->multicast_to_unicast >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
+        }
+
+        if (link->network->neighbor_suppression >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
+        }
+
+        if (link->network->learning >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
+        }
+
+        if (link->network->bridge_proxy_arp >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP, link->network->bridge_proxy_arp);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP attribute: %m");
+        }
+
+        if (link->network->bridge_proxy_arp_wifi >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP_WIFI, link->network->bridge_proxy_arp_wifi);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP_WIFI attribute: %m");
+        }
+
+        if (link->network->cost != 0) {
+                r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
+        }
+
+        if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
+                r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
+        }
+
+        if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bridge_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return r;
+}
+
 static void bridge_init(NetDev *n) {
         Bridge *b;
 
index 3edc93a767a3fdefd34c980f95881505bece1c44..2954155c373928a382fb9c3c6b4d685cc33d9993 100644 (file)
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
-#include "netdev/netdev.h"
+#include <netinet/in.h>
+#include <linux/if_bridge.h>
+
+#include "conf-parser.h"
+#include "netdev.h"
 
 typedef struct Bridge {
         NetDev meta;
@@ -20,5 +24,21 @@ typedef struct Bridge {
         usec_t ageing_time;
 } Bridge;
 
+typedef enum MulticastRouter {
+        MULTICAST_ROUTER_NONE            = MDB_RTR_TYPE_DISABLED,
+        MULTICAST_ROUTER_TEMPORARY_QUERY = MDB_RTR_TYPE_TEMP_QUERY,
+        MULTICAST_ROUTER_PERMANENT       = MDB_RTR_TYPE_PERM,
+        MULTICAST_ROUTER_TEMPORARY       = MDB_RTR_TYPE_TEMP,
+        _MULTICAST_ROUTER_MAX,
+        _MULTICAST_ROUTER_INVALID = -1,
+} MulticastRouter;
+
 DEFINE_NETDEV_CAST(BRIDGE, Bridge);
 extern const NetDevVTable bridge_vtable;
+
+int link_set_bridge(Link *link);
+
+const char* multicast_router_to_string(MulticastRouter i) _const_;
+MulticastRouter multicast_router_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_multicast_router);
index 2d4481e0602d7add39183caa6952205f3ad11e58..772f3db5e7b483584695b788ba5268966bc19cc7 100644 (file)
@@ -1,7 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <linux/fou.h>
 #include <net/if.h>
+#include <netinet/in.h>
 #include <linux/ip.h>
 
 #include "conf-parser.h"
@@ -46,6 +47,12 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PORT attribute: %m");
 
+        if (IN_SET(t->peer_family, AF_INET, AF_INET6)) {
+                r = sd_netlink_message_append_u16(m, FOU_ATTR_PEER_PORT, htobe16(t->peer_port));
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_PORT attribute: %m");
+        }
+
         switch (t->fou_encap_type) {
         case NETDEV_FOO_OVER_UDP_ENCAP_DIRECT:
                 encap_type = FOU_ENCAP_DIRECT;
@@ -69,6 +76,26 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_IPPROTO attribute: %m");
 
+        if (t->local_family == AF_INET) {
+                r = sd_netlink_message_append_in_addr(m, FOU_ATTR_LOCAL_V4, &t->local.in);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_LOCAL_V4 attribute: %m");
+        } else if (t->local_family == AF_INET6) {
+                r = sd_netlink_message_append_in6_addr(m, FOU_ATTR_LOCAL_V6, &t->local.in6);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_LOCAL_V6 attribute: %m");
+        }
+
+        if (t->peer_family == AF_INET) {
+                r = sd_netlink_message_append_in_addr(m, FOU_ATTR_PEER_V4, &t->peer.in);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_V4 attribute: %m");
+        } else if (t->peer_family == AF_INET6){
+                r = sd_netlink_message_append_in6_addr(m, FOU_ATTR_PEER_V6, &t->peer.in6);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_V6 attribute: %m");
+        }
+
         *ret = TAKE_PTR(m);
         return 0;
 }
@@ -150,6 +177,41 @@ int config_parse_ip_protocol(
         return 0;
 }
 
+int config_parse_fou_tunnel_address(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        union in_addr_union *addr = data;
+        FouTunnel *t = userdata;
+        int r, *f;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(lvalue, "Local"))
+                f = &t->local_family;
+        else
+                f = &t->peer_family;
+
+        r = in_addr_from_string_auto(rvalue, f, addr);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Foo over UDP tunnel '%s' address is invalid, ignoring assignment: %s",
+                           lvalue, rvalue);
+
+        return 0;
+}
+
 static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) {
         FouTunnel *t;
 
@@ -177,6 +239,14 @@ static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) {
                 assert_not_reached("Invalid fou encap type");
         }
 
+        if (t->peer_family == AF_UNSPEC && t->peer_port > 0)
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "FooOverUDP peer port is set but peer address not configured in %s. Rejecting configuration.",
+                                              filename);
+        else if (t->peer_family != AF_UNSPEC && t->peer_port == 0)
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "FooOverUDP peer port not set but peer address is configured in %s. Rejecting configuration.",
+                                              filename);
         return 0;
 }
 
index 51eeac41bd237e46e50bef874ae0770793757e98..6304e6b54927ea7ac6bae6d417ce376d90190a9f 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/fou.h>
 
 #include "in-addr-util.h"
@@ -20,8 +21,14 @@ typedef struct FouTunnel {
         uint8_t fou_protocol;
 
         uint16_t port;
+        uint16_t peer_port;
+
+        int local_family;
+        int peer_family;
 
         FooOverUDPEncapType fou_encap_type;
+        union in_addr_union local;
+        union in_addr_union peer;
 } FouTunnel;
 
 DEFINE_NETDEV_CAST(FOU, FouTunnel);
@@ -32,3 +39,4 @@ FooOverUDPEncapType fou_encap_type_from_string(const char *d) _pure_;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_fou_encap_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_ip_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_fou_tunnel_address);
index 0fb09961d626e55f1a49ae3b04b0359b5edf7a64..3dc8f083cc64709395d8ac7cbc21540344d37dcc 100644 (file)
@@ -10,6 +10,7 @@
 #include "geneve.h"
 #include "netlink-util.h"
 #include "parse-util.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "missing.h"
 #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
 #define DEFAULT_GENEVE_DESTINATION_PORT 6081
 
+static const char* const geneve_df_table[_NETDEV_GENEVE_DF_MAX] = {
+        [NETDEV_GENEVE_DF_NO] = "no",
+        [NETDEV_GENEVE_DF_YES] = "yes",
+        [NETDEV_GENEVE_DF_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(geneve_df, GeneveDF, NETDEV_GENEVE_DF_YES);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_geneve_df, geneve_df, GeneveDF, "Failed to parse Geneve IPDoNotFragment= setting");
+
 /* callback for geneve netdev's created without a backing Link */
 static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
         int r;
@@ -92,7 +102,11 @@ static int netdev_geneve_create(NetDev *netdev) {
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_REMOTE/IFLA_GENEVE_REMOTE6 attribute: %m");
         }
 
-        if (v->ttl > 0) {
+        if (v->inherit) {
+                r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL_INHERIT, 1);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL_INHERIT attribute: %m");
+        } else {
                 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
@@ -126,6 +140,12 @@ static int netdev_geneve_create(NetDev *netdev) {
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
         }
 
+        if (v->geneve_df != _NETDEV_GENEVE_DF_INVALID) {
+                r = sd_netlink_message_append_u8(m, IFLA_GENEVE_DF, v->geneve_df);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_DF attribute: %m");
+        }
+
         r = sd_netlink_message_close_container(m);
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
@@ -255,6 +275,47 @@ int config_parse_geneve_flow_label(const char *unit,
         return 0;
 }
 
+int config_parse_geneve_ttl(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) {
+        Geneve *v = userdata;
+        unsigned f;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "inherit"))
+                v->inherit = true;
+        else {
+                r = safe_atou(rvalue, &f);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse Geneve TTL '%s', ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+
+                if (f > 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid Geneve TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue);
+                        return 0;
+                }
+
+                v->ttl = f;
+        }
+
+        return 0;
+}
+
 static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
         Geneve *v = GENEVE(netdev);
 
@@ -262,10 +323,10 @@ static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
         assert(v);
         assert(filename);
 
-        if (v->ttl == 0) {
-                log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename);
-                return -EINVAL;
-        }
+        if (v->id > GENEVE_VID_MAX)
+                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                                "%s: Geneve without valid VNI (or Virtual Network Identifier) configured. Ignoring.",
+                                                filename);
 
         return 0;
 }
@@ -280,6 +341,7 @@ static void geneve_init(NetDev *netdev) {
         assert(v);
 
         v->id = GENEVE_VID_MAX + 1;
+        v->geneve_df = _NETDEV_GENEVE_DF_INVALID;
         v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
         v->udpcsum = false;
         v->udp6zerocsumtx = false;
index c201981e02110b62b270c06d5c2c19a73d8baa8c..32f7f038ba05551ab01a7b024a9b58b57ba8f3d6 100644 (file)
@@ -10,6 +10,14 @@ typedef struct Geneve Geneve;
 
 #define GENEVE_VID_MAX (1u << 24) - 1
 
+typedef enum GeneveDF {
+        NETDEV_GENEVE_DF_NO = GENEVE_DF_UNSET,
+        NETDEV_GENEVE_DF_YES = GENEVE_DF_SET,
+        NETDEV_GENEVE_DF_INHERIT = GENEVE_DF_INHERIT,
+        _NETDEV_GENEVE_DF_MAX,
+        _NETDEV_GENEVE_DF_INVALID = -1
+} GeneveDF;
+
 struct Geneve {
         NetDev meta;
 
@@ -26,13 +34,20 @@ struct Geneve {
         bool udpcsum;
         bool udp6zerocsumtx;
         bool udp6zerocsumrx;
+        bool inherit;
 
+        GeneveDF geneve_df;
         union in_addr_union remote;
 };
 
 DEFINE_NETDEV_CAST(GENEVE, Geneve);
 extern const NetDevVTable geneve_vtable;
 
+const char *geneve_df_to_string(GeneveDF d) _const_;
+GeneveDF geneve_df_from_string(const char *d) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_geneve_vni);
 CONFIG_PARSER_PROTOTYPE(config_parse_geneve_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_geneve_flow_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_geneve_df);
+CONFIG_PARSER_PROTOTYPE(config_parse_geneve_ttl);
index 5bb6a5bb35b7a6c421c40f43dd1537266035bc7d..f48cb0231ad05f9dafc261e0838e90dd6007b6af 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "conf-parser.h"
 #include "netdev/ipvlan.h"
+#include "networkd-link.h"
 #include "string-table.h"
 
 static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = {
@@ -32,7 +33,10 @@ static int netdev_ipvlan_fill_message_create(NetDev *netdev, Link *link, sd_netl
         assert(link);
         assert(netdev->ifname);
 
-        m = IPVLAN(netdev);
+        if (netdev->kind == NETDEV_KIND_IPVLAN)
+                m = IPVLAN(netdev);
+        else
+                m = IPVTAP(netdev);
 
         assert(m);
 
@@ -56,7 +60,10 @@ static void ipvlan_init(NetDev *n) {
 
         assert(n);
 
-        m = IPVLAN(n);
+        if (n->kind == NETDEV_KIND_IPVLAN)
+                m = IPVLAN(n);
+        else
+                m = IPVTAP(n);
 
         assert(m);
 
@@ -71,3 +78,26 @@ const NetDevVTable ipvlan_vtable = {
         .fill_message_create = netdev_ipvlan_fill_message_create,
         .create_type = NETDEV_CREATE_STACKED,
 };
+
+const NetDevVTable ipvtap_vtable = {
+        .object_size = sizeof(IPVlan),
+        .init = ipvlan_init,
+        .sections = "Match\0NetDev\0IPVTAP\0",
+        .fill_message_create = netdev_ipvlan_fill_message_create,
+        .create_type = NETDEV_CREATE_STACKED,
+};
+
+IPVlanMode link_get_ipvlan_mode(Link *link) {
+        NetDev *netdev;
+
+        if (!streq_ptr(link->kind, "ipvlan"))
+                return _NETDEV_IPVLAN_MODE_INVALID;
+
+        if (netdev_get(link->manager, link->ifname, &netdev) < 0)
+                return _NETDEV_IPVLAN_MODE_INVALID;
+
+        if (netdev->kind != NETDEV_KIND_IPVLAN)
+                return _NETDEV_IPVLAN_MODE_INVALID;
+
+        return IPVLAN(netdev)->mode;
+}
index 78f09dbb2d58a9915424bbc37239aaa579e51c52..3bad56d500cf518f8043db8b663b20354a49b4dd 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/if_link.h>
 
 #include "netdev/netdev.h"
@@ -29,7 +30,9 @@ typedef struct IPVlan {
 } IPVlan;
 
 DEFINE_NETDEV_CAST(IPVLAN, IPVlan);
+DEFINE_NETDEV_CAST(IPVTAP, IPVlan);
 extern const NetDevVTable ipvlan_vtable;
+extern const NetDevVTable ipvtap_vtable;
 
 const char *ipvlan_mode_to_string(IPVlanMode d) _const_;
 IPVlanMode ipvlan_mode_from_string(const char *d) _pure_;
@@ -39,3 +42,5 @@ IPVlanFlags ipvlan_flags_from_string(const char *d) _pure_;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_ipvlan_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipvlan_flags);
+
+IPVlanMode link_get_ipvlan_mode(Link *link);
index 2a74d89e5d229a4159a56bc3b5bed774cc0f3f3f..6ac23052bb3ce94ed37a6ba4852ac62869d63468 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <linux/l2tp.h>
 #include <linux/genetlink.h>
 
index a97c924c5d236e240f6f691585f5d88d9fe9116d..d314b9870344d278e1510841885d7ef5a1b3c919 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/l2tp.h>
 
 #include "in-addr-util.h"
index ccc37cded4684494603a2b8587e698558e1ed1fc..c82a6fd0ac16a4580eb517ddf99c5919da0a91c3 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <linux/if_ether.h>
 #include <linux/if_macsec.h>
 #include <linux/genetlink.h>
index 2bd08ac500950c744a8b0619c494317b888119d6..2a3443a6d4e6dcba45ee7926d5546194d3331095 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/if_macsec.h>
 
 #include "in-addr-util.h"
index 107827567ea857932c650ca8fc0a25f1ad4a89d0..0cf6949968b759c7dace9f964c6a73df5c93b414 100644 (file)
@@ -54,6 +54,8 @@ MACVLAN.Mode,                             config_parse_macvlan_mode,
 MACVTAP.Mode,                             config_parse_macvlan_mode,                 0,                             offsetof(MacVlan, mode)
 IPVLAN.Mode,                              config_parse_ipvlan_mode,                  0,                             offsetof(IPVlan, mode)
 IPVLAN.Flags,                             config_parse_ipvlan_flags,                 0,                             offsetof(IPVlan, flags)
+IPVTAP.Mode,                              config_parse_ipvlan_mode,                  0,                             offsetof(IPVlan, mode)
+IPVTAP.Flags,                             config_parse_ipvlan_flags,                 0,                             offsetof(IPVlan, flags)
 Tunnel.Local,                             config_parse_tunnel_address,               0,                             offsetof(Tunnel, local)
 Tunnel.Remote,                            config_parse_tunnel_address,               0,                             offsetof(Tunnel, remote)
 Tunnel.TOS,                               config_parse_unsigned,                     0,                             offsetof(Tunnel, tos)
@@ -79,6 +81,9 @@ Tunnel.ISATAP,                            config_parse_tristate,
 FooOverUDP.Protocol,                      config_parse_ip_protocol,                  0,                             offsetof(FouTunnel, fou_protocol)
 FooOverUDP.Encapsulation,                 config_parse_fou_encap_type,               0,                             offsetof(FouTunnel, fou_encap_type)
 FooOverUDP.Port,                          config_parse_ip_port,                      0,                             offsetof(FouTunnel, port)
+FooOverUDP.PeerPort,                      config_parse_ip_port,                      0,                             offsetof(FouTunnel, peer_port)
+FooOverUDP.Local,                         config_parse_fou_tunnel_address,           0,                             offsetof(FouTunnel, local)
+FooOverUDP.Peer,                          config_parse_fou_tunnel_address,           0,                             offsetof(FouTunnel, peer)
 L2TP.TunnelId,                            config_parse_l2tp_tunnel_id,               0,                             offsetof(L2tpTunnel, tunnel_id)
 L2TP.PeerTunnelId,                        config_parse_l2tp_tunnel_id,               0,                             offsetof(L2tpTunnel, peer_tunnel_id)
 L2TP.UDPSourcePort,                       config_parse_ip_port,                      0,                             offsetof(L2tpTunnel, l2tp_udp_sport)
@@ -96,12 +101,13 @@ L2TPSession.Name,                         config_parse_l2tp_session_name,
 Peer.Name,                                config_parse_ifname,                       0,                             offsetof(Veth, ifname_peer)
 Peer.MACAddress,                          config_parse_hwaddr,                       0,                             offsetof(Veth, mac_peer)
 VXCAN.Peer,                               config_parse_ifname,                       0,                             offsetof(VxCan, ifname_peer)
-VXLAN.Id,                                 config_parse_uint64,                       0,                             offsetof(VxLan, id)
-VXLAN.Group,                              config_parse_vxlan_address,                0,                             offsetof(VxLan, remote)
+VXLAN.VNI,                                config_parse_uint32,                       0,                             offsetof(VxLan, vni)
+VXLAN.Id,                                 config_parse_uint32,                       0,                             offsetof(VxLan, vni) /* deprecated */
+VXLAN.Group,                              config_parse_vxlan_address,                0,                             offsetof(VxLan, group)
 VXLAN.Local,                              config_parse_vxlan_address,                0,                             offsetof(VxLan, local)
 VXLAN.Remote,                             config_parse_vxlan_address,                0,                             offsetof(VxLan, remote)
 VXLAN.TOS,                                config_parse_unsigned,                     0,                             offsetof(VxLan, tos)
-VXLAN.TTL,                                config_parse_unsigned,                     0,                             offsetof(VxLan, ttl)
+VXLAN.TTL,                                config_parse_vxlan_ttl,                    0,                             offsetof(VxLan, ttl)
 VXLAN.MacLearning,                        config_parse_bool,                         0,                             offsetof(VxLan, learning)
 VXLAN.ARPProxy,                           config_parse_bool,                         0,                             offsetof(VxLan, arp_proxy)
 VXLAN.ReduceARPProxy,                     config_parse_bool,                         0,                             offsetof(VxLan, arp_proxy)
@@ -118,20 +124,23 @@ VXLAN.RemoteChecksumTx,                   config_parse_bool,
 VXLAN.RemoteChecksumRx,                   config_parse_bool,                         0,                             offsetof(VxLan, remote_csum_rx)
 VXLAN.FDBAgeingSec,                       config_parse_sec,                          0,                             offsetof(VxLan, fdb_ageing)
 VXLAN.GroupPolicyExtension,               config_parse_bool,                         0,                             offsetof(VxLan, group_policy)
+VXLAN.GenericProtocolExtension,           config_parse_bool,                         0,                             offsetof(VxLan, generic_protocol_extension)
 VXLAN.MaximumFDBEntries,                  config_parse_unsigned,                     0,                             offsetof(VxLan, max_fdb)
 VXLAN.PortRange,                          config_parse_port_range,                   0,                             0
 VXLAN.DestinationPort,                    config_parse_ip_port,                      0,                             offsetof(VxLan, dest_port)
 VXLAN.FlowLabel,                          config_parse_flow_label,                   0,                             0
+VXLAN.IPDoNotFragment,                    config_parse_df,                           0,                             offsetof(VxLan, df)
 GENEVE.Id,                                config_parse_geneve_vni,                   0,                             offsetof(Geneve, id)
 GENEVE.Remote,                            config_parse_geneve_address,               0,                             offsetof(Geneve, remote)
 GENEVE.TOS,                               config_parse_uint8,                        0,                             offsetof(Geneve, tos)
-GENEVE.TTL,                               config_parse_uint8,                        0,                             offsetof(Geneve, ttl)
+GENEVE.TTL,                               config_parse_geneve_ttl,                   0,                             offsetof(Geneve, ttl)
 GENEVE.UDPChecksum,                       config_parse_bool,                         0,                             offsetof(Geneve, udpcsum)
 GENEVE.UDP6ZeroCheckSumRx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumrx)
 GENEVE.UDP6ZeroChecksumRx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumrx)
 GENEVE.UDP6ZeroCheckSumTx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumtx)
 GENEVE.UDP6ZeroChecksumTx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumtx)
 GENEVE.DestinationPort,                   config_parse_ip_port,                      0,                             offsetof(Geneve, dest_port)
+GENEVE.IPDoNotFragment,                   config_parse_geneve_df,                    0,                             offsetof(Geneve, geneve_df)
 GENEVE.FlowLabel,                         config_parse_geneve_flow_label,            0,                             0
 MACsec.Port,                              config_parse_macsec_port,                  0,                             0
 MACsec.Encrypt,                           config_parse_tristate,                     0,                             offsetof(MACsec, encrypt)
@@ -150,12 +159,13 @@ MACsecReceiveAssociation.KeyId,           config_parse_macsec_key_id,
 MACsecReceiveAssociation.Key,             config_parse_macsec_key,                   0,                             0
 MACsecReceiveAssociation.KeyFile,         config_parse_macsec_key_file,              0,                             0
 MACsecReceiveAssociation.Activate,        config_parse_macsec_sa_activate,           0,                             0
-Tun.OneQueue,                             config_parse_bool,                         0,                             offsetof(TunTap, one_queue)
+Tun.OneQueue,                             config_parse_warn_compat,                  DISABLED_LEGACY,               0
 Tun.MultiQueue,                           config_parse_bool,                         0,                             offsetof(TunTap, multi_queue)
 Tun.PacketInfo,                           config_parse_bool,                         0,                             offsetof(TunTap, packet_info)
+Tun.VNetHeader,                           config_parse_bool,                         0,                             offsetof(TunTap, vnet_hdr)
 Tun.User,                                 config_parse_string,                       0,                             offsetof(TunTap, user_name)
 Tun.Group,                                config_parse_string,                       0,                             offsetof(TunTap, group_name)
-Tap.OneQueue,                             config_parse_bool,                         0,                             offsetof(TunTap, one_queue)
+Tap.OneQueue,                             config_parse_warn_compat,                  DISABLED_LEGACY,               0
 Tap.MultiQueue,                           config_parse_bool,                         0,                             offsetof(TunTap, multi_queue)
 Tap.PacketInfo,                           config_parse_bool,                         0,                             offsetof(TunTap, packet_info)
 Tap.VNetHeader,                           config_parse_bool,                         0,                             offsetof(TunTap, vnet_hdr)
@@ -197,7 +207,8 @@ Bridge.VLANFiltering,                     config_parse_tristate,
 Bridge.STP,                               config_parse_tristate,                     0,                             offsetof(Bridge, stp)
 VRF.TableId,                              config_parse_uint32,                       0,                             offsetof(Vrf, table) /* deprecated */
 VRF.Table,                                config_parse_uint32,                       0,                             offsetof(Vrf, table)
-WireGuard.FwMark,                         config_parse_unsigned,                     0,                             offsetof(Wireguard, fwmark)
+WireGuard.FirewallMark,                   config_parse_unsigned,                     0,                             offsetof(Wireguard, fwmark)
+WireGuard.FwMark,                         config_parse_unsigned,                     0,                             offsetof(Wireguard, fwmark) /* deprecated */
 WireGuard.ListenPort,                     config_parse_wireguard_listen_port,        0,                             offsetof(Wireguard, port)
 WireGuard.PrivateKey,                     config_parse_wireguard_private_key,        0,                             0
 WireGuard.PrivateKeyFile,                 config_parse_wireguard_private_key_file,   0,                             0
index d8b8bca7e83d2fb7a136128220a4925f732c9ab8..3968ab54956c7e8c0d6d2cae499e6a777d4ee67d 100644 (file)
@@ -45,6 +45,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
         [NETDEV_KIND_MACVTAP] = &macvtap_vtable,
         [NETDEV_KIND_IPVLAN] = &ipvlan_vtable,
+        [NETDEV_KIND_IPVTAP] = &ipvtap_vtable,
         [NETDEV_KIND_VXLAN] = &vxlan_vtable,
         [NETDEV_KIND_IPIP] = &ipip_vtable,
         [NETDEV_KIND_GRE] = &gre_vtable,
@@ -78,6 +79,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_MACVLAN] = "macvlan",
         [NETDEV_KIND_MACVTAP] = "macvtap",
         [NETDEV_KIND_IPVLAN] = "ipvlan",
+        [NETDEV_KIND_IPVTAP] = "ipvtap",
         [NETDEV_KIND_VXLAN] = "vxlan",
         [NETDEV_KIND_IPIP] = "ipip",
         [NETDEV_KIND_GRE] = "gre",
@@ -254,7 +256,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, link_netlink_message
 
         if (link->flags & IFF_UP && netdev->kind == NETDEV_KIND_BOND) {
                 log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname);
-                r = link_down(link);
+                r = link_down(link, NULL);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not bring link down: %m");
         }
@@ -732,7 +734,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
         if (!netdev->filename)
                 return log_oom();
 
-        if (!netdev->mac && netdev->kind != NETDEV_KIND_VLAN) {
+        if (!netdev->mac && !IN_SET(netdev->kind, NETDEV_KIND_VLAN, NETDEV_KIND_BRIDGE)) {
                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r,
index 29ecead029b8bca71e509a8857869a01a6dbefab..dcf072ce94452ef34cc02e40cf6549e6a6ad3ef7 100644 (file)
@@ -24,6 +24,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_MACVLAN,
         NETDEV_KIND_MACVTAP,
         NETDEV_KIND_IPVLAN,
+        NETDEV_KIND_IPVTAP,
         NETDEV_KIND_VXLAN,
         NETDEV_KIND_IPIP,
         NETDEV_KIND_GRE,
index 84f6af8578fc4628d089a73e0c1476bb3990a746..e69a009c315a2deb1d097111885b5d963177ceae 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <linux/fou.h>
 #include <linux/ip.h>
 #include <linux/if_tunnel.h>
index 951138d257a37bdd70c7b47b12b6dd33e13bd7d2..5b799e73a35b8654b490d144d2078db31d25f6a3 100644 (file)
@@ -2,12 +2,12 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/if_tun.h>
 #include <net/if.h>
 #include <netinet/if_ether.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <linux/if_tun.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
@@ -34,9 +34,6 @@ static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
         if (!t->packet_info)
                 ifr->ifr_flags |= IFF_NO_PI;
 
-        if (t->one_queue)
-                ifr->ifr_flags |= IFF_ONE_QUEUE;
-
         if (t->multi_queue)
                 ifr->ifr_flags |= IFF_MULTI_QUEUE;
 
@@ -134,10 +131,16 @@ static int tuntap_verify(NetDev *netdev, const char *filename) {
         assert(netdev);
 
         if (netdev->mtu != 0)
-                log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
+                log_netdev_warning(netdev,
+                                   "MTUBytes= configured for %s device in %s will be ignored.\n"
+                                   "Please set it in the corresponding .network file.",
+                                   netdev_kind_to_string(netdev->kind), filename);
 
         if (netdev->mac)
-                log_netdev_warning(netdev, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
+                log_netdev_warning(netdev,
+                                   "MACAddress= configured for %s device in %s will be ignored.\n"
+                                   "Please set it in the corresponding .network file.",
+                                   netdev_kind_to_string(netdev->kind), filename);
 
         return 0;
 }
index 9d9f9922b508429d4aadab65f4d554ba866e199a..1a1600b05529f2c9767391c2b9c3a08c5309b6c7 100644 (file)
@@ -10,7 +10,6 @@ struct TunTap {
 
         char *user_name;
         char *group_name;
-        bool one_queue;
         bool multi_queue;
         bool packet_info;
         bool vnet_hdr;
index 6f62686d0801e8491f9d5056eee38a4dfa55b89e..671b5cb6390a2dadfea2ef2a6a637557b6b06b30 100644 (file)
@@ -3,6 +3,7 @@
 
 typedef struct VCan VCan;
 
+#include <netinet/in.h>
 #include <linux/can/netlink.h>
 
 #include "netdev/netdev.h"
index 3ad95ade0f2be6fbfaa48d28ed78ce8deaa134e3..a0a0b8e39ec4599a4f772c6736c874f2f0cb59b0 100644 (file)
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
-#include <linux/veth.h>
 #include <net/if.h>
+#include <linux/veth.h>
 
 #include "sd-netlink.h"
 
index dd548b338aebc5eebeea7fb268867768b1498172..4d939ab0456adeeba34cc723be728b75d7e9c924 100644 (file)
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
-#include <linux/if_vlan.h>
 #include <net/if.h>
+#include <linux/if_vlan.h>
 
 #include "netdev/vlan.h"
 #include "vlan-util.h"
index 4b855ae1e1161b3d76f989b2da053dda1b1ca930..e24537083b64fbecc18e10835906214020236bc7 100644 (file)
@@ -7,6 +7,7 @@
 #include "conf-parser.h"
 #include "alloc-util.h"
 #include "extract-word.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "parse-util.h"
 #include "networkd-link.h"
 #include "netdev/vxlan.h"
 
+static const char* const df_table[_NETDEV_VXLAN_DF_MAX] = {
+        [NETDEV_VXLAN_DF_NO] = "no",
+        [NETDEV_VXLAN_DF_YES] = "yes",
+        [NETDEV_VXLAN_DF_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(df, VxLanDF, NETDEV_VXLAN_DF_YES);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_df, df, VxLanDF, "Failed to parse VXLAN IPDoNotFragment= setting");
+
 static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
         VxLan *v;
         int r;
@@ -27,8 +37,8 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
 
         assert(v);
 
-        if (v->id <= VXLAN_VID_MAX) {
-                r = sd_netlink_message_append_u32(m, IFLA_VXLAN_ID, v->id);
+        if (v->vni <= VXLAN_VID_MAX) {
+                r = sd_netlink_message_append_u32(m, IFLA_VXLAN_ID, v->vni);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_ID attribute: %m");
         }
@@ -55,7 +65,11 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m");
 
-        if (v->ttl != 0) {
+        if (v->inherit) {
+                r = sd_netlink_message_append_flag(m, IFLA_VXLAN_TTL_INHERIT);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL_INHERIT attribute: %m");
+        } else {
                 r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m");
@@ -144,6 +158,18 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GBP attribute: %m");
         }
 
+        if (v->generic_protocol_extension) {
+                r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GPE);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GPE attribute: %m");
+        }
+
+        if (v->df != _NETDEV_VXLAN_DF_INVALID) {
+                r = sd_netlink_message_append_u8(m, IFLA_VXLAN_DF, v->df);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_DF attribute: %m");
+        }
+
         return r;
 }
 
@@ -180,7 +206,7 @@ int config_parse_vxlan_address(const char *unit,
                         return 0;
                 }
 
-                v->remote_family = f;
+                v->group_family = f;
         } else {
                 if (r > 0) {
                         log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue, rvalue);
@@ -266,6 +292,47 @@ int config_parse_flow_label(const char *unit,
         return 0;
 }
 
+int config_parse_vxlan_ttl(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) {
+        VxLan *v = userdata;
+        unsigned f;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "inherit"))
+                v->inherit = true;
+        else {
+                r = safe_atou(rvalue, &f);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse VXLAN TTL '%s', ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+
+                if (f > 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid VXLAN TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue);
+                        return 0;
+                }
+
+                v->ttl = f;
+        }
+
+        return 0;
+}
+
 static int netdev_vxlan_verify(NetDev *netdev, const char *filename) {
         VxLan *v = VXLAN(netdev);
 
@@ -273,10 +340,18 @@ static int netdev_vxlan_verify(NetDev *netdev, const char *filename) {
         assert(v);
         assert(filename);
 
-        if (v->id > VXLAN_VID_MAX) {
-                log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
-                return -EINVAL;
-        }
+        if (v->vni > VXLAN_VID_MAX)
+                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                                "%s: VXLAN without valid VNI (or VXLAN Segment ID) configured. Ignoring.",
+                                                filename);
+
+        if (v->ttl > 255)
+                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                                "%s: VXLAN TTL must be <= 255. Ignoring.",
+                                                filename);
+
+        if (!v->dest_port && v->generic_protocol_extension)
+                v->dest_port = 4790;
 
         return 0;
 }
@@ -290,7 +365,8 @@ static void vxlan_init(NetDev *netdev) {
 
         assert(v);
 
-        v->id = VXLAN_VID_MAX + 1;
+        v->vni = VXLAN_VID_MAX + 1;
+        v->df = _NETDEV_VXLAN_DF_INVALID;
         v->learning = true;
         v->udpcsum = false;
         v->udp6zerocsumtx = false;
index 3b273e97bdbbf58f6d44361c923c85405ced4eb1..0c61bba2b89de3b3753a80f0a46ce2df1baf7a77 100644 (file)
@@ -3,22 +3,36 @@
 
 typedef struct VxLan VxLan;
 
+#include <linux/if_link.h>
+
 #include "in-addr-util.h"
 #include "netdev/netdev.h"
 
 #define VXLAN_VID_MAX (1u << 24) - 1
 #define VXLAN_FLOW_LABEL_MAX_MASK 0xFFFFFU
 
+typedef enum VxLanDF {
+        NETDEV_VXLAN_DF_NO = VXLAN_DF_UNSET,
+        NETDEV_VXLAN_DF_YES = VXLAN_DF_SET,
+        NETDEV_VXLAN_DF_INHERIT = VXLAN_DF_INHERIT,
+        _NETDEV_VXLAN_DF_MAX,
+        _NETDEV_VXLAN_DF_INVALID = -1
+} VxLanDF;
+
 struct VxLan {
         NetDev meta;
 
-        uint64_t id;
+        uint32_t vni;
 
         int remote_family;
         int local_family;
+        int group_family;
+
+        VxLanDF df;
 
         union in_addr_union remote;
         union in_addr_union local;
+        union in_addr_union group;
 
         unsigned tos;
         unsigned ttl;
@@ -40,6 +54,8 @@ struct VxLan {
         bool remote_csum_tx;
         bool remote_csum_rx;
         bool group_policy;
+        bool generic_protocol_extension;
+        bool inherit;
 
         struct ifla_vxlan_port_range port_range;
 };
@@ -47,6 +63,11 @@ struct VxLan {
 DEFINE_NETDEV_CAST(VXLAN, VxLan);
 extern const NetDevVTable vxlan_vtable;
 
+const char *df_to_string(VxLanDF d) _const_;
+VxLanDF df_from_string(const char *d) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_vxlan_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_port_range);
 CONFIG_PARSER_PROTOTYPE(config_parse_flow_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_df);
+CONFIG_PARSER_PROTOTYPE(config_parse_vxlan_ttl);
index 5ebc5dfed84bffe52e496d6c1380d06cf6919b15..91fcee1401b0056d7c01cb30ae300f57c309a243 100644 (file)
@@ -401,7 +401,7 @@ static void resolve_endpoints(NetDev *netdev) {
         WireguardPeer *peer;
         Wireguard *w;
         Iterator i;
-        int r = 0;
+        int r;
 
         assert(netdev);
         w = WIREGUARD(netdev);
index 862f2a99c4c7b3f4cd74f9a20c9aecc246aab814..ce336c985acdc6b6185fc8f42b96dd5dacc799aa 100644 (file)
@@ -2,6 +2,7 @@
 
 typedef struct Wireguard Wireguard;
 
+#include <netinet/in.h>
 #include <linux/wireguard.h>
 
 #include "in-addr-util.h"
index 3881aaa42b577b43c4d484f448445fb7cce9ff50..824db8cc9ae175c5e33253718375829bf3a4c066 100644 (file)
@@ -101,9 +101,17 @@ typedef struct LinkInfo {
         unsigned short iftype;
         struct ether_addr mac_address;
         uint32_t mtu;
+        uint32_t min_mtu;
+        uint32_t max_mtu;
+        uint32_t tx_queues;
+        uint32_t rx_queues;
 
         bool has_mac_address:1;
         bool has_mtu:1;
+        bool has_min_mtu:1;
+        bool has_max_mtu:1;
+        bool has_tx_queues:1;
+        bool has_rx_queues:1;
 } LinkInfo;
 
 static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
@@ -154,9 +162,25 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) {
                 memcmp(&info->mac_address, &ETHER_ADDR_NULL, sizeof(struct ether_addr)) != 0;
 
         info->has_mtu =
-                sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) &&
+                sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) >= 0 &&
                 info->mtu > 0;
 
+        info->has_min_mtu =
+                sd_netlink_message_read_u32(m, IFLA_MIN_MTU, &info->min_mtu) >= 0 &&
+                info->min_mtu > 0;
+
+        info->has_max_mtu =
+                sd_netlink_message_read_u32(m, IFLA_MAX_MTU, &info->max_mtu) >= 0 &&
+                info->min_mtu > 0;
+
+        info->has_rx_queues =
+                sd_netlink_message_read_u32(m, IFLA_NUM_RX_QUEUES, &info->rx_queues) >= 0 &&
+                info->rx_queues > 0;
+
+        info->has_tx_queues =
+                sd_netlink_message_read_u32(m, IFLA_NUM_TX_QUEUES, &info->tx_queues) >= 0 &&
+                info->tx_queues > 0;
+
         return 1;
 }
 
@@ -320,8 +344,8 @@ static int get_gateway_description(
                 return r;
 
         for (m = reply; m; m = sd_netlink_message_next(m)) {
-                union in_addr_union gw = {};
-                struct ether_addr mac = {};
+                union in_addr_union gw = IN_ADDR_NULL;
+                struct ether_addr mac = ETHER_ADDR_NULL;
                 uint16_t type;
                 int ifi, fam;
 
@@ -514,7 +538,7 @@ static int dump_address_labels(sd_netlink *rtnl) {
 
         for (m = reply; m; m = sd_netlink_message_next(m)) {
                 _cleanup_free_ char *pretty = NULL;
-                union in_addr_union prefix = {};
+                union in_addr_union prefix = IN_ADDR_NULL;
                 uint8_t prefixlen;
                 uint32_t label;
 
@@ -746,10 +770,10 @@ static int link_status_one(
 
         printf("%s%s%s %i: %s\n", on_color_operational, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off_color_operational, info->ifindex, info->name);
 
-        printf("       Link File: %s\n"
-               "    Network File: %s\n"
-               "            Type: %s\n"
-               "           State: %s%s%s (%s%s%s)\n",
+        printf("            Link File: %s\n"
+               "         Network File: %s\n"
+               "                 Type: %s\n"
+               "                State: %s%s%s (%s%s%s)\n",
                strna(link),
                strna(network),
                strna(t),
@@ -757,13 +781,13 @@ static int link_status_one(
                on_color_setup, strna(setup_state), off_color_setup);
 
         if (path)
-                printf("            Path: %s\n", path);
+                printf("                 Path: %s\n", path);
         if (driver)
-                printf("          Driver: %s\n", driver);
+                printf("               Driver: %s\n", driver);
         if (vendor)
-                printf("          Vendor: %s\n", vendor);
+                printf("               Vendor: %s\n", vendor);
         if (model)
-                printf("           Model: %s\n", model);
+                printf("                Model: %s\n", model);
 
         if (info->has_mac_address) {
                 _cleanup_free_ char *description = NULL;
@@ -772,31 +796,40 @@ static int link_status_one(
                 (void) ieee_oui(hwdb, &info->mac_address, &description);
 
                 if (description)
-                        printf("      HW Address: %s (%s)\n", ether_addr_to_string(&info->mac_address, ea), description);
+                        printf("           HW Address: %s (%s)\n", ether_addr_to_string(&info->mac_address, ea), description);
                 else
-                        printf("      HW Address: %s\n", ether_addr_to_string(&info->mac_address, ea));
+                        printf("           HW Address: %s\n", ether_addr_to_string(&info->mac_address, ea));
         }
 
         if (info->has_mtu)
-                printf("             MTU: %" PRIu32 "\n", info->mtu);
+                printf("                  MTU: %" PRIu32 "\n", info->mtu);
+        if (info->has_min_mtu)
+                printf("          Minimum MTU: %" PRIu32 "\n", info->min_mtu);
+        if (info->has_max_mtu)
+                printf("          Maximum MTU: %" PRIu32 "\n", info->max_mtu);
+
+        if (info->has_tx_queues)
+                printf("Transmit Queue Length: %" PRIu32 "\n", info->tx_queues);
+        if (info->has_rx_queues)
+                printf(" Receive Queue Length: %" PRIu32 "\n", info->rx_queues);
 
-        (void) dump_addresses(rtnl, "         Address: ", info->ifindex);
-        (void) dump_gateways(rtnl, hwdb, "         Gateway: ", info->ifindex);
+        (void) dump_addresses(rtnl, "              Address: ", info->ifindex);
+        (void) dump_gateways(rtnl, hwdb, "              Gateway: ", info->ifindex);
 
-        dump_list("             DNS: ", dns);
-        dump_list("  Search Domains: ", search_domains);
-        dump_list("   Route Domains: ", route_domains);
+        dump_list("                  DNS: ", dns);
+        dump_list("       Search Domains: ", search_domains);
+        dump_list("        Route Domains: ", route_domains);
 
-        dump_list("             NTP: ", ntp);
+        dump_list("                  NTP: ", ntp);
 
         dump_ifindexes("Carrier Bound To: ", carrier_bound_to);
         dump_ifindexes("Carrier Bound By: ", carrier_bound_by);
 
         (void) sd_network_link_get_timezone(info->ifindex, &tz);
         if (tz)
-                printf("       Time Zone: %s\n", tz);
+                printf("            Time Zone: %s\n", tz);
 
-        (void) dump_lldp_neighbors("    Connected To: ", info->ifindex);
+        (void) dump_lldp_neighbors("         Connected To: ", info->ifindex);
 
         return 0;
 }
@@ -1128,6 +1161,7 @@ static void warn_networkd_missing(void) {
 static int run(int argc, char* argv[]) {
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index eaf056d11864d2625ff1c7cc3002448ee10da4d3..db6c1456dc7e5c20b70783ffae1a29b26b8a8e58 100644 (file)
@@ -106,7 +106,7 @@ static bool address_pool_prefix_is_taken(
         }
 
         /* And don't clash with configured but un-assigned addresses either */
-        LIST_FOREACH(networks, n, p->manager->networks) {
+        ORDERED_HASHMAP_FOREACH(n, p->manager->networks, i) {
                 Address *a;
 
                 LIST_FOREACH(addresses, a, n->static_addresses) {
index 42d61cc0e50569eb5afcf93a18b9137ee914584f..600bad474dcf507d18289cff93f64a525da9cac2 100644 (file)
@@ -490,7 +490,7 @@ int address_remove(
 }
 
 static int address_acquire(Link *link, Address *original, Address **ret) {
-        union in_addr_union in_addr = {};
+        union in_addr_union in_addr = IN_ADDR_NULL;
         struct in_addr broadcast = {};
         _cleanup_(address_freep) Address *na = NULL;
         int r;
diff --git a/src/network/networkd-can.c b/src/network/networkd-can.c
new file mode 100644 (file)
index 0000000..5755df5
--- /dev/null
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <net/if.h>
+#include <linux/can/netlink.h>
+
+#include "netlink-util.h"
+#include "networkd-can.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "string-util.h"
+
+static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0)
+                /* we warn but don't fail the link, as it may be brought up later */
+                log_link_warning_errno(link, r, "Could not bring up interface: %m");
+
+        return 1;
+}
+
+static int link_up_can(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+
+        log_link_debug(link, "Bringing CAN link up");
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set link flags: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return 0;
+}
+
+static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        log_link_debug(link, "Set link");
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0 && r != -EEXIST) {
+                log_link_error_errno(link, r, "Failed to configure CAN link: %m");
+                link_enter_failed(link);
+        }
+
+        return 1;
+}
+
+static int link_set_can(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(link->manager);
+        assert(link->manager->rtnl);
+
+        log_link_debug(link, "Configuring CAN link.");
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to allocate netlink message: %m");
+
+        r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to open netlink container: %m");
+
+        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) {
+                struct can_bittiming bt = {
+                        .bitrate = link->network->can_bitrate,
+                        .sample_point = link->network->can_sample_point,
+                };
+
+                if (link->network->can_bitrate > UINT32_MAX) {
+                        log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate);
+                        return -ERANGE;
+                }
+
+                log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
+                if (link->network->can_sample_point > 0)
+                        log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
+                else
+                        log_link_debug(link, "Using default sample point");
+
+                r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
+        }
+
+        if (link->network->can_restart_us > 0) {
+                char time_string[FORMAT_TIMESPAN_MAX];
+                uint64_t restart_ms;
+
+                if (link->network->can_restart_us == USEC_INFINITY)
+                        restart_ms = 0;
+                else
+                        restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC);
+
+                format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC);
+
+                if (restart_ms > UINT32_MAX) {
+                        log_link_error(link, "restart timeout (%s) too big.", time_string);
+                        return -ERANGE;
+                }
+
+                log_link_debug(link, "Setting restart = %s", time_string);
+
+                r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
+        }
+
+        if (link->network->can_triple_sampling >= 0) {
+                struct can_ctrlmode cm = {
+                        .mask = CAN_CTRLMODE_3_SAMPLES,
+                        .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0,
+                };
+
+                log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis");
+
+                r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(m);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
+
+        r = sd_netlink_message_close_container(m);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        if (!(link->flags & IFF_UP))
+                return link_up_can(link);
+
+        return 0;
+}
+
+static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not bring down interface: %m");
+                link_enter_failed(link);
+                return 1;
+        }
+
+        r = link_set_can(link);
+        if (r < 0)
+                link_enter_failed(link);
+
+        return 1;
+}
+
+int link_configure_can(Link *link) {
+        int r;
+
+        link_set_state(link, LINK_STATE_CONFIGURING);
+
+        if (streq_ptr(link->kind, "can")) {
+                /* The CAN interface must be down to configure bitrate, etc... */
+                if ((link->flags & IFF_UP)) {
+                        r = link_down(link, link_down_handler);
+                        if (r < 0) {
+                                link_enter_failed(link);
+                                return r;
+                        }
+                } else {
+                        r = link_set_can(link);
+                        if (r < 0) {
+                                link_enter_failed(link);
+                                return r;
+                        }
+                }
+
+                return 0;
+        }
+
+        if (!(link->flags & IFF_UP)) {
+                r = link_up_can(link);
+                if (r < 0) {
+                        link_enter_failed(link);
+                        return r;
+                }
+        }
+
+        return 0;
+}
diff --git a/src/network/networkd-can.h b/src/network/networkd-can.h
new file mode 100644 (file)
index 0000000..c744bdf
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+typedef struct Link Link;
+
+int link_configure_can(Link *link);
index 301d9c67b934338b3ae2128decd271c10ebb5e18..b170906f2129a22e50bcb7ab29b43e13933de5e0 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 
 #include "alloc-util.h"
@@ -261,7 +261,7 @@ static int dhcp_lease_lost(Link *link) {
 
                 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
                 if (r >= 0 && link->original_mtu != mtu) {
-                        r = link_set_mtu(link, link->original_mtu, true);
+                        r = link_set_mtu(link, link->original_mtu);
                         if (r < 0) {
                                 log_link_warning(link,
                                                  "DHCP error: could not reset MTU");
@@ -454,7 +454,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
 
                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
                 if (r >= 0) {
-                        r = link_set_mtu(link, mtu, true);
+                        r = link_set_mtu(link, mtu);
                         if (r < 0)
                                 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
                 }
@@ -511,31 +511,76 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
 
         return 0;
 }
-static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
+
+static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) {
+        sd_dhcp_lease *lease;
+        struct in_addr addr;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(client);
+
+        r = sd_dhcp_client_get_lease(client, &lease);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
+
+        r = sd_dhcp_lease_get_server_identifier(lease, &addr);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
+
+        if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
+                log_struct(LOG_DEBUG,
+                           LOG_LINK_INTERFACE(link),
+                           LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer",
+                                            ADDRESS_FMT_VAL(addr)));
+                return true;
+        }
+
+        return false;
+}
+
+static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
         Link *link = userdata;
-        int r = 0;
+        int r;
 
         assert(link);
         assert(link->network);
         assert(link->manager);
 
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return;
+                return 0;
 
         switch (event) {
-                case SD_DHCP_CLIENT_EVENT_EXPIRED:
                 case SD_DHCP_CLIENT_EVENT_STOP:
+
+                        if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4)) {
+                                assert(link->ipv4ll);
+
+                                log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
+
+                                r = sd_ipv4ll_start(link->ipv4ll);
+                                if (r < 0)
+                                        return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
+                        }
+
+                        if (link->network->dhcp_send_release)
+                                (void) sd_dhcp_client_send_release(client);
+
+                        _fallthrough_;
+                case SD_DHCP_CLIENT_EVENT_EXPIRED:
                 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
+
                         if (link->network->dhcp_critical) {
                                 log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
-                                return;
+                                return 0;
                         }
 
                         if (link->dhcp_lease) {
                                 r = dhcp_lease_lost(link);
                                 if (r < 0) {
                                         link_enter_failed(link);
-                                        return;
+                                        return r;
                                 }
                         }
 
@@ -543,7 +588,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                                 r = dhcp_lease_acquired(client, link);
                                 if (r < 0) {
                                         link_enter_failed(link);
-                                        return;
+                                        return r;
                                 }
                         }
 
@@ -552,16 +597,23 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         r = dhcp_lease_renew(client, link);
                         if (r < 0) {
                                 link_enter_failed(link);
-                                return;
+                                return r;
                         }
                         break;
                 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
                         r = dhcp_lease_acquired(client, link);
                         if (r < 0) {
                                 link_enter_failed(link);
-                                return;
+                                return r;
                         }
                         break;
+                case SD_DHCP_CLIENT_EVENT_SELECTING:
+                        r = dhcp_server_is_black_listed(link, client);
+                        if (r < 0)
+                                return r;
+                        if (r != 0)
+                                return -ENOMSG;
+                        break;
                 default:
                         if (event < 0)
                                 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
@@ -570,7 +622,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         break;
         }
 
-        return;
+        return 0;
 }
 
 static int dhcp4_set_hostname(Link *link) {
@@ -817,5 +869,11 @@ int dhcp4_configure(Link *link) {
                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
         }
 
+        if (link->network->dhcp_max_attempts > 0) {
+                r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
+        }
+
         return dhcp4_set_client_identifier(link);
 }
index 90361c9f4a361e59195deea82290aa34d4c33e44..afa3e2cfd68a883d06aa0247825585c337ee4f92 100644 (file)
@@ -3,7 +3,7 @@
   Copyright © 2014 Intel Corporation. All rights reserved.
 ***/
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 #include "sd-radv.h"
 
@@ -90,7 +90,7 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
         if (r < 0 && r != -EEXIST)
                 return r;
 
-        r = manager_dhcp6_prefix_add(link->manager, &p->opt.in6_addr, link);
+        r = manager_dhcp6_prefix_add(link->manager, prefix, link);
         if (r < 0)
                 return r;
 
@@ -126,47 +126,33 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
                                      &lifetime_preferred,
                                      &lifetime_valid) >= 0) {
                 _cleanup_free_ char *buf = NULL;
-                _cleanup_free_ Route *route = NULL;
+                Route *route;
 
-                if (pd_prefix_len > 64)
+                if (pd_prefix_len >= 64)
                         continue;
 
                 (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
 
-                if (pd_prefix_len < 64) {
-                        r = route_new(&route);
-                        if (r < 0) {
-                                log_link_warning_errno(link, r, "Cannot create unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m",
-                                                       strnull(buf),
-                                                       pd_prefix_len);
-                                continue;
-                        }
-
-                        r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, 0, 0, 0, &route);
-                        if (r < 0) {
-                                log_link_warning_errno(link, r, "Failed to add unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m",
-                                                       strnull(buf),
-                                                       pd_prefix_len);
-                                continue;
-                        }
-
-                        route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE);
-
-                        r = route_remove(route, link, dhcp6_route_remove_handler);
-                        if (r < 0) {
-                                (void) in_addr_to_string(AF_INET6,
-                                                         &pd_prefix, &buf);
-
-                                log_link_warning_errno(link, r, "Cannot delete unreachable route for DHCPv6 delegated subnet %s/%u: %m",
-                                                       strnull(buf),
-                                                       pd_prefix_len);
+                r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, 0, 0, 0, &route);
+                if (r < 0) {
+                        log_link_warning_errno(link, r, "Failed to add unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m",
+                                               strnull(buf),
+                                               pd_prefix_len);
+                        continue;
+                }
 
-                                continue;
-                        }
+                route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE);
 
-                        log_link_debug(link, "Removing unreachable route %s/%u",
-                                       strnull(buf), pd_prefix_len);
+                r = route_remove(route, link, dhcp6_route_remove_handler);
+                if (r < 0) {
+                        log_link_warning_errno(link, r, "Cannot delete unreachable route for DHCPv6 delegated subnet %s/%u: %m",
+                                               strnull(buf),
+                                               pd_prefix_len);
+                        continue;
                 }
+
+                log_link_debug(link, "Removing unreachable route %s/%u",
+                               strnull(buf), pd_prefix_len);
         }
 
         return 0;
@@ -217,7 +203,7 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i,
                         continue;
 
                 assigned_link = manager_dhcp6_prefix_get(manager, &prefix.in6);
-                if (assigned_link != NULL && assigned_link != link)
+                if (assigned_link && assigned_link != link)
                         continue;
 
                 (void) in_addr_to_string(AF_INET6, &prefix, &assigned_buf);
@@ -229,7 +215,7 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i,
                                              strnull(assigned_buf),
                                              strnull(buf), pd_prefix_len);
 
-                        if (assigned_link == NULL)
+                        if (!assigned_link)
                                 continue;
 
                 } else
@@ -266,7 +252,6 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
         union in_addr_union pd_prefix;
         uint8_t pd_prefix_len;
         uint32_t lifetime_preferred, lifetime_valid;
-        _cleanup_free_ char *buf = NULL;
         Iterator i = ITERATOR_FIRST;
 
         r = sd_dhcp6_client_get_lease(client, &lease);
@@ -279,32 +264,23 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
                                      &lifetime_preferred,
                                      &lifetime_valid) >= 0) {
 
+                _cleanup_free_ char *buf = NULL;
+
+                (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
+
                 if (pd_prefix_len > 64) {
-                        (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
                         log_link_debug(link, "PD Prefix length > 64, ignoring prefix %s/%u",
                                        strnull(buf), pd_prefix_len);
                         continue;
                 }
 
-                if (pd_prefix_len < 48) {
-                        (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
+                if (pd_prefix_len < 48)
                         log_link_warning(link, "PD Prefix length < 48, looks unusual %s/%u",
                                        strnull(buf), pd_prefix_len);
-                }
 
                 if (pd_prefix_len < 64) {
-                        _cleanup_(route_freep) Route *route = NULL;
                         uint32_t table;
-
-                        (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
-
-                        r = route_new(&route);
-                        if (r < 0) {
-                                log_link_warning_errno(link, r, "Cannot create unreachable route for DHCPv6 delegated subnet %s/%u: %m",
-                                                       strnull(buf),
-                                                       pd_prefix_len);
-                                continue;
-                        }
+                        Route *route;
 
                         table = link_get_dhcp_route_table(link);
 
@@ -328,7 +304,6 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
 
                         log_link_debug(link, "Configuring unreachable route for %s/%u",
                                        strnull(buf), pd_prefix_len);
-
                 } else
                         log_link_debug(link, "Not adding a blocking route since distributed prefix is /64");
 
@@ -443,7 +418,7 @@ static int dhcp6_address_change(
                 uint32_t lifetime_valid) {
 
         _cleanup_(address_freep) Address *addr = NULL;
-        char buffer[INET6_ADDRSTRLEN];
+        _cleanup_free_ char *buffer = NULL;
         int r;
 
         r = address_new(&addr);
@@ -451,7 +426,7 @@ static int dhcp6_address_change(
                 return r;
 
         addr->family = AF_INET6;
-        memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
+        addr->in_addr.in6 = *ip6_addr;
 
         addr->flags = IFA_F_NOPREFIXROUTE;
         addr->prefixlen = 128;
@@ -459,10 +434,10 @@ static int dhcp6_address_change(
         addr->cinfo.ifa_prefered = lifetime_preferred;
         addr->cinfo.ifa_valid = lifetime_valid;
 
+        (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer);
         log_link_info(link,
                       "DHCPv6 address %s/%d timeout preferred %d valid %d",
-                      inet_ntop(AF_INET6, &addr->in_addr.in6, buffer, sizeof(buffer)),
-                      addr->prefixlen, lifetime_preferred, lifetime_valid);
+                      strnull(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid);
 
         r = address_configure(addr, link, dhcp6_address_handler, true);
         if (r < 0)
index fa13949538134612996322df53e83d0d93c3a2e6..4ae511fc7aeb3f9a3f4bfe5148d0af5d69f1c512 100644 (file)
@@ -9,14 +9,27 @@
 #include "alloc-util.h"
 #include "conf-parser.h"
 #include "netdev/bridge.h"
+#include "netdev/vxlan.h"
 #include "netlink-util.h"
 #include "networkd-fdb.h"
 #include "networkd-manager.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "string-table.h"
 #include "util.h"
 #include "vlan-util.h"
 
 #define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U
 
+static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = {
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use",
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self",
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master",
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags);
+
 /* create a new FDB entry or get an existing one. */
 static int fdb_entry_new_static(
                 Network *network,
@@ -64,6 +77,8 @@ static int fdb_entry_new_static(
         *fdb_entry = (FdbEntry) {
                 .network = network,
                 .mac_addr = TAKE_PTR(mac_addr),
+                .vni = VXLAN_VID_MAX + 1,
+                .fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
         };
 
         LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
@@ -102,30 +117,19 @@ static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
 /* send a request to the kernel to add a FDB entry in its static MAC table. */
 int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        sd_netlink *rtnl;
         int r;
-        uint8_t flags;
-        Bridge *bridge;
 
         assert(link);
         assert(link->network);
         assert(link->manager);
         assert(fdb_entry);
 
-        rtnl = link->manager->rtnl;
-        bridge = BRIDGE(link->network->bridge);
-
         /* create new RTM message */
-        r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
+        r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
         if (r < 0)
                 return rtnl_log_create_error(r);
 
-        if (bridge)
-                flags = NTF_MASTER;
-        else
-                flags = NTF_SELF;
-
-        r = sd_rtnl_message_neigh_set_flags(req, flags);
+        r = sd_rtnl_message_neigh_set_flags(req, fdb_entry->fdb_ntf_flags);
         if (r < 0)
                 return rtnl_log_create_error(r);
 
@@ -139,14 +143,26 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
                 return rtnl_log_create_error(r);
 
         /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */
-        if (0 != fdb_entry->vlan_id) {
+        if (fdb_entry->vlan_id > 0) {
                 r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id);
                 if (r < 0)
                         return rtnl_log_create_error(r);
         }
 
+        if (!in_addr_is_null(fdb_entry->family, &fdb_entry->destination_addr)) {
+                r = netlink_message_append_in_addr_union(req, NDA_DST, fdb_entry->family, &fdb_entry->destination_addr);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
+        }
+
+        if (fdb_entry->vni <= VXLAN_VID_MAX) {
+                r = sd_netlink_message_append_u32(req, NDA_VNI, fdb_entry->vni);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append NDA_VNI attribute: %m");
+        }
+
         /* send message to the kernel to update its internal static MAC table. */
-        r = netlink_call_async(rtnl, NULL, req, set_fdb_handler,
+        r = netlink_call_async(link->manager->rtnl, NULL, req, set_fdb_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@@ -258,3 +274,130 @@ int config_parse_fdb_vlan_id(
 
         return 0;
 }
+
+int config_parse_fdb_destination(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
+        Network *network = userdata;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
+        if (r < 0)
+                return log_oom();
+
+        r = in_addr_from_string_auto(rvalue, &fdb_entry->family, &fdb_entry->destination_addr);
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r,
+                                  "FDB destination IP address is invalid, ignoring assignment: %s",
+                                  rvalue);
+
+        fdb_entry = NULL;
+
+        return 0;
+}
+
+int config_parse_fdb_vxlan_vni(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
+        Network *network = userdata;
+        uint32_t vni;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
+        if (r < 0)
+                return log_oom();
+
+        r = safe_atou32(rvalue, &vni);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse VXLAN Network Identifier (VNI), ignoring assignment: %s",
+                           rvalue);
+                return 0;
+        }
+
+        if (vni > VXLAN_VID_MAX) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "FDB invalid VXLAN Network Identifier (VNI), ignoring assignment: %s",
+                           rvalue);
+                return 0;
+        }
+
+        fdb_entry->vni = vni;
+        fdb_entry = NULL;
+
+        return 0;
+}
+
+
+int config_parse_fdb_ntf_flags(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
+        Network *network = userdata;
+        NeighborCacheEntryFlags f;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
+        if (r < 0)
+                return log_oom();
+
+        f = fdb_ntf_flags_from_string(rvalue);
+        if (f < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "FDB failed to parse AssociatedWith=, ignoring assignment: %s",
+                           rvalue);
+                return 0;
+        }
+
+        fdb_entry->fdb_ntf_flags = f;
+        fdb_entry = NULL;
+
+        return 0;
+}
index 6b7da2e7413598d399fd508a40e4452baa33f7b1..bcdd8ce3cb241ab21ed262352c5e31f002c4d9a3 100644 (file)
@@ -5,6 +5,8 @@
   Copyright © 2014 Intel Corporation. All rights reserved.
 ***/
 
+#include <linux/neighbour.h>
+
 #include "conf-parser.h"
 #include "list.h"
 #include "macro.h"
@@ -15,13 +17,28 @@ typedef struct FdbEntry FdbEntry;
 typedef struct Link Link;
 typedef struct NetworkConfigSection NetworkConfigSection;
 
+typedef enum NeighborCacheEntryFlags {
+        NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE,
+        NEIGHBOR_CACHE_ENTRY_FLAGS_SELF = NTF_SELF,
+        NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER = NTF_MASTER,
+        NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER = NTF_ROUTER,
+        _NEIGHBOR_CACHE_ENTRY_FLAGS_MAX,
+        _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1,
+} NeighborCacheEntryFlags;
+
 struct FdbEntry {
         Network *network;
         NetworkConfigSection *section;
 
-        struct ether_addr *mac_addr;
+        uint32_t vni;
+
+        int family;
         uint16_t vlan_id;
 
+        struct ether_addr *mac_addr;
+        union in_addr_union destination_addr;
+        NeighborCacheEntryFlags fdb_ntf_flags;
+
         LIST_FIELDS(FdbEntry, static_fdb_entries);
 };
 
@@ -30,5 +47,11 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry);
 
 DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free);
 
+const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_;
+NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
 CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vxlan_vni);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_ntf_flags);
index 829dc48a0a16e37ccb46c988c63831e4d86b060d..9df5646a7e61c0186375383f7b42c8ea4ee2334d 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 
 #include "network-internal.h"
@@ -34,7 +34,9 @@ static int ipv4ll_address_lost(Link *link) {
         address->prefixlen = 16;
         address->scope = RT_SCOPE_LINK;
 
-        address_remove(address, link, NULL);
+        r = address_remove(address, link, NULL);
+        if (r < 0)
+                return r;
 
         r = route_new(&route);
         if (r < 0)
@@ -44,7 +46,9 @@ static int ipv4ll_address_lost(Link *link) {
         route->scope = RT_SCOPE_LINK;
         route->priority = IPV4LL_ROUTE_METRIC;
 
-        route_remove(route, link, NULL);
+        r = route_remove(route, link, NULL);
+        if (r < 0)
+                return r;
 
         link_check_ready(link);
 
@@ -175,7 +179,7 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
 
                         r = sd_ipv4ll_restart(ll);
                         if (r < 0)
-                                log_link_warning(link, "Could not acquire IPv4 link-local address");
+                                log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
                         break;
                 case SD_IPV4LL_EVENT_BIND:
                         r = ipv4ll_address_claimed(ll, link);
@@ -197,7 +201,7 @@ int ipv4ll_configure(Link *link) {
 
         assert(link);
         assert(link->network);
-        assert(link->network->link_local & ADDRESS_FAMILY_IPV4);
+        assert(link->network->link_local & (ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4));
 
         if (!link->ipv4ll) {
                 r = sd_ipv4ll_new(&link->ipv4ll);
index e2d77e9ad2c56f24892733d66929004a20caad11..863171b0712ffcff041de28f629dc3e51b8625ad 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 #include <unistd.h>
 
index 3e22efb92a6b48df0a4e79bc4ae7c80c26f58902..924cc8ce6af25b32f1eea102debb813b4551ee07 100644 (file)
@@ -1,8 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
-#include <linux/can/netlink.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "missing_network.h"
+#include "netdev/bond.h"
+#include "netdev/bridge.h"
+#include "netdev/ipvlan.h"
 #include "netdev/vrf.h"
 #include "netlink-util.h"
 #include "network-internal.h"
+#include "networkd-can.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
@@ -74,6 +77,9 @@ static bool link_dhcp6_enabled(Link *link) {
         if (link->network->bond)
                 return false;
 
+        if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+                return false;
+
         if (manager_sysctl_ipv6_enabled(link->manager) == 0)
                 return false;
 
@@ -92,6 +98,9 @@ static bool link_dhcp4_enabled(Link *link) {
         if (link->network->bond)
                 return false;
 
+        if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+                return false;
+
         return link->network->dhcp & ADDRESS_FAMILY_IPV4;
 }
 
@@ -107,11 +116,15 @@ static bool link_dhcp4_server_enabled(Link *link) {
         if (link->network->bond)
                 return false;
 
+        if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+                return false;
+
         return link->network->dhcp_server;
 }
 
-static bool link_ipv4ll_enabled(Link *link) {
+bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
         assert(link);
+        assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0);
 
         if (link->flags & IFF_LOOPBACK)
                 return false;
@@ -119,13 +132,17 @@ static bool link_ipv4ll_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan"))
+                return false;
+
+        /* L3 or L3S mode do not support ARP. */
+        if (IN_SET(link_get_ipvlan_mode(link), NETDEV_IPVLAN_MODE_L3, NETDEV_IPVLAN_MODE_L3S))
                 return false;
 
         if (link->network->bond)
                 return false;
 
-        return link->network->link_local & ADDRESS_FAMILY_IPV4;
+        return link->network->link_local & mask;
 }
 
 static bool link_ipv6ll_enabled(Link *link) {
@@ -140,7 +157,7 @@ static bool link_ipv6ll_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan"))
                 return false;
 
         if (link->network->bond)
@@ -164,6 +181,9 @@ static bool link_ipv6_enabled(Link *link) {
         if (manager_sysctl_ipv6_enabled(link->manager) == 0)
                 return false;
 
+        if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
+                return false;
+
         /* DHCPv6 client will not be started if no IPv6 link-local address is configured. */
         return link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network);
 }
@@ -177,42 +197,6 @@ static bool link_radv_enabled(Link *link) {
         return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE;
 }
 
-static bool link_lldp_rx_enabled(Link *link) {
-        assert(link);
-
-        if (link->flags & IFF_LOOPBACK)
-                return false;
-
-        if (link->iftype != ARPHRD_ETHER)
-                return false;
-
-        if (!link->network)
-                return false;
-
-        /* LLDP should be handled on bridge slaves as those have a direct
-         * connection to their peers not on the bridge master. Linux doesn't
-         * even (by default) forward lldp packets to the bridge master.*/
-        if (streq_ptr("bridge", link->kind))
-                return false;
-
-        return link->network->lldp_mode != LLDP_MODE_NO;
-}
-
-static bool link_lldp_emit_enabled(Link *link) {
-        assert(link);
-
-        if (link->flags & IFF_LOOPBACK)
-                return false;
-
-        if (link->iftype != ARPHRD_ETHER)
-                return false;
-
-        if (!link->network)
-                return false;
-
-        return link->network->lldp_emit != LLDP_EMIT_NO;
-}
-
 static bool link_ipv4_forward_enabled(Link *link) {
         assert(link);
 
@@ -320,8 +304,7 @@ static int link_enable_ipv6(Link *link) {
 
         r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", disabled);
         if (r < 0)
-                log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m",
-                                       enable_disable(!disabled), link->ifname);
+                log_link_warning_errno(link, r, "Cannot %s IPv6: %m", enable_disable(!disabled));
         else
                 log_link_info(link, "IPv6 successfully %sd", enable_disable(!disabled));
 
@@ -333,16 +316,14 @@ static bool link_is_enslaved(Link *link) {
                 /* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */
                 return true;
 
-        if (!link->enslaved_raw)
-                return false;
-
         if (!link->network)
                 return false;
 
-        if (link->network->bridge)
-                /* TODO: support the case when link is not managed by networkd. */
+        if (link->master_ifindex > 0 && link->network->bridge)
                 return true;
 
+        /* TODO: add conditions for other netdevs. */
+
         return false;
 }
 
@@ -434,7 +415,7 @@ void link_update_operstate(Link *link, bool also_update_master) {
                 ? ((old & flag) ? (" -" string) : (" +" string)) \
                 : "")
 
-static int link_update_flags(Link *link, sd_netlink_message *m) {
+static int link_update_flags(Link *link, sd_netlink_message *m, bool force_update_operstate) {
         unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
         uint8_t operstate;
         int r;
@@ -451,7 +432,7 @@ static int link_update_flags(Link *link, sd_netlink_message *m) {
                    the state was unchanged */
                 operstate = link->kernel_operstate;
 
-        if ((link->flags == flags) && (link->kernel_operstate == operstate))
+        if (!force_update_operstate && (link->flags == flags) && (link->kernel_operstate == operstate))
                 return 0;
 
         if (link->flags != flags) {
@@ -506,8 +487,6 @@ static int link_update_flags(Link *link, sd_netlink_message *m) {
         return 0;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
-
 static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         _cleanup_(link_unrefp) Link *link = NULL;
         uint16_t type;
@@ -596,7 +575,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         if (r < 0)
                 return r;
 
-        r = link_update_flags(link, message);
+        r = link_update_flags(link, message, false);
         if (r < 0)
                 return r;
 
@@ -606,30 +585,15 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
 }
 
 static Link *link_free(Link *link) {
-        Link *carrier;
         Address *address;
-        Route *route;
-        Iterator i;
 
         assert(link);
 
-        while ((route = set_first(link->routes)))
-                route_free(route);
+        link->routes = set_free_with_destructor(link->routes, route_free);
+        link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free);
 
-        while ((route = set_first(link->routes_foreign)))
-                route_free(route);
-
-        link->routes = set_free(link->routes);
-        link->routes_foreign = set_free(link->routes_foreign);
-
-        while ((address = set_first(link->addresses)))
-                address_free(address);
-
-        while ((address = set_first(link->addresses_foreign)))
-                address_free(address);
-
-        link->addresses = set_free(link->addresses);
-        link->addresses_foreign = set_free(link->addresses_foreign);
+        link->addresses = set_free_with_destructor(link->addresses, address_free);
+        link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free);
 
         while ((address = link->pool_addresses)) {
                 LIST_REMOVE(addresses, link->pool_addresses, address);
@@ -662,16 +626,13 @@ static Link *link_free(Link *link) {
 
         sd_device_unref(link->sd_device);
 
-        HASHMAP_FOREACH (carrier, link->bound_to_links, i)
-                hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
         hashmap_free(link->bound_to_links);
-
-        HASHMAP_FOREACH (carrier, link->bound_by_links, i)
-                hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
         hashmap_free(link->bound_by_links);
 
         set_free_with_destructor(link->slaves, link_unref);
 
+        network_unref(link->network);
+
         return mfree(link);
 }
 
@@ -693,7 +654,7 @@ int link_get(Manager *m, int ifindex, Link **ret) {
         return 0;
 }
 
-static void link_set_state(Link *link, LinkState state) {
+void link_set_state(Link *link, LinkState state) {
         assert(link);
 
         if (link->state == state)
@@ -711,14 +672,12 @@ static void link_set_state(Link *link, LinkState state) {
 static void link_enter_unmanaged(Link *link) {
         assert(link);
 
-        log_link_debug(link, "Unmanaged");
-
         link_set_state(link, LINK_STATE_UNMANAGED);
 
         link_dirty(link);
 }
 
-static int link_stop_clients(Link *link) {
+int link_stop_clients(Link *link) {
         int r = 0, k;
 
         assert(link);
@@ -986,6 +945,7 @@ void link_check_ready(Link *link) {
         if (!link->addresses_ready) {
                 link->addresses_ready = true;
                 link_request_set_routes(link);
+                return;
         }
 
         if (!link->static_routes_configured)
@@ -994,21 +954,18 @@ void link_check_ready(Link *link) {
         if (!link->routing_policy_rules_configured)
                 return;
 
-        if (link_ipv4ll_enabled(link))
-                if (!link->ipv4ll_address ||
-                    !link->ipv4ll_route)
-                        return;
+        if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !(link->ipv4ll_address && link->ipv4ll_route))
+                return;
 
         if (link_ipv6ll_enabled(link) &&
             in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address))
                 return;
 
-        if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
-             !link->dhcp4_configured) ||
-            (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
-             !link->dhcp6_configured) ||
-            (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
-             !link->dhcp4_configured && !link->dhcp6_configured))
+        if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
+            !(link->dhcp4_configured || link->dhcp6_configured) &&
+            !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address && link->ipv4ll_route))
+                /* When DHCP is enabled, at least one protocol must provide an address, or
+                 * an IPv4ll fallback address must be configured. */
                 return;
 
         if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
@@ -1142,20 +1099,20 @@ static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
         log_debug("Copying NTP server information from %s", link->ifname);
 
         STRV_FOREACH(a, link->network->ntp) {
-                struct in_addr ia;
+                union in_addr_union ia;
 
                 /* Only look for IPv4 addresses */
-                if (inet_pton(AF_INET, *a, &ia) <= 0)
+                if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
                         continue;
 
                 /* Never propagate obviously borked data */
-                if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
+                if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
                         continue;
 
                 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
                         return log_oom();
 
-                addresses[n_addresses++] = ia;
+                addresses[n_addresses++] = ia.in;
         }
 
         if (link->network->dhcp_use_ntp && link->dhcp_lease) {
@@ -1373,7 +1330,7 @@ static int link_request_set_addresses(Link *link) {
 }
 
 static int link_set_bridge_vlan(Link *link) {
-        int r = 0;
+        int r;
 
         r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
         if (r < 0)
@@ -1395,22 +1352,6 @@ static int link_set_proxy_arp(Link *link) {
         return 0;
 }
 
-static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        log_link_debug(link, "Set link");
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0 && r != -EEXIST) {
-                log_link_error_errno(link, r, "Could not join netdev: %m");
-                link_enter_failed(link);
-        }
-
-        return 1;
-}
-
 static int link_configure_after_setting_mtu(Link *link);
 
 static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@@ -1439,7 +1380,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
         return 1;
 }
 
-int link_set_mtu(Link *link, uint32_t mtu, bool force) {
+int link_set_mtu(Link *link, uint32_t mtu) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -1450,7 +1391,7 @@ int link_set_mtu(Link *link, uint32_t mtu, bool force) {
         if (mtu == 0 || link->setting_mtu)
                 return 0;
 
-        if (force ? link->mtu == mtu : link->mtu >= mtu)
+        if (link->mtu == mtu)
                 return 0;
 
         log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
@@ -1488,6 +1429,48 @@ int link_set_mtu(Link *link, uint32_t mtu, bool force) {
         return 0;
 }
 
+static bool link_reduces_vlan_mtu(Link *link) {
+        /* See netif_reduces_vlan_mtu() in kernel. */
+        return streq_ptr(link->kind, "macsec");
+}
+
+static uint32_t link_get_requested_mtu_by_stacked_netdevs(Link *link) {
+        uint32_t mtu = 0;
+        NetDev *dev;
+        Iterator i;
+
+        HASHMAP_FOREACH(dev, link->network->stacked_netdevs, i)
+                if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
+                        /* See vlan_dev_change_mtu() in kernel. */
+                        mtu = MAX(mtu, link_reduces_vlan_mtu(link) ? dev->mtu + 4 : dev->mtu);
+
+                else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
+                        /* See macvlan_change_mtu() in kernel. */
+                        mtu = dev->mtu;
+
+        return mtu;
+}
+
+static int link_configure_mtu(Link *link) {
+        uint32_t mtu;
+
+        assert(link);
+        assert(link->network);
+
+        if (link->network->mtu > 0)
+                return link_set_mtu(link, link->network->mtu);
+
+        mtu = link_get_requested_mtu_by_stacked_netdevs(link);
+        if (link->mtu >= mtu)
+                return 0;
+
+        log_link_notice(link, "Bumping MTU bytes from %"PRIu32" to %"PRIu32" because of stacked device. "
+                        "If it is not desired, then please explicitly specify MTUBytes= setting.",
+                        link->mtu, mtu);
+
+        return link_set_mtu(link, mtu);
+}
+
 static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -1557,268 +1540,6 @@ static int link_set_flags(Link *link) {
         return 0;
 }
 
-static int link_set_bridge(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set message family: %m");
-
-        r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
-
-        if (link->network->use_bpdu >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
-        }
-
-        if (link->network->hairpin >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
-        }
-
-        if (link->network->fast_leave >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
-        }
-
-        if (link->network->allow_port_to_be_root >=  0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
-
-        }
-
-        if (link->network->unicast_flood >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
-        }
-
-        if (link->network->multicast_flood >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
-        }
-
-        if (link->network->multicast_to_unicast >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
-        }
-
-        if (link->network->neighbor_suppression >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
-        }
-
-        if (link->network->learning >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
-        }
-
-        if (link->network->cost != 0) {
-                r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
-        }
-
-        if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
-                r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
-        }
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return r;
-}
-
-static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(m);
-        assert(link);
-        assert(link->ifname);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0) {
-                log_link_warning_errno(link, r, "Could not set bonding interface: %m");
-                return 1;
-        }
-
-        return 1;
-}
-
-static int link_set_bond(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
-
-        r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
-
-        r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
-
-        if (link->network->active_slave) {
-                r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
-        }
-
-        if (link->network->primary_slave) {
-                r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
-        }
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r,  "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return r;
-}
-
-static int link_lldp_save(Link *link) {
-        _cleanup_free_ char *temp_path = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        sd_lldp_neighbor **l = NULL;
-        int n = 0, r, i;
-
-        assert(link);
-        assert(link->lldp_file);
-
-        if (!link->lldp) {
-                (void) unlink(link->lldp_file);
-                return 0;
-        }
-
-        r = sd_lldp_get_neighbors(link->lldp, &l);
-        if (r < 0)
-                goto finish;
-        if (r == 0) {
-                (void) unlink(link->lldp_file);
-                goto finish;
-        }
-
-        n = r;
-
-        r = fopen_temporary(link->lldp_file, &f, &temp_path);
-        if (r < 0)
-                goto finish;
-
-        fchmod(fileno(f), 0644);
-
-        for (i = 0; i < n; i++) {
-                const void *p;
-                le64_t u;
-                size_t sz;
-
-                r = sd_lldp_neighbor_get_raw(l[i], &p, &sz);
-                if (r < 0)
-                        goto finish;
-
-                u = htole64(sz);
-                (void) fwrite(&u, 1, sizeof(u), f);
-                (void) fwrite(p, 1, sz, f);
-        }
-
-        r = fflush_and_check(f);
-        if (r < 0)
-                goto finish;
-
-        if (rename(temp_path, link->lldp_file) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-finish:
-        if (r < 0) {
-                (void) unlink(link->lldp_file);
-                if (temp_path)
-                        (void) unlink(temp_path);
-
-                log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
-        }
-
-        if (l) {
-                for (i = 0; i < n; i++)
-                        sd_lldp_neighbor_unref(l[i]);
-                free(l);
-        }
-
-        return r;
-}
-
-static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
-        Link *link = userdata;
-        int r;
-
-        assert(link);
-
-        (void) link_lldp_save(link);
-
-        if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) {
-                /* If we received information about a new neighbor, restart the LLDP "fast" logic */
-
-                log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
-
-                r = link_lldp_emit_start(link);
-                if (r < 0)
-                        log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
-        }
-}
-
 static int link_acquire_ipv6_conf(Link *link) {
         int r;
 
@@ -1857,7 +1578,7 @@ static int link_acquire_ipv4_conf(Link *link) {
         assert(link->manager);
         assert(link->manager->event);
 
-        if (link_ipv4ll_enabled(link)) {
+        if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4)) {
                 assert(link->ipv4ll);
 
                 log_link_debug(link, "Acquiring IPv4 link-local address");
@@ -1912,7 +1633,8 @@ bool link_has_carrier(Link *link) {
 
         if (link->kernel_operstate == IF_OPER_UNKNOWN)
                 /* operstate may not be implemented, so fall back to flags */
-                if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
+                if (FLAGS_SET(link->flags, IFF_LOWER_UP | IFF_RUNNING) &&
+                    !FLAGS_SET(link->flags, IFF_DORMANT))
                         return true;
 
         return false;
@@ -1943,6 +1665,9 @@ static int link_configure_addrgen_mode(Link *link) {
         assert(link->manager);
         assert(link->manager->rtnl);
 
+        if (!socket_ipv6_is_supported())
+                return 0;
+
         log_link_debug(link, "Setting address genmode for link");
 
         r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
@@ -2036,31 +1761,6 @@ static int link_up(Link *link) {
                         return log_link_error_errno(link, r, "Could not set MAC address: %m");
         }
 
-        if (link_ipv6_enabled(link)) {
-                r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
-
-                /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
-                r = sd_netlink_message_open_container(req, AF_INET6);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
-
-                if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
-                        r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
-                }
-
-                r = sd_netlink_message_close_container(req);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
-
-                r = sd_netlink_message_close_container(req);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
-        }
-
         r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
@@ -2071,145 +1771,6 @@ static int link_up(Link *link) {
         return 0;
 }
 
-static int link_up_can(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-
-        log_link_debug(link, "Bringing CAN link up");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set link flags: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return 0;
-}
-
-static int link_set_can(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->manager);
-        assert(link->manager->rtnl);
-
-        log_link_debug(link, "link_set_can");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to allocate netlink message: %m");
-
-        r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
-
-        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to open netlink container: %m");
-
-        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
-
-        if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) {
-                struct can_bittiming bt = {
-                        .bitrate = link->network->can_bitrate,
-                        .sample_point = link->network->can_sample_point,
-                };
-
-                if (link->network->can_bitrate > UINT32_MAX) {
-                        log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate);
-                        return -ERANGE;
-                }
-
-                log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
-                if (link->network->can_sample_point > 0)
-                        log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
-                else
-                        log_link_debug(link, "Using default sample point");
-
-                r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
-        }
-
-        if (link->network->can_restart_us > 0) {
-                char time_string[FORMAT_TIMESPAN_MAX];
-                uint64_t restart_ms;
-
-                if (link->network->can_restart_us == USEC_INFINITY)
-                        restart_ms = 0;
-                else
-                        restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC);
-
-                format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC);
-
-                if (restart_ms > UINT32_MAX) {
-                        log_link_error(link, "restart timeout (%s) too big.", time_string);
-                        return -ERANGE;
-                }
-
-                log_link_debug(link, "Setting restart = %s", time_string);
-
-                r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
-        }
-
-        if (link->network->can_triple_sampling >= 0) {
-                struct can_ctrlmode cm = {
-                        .mask = CAN_CTRLMODE_3_SAMPLES,
-                        .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0,
-                };
-
-                log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis");
-
-                r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
-        }
-
-        r = sd_netlink_message_close_container(m);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
-
-        r = sd_netlink_message_close_container(m);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        if (!(link->flags & IFF_UP)) {
-                r = link_up_can(link);
-                if (r < 0) {
-                        link_enter_failed(link);
-                        return r;
-                }
-        }
-
-        log_link_debug(link, "link_set_can done");
-
-        return r;
-}
-
 static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -2222,13 +1783,10 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link
         if (r < 0)
                 log_link_warning_errno(link, r, "Could not bring down interface: %m");
 
-        if (streq_ptr(link->kind, "can"))
-                link_set_can(link);
-
         return 1;
 }
 
-int link_down(Link *link) {
+int link_down(Link *link, link_netlink_message_handler_t callback) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -2247,7 +1805,8 @@ int link_down(Link *link) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not set link flags: %m");
 
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_handler,
+        r = netlink_call_async(link->manager->rtnl, NULL, req,
+                               callback ?: link_down_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@@ -2279,7 +1838,7 @@ static int link_handle_bound_to_list(Link *link) {
                 }
 
         if (!required_up && link_is_up) {
-                r = link_down(link);
+                r = link_down(link, NULL);
                 if (r < 0)
                         return r;
         } else if (required_up && !link_is_up) {
@@ -2618,7 +2177,6 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
         assert(link);
         assert(link->network);
         assert(link->enslaving > 0);
-        assert(!link->enslaved_raw);
 
         link->enslaving--;
 
@@ -2634,7 +2192,6 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
                 log_link_debug(link, "Joined netdev");
 
         if (link->enslaving == 0) {
-                link->enslaved_raw = true;
                 link_joined(link);
         }
 
@@ -2654,7 +2211,6 @@ static int link_enter_join_netdev(Link *link) {
 
         link_dirty(link);
         link->enslaving = 0;
-        link->enslaved_raw = false;
 
         if (link->network->bond) {
                 if (link->network->bond->state == NETDEV_STATE_READY &&
@@ -3006,56 +2562,6 @@ static int link_drop_config(Link *link) {
         return 0;
 }
 
-static int link_update_lldp(Link *link) {
-        int r;
-
-        assert(link);
-
-        if (!link->lldp)
-                return 0;
-
-        if (link->flags & IFF_UP) {
-                r = sd_lldp_start(link->lldp);
-                if (r > 0)
-                        log_link_debug(link, "Started LLDP.");
-        } else {
-                r = sd_lldp_stop(link->lldp);
-                if (r > 0)
-                        log_link_debug(link, "Stopped LLDP.");
-        }
-
-        return r;
-}
-
-static int link_configure_can(Link *link) {
-        int r;
-
-        if (streq_ptr(link->kind, "can")) {
-                /* The CAN interface must be down to configure bitrate, etc... */
-                if ((link->flags & IFF_UP)) {
-                        r = link_down(link);
-                        if (r < 0) {
-                                link_enter_failed(link);
-                                return r;
-                        }
-
-                        return 0;
-                }
-
-                return link_set_can(link);
-        }
-
-        if (!(link->flags & IFF_UP)) {
-                r = link_up_can(link);
-                if (r < 0) {
-                        link_enter_failed(link);
-                        return r;
-                }
-        }
-
-        return 0;
-}
-
 static int link_configure(Link *link) {
         int r;
 
@@ -3063,7 +2569,7 @@ static int link_configure(Link *link) {
         assert(link->network);
         assert(link->state == LINK_STATE_INITIALIZED);
 
-        if (STRPTR_IN_SET(link->kind, "can", "vcan"))
+        if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan"))
                 return link_configure_can(link);
 
         /* Drop foreign config, but ignore loopback or critical devices.
@@ -3114,7 +2620,7 @@ static int link_configure(Link *link) {
         if (r < 0)
                 return r;
 
-        if (link_ipv4ll_enabled(link)) {
+        if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) {
                 r = ipv4ll_configure(link);
                 if (r < 0)
                         return r;
@@ -3160,47 +2666,18 @@ static int link_configure(Link *link) {
         }
 
         if (link_lldp_rx_enabled(link)) {
-                r = sd_lldp_new(&link->lldp);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_match_capabilities(link->lldp,
-                                               link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
-                                               SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
-                                               SD_LLDP_SYSTEM_CAPABILITIES_ALL);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_set_filter_address(link->lldp, &link->mac);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_attach_event(link->lldp, NULL, 0);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
-                if (r < 0)
-                        return r;
-
-                r = link_update_lldp(link);
+                r = link_lldp_rx_configure(link);
                 if (r < 0)
                         return r;
         }
 
-        r = link_set_mtu(link, link->network->mtu, link->network->mtu_is_set);
+        r = link_configure_mtu(link);
         if (r < 0)
                 return r;
 
-        if (socket_ipv6_is_supported()) {
-                r = link_configure_addrgen_mode(link);
-                if (r < 0)
-                        return r;
-        }
+        r = link_configure_addrgen_mode(link);
+        if (r < 0)
+                return r;
 
         return link_configure_after_setting_mtu(link);
 }
@@ -3734,7 +3211,7 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address) {
         link->ipv6ll_address = *address;
         link_check_ready(link);
 
-        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+        if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
                 r = link_acquire_ipv6_conf(link);
                 if (r < 0) {
                         link_enter_failed(link);
@@ -3750,7 +3227,7 @@ static int link_carrier_gained(Link *link) {
 
         assert(link);
 
-        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+        if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
                 r = link_acquire_conf(link);
                 if (r < 0) {
                         link_enter_failed(link);
@@ -3835,7 +3312,7 @@ int link_update(Link *link, sd_netlink_message *m) {
         const char *ifname;
         uint32_t mtu;
         bool had_carrier, carrier_gained, carrier_lost;
-        int r;
+        int old_master, r;
 
         assert(link);
         assert(link->ifname);
@@ -3961,9 +3438,12 @@ int link_update(Link *link, sd_netlink_message *m) {
                 }
         }
 
+        old_master = link->master_ifindex;
+        (void) sd_netlink_message_read_u32(m, IFLA_MASTER, (uint32_t *) &link->master_ifindex);
+
         had_carrier = link_has_carrier(link);
 
-        r = link_update_flags(link, m);
+        r = link_update_flags(link, m, old_master != link->master_ifindex);
         if (r < 0)
                 return r;
 
@@ -4054,12 +3534,11 @@ int link_save(Link *link) {
                 admin_state, oper_state);
 
         if (link->network) {
-                bool space;
+                char **dhcp6_domains = NULL, **dhcp_domains = NULL;
+                const char *dhcp_domainname = NULL, *p;
                 sd_dhcp6_lease *dhcp6_lease = NULL;
-                const char *dhcp_domainname = NULL;
-                char **dhcp6_domains = NULL;
-                char **dhcp_domains = NULL;
                 unsigned j;
+                bool space;
 
                 fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
                         yes_no(link->network->required_for_online));
@@ -4176,7 +3655,10 @@ int link_save(Link *link) {
                                 (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
                 }
 
-                ordered_set_print(f, "DOMAINS=", link->network->search_domains);
+                fputs("DOMAINS=", f);
+                space = false;
+                ORDERED_SET_FOREACH(p, link->network->search_domains, i)
+                        fputs_with_space(f, p, NULL, &space);
 
                 if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
                         NDiscDNSSL *dd;
@@ -4194,7 +3676,10 @@ int link_save(Link *link) {
 
                 fputc('\n', f);
 
-                ordered_set_print(f, "ROUTE_DOMAINS=", link->network->route_domains);
+                fputs("ROUTE_DOMAINS=", f);
+                space = false;
+                ORDERED_SET_FOREACH(p, link->network->route_domains, i)
+                        fputs_with_space(f, p, NULL, &space);
 
                 if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
                         NDiscDNSSL *dd;
index 7d8808e400fecb7aed36bc0d3e4ca7fb64aa9c6f..f8121180c0d3a3f9c122346ccbf07a3ed3892aa5 100644 (file)
@@ -17,6 +17,7 @@
 #include "list.h"
 #include "log-link.h"
 #include "network-util.h"
+#include "networkd-util.h"
 #include "set.h"
 
 typedef enum LinkState {
@@ -67,8 +68,6 @@ typedef struct Link {
         unsigned routing_policy_rule_messages;
         unsigned routing_policy_rule_remove_messages;
         unsigned enslaving;
-        /* link_is_enslaved() has additional checks. So, it is named _raw. */
-        bool enslaved_raw;
 
         Set *addresses;
         Set *addresses_foreign;
@@ -132,17 +131,19 @@ int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *re
 
 Link *link_unref(Link *link);
 Link *link_ref(Link *link);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
 DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref);
 
 int link_get(Manager *m, int ifindex, Link **ret);
 int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
 void link_drop(Link *link);
 
-int link_down(Link *link);
+int link_down(Link *link, link_netlink_message_handler_t callback);
 
 void link_enter_failed(Link *link);
 int link_initialized(Link *link, sd_device *device);
 
+void link_set_state(Link *link, LinkState state);
 void link_check_ready(Link *link);
 
 void link_update_operstate(Link *link, bool also_update_bond_master);
@@ -157,9 +158,11 @@ bool link_has_carrier(Link *link);
 
 int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
 
-int link_set_mtu(Link *link, uint32_t mtu, bool force);
+int link_set_mtu(Link *link, uint32_t mtu);
 
 int ipv4ll_configure(Link *link);
+bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask);
+
 int dhcp4_configure(Link *link);
 int dhcp4_set_client_identifier(Link *link);
 int dhcp4_set_promote_secondaries(Link *link);
@@ -168,6 +171,8 @@ int dhcp6_configure(Link *link);
 int dhcp6_request_address(Link *link, int ir);
 int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
 
+int link_stop_clients(Link *link);
+
 const char* link_state_to_string(LinkState s) _const_;
 LinkState link_state_from_string(const char *s) _pure_;
 
diff --git a/src/network/networkd-lldp-rx.c b/src/network/networkd-lldp-rx.c
new file mode 100644 (file)
index 0000000..95018d3
--- /dev/null
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <net/if.h>
+#include <unistd.h>
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "networkd-link.h"
+#include "networkd-lldp-rx.h"
+#include "networkd-lldp-tx.h"
+#include "networkd-network.h"
+#include "string-table.h"
+#include "string-util.h"
+#include "tmpfile-util.h"
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
+
+static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
+        [LLDP_MODE_NO] = "no",
+        [LLDP_MODE_YES] = "yes",
+        [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
+
+bool link_lldp_rx_enabled(Link *link) {
+        assert(link);
+
+        if (link->flags & IFF_LOOPBACK)
+                return false;
+
+        if (link->iftype != ARPHRD_ETHER)
+                return false;
+
+        if (!link->network)
+                return false;
+
+        /* LLDP should be handled on bridge slaves as those have a direct
+         * connection to their peers not on the bridge master. Linux doesn't
+         * even (by default) forward lldp packets to the bridge master.*/
+        if (streq_ptr("bridge", link->kind))
+                return false;
+
+        return link->network->lldp_mode != LLDP_MODE_NO;
+}
+
+static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
+        Link *link = userdata;
+        int r;
+
+        assert(link);
+
+        (void) link_lldp_save(link);
+
+        if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) {
+                /* If we received information about a new neighbor, restart the LLDP "fast" logic */
+
+                log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
+
+                r = link_lldp_emit_start(link);
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
+        }
+}
+
+int link_lldp_rx_configure(Link *link) {
+        int r;
+
+        r = sd_lldp_new(&link->lldp);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_match_capabilities(link->lldp,
+                                       link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
+                                       SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
+                                       SD_LLDP_SYSTEM_CAPABILITIES_ALL);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_set_filter_address(link->lldp, &link->mac);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_attach_event(link->lldp, NULL, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
+        if (r < 0)
+                return r;
+
+        r = link_update_lldp(link);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int link_update_lldp(Link *link) {
+        int r;
+
+        assert(link);
+
+        if (!link->lldp)
+                return 0;
+
+        if (link->flags & IFF_UP) {
+                r = sd_lldp_start(link->lldp);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to start LLDP: %m");
+                if (r > 0)
+                        log_link_debug(link, "Started LLDP.");
+        } else {
+                r = sd_lldp_stop(link->lldp);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to stop LLDP: %m");
+                if (r > 0)
+                        log_link_debug(link, "Stopped LLDP.");
+        }
+
+        return r;
+}
+
+int link_lldp_save(Link *link) {
+        _cleanup_free_ char *temp_path = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        sd_lldp_neighbor **l = NULL;
+        int n = 0, r, i;
+
+        assert(link);
+        assert(link->lldp_file);
+
+        if (!link->lldp) {
+                (void) unlink(link->lldp_file);
+                return 0;
+        }
+
+        r = sd_lldp_get_neighbors(link->lldp, &l);
+        if (r < 0)
+                goto finish;
+        if (r == 0) {
+                (void) unlink(link->lldp_file);
+                goto finish;
+        }
+
+        n = r;
+
+        r = fopen_temporary(link->lldp_file, &f, &temp_path);
+        if (r < 0)
+                goto finish;
+
+        fchmod(fileno(f), 0644);
+
+        for (i = 0; i < n; i++) {
+                const void *p;
+                le64_t u;
+                size_t sz;
+
+                r = sd_lldp_neighbor_get_raw(l[i], &p, &sz);
+                if (r < 0)
+                        goto finish;
+
+                u = htole64(sz);
+                (void) fwrite(&u, 1, sizeof(u), f);
+                (void) fwrite(p, 1, sz, f);
+        }
+
+        r = fflush_and_check(f);
+        if (r < 0)
+                goto finish;
+
+        if (rename(temp_path, link->lldp_file) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+finish:
+        if (r < 0) {
+                (void) unlink(link->lldp_file);
+                if (temp_path)
+                        (void) unlink(temp_path);
+
+                log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
+        }
+
+        if (l) {
+                for (i = 0; i < n; i++)
+                        sd_lldp_neighbor_unref(l[i]);
+                free(l);
+        }
+
+        return r;
+}
diff --git a/src/network/networkd-lldp-rx.h b/src/network/networkd-lldp-rx.h
new file mode 100644 (file)
index 0000000..12f512f
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+typedef enum LLDPMode {
+        LLDP_MODE_NO = 0,
+        LLDP_MODE_YES = 1,
+        LLDP_MODE_ROUTERS_ONLY = 2,
+        _LLDP_MODE_MAX,
+        _LLDP_MODE_INVALID = -1,
+} LLDPMode;
+
+bool link_lldp_rx_enabled(Link *link);
+int link_lldp_rx_configure(Link *link);
+int link_update_lldp(Link *link);
+int link_lldp_save(Link *link);
+
+const char* lldp_mode_to_string(LLDPMode m) _const_;
+LLDPMode lldp_mode_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
index 8fd6365e68b42870ba5c719d91dcfce59ccc383c..00c4358a0a89500900de89406815f7fa9913b766 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <endian.h>
 #include <inttypes.h>
+#include <net/if.h>
 #include <string.h>
 
 #include "alloc-util.h"
@@ -9,6 +10,7 @@
 #include "fd-util.h"
 #include "hostname-util.h"
 #include "missing_network.h"
+#include "networkd-link.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
 #include "parse-util.h"
@@ -38,6 +40,21 @@ static const struct ether_addr lldp_multicast_addr[_LLDP_EMIT_MAX] = {
         [LLDP_EMIT_CUSTOMER_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }},
 };
 
+bool link_lldp_emit_enabled(Link *link) {
+        assert(link);
+
+        if (link->flags & IFF_LOOPBACK)
+                return false;
+
+        if (link->iftype != ARPHRD_ETHER)
+                return false;
+
+        if (!link->network)
+                return false;
+
+        return link->network->lldp_emit != LLDP_EMIT_NO;
+}
+
 static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) {
         assert(p);
 
index 6842804a7e0de7b1e78e13169e20b84ce081c77e..561becda41c84fec4d967165e0fe181009e9c637 100644 (file)
@@ -1,8 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <stdbool.h>
+
 #include "conf-parser.h"
-#include "networkd-link.h"
+
+typedef struct Link Link;
 
 typedef enum LLDPEmit {
         LLDP_EMIT_NO,
@@ -12,6 +15,7 @@ typedef enum LLDPEmit {
         _LLDP_EMIT_MAX,
 } LLDPEmit;
 
+bool link_lldp_emit_enabled(Link *link);
 int link_lldp_emit_start(Link *link);
 void link_lldp_emit_stop(Link *link);
 
index c9579370cb93f684885b1315f3c04f51dd083e83..de177e6d1abfa9e80d72a4eed5f519fbc97ec3c1 100644 (file)
@@ -1,9 +1,10 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <netinet/in.h>
 #include <sys/socket.h>
+#include <unistd.h>
 #include <linux/if.h>
 #include <linux/fib_rules.h>
-#include <unistd.h>
 
 #include "sd-daemon.h"
 #include "sd-netlink.h"
@@ -266,7 +267,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
         unsigned char protocol, scope, tos, table, rt_type;
         int family;
         unsigned char dst_prefixlen, src_prefixlen;
-        union in_addr_union dst = {}, gw = {}, src = {}, prefsrc = {};
+        union in_addr_union dst = IN_ADDR_NULL, gw = IN_ADDR_NULL, src = IN_ADDR_NULL, prefsrc = IN_ADDR_NULL;
         Route *route = NULL;
         int r;
 
@@ -477,19 +478,17 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
 }
 
 int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
+        _cleanup_free_ char *buf = NULL;
         Manager *m = userdata;
         Link *link = NULL;
         uint16_t type;
-        unsigned char flags;
-        int family;
-        unsigned char prefixlen;
-        unsigned char scope;
-        union in_addr_union in_addr;
+        unsigned char flags, prefixlen, scope;
+        union in_addr_union in_addr = IN_ADDR_NULL;
         struct ifa_cacheinfo cinfo;
         Address *address = NULL;
-        char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
+        char valid_buf[FORMAT_TIMESPAN_MAX];
         const char *valid_str = NULL;
-        int r, ifindex;
+        int ifindex, family, r;
 
         assert(rtnl);
         assert(message);
@@ -577,8 +576,9 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
                 assert_not_reached("Received unsupported address family");
         }
 
-        if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) {
-                log_link_warning(link, "Could not print address, ignoring");
+        r = in_addr_to_string(family, &in_addr, &buf);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not print address, ignoring: %m");
                 return 0;
         }
 
@@ -586,12 +586,10 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
         if (r < 0 && r != -ENODATA) {
                 log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
                 return 0;
-        } else if (r >= 0) {
-                if (cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
-                        valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
-                                                    cinfo.ifa_valid * USEC_PER_SEC,
-                                                    USEC_PER_SEC);
-        }
+        } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
+                valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
+                                            cinfo.ifa_valid * USEC_PER_SEC,
+                                            USEC_PER_SEC);
 
         (void) address_get(link, family, &in_addr, prefixlen, &address);
 
@@ -728,7 +726,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
 int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
         uint8_t tos = 0, to_prefixlen = 0, from_prefixlen = 0, protocol = 0;
         struct fib_rule_port_range sport = {}, dport = {};
-        union in_addr_union to = {}, from = {};
+        union in_addr_union to = IN_ADDR_NULL, from = IN_ADDR_NULL;
         RoutingPolicyRule *rule = NULL;
         uint32_t fwmark = 0, table = 0;
         const char *iif = NULL, *oif = NULL;
@@ -1266,20 +1264,10 @@ static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *
         return 0;
 }
 
-static void dhcp6_prefixes_hash_func(const struct in6_addr *addr, struct siphash *state) {
-        assert(addr);
-
-        siphash24_compress(addr, sizeof(*addr), state);
-}
-
-static int dhcp6_prefixes_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
-        return memcmp(a, b, sizeof(*a));
-}
-
-DEFINE_PRIVATE_HASH_OPS(dhcp6_prefixes_hash_ops, struct in6_addr, dhcp6_prefixes_hash_func, dhcp6_prefixes_compare_func);
-
 int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
+        _cleanup_free_ struct in6_addr *a = NULL;
         _cleanup_free_ char *buf = NULL;
+        Link *assigned_link;
         Route *route;
         int r;
 
@@ -1298,11 +1286,27 @@ int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
         (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
         log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
 
-        r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &dhcp6_prefixes_hash_ops);
+        assigned_link = hashmap_get(m->dhcp6_prefixes, addr);
+        if (assigned_link) {
+                assert(assigned_link == link);
+                return 0;
+        }
+
+        a = newdup(struct in6_addr, addr, 1);
+        if (!a)
+                return -ENOMEM;
+
+        r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops);
+        if (r < 0)
+                return r;
+
+        r = hashmap_put(m->dhcp6_prefixes, a, link);
         if (r < 0)
                 return r;
 
-        return hashmap_put(m->dhcp6_prefixes, addr, link);
+        TAKE_PTR(a);
+        link_ref(link);
+        return 0;
 }
 
 static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
@@ -1318,21 +1322,21 @@ static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Lin
 }
 
 static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
+        _cleanup_free_ struct in6_addr *a = NULL;
+        _cleanup_(link_unrefp) Link *l = NULL;
         _cleanup_free_ char *buf = NULL;
         Route *route;
-        Link *l;
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(addr, -EINVAL);
 
-        l = hashmap_remove(m->dhcp6_prefixes, addr);
+        l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a);
         if (!l)
                 return -EINVAL;
 
         (void) sd_radv_remove_prefix(l->radv, addr, 64);
-        r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64,
-                      0, 0, 0, &route);
+        r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
         if (r < 0)
                 return r;
 
@@ -1354,12 +1358,9 @@ int manager_dhcp6_prefix_remove_all(Manager *m, Link *link) {
         assert_return(m, -EINVAL);
         assert_return(link, -EINVAL);
 
-        HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i) {
-                if (l != link)
-                        continue;
-
-                (void) manager_dhcp6_prefix_remove(m, addr);
-        }
+        HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i)
+                if (l == link)
+                        (void) manager_dhcp6_prefix_remove(m, addr);
 
         return 0;
 }
@@ -1402,8 +1403,6 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        LIST_HEAD_INIT(m->networks);
-
         r = sd_resolve_default(&m->resolve);
         if (r < 0)
                 return r;
@@ -1426,8 +1425,8 @@ int manager_new(Manager **ret) {
 }
 
 void manager_free(Manager *m) {
+        struct in6_addr *a;
         AddressPool *pool;
-        Network *network;
         Link *link;
 
         if (!m)
@@ -1435,17 +1434,16 @@ void manager_free(Manager *m) {
 
         free(m->state_file);
 
-        sd_netlink_unref(m->rtnl);
-        sd_netlink_unref(m->genl);
-        sd_resolve_unref(m->resolve);
-
-        while ((link = hashmap_first(m->dhcp6_prefixes)))
-                manager_dhcp6_prefix_remove_all(m, link);
+        while ((a = hashmap_first_key(m->dhcp6_prefixes)))
+                (void) manager_dhcp6_prefix_remove(m, a);
         hashmap_free(m->dhcp6_prefixes);
 
         while ((link = hashmap_steal_first(m->links))) {
                 if (link->dhcp6_client)
                         (void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client, link);
+
+                link_stop_clients(link);
+
                 link_unref(link);
         }
 
@@ -1454,9 +1452,7 @@ void manager_free(Manager *m) {
         m->links = hashmap_free_with_destructor(m->links, link_unref);
 
         m->duids_requesting_uuid = set_free(m->duids_requesting_uuid);
-        while ((network = m->networks))
-                network_free(network);
-        hashmap_free(m->networks_by_name);
+        m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
 
         m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
 
@@ -1469,6 +1465,10 @@ void manager_free(Manager *m) {
         m->rules_foreign = set_free_with_destructor(m->rules_foreign, routing_policy_rule_free);
         set_free_with_destructor(m->rules_saved, routing_policy_rule_free);
 
+        sd_netlink_unref(m->rtnl);
+        sd_netlink_unref(m->genl);
+        sd_resolve_unref(m->resolve);
+
         sd_event_unref(m->event);
 
         sd_device_monitor_unref(m->device_monitor);
index 35ab6bedb17058718a37a89b3cace8ee98c47f3d..06fa9d8d32f7ffd66b7f0c301538798f3126403d 100644 (file)
@@ -1,8 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
-#include <arpa/inet.h>
-
 #include "sd-bus.h"
 #include "sd-device.h"
 #include "sd-event.h"
@@ -37,9 +35,8 @@ struct Manager {
 
         Hashmap *links;
         Hashmap *netdevs;
-        Hashmap *networks_by_name;
+        OrderedHashmap *networks;
         Hashmap *dhcp6_prefixes;
-        LIST_HEAD(Network, networks);
         LIST_HEAD(AddressPool, address_pools);
 
         usec_t network_dirs_ts_usec;
index eb470a4d481509b3ccfc2aea3f535c067717bd00..3016f3448bddc9644767010f21f0246ae62e71d4 100644 (file)
@@ -39,7 +39,7 @@ static int ndisc_netlink_message_handler(sd_netlink *rtnl, sd_netlink_message *m
 
 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         _cleanup_(route_freep) Route *route = NULL;
-        struct in6_addr gateway;
+        union in_addr_union gateway;
         uint16_t lifetime;
         unsigned preference;
         uint32_t mtu;
@@ -58,31 +58,35 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (lifetime == 0) /* not a default router */
                 return 0;
 
-        r = sd_ndisc_router_get_address(rt, &gateway);
+        r = sd_ndisc_router_get_address(rt, &gateway.in6);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
 
-        SET_FOREACH(address, link->addresses, i)
-                if (!memcmp(&gateway, &address->in_addr.in6, sizeof(address->in_addr.in6))) {
-                        char buffer[INET6_ADDRSTRLEN];
+        SET_FOREACH(address, link->addresses, i) {
+                if (address->family != AF_INET6)
+                        continue;
+                if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
+                        _cleanup_free_ char *buffer = NULL;
 
+                        (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
                         log_link_debug(link, "No NDisc route added, gateway %s matches local address",
-                                       inet_ntop(AF_INET6,
-                                                 &address->in_addr.in6,
-                                                 buffer, sizeof(buffer)));
+                                       strnull(buffer));
                         return 0;
                 }
+        }
 
-        SET_FOREACH(address, link->addresses_foreign, i)
-                if (!memcmp(&gateway, &address->in_addr.in6, sizeof(address->in_addr.in6))) {
-                        char buffer[INET6_ADDRSTRLEN];
+        SET_FOREACH(address, link->addresses_foreign, i) {
+                if (address->family != AF_INET6)
+                        continue;
+                if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
+                        _cleanup_free_ char *buffer = NULL;
 
+                        (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
                         log_link_debug(link, "No NDisc route added, gateway %s matches local address",
-                                       inet_ntop(AF_INET6,
-                                                 &address->in_addr.in6,
-                                                 buffer, sizeof(buffer)));
+                                       strnull(buffer));
                         return 0;
                 }
+        }
 
         r = sd_ndisc_router_get_preference(rt, &preference);
         if (r < 0)
@@ -107,7 +111,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         route->priority = link->network->dhcp_route_metric;
         route->protocol = RTPROT_RA;
         route->pref = preference;
-        route->gw.in6 = gateway;
+        route->gw = gateway;
         route->lifetime = time_now + lifetime * USEC_PER_SEC;
         route->mtu = mtu;
 
@@ -553,9 +557,49 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
         return 0;
 }
 
+static int ndisc_prefix_is_black_listed(Link *link, sd_ndisc_router *rt) {
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(rt);
+
+        for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
+                union in_addr_union a;
+                uint8_t type;
+
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
+                if (r == 0) /* EOF */
+                        return false;
+
+                r = sd_ndisc_router_option_get_type(rt, &type);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
+
+                if (type != SD_NDISC_OPTION_PREFIX_INFORMATION)
+                        continue;
+
+                r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Failed to get prefix address: %m");
+
+                if (set_contains(link->network->ndisc_black_listed_prefix, &a.in6)) {
+                        if (DEBUG_LOGGING) {
+                                _cleanup_free_ char *b = NULL;
+
+                                (void) in_addr_to_string(AF_INET6, &a, &b);
+                                log_link_debug(link, "Prefix '%s' is black listed, ignoring", strna(b));
+                        }
+
+                        return true;
+                }
+        }
+}
+
 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
         uint64_t flags;
-        int r = 0;
+        int r;
 
         assert(link);
         assert(link->network);
@@ -577,8 +621,10 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
                 }
         }
 
-        (void) ndisc_router_process_default(link, rt);
-        (void) ndisc_router_process_options(link, rt);
+        if (ndisc_prefix_is_black_listed(link, rt) == 0) {
+                (void) ndisc_router_process_default(link, rt);
+                (void) ndisc_router_process_options(link, rt);
+        }
 
         return r;
 }
@@ -668,3 +714,76 @@ void ndisc_flush(Link *link) {
         link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
         link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
 }
+
+int config_parse_ndisc_black_listed_prefix(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->ndisc_black_listed_prefix = set_free_free(network->ndisc_black_listed_prefix);
+                return 0;
+        }
+
+        for (p = rvalue;;) {
+                _cleanup_free_ char *n = NULL;
+                _cleanup_free_ struct in6_addr *a = NULL;
+                union in_addr_union ip;
+
+                r = extract_first_word(&p, &n, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse NDISC black listed prefix, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET6, n, &ip);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "NDISC black listed prefix is invalid, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
+                if (r < 0)
+                        return log_oom();
+
+                a = newdup(struct in6_addr, &ip.in6, 1);
+                if (!a)
+                        return log_oom();
+
+                r = set_put(network->ndisc_black_listed_prefix, a);
+                if (r < 0) {
+                        if (r == -EEXIST)
+                                log_syntax(unit, LOG_WARNING, filename, line, r,
+                                           "NDISC black listed prefixs is duplicated, ignoring assignment: %s", n);
+                        else
+                                log_syntax(unit, LOG_ERR, filename, line, r,
+                                           "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
+                        continue;
+                }
+
+                TAKE_PTR(a);
+        }
+
+        return 0;
+}
index 0b614bf50ffcc35c1186004a96223129f4726b4b..dc0a44f523096dd5b075d358994f1a9b7ff95cf3 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include "conf-parser.h"
 #include "networkd-link.h"
 #include "time-util.h"
 
@@ -21,3 +22,5 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
 int ndisc_configure(Link *link);
 void ndisc_vacuum(Link *link);
 void ndisc_flush(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_black_listed_prefix);
index 07e453cc8086a143582c93d568b52b1b555f6eb3..e3ba148ce1bf744d171fb5f68145436494bb89bc 100644 (file)
@@ -87,6 +87,7 @@ int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
         _cleanup_strv_free_ char **l = NULL;
         Manager *m = userdata;
         Network *network;
+        Iterator i;
         int r;
 
         assert(bus);
@@ -94,7 +95,7 @@ int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
         assert(m);
         assert(nodes);
 
-        LIST_FOREACH(networks, network, m->networks) {
+        ORDERED_HASHMAP_FOREACH(network, m->networks, i) {
                 char *p;
 
                 p = network_bus_path(network);
index 0db59473ffd2932bba7c2f76554ab2b89542cc2f..9ef07ea372be1927393cc95028d4f5284b51aa0d 100644 (file)
@@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "conf-parser.h"
 #include "network-internal.h"
 #include "networkd-conf.h"
+#include "networkd-ndisc.h"
 #include "networkd-network.h"
 #include "vlan-util.h"
 %}
@@ -44,6 +45,7 @@ Network.VLAN,                           config_parse_stacked_netdev,
 Network.MACVLAN,                        config_parse_stacked_netdev,                     NETDEV_KIND_MACVLAN,           offsetof(Network, stacked_netdev_names)
 Network.MACVTAP,                        config_parse_stacked_netdev,                     NETDEV_KIND_MACVTAP,           offsetof(Network, stacked_netdev_names)
 Network.IPVLAN,                         config_parse_stacked_netdev,                     NETDEV_KIND_IPVLAN,            offsetof(Network, stacked_netdev_names)
+Network.IPVTAP,                         config_parse_stacked_netdev,                     NETDEV_KIND_IPVTAP,            offsetof(Network, stacked_netdev_names)
 Network.VXLAN,                          config_parse_stacked_netdev,                     NETDEV_KIND_VXLAN,             offsetof(Network, stacked_netdev_names)
 Network.L2TP,                           config_parse_stacked_netdev,                     NETDEV_KIND_L2TP,              offsetof(Network, stacked_netdev_names)
 Network.MACsec,                         config_parse_stacked_netdev,                     NETDEV_KIND_MACSEC,            offsetof(Network, stacked_netdev_names)
@@ -51,8 +53,9 @@ Network.Tunnel,                         config_parse_stacked_netdev,
 Network.VRF,                            config_parse_ifname,                             0,                             offsetof(Network, vrf_name)
 Network.DHCP,                           config_parse_dhcp,                               0,                             offsetof(Network, dhcp)
 Network.DHCPServer,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server)
-Network.LinkLocalAddressing,            config_parse_address_family_boolean,             0,                             offsetof(Network, link_local)
+Network.LinkLocalAddressing,            config_parse_link_local_address_family_boolean,  0,                             offsetof(Network, link_local)
 Network.IPv4LLRoute,                    config_parse_bool,                               0,                             offsetof(Network, ipv4ll_route)
+Network.DefaultRouteOnDevice,           config_parse_bool,                               0,                             offsetof(Network, default_route_on_device)
 Network.IPv6Token,                      config_parse_ipv6token,                          0,                             offsetof(Network, ipv6_token)
 Network.LLDP,                           config_parse_lldp_mode,                          0,                             offsetof(Network, lldp_mode)
 Network.EmitLLDP,                       config_parse_lldp_emit,                          0,                             offsetof(Network, lldp_emit)
@@ -127,6 +130,8 @@ Route.Type,                             config_parse_route_type,
 Route.InitialCongestionWindow,          config_parse_tcp_window,                         0,                             0
 Route.InitialAdvertisedReceiveWindow,   config_parse_tcp_window,                         0,                             0
 Route.QuickAck,                         config_parse_quickack,                           0,                             0
+Route.FastOpenNoCookie,                 config_parse_fast_open_no_cookie,                0,                             0
+Route.TTLPropagate,                     config_parse_route_ttl_propagate,                0,                             0
 DHCP.ClientIdentifier,                  config_parse_dhcp_client_identifier,             0,                             offsetof(Network, dhcp_client_identifier)
 DHCP.UseDNS,                            config_parse_bool,                               0,                             offsetof(Network, dhcp_use_dns)
 DHCP.UseNTP,                            config_parse_bool,                               0,                             offsetof(Network, dhcp_use_ntp)
@@ -140,6 +145,7 @@ DHCP.Hostname,                          config_parse_hostname,
 DHCP.RequestBroadcast,                  config_parse_bool,                               0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,                config_parse_bool,                               0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,             config_parse_string,                             0,                             offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.MaxAttempts,                       config_parse_dhcp_max_attempts,                  0,                             0
 DHCP.UserClass,                         config_parse_dhcp_user_class,                    0,                             offsetof(Network, dhcp_user_class)
 DHCP.DUIDType,                          config_parse_duid_type,                          0,                             offsetof(Network, duid)
 DHCP.DUIDRawData,                       config_parse_duid_rawdata,                       0,                             offsetof(Network, duid)
@@ -148,13 +154,16 @@ DHCP.RouteTable,                        config_parse_section_route_table,
 DHCP.UseTimezone,                       config_parse_bool,                               0,                             offsetof(Network, dhcp_use_timezone)
 DHCP.IAID,                              config_parse_iaid,                               0,                             0
 DHCP.ListenPort,                        config_parse_uint16,                             0,                             offsetof(Network, dhcp_client_port)
+DHCP.SendRelease,                       config_parse_bool,                               0,                             offsetof(Network, dhcp_send_release)
 DHCP.RapidCommit,                       config_parse_bool,                               0,                             offsetof(Network, rapid_commit)
+DHCP.BlackList,                         config_parse_dhcp_black_listed_ip_address,       0,                             0
 DHCP.ForceDHCPv6PDOtherInformation,     config_parse_bool,                               0,                             offsetof(Network, dhcp6_force_pd_other_information)
 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.UseDNS,                    config_parse_bool,                               0,                             offsetof(Network, ipv6_accept_ra_use_dns)
 IPv6AcceptRA.UseDomains,                config_parse_dhcp_use_domains,                   0,                             offsetof(Network, ipv6_accept_ra_use_domains)
 IPv6AcceptRA.RouteTable,                config_parse_section_route_table,                0,                             0
+IPv6AcceptRA.BlackList,                 config_parse_ndisc_black_listed_prefix,          0,                             0
 DHCPServer.MaxLeaseTimeSec,             config_parse_sec,                                0,                             offsetof(Network, dhcp_server_max_lease_time_usec)
 DHCPServer.DefaultLeaseTimeSec,         config_parse_sec,                                0,                             offsetof(Network, dhcp_server_default_lease_time_usec)
 DHCPServer.EmitDNS,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server_emit_dns)
@@ -176,9 +185,15 @@ Bridge.MulticastFlood,                  config_parse_tristate,
 Bridge.MulticastToUnicast,              config_parse_tristate,                           0,                             offsetof(Network, multicast_to_unicast)
 Bridge.NeighborSuppression,             config_parse_tristate,                           0,                             offsetof(Network, neighbor_suppression)
 Bridge.Learning,                        config_parse_tristate,                           0,                             offsetof(Network, learning)
+Bridge.ProxyARP,                        config_parse_tristate,                           0,                             offsetof(Network, bridge_proxy_arp)
+Bridge.ProxyARPWiFi,                    config_parse_tristate,                           0,                             offsetof(Network, bridge_proxy_arp_wifi)
 Bridge.Priority,                        config_parse_bridge_port_priority,               0,                             offsetof(Network, priority)
+Bridge.MulticastRouter,                 config_parse_multicast_router,                   0,                             offsetof(Network, multicast_router)
 BridgeFDB.MACAddress,                   config_parse_fdb_hwaddr,                         0,                             0
 BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,                        0,                             0
+BridgeFDB.Destination,                  config_parse_fdb_destination,                    0,                             0
+BridgeFDB.VNI,                          config_parse_fdb_vxlan_vni,                      0,                             0
+BridgeFDB.AssociatedWith,               config_parse_fdb_ntf_flags,                      0,                             0
 BridgeVLAN.PVID,                        config_parse_brvlan_pvid,                        0,                             0
 BridgeVLAN.VLAN,                        config_parse_brvlan_vlan,                        0,                             0
 BridgeVLAN.EgressUntagged,              config_parse_brvlan_untagged,                    0,                             0
index 1828d1126c05aea9d79e4637df225dca9c17787a..a5e7cad58a4c9b910d4bd647e8397fe26912a424 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <net/if.h>
+#include <netinet/in.h>
 #include <linux/netdevice.h>
 
 #include "alloc-util.h"
@@ -141,24 +143,6 @@ static int network_resolve_stacked_netdevs(Network *network) {
         return 0;
 }
 
-static uint32_t network_get_stacked_netdevs_mtu(Network *network) {
-        uint32_t mtu = 0;
-        NetDev *dev;
-        Iterator i;
-
-        HASHMAP_FOREACH(dev, network->stacked_netdevs, i)
-                if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
-                        /* See vlan_dev_change_mtu() in kernel.
-                         * Note that the additional 4bytes may not be necessary for all devices. */
-                        mtu = MAX(mtu, dev->mtu + 4);
-
-                else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
-                        /* See macvlan_change_mtu() in kernel. */
-                        mtu = dev->mtu;
-
-        return mtu;
-}
-
 int network_verify(Network *network) {
         Address *address, *address_next;
         Route *route, *route_next;
@@ -167,7 +151,6 @@ int network_verify(Network *network) {
         AddressLabel *label, *label_next;
         Prefix *prefix, *prefix_next;
         RoutingPolicyRule *rule, *rule_next;
-        uint32_t mtu;
 
         assert(network);
         assert(network->filename);
@@ -236,6 +219,13 @@ int network_verify(Network *network) {
         if (network->link_local < 0)
                 network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
 
+        if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) &&
+            !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) {
+                log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. "
+                            "Disabling the fallback assignment.", network->filename);
+                SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
+        }
+
         if (network->ipv6_accept_ra < 0 && network->bridge)
                 network->ipv6_accept_ra = false;
 
@@ -243,16 +233,7 @@ int network_verify(Network *network) {
         if (network->ip_masquerade)
                 network->ip_forward |= ADDRESS_FAMILY_IPV4;
 
-        network->mtu_is_set = network->mtu > 0;
-        mtu = network_get_stacked_netdevs_mtu(network);
-        if (network->mtu < mtu) {
-                if (network->mtu_is_set)
-                        log_notice("%s: Bumping MTUBytes= from %"PRIu32" to %"PRIu32" because of stacked device",
-                                   network->filename, network->mtu, mtu);
-                network->mtu = mtu;
-        }
-
-        if (network->mtu_is_set && network->dhcp_use_mtu) {
+        if (network->mtu > 0 && network->dhcp_use_mtu) {
                 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
                             "Disabling UseMTU=.", network->filename);
                 network->dhcp_use_mtu = false;
@@ -291,7 +272,7 @@ int network_verify(Network *network) {
 
 int network_load_one(Manager *manager, const char *filename) {
         _cleanup_free_ char *fname = NULL, *name = NULL;
-        _cleanup_(network_freep) Network *network = NULL;
+        _cleanup_(network_unrefp) Network *network = NULL;
         _cleanup_fclose_ FILE *file = NULL;
         const char *dropin_dirname;
         char *d;
@@ -337,6 +318,9 @@ int network_load_one(Manager *manager, const char *filename) {
                 .filename = TAKE_PTR(fname),
                 .name = TAKE_PTR(name),
 
+                .manager = manager,
+                .n_ref = 1,
+
                 .required_for_online = true,
                 .required_operstate_for_online = LINK_OPERSTATE_DEGRADED,
                 .dhcp = ADDRESS_FAMILY_NO,
@@ -349,7 +333,7 @@ int network_load_one(Manager *manager, const char *filename) {
                 /* To enable/disable RFC7844 Anonymity Profiles */
                 .dhcp_anonymize = false,
                 .dhcp_route_metric = DHCP_ROUTE_METRIC,
-                /* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
+                /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
                 .dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
                 .dhcp_route_table = RT_TABLE_MAIN,
                 .dhcp_route_table_set = false,
@@ -376,7 +360,10 @@ int network_load_one(Manager *manager, const char *filename) {
                 .multicast_to_unicast = -1,
                 .neighbor_suppression = -1,
                 .learning = -1,
+                .bridge_proxy_arp = -1,
+                .bridge_proxy_arp_wifi = -1,
                 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
+                .multicast_router = _MULTICAST_ROUTER_INVALID,
 
                 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
 
@@ -439,14 +426,16 @@ int network_load_one(Manager *manager, const char *filename) {
         if (r < 0)
                 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
 
-        LIST_PREPEND(networks, manager->networks, network);
-        network->manager = manager;
+        r = network_add_default_route_on_device(network);
+        if (r < 0)
+                log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
+                                  network->filename);
 
-        r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
+        r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
         if (r < 0)
                 return r;
 
-        r = hashmap_put(manager->networks_by_name, network->name, network);
+        r = ordered_hashmap_put(manager->networks, network->name, network);
         if (r < 0)
                 return r;
 
@@ -458,21 +447,19 @@ int network_load_one(Manager *manager, const char *filename) {
 }
 
 int network_load(Manager *manager) {
-        Network *network;
         _cleanup_strv_free_ char **files = NULL;
         char **f;
         int r;
 
         assert(manager);
 
-        while ((network = manager->networks))
-                network_free(network);
+        ordered_hashmap_clear_with_destructor(manager->networks, network_unref);
 
         r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
         if (r < 0)
                 return log_error_errno(r, "Failed to enumerate network files: %m");
 
-        STRV_FOREACH_BACKWARDS(f, files) {
+        STRV_FOREACH(f, files) {
                 r = network_load_one(manager, *f);
                 if (r < 0)
                         return r;
@@ -481,7 +468,7 @@ int network_load(Manager *manager) {
         return 0;
 }
 
-void network_free(Network *network) {
+static Network *network_free(Network *network) {
         IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
         RoutingPolicyRule *rule;
         FdbEntry *fdb_entry;
@@ -492,7 +479,7 @@ void network_free(Network *network) {
         Route *route;
 
         if (!network)
-                return;
+                return NULL;
 
         free(network->filename);
 
@@ -507,7 +494,7 @@ void network_free(Network *network) {
         free(network->dhcp_vendor_class_identifier);
         strv_free(network->dhcp_user_class);
         free(network->dhcp_hostname);
-
+        set_free(network->dhcp_black_listed_ip);
         free(network->mac);
 
         strv_free(network->ntp);
@@ -518,6 +505,7 @@ void network_free(Network *network) {
 
         ordered_set_free_free(network->router_search_domains);
         free(network->router_dns);
+        set_free_free(network->ndisc_black_listed_prefix);
 
         free(network->bridge_name);
         free(network->bond_name);
@@ -561,11 +549,8 @@ void network_free(Network *network) {
         hashmap_free(network->rules_by_section);
 
         if (network->manager) {
-                if (network->manager->networks)
-                        LIST_REMOVE(networks, network->manager->networks, network);
-
-                if (network->manager->networks_by_name && network->name)
-                        hashmap_remove(network->manager->networks_by_name, network->name);
+                if (network->manager->networks && network->name)
+                        ordered_hashmap_remove(network->manager->networks, network->name);
 
                 if (network->manager->duids_requesting_uuid)
                         set_remove(network->manager->duids_requesting_uuid, &network->duid);
@@ -579,9 +564,11 @@ void network_free(Network *network) {
 
         set_free_free(network->dnssec_negative_trust_anchors);
 
-        free(network);
+        return mfree(network);
 }
 
+DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
+
 int network_get_by_name(Manager *manager, const char *name, Network **ret) {
         Network *network;
 
@@ -589,7 +576,7 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
         assert(name);
         assert(ret);
 
-        network = hashmap_get(manager->networks_by_name, name);
+        network = ordered_hashmap_get(manager->networks, name);
         if (!network)
                 return -ENOENT;
 
@@ -603,6 +590,7 @@ int network_get(Manager *manager, sd_device *device,
                 Network **ret) {
         const char *path = NULL, *driver = NULL, *devtype = NULL;
         Network *network;
+        Iterator i;
 
         assert(manager);
         assert(ret);
@@ -615,7 +603,7 @@ int network_get(Manager *manager, sd_device *device,
                 (void) sd_device_get_devtype(device, &devtype);
         }
 
-        LIST_FOREACH(networks, network, manager->networks) {
+        ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
                 if (net_match_config(network->match_mac, network->match_path,
                                      network->match_driver, network->match_type,
                                      network->match_name,
@@ -638,7 +626,6 @@ int network_get(Manager *manager, sd_device *device,
                         *ret = network;
                         return 0;
                 }
-        }
 
         *ret = NULL;
 
@@ -649,7 +636,7 @@ int network_apply(Network *network, Link *link) {
         assert(network);
         assert(link);
 
-        link->network = network;
+        link->network = network_ref(network);
 
         if (network->n_dns > 0 ||
             !strv_isempty(network->ntp) ||
@@ -694,8 +681,8 @@ int config_parse_stacked_netdev(const char *unit,
         assert(data);
         assert(IN_SET(kind,
                       NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
-                      NETDEV_KIND_IPVLAN, NETDEV_KIND_VXLAN, NETDEV_KIND_L2TP,
-                      NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
+                      NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
+                      NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
 
         if (!ifname_valid(rvalue)) {
                 log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -818,6 +805,7 @@ int config_parse_ipv4ll(
                 void *userdata) {
 
         AddressFamilyBoolean *link_local = data;
+        int r;
 
         assert(filename);
         assert(lvalue);
@@ -828,7 +816,20 @@ int config_parse_ipv4ll(
          * config_parse_address_family_boolean(), except that it
          * applies only to IPv4 */
 
-        SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse %s=%s, ignoring assignment. "
+                           "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
+                           lvalue, rvalue, lvalue);
+                return 0;
+        }
+
+        SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
+
+        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                   "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
+                   lvalue, rvalue, address_family_boolean_to_string(*link_local));
 
         return 0;
 }
@@ -1097,7 +1098,8 @@ int config_parse_dhcp_server_dns(
 
         for (;;) {
                 _cleanup_free_ char *w = NULL;
-                struct in_addr a, *m;
+                union in_addr_union a;
+                struct in_addr *m;
 
                 r = extract_first_word(&p, &w, NULL, 0);
                 if (r == -ENOMEM)
@@ -1110,9 +1112,10 @@ int config_parse_dhcp_server_dns(
                 if (r == 0)
                         break;
 
-                if (inet_pton(AF_INET, w, &a) <= 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Failed to parse DNS server address, ignoring: %s", w);
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
                         continue;
                 }
 
@@ -1120,7 +1123,7 @@ int config_parse_dhcp_server_dns(
                 if (!m)
                         return log_oom();
 
-                m[n->n_dhcp_server_dns++] = a;
+                m[n->n_dhcp_server_dns++] = a.in;
                 n->dhcp_server_dns = m;
         }
 
@@ -1257,7 +1260,8 @@ int config_parse_dhcp_server_ntp(
 
         for (;;) {
                 _cleanup_free_ char *w = NULL;
-                struct in_addr a, *m;
+                union in_addr_union a;
+                struct in_addr *m;
 
                 r = extract_first_word(&p, &w, NULL, 0);
                 if (r == -ENOMEM)
@@ -1270,9 +1274,10 @@ int config_parse_dhcp_server_ntp(
                 if (r == 0)
                         return 0;
 
-                if (inet_pton(AF_INET, w, &a) <= 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Failed to parse NTP server address, ignoring: %s", w);
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse NTP server address '%s', ignoring: %m", w);
                         continue;
                 }
 
@@ -1280,7 +1285,7 @@ int config_parse_dhcp_server_ntp(
                 if (!m)
                         return log_oom();
 
-                m[n->n_dhcp_server_ntp++] = a;
+                m[n->n_dhcp_server_ntp++] = a.in;
                 n->dhcp_server_ntp = m;
         }
 }
@@ -1554,6 +1559,114 @@ int config_parse_section_route_table(
         return 0;
 }
 
+int config_parse_dhcp_max_attempts(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        uint64_t a;
+        int r;
+
+        assert(network);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                network->dhcp_max_attempts = 0;
+                return 0;
+        }
+
+        if (streq(rvalue, "infinity")) {
+                network->dhcp_max_attempts = (uint64_t) -1;
+                return 0;
+        }
+
+        r = safe_atou64(rvalue, &a);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (a == 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        network->dhcp_max_attempts = a;
+
+        return 0;
+}
+
+int config_parse_dhcp_black_listed_ip_address(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
+                return 0;
+        }
+
+        for (p = rvalue;;) {
+                _cleanup_free_ char *n = NULL;
+                union in_addr_union ip;
+
+                r = extract_first_word(&p, &n, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET, n, &ip);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
+                if (r < 0)
+                        return log_oom();
+
+                r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
+        }
+
+        return 0;
+}
+
 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
                          "Failed to parse DHCP use domains setting");
 
@@ -1565,16 +1678,6 @@ static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
 
-DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
-
-static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
-        [LLDP_MODE_NO] = "no",
-        [LLDP_MODE_YES] = "yes",
-        [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
-
 int config_parse_iaid(const char *unit,
                       const char *filename,
                       unsigned line,
index 852144da3c0a0d9d0fbd1803bd59c953170b3dab..d2a0b8c5f14ee6d59e637d4033d7da34390ae7a7 100644 (file)
@@ -8,12 +8,14 @@
 #include "conf-parser.h"
 #include "dhcp-identifier.h"
 #include "hashmap.h"
+#include "netdev/bridge.h"
 #include "netdev/netdev.h"
 #include "networkd-address-label.h"
 #include "networkd-address.h"
 #include "networkd-brvlan.h"
 #include "networkd-fdb.h"
 #include "networkd-ipv6-proxy-ndp.h"
+#include "networkd-lldp-rx.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-neighbor.h"
 #include "networkd-radv.h"
@@ -58,14 +60,6 @@ typedef enum DHCPUseDomains {
         _DHCP_USE_DOMAINS_INVALID = -1,
 } DHCPUseDomains;
 
-typedef enum LLDPMode {
-        LLDP_MODE_NO = 0,
-        LLDP_MODE_YES = 1,
-        LLDP_MODE_ROUTERS_ONLY = 2,
-        _LLDP_MODE_MAX,
-        _LLDP_MODE_INVALID = -1,
-} LLDPMode;
-
 typedef struct DUID {
         /* Value of Type in [DHCP] section */
         DUIDType type;
@@ -92,6 +86,8 @@ struct Network {
         char *filename;
         char *name;
 
+        unsigned n_ref;
+
         Set *match_mac;
         char **match_path;
         char **match_driver;
@@ -116,6 +112,7 @@ struct Network {
         char *dhcp_vendor_class_identifier;
         char **dhcp_user_class;
         char *dhcp_hostname;
+        uint64_t dhcp_max_attempts;
         unsigned dhcp_route_metric;
         uint32_t dhcp_route_table;
         uint16_t dhcp_client_port;
@@ -131,7 +128,9 @@ struct Network {
         bool rapid_commit;
         bool dhcp_use_hostname;
         bool dhcp_route_table_set;
+        bool dhcp_send_release;
         DHCPUseDomains dhcp_use_domains;
+        Set *dhcp_black_listed_ip;
 
         /* DHCP Server Support */
         bool dhcp_server;
@@ -152,6 +151,8 @@ struct Network {
         AddressFamilyBoolean link_local;
         bool ipv4ll_route;
 
+        bool default_route_on_device;
+
         /* IPv6 prefix delegation support */
         RADVPrefixDelegation router_prefix_delegation;
         usec_t router_lifetime_usec;
@@ -178,8 +179,11 @@ struct Network {
         int multicast_to_unicast;
         int neighbor_suppression;
         int learning;
+        int bridge_proxy_arp;
+        int bridge_proxy_arp_wifi;
         uint32_t cost;
         uint16_t priority;
+        MulticastRouter multicast_router;
 
         bool use_br_vlan;
         uint16_t pvid;
@@ -210,13 +214,13 @@ struct Network {
         DHCPUseDomains ipv6_accept_ra_use_domains;
         uint32_t ipv6_accept_ra_route_table;
         bool ipv6_accept_ra_route_table_set;
+        Set *ndisc_black_listed_prefix;
 
         union in_addr_union ipv6_token;
         IPv6PrivacyExtensions ipv6_privacy_extensions;
 
         struct ether_addr *mac;
         uint32_t mtu;
-        bool mtu_is_set; /* Indicate MTUBytes= is specified. */
         int arp;
         int multicast;
         int allmulticast;
@@ -274,13 +278,11 @@ struct Network {
 
         char **ntp;
         char **bind_carrier;
-
-        LIST_FIELDS(Network, networks);
 };
 
-void network_free(Network *network);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
+Network *network_ref(Network *network);
+Network *network_unref(Network *network);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_unref);
 
 int network_load(Manager *manager);
 int network_load_one(Manager *manager, const char *filename);
@@ -304,17 +306,18 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
 CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
 CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
-CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
 CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
 CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
 CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
 /* Legacy IPv4LL support */
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
 
@@ -331,8 +334,5 @@ IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
 const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
 DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
 
-const char* lldp_mode_to_string(LLDPMode m) _const_;
-LLDPMode lldp_mode_from_string(const char *s) _pure_;
-
 const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
 RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
index 8cb14b588cfbd5a7ab4f0c4e93e9697f5219c0e8..fdbf7cac62880f7105bfe5ca4e2b8576bf6d9ea6 100644 (file)
@@ -356,7 +356,7 @@ static int radv_set_dns(Link *link, Link *uplink) {
         if (link->network->router_dns) {
                 dns = newdup(struct in6_addr, link->network->router_dns,
                              link->network->n_router_dns);
-                if (dns == NULL)
+                if (!dns)
                         return -ENOMEM;
 
                 n_dns = link->network->n_router_dns;
@@ -372,7 +372,7 @@ static int radv_set_dns(Link *link, Link *uplink) {
                 goto set_dns;
 
         if (uplink) {
-                if (uplink->network == NULL) {
+                if (!uplink->network) {
                         log_link_debug(uplink, "Cannot fetch DNS servers as uplink interface is not managed by us");
                         return 0;
                 }
@@ -411,7 +411,7 @@ static int radv_set_domains(Link *link, Link *uplink) {
                 goto set_domains;
 
         if (uplink) {
-                if (uplink->network == NULL) {
+                if (!uplink->network) {
                         log_link_debug(uplink, "Cannot fetch DNS search domains as uplink interface is not managed by us");
                         return 0;
                 }
index 379077cbfde9c5b17303de832f5228fb9d897c73..b21e7dfd86f2a2c3be846b402111ba7b86a8204e 100644 (file)
@@ -59,7 +59,9 @@ int route_new(Route **ret) {
                 .table = RT_TABLE_MAIN,
                 .lifetime = USEC_INFINITY,
                 .quickack = -1,
+                .fast_open_no_cookie = -1,
                 .gateway_onlink = -1,
+                .ttl_propagate = -1,
         };
 
         *ret = TAKE_PTR(route);
@@ -616,6 +618,12 @@ int route_configure(
                         return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
         }
 
+        if (route->ttl_propagate >= 0) {
+                r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m");
+        }
+
         r = sd_netlink_message_open_container(req, RTA_METRICS);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
@@ -638,12 +646,18 @@ int route_configure(
                         return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
         }
 
-        if (route->quickack != -1) {
+        if (route->quickack >= 0) {
                 r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
         }
 
+        if (route->fast_open_no_cookie >= 0) {
+                r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m");
+        }
+
         r = sd_netlink_message_close_container(req);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
@@ -705,6 +719,30 @@ int network_add_ipv4ll_route(Network *network) {
         return 0;
 }
 
+int network_add_default_route_on_device(Network *network) {
+        _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+        int r;
+
+        assert(network);
+
+        if (!network->default_route_on_device)
+                return 0;
+
+        /* DefaultRouteOnDevice= is in [Network] section. */
+        r = route_new_static(network, NULL, 0, &n);
+        if (r < 0)
+                return r;
+
+        r = in_addr_from_string(AF_INET, "169.254.0.0", &n->dst);
+        if (r < 0)
+                return r;
+
+        n->family = AF_INET;
+
+        TAKE_PTR(n);
+        return 0;
+}
+
 int config_parse_gateway(
                 const char *unit,
                 const char *filename,
@@ -1197,6 +1235,44 @@ int config_parse_quickack(
         return 0;
 }
 
+int config_parse_fast_open_no_cookie(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+        Network *network = userdata;
+        int k, r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        k = parse_boolean(rvalue);
+        if (k < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, k,
+                           "Failed to parse TCP fastopen no cookie, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        n->fast_open_no_cookie = k;
+        TAKE_PTR(n);
+        return 0;
+}
+
 int config_parse_route_mtu(
                 const char *unit,
                 const char *filename,
@@ -1231,6 +1307,45 @@ int config_parse_route_mtu(
         return 0;
 }
 
+int config_parse_route_ttl_propagate(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = userdata;
+        _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+        int r, k;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        k = parse_boolean(rvalue);
+        if (k < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, k,
+                           "Failed to parse TTLPropagate= value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        n->ttl_propagate = k;
+
+        TAKE_PTR(n);
+        return 0;
+}
+
 int route_section_verify(Route *route, Network *network) {
         if (section_is_invalid(route->section))
                 return -EINVAL;
index 1e8320fdc087814ca3c74af89a3f10aeb0c548a4..3c0ac896aea5a26961c11dea9cae0a6cd331fb2d 100644 (file)
@@ -17,6 +17,8 @@ struct Route {
 
         int family;
         int quickack;
+        int fast_open_no_cookie;
+        int ttl_propagate;
 
         unsigned char dst_prefixlen;
         unsigned char src_prefixlen;
@@ -61,6 +63,7 @@ int route_section_verify(Route *route, Network *network);
 DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
 
 int network_add_ipv4ll_route(Network *network);
+int network_add_default_route_on_device(Network *network);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
 CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
@@ -74,4 +77,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
 CONFIG_PARSER_PROTOTYPE(config_parse_quickack);
+CONFIG_PARSER_PROTOTYPE(config_parse_fast_open_no_cookie);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_ttl_propagate);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
index 28699ba2369d9f070df9fe3b90196e475df6d16a..4ee0b5489ef7002c5ae3fa90bb5de9c53898e8ad 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <inttypes.h>
+#include <netinet/in.h>
 #include <linux/fib_rules.h>
 #include <stdbool.h>
 
index a088d259814ea5e79b7ab1c677a8f4f79bd59ae8..d01de53f7be70a16407732818b9dd2161577b593 100644 (file)
@@ -8,38 +8,26 @@
 #include "string-util.h"
 #include "util.h"
 
-const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
-        if (IN_SET(b, ADDRESS_FAMILY_YES, ADDRESS_FAMILY_NO))
-                return yes_no(b == ADDRESS_FAMILY_YES);
-
-        if (b == ADDRESS_FAMILY_IPV4)
-                return "ipv4";
-        if (b == ADDRESS_FAMILY_IPV6)
-                return "ipv6";
-
-        return NULL;
-}
-
-AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
-        int r;
-
-        /* Make this a true superset of a boolean */
-
-        r = parse_boolean(s);
-        if (r > 0)
-                return ADDRESS_FAMILY_YES;
-        if (r == 0)
-                return ADDRESS_FAMILY_NO;
-
-        if (streq(s, "ipv4"))
-                return ADDRESS_FAMILY_IPV4;
-        if (streq(s, "ipv6"))
-                return ADDRESS_FAMILY_IPV6;
-
-        return _ADDRESS_FAMILY_BOOLEAN_INVALID;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
+static const char * const address_family_boolean_table[_ADDRESS_FAMILY_BOOLEAN_MAX] = {
+        [ADDRESS_FAMILY_NO]            = "no",
+        [ADDRESS_FAMILY_YES]           = "yes",
+        [ADDRESS_FAMILY_IPV4]          = "ipv4",
+        [ADDRESS_FAMILY_IPV6]          = "ipv6",
+};
+
+static const char * const link_local_address_family_boolean_table[_ADDRESS_FAMILY_BOOLEAN_MAX] = {
+        [ADDRESS_FAMILY_NO]            = "no",
+        [ADDRESS_FAMILY_YES]           = "yes",
+        [ADDRESS_FAMILY_IPV4]          = "ipv4",
+        [ADDRESS_FAMILY_IPV6]          = "ipv6",
+        [ADDRESS_FAMILY_FALLBACK]      = "fallback",
+        [ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family_boolean, AddressFamilyBoolean, ADDRESS_FAMILY_YES);
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family_boolean, AddressFamilyBoolean, ADDRESS_FAMILY_YES);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family_boolean, link_local_address_family_boolean,
+                         AddressFamilyBoolean, "Failed to parse option");
 
 int config_parse_address_family_boolean_with_kernel(
                 const char* unit,
index 9c472cfd50d5c9f0da3c94c4f733a65f619b4c52..aafbac7df63eb24b76f6b821be329cdd31dd3427 100644 (file)
@@ -7,10 +7,12 @@
 
 typedef enum AddressFamilyBoolean {
         /* This is a bitmask, though it usually doesn't feel that way! */
-        ADDRESS_FAMILY_NO   = 0,
-        ADDRESS_FAMILY_IPV4 = 1 << 0,
-        ADDRESS_FAMILY_IPV6 = 1 << 1,
-        ADDRESS_FAMILY_YES  = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
+        ADDRESS_FAMILY_NO             = 0,
+        ADDRESS_FAMILY_IPV4           = 1 << 0,
+        ADDRESS_FAMILY_IPV6           = 1 << 1,
+        ADDRESS_FAMILY_YES            = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6,
+        ADDRESS_FAMILY_FALLBACK_IPV4  = 1 << 2,
+        ADDRESS_FAMILY_FALLBACK       = ADDRESS_FAMILY_FALLBACK_IPV4 | ADDRESS_FAMILY_IPV6,
         _ADDRESS_FAMILY_BOOLEAN_MAX,
         _ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
 } AddressFamilyBoolean;
@@ -21,11 +23,14 @@ typedef struct NetworkConfigSection {
         char filename[];
 } NetworkConfigSection;
 
-CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean);
+CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family_boolean);
 CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean_with_kernel);
 
 const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
-AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
+AddressFamilyBoolean address_family_boolean_from_string(const char *s) _pure_;
+
+const char *link_local_address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
+AddressFamilyBoolean link_local_address_family_boolean_from_string(const char *s) _pure_;
 
 int kernel_route_expiration_supported(void);
 
index 4b04aa0463c91c862470ad2411d1db433e50e088..090f3777a5ae2de7304c05f25c0e8119b018bf3d 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <netinet/in.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
index 6b110b7110abb56ff5a128c085e59f8663874daf..711954e4a2cedb22e7c51bd0d5c0f6489a7a7cb9 100644 (file)
@@ -14,7 +14,6 @@
 #include "test-tables.h"
 
 int main(int argc, char **argv) {
-        test_table(address_family_boolean, ADDRESS_FAMILY_BOOLEAN);
         test_table(bond_ad_select, NETDEV_BOND_AD_SELECT);
         test_table(bond_arp_all_targets, NETDEV_BOND_ARP_ALL_TARGETS);
         test_table(bond_arp_validate, NETDEV_BOND_ARP_VALIDATE);
@@ -42,6 +41,7 @@ int main(int argc, char **argv) {
 
         test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE);
         test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE);
+        test_table_sparse(address_family_boolean, ADDRESS_FAMILY_BOOLEAN);
 
         return EXIT_SUCCESS;
 }
index 6e169e0fca00c0d82f9ce56f6d37990c036f0db6..23fcea666e6eeeb73dd994073c35b8114ff33c82 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <arpa/inet.h>
 #include <sys/param.h>
 
 #include "sd-device.h"
 static void test_deserialize_in_addr(void) {
         _cleanup_free_ struct in_addr *addresses = NULL;
         _cleanup_free_ struct in6_addr *addresses6 = NULL;
-        struct in_addr  a, b, c;
-        struct in6_addr d, e, f;
+        union in_addr_union a, b, c, d, e, f;
         int size;
         const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8";
 
-        assert_se(inet_pton(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) == 0);
-        assert_se(inet_pton(AF_INET6, "192.168.0.1", &d) == 0);
+        assert_se(in_addr_from_string(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) < 0);
+        assert_se(in_addr_from_string(AF_INET6, "192.168.0.1", &d) < 0);
 
-        assert_se(inet_pton(AF_INET, "192.168.0.1", &a) == 1);
-        assert_se(inet_pton(AF_INET, "192.168.0.2", &b) == 1);
-        assert_se(inet_pton(AF_INET, "192.168.0.3", &c) == 1);
-        assert_se(inet_pton(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) == 1);
-        assert_se(inet_pton(AF_INET6, "::1", &e) == 1);
-        assert_se(inet_pton(AF_INET6, "1:0:0:0:0:0:0:8", &f) == 1);
+        assert_se(in_addr_from_string(AF_INET, "192.168.0.1", &a) >= 0);
+        assert_se(in_addr_from_string(AF_INET, "192.168.0.2", &b) >= 0);
+        assert_se(in_addr_from_string(AF_INET, "192.168.0.3", &c) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "::1", &e) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "1:0:0:0:0:0:0:8", &f) >= 0);
 
         assert_se((size = deserialize_in_addrs(&addresses, addresses_string)) >= 0);
         assert_se(size == 3);
-        assert_se(!memcmp(&a, &addresses[0], sizeof(struct in_addr)));
-        assert_se(!memcmp(&b, &addresses[1], sizeof(struct in_addr)));
-        assert_se(!memcmp(&c, &addresses[2], sizeof(struct in_addr)));
+        assert_se(in_addr_equal(AF_INET, &a, (union in_addr_union *) &addresses[0]));
+        assert_se(in_addr_equal(AF_INET, &b, (union in_addr_union *) &addresses[1]));
+        assert_se(in_addr_equal(AF_INET, &c, (union in_addr_union *) &addresses[2]));
 
         assert_se((size = deserialize_in6_addrs(&addresses6, addresses_string)) >= 0);
         assert_se(size == 3);
-        assert_se(!memcmp(&d, &addresses6[0], sizeof(struct in6_addr)));
-        assert_se(!memcmp(&e, &addresses6[1], sizeof(struct in6_addr)));
-        assert_se(!memcmp(&f, &addresses6[2], sizeof(struct in6_addr)));
+        assert_se(in_addr_equal(AF_INET6, &d, (union in_addr_union *) &addresses6[0]));
+        assert_se(in_addr_equal(AF_INET6, &e, (union in_addr_union *) &addresses6[1]));
+        assert_se(in_addr_equal(AF_INET6, &f, (union in_addr_union *) &addresses6[2]));
 }
 
 static void test_deserialize_dhcp_routes(void) {
@@ -121,7 +121,7 @@ static int test_load_config(Manager *manager) {
 
 static void test_network_get(Manager *manager, sd_device *loopback) {
         Network *network;
-        const struct ether_addr mac = {};
+        const struct ether_addr mac = ETHER_ADDR_NULL;
 
         /* let's assume that the test machine does not have a .network file
            that applies to the loopback device... */
@@ -146,13 +146,13 @@ static void test_address_equality(void) {
         a2->family = AF_INET;
         assert_se(address_equal(a1, a2));
 
-        assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a1->in_addr) >= 0);
         assert_se(!address_equal(a1, a2));
-        assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a2->in_addr) >= 0);
         assert_se(address_equal(a1, a2));
-        assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.10", &a1->in_addr_peer) >= 0);
         assert_se(address_equal(a1, a2));
-        assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.11", &a2->in_addr_peer) >= 0);
         assert_se(address_equal(a1, a2));
         a1->prefixlen = 10;
         assert_se(!address_equal(a1, a2));
@@ -163,14 +163,14 @@ static void test_address_equality(void) {
         assert_se(!address_equal(a1, a2));
 
         a2->family = AF_INET6;
-        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6));
-        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6));
+        assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr) >= 0);
         assert_se(address_equal(a1, a2));
 
         a2->prefixlen = 8;
         assert_se(address_equal(a1, a2));
 
-        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6));
+        assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr) >= 0);
         assert_se(!address_equal(a1, a2));
 }
 
index 05fc01d048dc7708f817824eb02715c35e22822a..dfb41f801b359d1b65063cc57e06b9c6ef6967a6 100644 (file)
@@ -169,9 +169,10 @@ static void test_config_parse_hwaddr(void) {
 }
 
 static void test_config_parse_address_one(const char *rvalue, int family, unsigned n_addresses, const union in_addr_union *u, unsigned char prefixlen) {
-        _cleanup_(network_freep) Network *network = NULL;
+        _cleanup_(network_unrefp) Network *network = NULL;
 
         assert_se(network = new0(Network, 1));
+        network->n_ref = 1;
         assert_se(network->filename = strdup("hogehoge.network"));
         assert_se(config_parse_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
         assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
index e1f9a812fbb8c863ffb0f2c3aab44e1bcf4d3f48..e38b5603c22a043d512be3880711eb534d5a7106 100644 (file)
@@ -164,7 +164,7 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *
                         log_link_warning_errno(l, r, "Failed to process RTNL link message, ignoring: %m");
 
                 r = link_update_monitor(l);
-                if (r < 0)
+                if (r < 0 && r != -ENODATA)
                         log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m");
 
                 break;
@@ -253,8 +253,8 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
 
         HASHMAP_FOREACH(l, m->links, i) {
                 r = link_update_monitor(l);
-                if (r < 0)
-                        log_link_warning_errno(l, r, "Failed to update monitor information: %m");
+                if (r < 0 && r != -ENODATA)
+                        log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m");
         }
 
         if (manager_configured(m))
index f50a322ea599421134133019205e9a508cfb107b..750529bbbd39985ebf6a7d79d7e76337c538bba0 100644 (file)
@@ -151,6 +151,7 @@ static int run(int argc, char* argv[]) {
         unsigned i = 0;
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 31217c7b4637daaf08b6f77feb86aec69acb87ac..c049ac6754113eee3fe2e12ec6ad07329f0b04bd 100644 (file)
@@ -48,7 +48,7 @@ tests += [
         [['src/nspawn/test-nspawn-tables.c'],
          [libnspawn_core,
           libshared],
-         []],
+         [libseccomp]],
 
         [['src/nspawn/test-patch-uid.c'],
          [libnspawn_core,
index 97323f31dd97b9fe0542b125fab0eda3ed44c52b..b00ff289a6fceeac9b310659d450219726f19994 100644 (file)
@@ -1656,13 +1656,19 @@ static int oci_seccomp_action_from_string(const char *name, uint32_t *ret) {
                 const char *name;
                 uint32_t action;
         } table[] = {
-                { "SCMP_ACT_ALLOW", SCMP_ACT_ALLOW        },
-                { "SCMP_ACT_ERRNO", SCMP_ACT_ERRNO(EPERM) }, /* the OCI spec doesn't document the error, but it appears EPERM is supposed to be used */
-                { "SCMP_ACT_KILL",  SCMP_ACT_KILL         },
+                { "SCMP_ACT_ALLOW",         SCMP_ACT_ALLOW        },
+                { "SCMP_ACT_ERRNO",         SCMP_ACT_ERRNO(EPERM) }, /* the OCI spec doesn't document the error, but it appears EPERM is supposed to be used */
+                { "SCMP_ACT_KILL",          SCMP_ACT_KILL         },
+#ifdef SCMP_ACT_KILL_PROCESS
+                { "SCMP_ACT_KILL_PROCESS",  SCMP_ACT_KILL_PROCESS },
+#endif
+#ifdef SCMP_ACT_KILL_THREAD
+                { "SCMP_ACT_KILL_THREAD",   SCMP_ACT_KILL_THREAD  },
+#endif
 #ifdef SCMP_ACT_LOG
-                { "SCMP_ACT_LOG",   SCMP_ACT_LOG          },
+                { "SCMP_ACT_LOG",           SCMP_ACT_LOG          },
 #endif
-                { "SCMP_ACT_TRAP",  SCMP_ACT_TRAP         },
+                { "SCMP_ACT_TRAP",          SCMP_ACT_TRAP         },
 
                 /* We don't support SCMP_ACT_TRACE because that requires a tracer, and that doesn't really make sense
                  * here */
index 7b630a5714a558997d23f408ff78eeacd5204097..568b5fb04bee61c81e3810c7ab78137ca42d9dae 100644 (file)
@@ -171,6 +171,7 @@ static int parse_argv(int argc, char *argv[]) {
 static int run(int argc, char* argv[]) {
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 2c59f04eb5e700ffc2a0aa46d9a756fb933d9a06..5041745b3d06a754d2f044c71a4c2894d58da152 100644 (file)
@@ -956,6 +956,7 @@ static int run(int argc, char *argv[]) {
 
         int r;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 7a3948e92d986f0a9b460d16ac5943eebb4b76a7..908e6272a8a6a982945fc2198946aa7c1238e232 100644 (file)
@@ -65,12 +65,6 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
                 r = add_symlink("rc-local.service", "multi-user.target");
         }
 
-        if (check_executable(RC_LOCAL_SCRIPT_PATH_STOP) >= 0) {
-                log_debug("Automatically adding halt-local.service.");
-
-                k = add_symlink("halt-local.service", "final.target");
-        }
-
         return r < 0 ? r : k;
 }
 
index 1d2fc713092bdc63ca50131a2d0e01ac68fd99f2..9637e00e6079845326ed02318218f499afec071f 100644 (file)
@@ -3137,6 +3137,7 @@ static int run(int argc, char **argv) {
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index babd9027e49fd039c9bd7cd4e5bc8f61fd6da0c6..05c1552a8b7ff74bb36aa8b5c7d9e9c413133c61 100644 (file)
@@ -390,11 +390,10 @@ static int parse_argv(int argc, char *argv[]) {
 
                         r = calendar_spec_next_usec(cs, now(CLOCK_REALTIME), NULL);
                         if (r == -ENOENT)
-                                /* The calendar event is in the past - let's warn about this, but install it
-                                 * anyway as it is. The service manager will trigger the service right-away
-                                 * then, but everything is discoverable as usual. Moreover, the server side
-                                 * might have a different clock or timezone than we do, hence it should
-                                 * decide when or whether to run something. */
+                                /* The calendar event is in the past — let's warn about this, but install it
+                                 * anyway as is. The service manager will trigger the service right away.
+                                 * Moreover, the server side might have a different clock or timezone than we
+                                 * do, hence it should decide when or whether to run something. */
                                 log_warning("Specified calendar expression is in the past, proceeding anyway.");
                         else if (r < 0)
                                 return log_error_errno(r, "Failed to calculate next time calendar expression elapses: %m");
@@ -1653,6 +1652,7 @@ static int run(int argc, char* argv[]) {
         _cleanup_free_ char *description = NULL;
         int r, retval = EXIT_SUCCESS;
 
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index ab0c34692f1ce22b34157e16762f189a18595002..6c0a36990291832e7c2c36953515c5ecb91448c2 100644 (file)
@@ -80,7 +80,7 @@ static int retrieve_key(key_serial_t serial, char ***ret) {
                 if (n < m)
                         break;
 
-                explicit_bzero_safe(p, n);
+                explicit_bzero_safe(p, m);
 
                 if (m > LONG_MAX / 2) /* overflow check */
                         return -ENOMEM;
index c6cbc9828c88d9ef0c16315136e4e65e797db952..2b425efc9c6b349acbb7bfb67193f12ba4346edc 100644 (file)
@@ -413,7 +413,7 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
                 return 1;
         }
 
-        if (STR_IN_SET(field, "MemoryMin", "DefaultMemoryLow", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit", "TasksMax")) {
+        if (STR_IN_SET(field, "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit", "TasksMax")) {
 
                 if (isempty(eq) || streq(eq, "infinity")) {
                         r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX);
index 9c3ce2f712b2f42050564ef40ab24eb965b5ffd4..c2440271feb13226dd7cf1e03b376cac89872937 100644 (file)
@@ -794,7 +794,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
 
                         bus_print_property_value(name, expected_value, value, "[not set]");
 
-                else if ((STR_IN_SET(name, "DefaultMemoryLow", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
+                else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
                          (startswith(name, "Limit") && u == (uint64_t) -1) ||
                          (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
index 4365dbaca88c6c4f1da5bdbe366aa4f63795b621..1045b009290363565f59572cb952a9bdc3dc19fb 100644 (file)
@@ -862,7 +862,6 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         int r;
 
         assert(p);
-        assert(spec);
 
         c = new(CalendarSpec, 1);
         if (!c)
@@ -1076,7 +1075,8 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         if (!calendar_spec_valid(c))
                 return -EINVAL;
 
-        *spec = TAKE_PTR(c);
+        if (spec)
+                *spec = TAKE_PTR(c);
         return 0;
 }
 
index 91a243944c78b9fa914abce1be4fec838c0f0399..e6fdcfa277deddfbfca7c1001b57058b72ad3ab4 100644 (file)
@@ -29,7 +29,7 @@ static void show_pid_array(
                 pid_t pids[],
                 unsigned n_pids,
                 const char *prefix,
-                unsigned n_columns,
+                size_t n_columns,
                 bool extra,
                 bool more,
                 OutputFlags flags) {
@@ -51,17 +51,19 @@ static void show_pid_array(
         pid_width = DECIMAL_STR_WIDTH(pids[j]);
 
         if (flags & OUTPUT_FULL_WIDTH)
-                n_columns = 0;
+                n_columns = SIZE_MAX;
         else {
-                if (n_columns > pid_width+2)
-                        n_columns -= pid_width+2;
+                if (n_columns > pid_width + 3) /* something like "├─1114784 " */
+                        n_columns -= pid_width + 3;
                 else
                         n_columns = 20;
         }
         for (i = 0; i < n_pids; i++) {
                 _cleanup_free_ char *t = NULL;
 
-                (void) get_process_cmdline(pids[i], n_columns, true, &t);
+                (void) get_process_cmdline(pids[i], n_columns,
+                                           PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_USE_LOCALE,
+                                           &t);
 
                 if (extra)
                         printf("%s%s ", prefix, special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
@@ -75,7 +77,7 @@ static void show_pid_array(
 static int show_cgroup_one_by_path(
                 const char *path,
                 const char *prefix,
-                unsigned n_columns,
+                size_t n_columns,
                 bool more,
                 OutputFlags flags) {
 
@@ -119,7 +121,7 @@ static int show_cgroup_one_by_path(
 int show_cgroup_by_path(
                 const char *path,
                 const char *prefix,
-                unsigned n_columns,
+                size_t n_columns,
                 OutputFlags flags) {
 
         _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
@@ -199,7 +201,7 @@ int show_cgroup_by_path(
 int show_cgroup(const char *controller,
                 const char *path,
                 const char *prefix,
-                unsigned n_columns,
+                size_t n_columns,
                 OutputFlags flags) {
         _cleanup_free_ char *p = NULL;
         int r;
@@ -217,7 +219,7 @@ static int show_extra_pids(
                 const char *controller,
                 const char *path,
                 const char *prefix,
-                unsigned n_columns,
+                size_t n_columns,
                 const pid_t pids[],
                 unsigned n_pids,
                 OutputFlags flags) {
@@ -262,7 +264,7 @@ int show_cgroup_and_extra(
                 const char *controller,
                 const char *path,
                 const char *prefix,
-                unsigned n_columns,
+                size_t n_columns,
                 const pid_t extra_pids[],
                 unsigned n_extra_pids,
                 OutputFlags flags) {
index 3593e9dcf43adcc9a1a0f371e2bf604b90a73785..dfb26f82910f82e2f45298c4953301263f994a7f 100644 (file)
@@ -9,10 +9,10 @@
 #include "logs-show.h"
 #include "output-mode.h"
 
-int show_cgroup_by_path(const char *path, const char *prefix, unsigned columns, OutputFlags flags);
-int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned columns, OutputFlags flags);
+int show_cgroup_by_path(const char *path, const char *prefix, size_t n_columns, OutputFlags flags);
+int show_cgroup(const char *controller, const char *path, const char *prefix, size_t n_columns, OutputFlags flags);
 
-int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags);
+int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, size_t n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags);
 
 int show_cgroup_get_unit_path_and_warn(
                 sd_bus *bus,
index 4b31cb36ede3790fc1cd760c1ad8ac9af37d561a..f62ad0a0f58aa7307df55d7e7208aeaac0dc68f9 100644 (file)
@@ -37,7 +37,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f
         d = dest;
 
         for (;;) {
-                if (*n == 0 || *n == '.') {
+                if (IN_SET(*n, 0, '.')) {
                         if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-')
                                 /* Trailing dash */
                                 return -EINVAL;
index fc884dedf06b38e4306a947ad2e25ee30834ee91..f16c2db739625598add525dd43034fcee5589095 100644 (file)
@@ -514,7 +514,7 @@ int efi_get_boot_option(
         if (path)
                 *path = TAKE_PTR(p);
         if (active)
-                *active = !!(header->attr & LOAD_OPTION_ACTIVE);
+                *active = header->attr & LOAD_OPTION_ACTIVE;
 
         return 0;
 }
@@ -909,7 +909,7 @@ bool efi_loader_entry_name_valid(const char *s) {
         if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */
                 return false;
 
-        return in_charset(s, ALPHANUMERICAL "-_.");
+        return in_charset(s, ALPHANUMERICAL "+-_.");
 }
 
 char *efi_tilt_backslashes(char *s) {
index 5ff247953b5f2cb653812c8c421fe2c1d9f3d145..85e3afce4c3511e41c3c949af50f05d1e2334740 100644 (file)
@@ -75,4 +75,4 @@ const void *table_get(Table *t, TableCell *cell);
 const void *table_get_at(Table *t, size_t row, size_t column);
 
 int table_to_json(Table *t, JsonVariant **ret);
-int table_print_json(Table *t, FILE *f, unsigned json_flags);
+int table_print_json(Table *t, FILE *f, JsonFormatFlags json_flags);
index 8638cd3cc98b07df2196b9dbfa7a1cd0d7acf87d..8dc2c42ad15d335c39100de5ccef14198f4a50e2 100644 (file)
@@ -94,7 +94,7 @@ static int get_line(JournalImporter *imp, char **line, size_t *size) {
 
                         c = memchr(imp->buf + start, '\n',
                                    imp->filled - start);
-                        if (c != NULL)
+                        if (c)
                                 break;
                 }
 
index 073f800b3464301eae6595549b71a3e8ab2cedc3..782d80af16aac0a2d77e591bd872b95e445340e2 100644 (file)
@@ -2296,9 +2296,9 @@ static int json_parse_internal(
                 column = &column_buffer;
 
         for (;;) {
+                _cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
                 _cleanup_free_ char *string = NULL;
                 unsigned line_token, column_token;
-                JsonVariant *add = NULL;
                 JsonStack *current;
                 JsonValue value;
                 int token;
@@ -2591,7 +2591,7 @@ static int json_parse_internal(
                                 goto finish;
                         }
 
-                        current->elements[current->n_elements++] = add;
+                        current->elements[current->n_elements++] = TAKE_PTR(add);
                 }
         }
 
index 7d94468e52852aedff078bf0f790f1d1a7396a20..7c3b855df52056e1b1bb15f2dba7ad39b16bb930 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <stdio.h>
+
 /* This needs to be after sys/mount.h */
 #include <libmount.h>
 
@@ -8,3 +10,38 @@
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
+
+static inline int libmount_parse(
+                const char *path,
+                FILE *source,
+                struct libmnt_table **ret_table,
+                struct libmnt_iter **ret_iter) {
+
+        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
+        int r;
+
+        /* Older libmount seems to require this. */
+        assert(!source || path);
+
+        table = mnt_new_table();
+        iter = mnt_new_iter(MNT_ITER_FORWARD);
+        if (!table || !iter)
+                return -ENOMEM;
+
+        /* If source or path are specified, we use on the functions which ignore utab.
+         * Only if both are empty, we use mnt_table_parse_mtab(). */
+
+        if (source)
+                r = mnt_table_parse_stream(table, source, path);
+        else if (path)
+                r = mnt_table_parse_file(table, path);
+        else
+                r = mnt_table_parse_mtab(table, NULL);
+        if (r < 0)
+                return r;
+
+        *ret_table = TAKE_PTR(table);
+        *ret_iter = TAKE_PTR(iter);
+        return 0;
+}
index 5fb736f63307ab4e2e02973a2d8d8118ed7188b5..aa5bc5b4ed78e17e21ec5c82ff792454fe4e0cb0 100644 (file)
@@ -154,6 +154,7 @@ static bool print_multiline(
                 unsigned n_columns,
                 OutputFlags flags,
                 int priority,
+                bool audit,
                 const char* message,
                 size_t message_len,
                 size_t highlight[2]) {
@@ -164,18 +165,11 @@ static bool print_multiline(
         int line = 0;
 
         if (flags & OUTPUT_COLOR) {
-                if (priority <= LOG_ERR) {
-                        color_on = ANSI_HIGHLIGHT_RED;
-                        color_off = ANSI_NORMAL;
-                        highlight_on = ANSI_HIGHLIGHT;
-                } else if (priority <= LOG_NOTICE) {
-                        color_on = ANSI_HIGHLIGHT;
-                        color_off = ANSI_NORMAL;
-                        highlight_on = ANSI_HIGHLIGHT_RED;
-                } else if (priority >= LOG_DEBUG) {
-                        color_on = ANSI_GREY;
+                get_log_colors(priority, &color_on, &color_off, &highlight_on);
+
+                if (audit && strempty(color_on)) {
+                        color_on = ANSI_BLUE;
                         color_off = ANSI_NORMAL;
-                        highlight_on = ANSI_HIGHLIGHT_RED;
                 }
         }
 
@@ -381,15 +375,16 @@ static int output_short(
         const void *data;
         size_t length;
         size_t n = 0;
-        _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *unit = NULL, *user_unit = NULL;
-        size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, unit_len = 0, user_unit_len = 0;
+        _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *transport = NULL, *unit = NULL, *user_unit = NULL;
+        size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, transport_len = 0, unit_len = 0, user_unit_len = 0;
         int p = LOG_INFO;
-        bool ellipsized = false;
+        bool ellipsized = false, audit;
         const ParseFieldVec fields[] = {
                 PARSE_FIELD_VEC_ENTRY("_PID=", &pid, &pid_len),
                 PARSE_FIELD_VEC_ENTRY("_COMM=", &comm, &comm_len),
                 PARSE_FIELD_VEC_ENTRY("MESSAGE=", &message, &message_len),
                 PARSE_FIELD_VEC_ENTRY("PRIORITY=", &priority, &priority_len),
+                PARSE_FIELD_VEC_ENTRY("_TRANSPORT=", &transport, &transport_len),
                 PARSE_FIELD_VEC_ENTRY("_HOSTNAME=", &hostname, &hostname_len),
                 PARSE_FIELD_VEC_ENTRY("SYSLOG_PID=", &fake_pid, &fake_pid_len),
                 PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len),
@@ -434,6 +429,9 @@ static int output_short(
         if (priority_len == 1 && *priority >= '0' && *priority <= '7')
                 p = *priority - '0';
 
+
+        audit = streq_ptr(transport, "audit");
+
         if (mode == OUTPUT_SHORT_MONOTONIC)
                 r = output_timestamp_monotonic(f, j, monotonic);
         else
@@ -488,7 +486,7 @@ static int output_short(
         } else {
                 fputs(": ", f);
                 ellipsized |=
-                        print_multiline(f, n + 2, n_columns, flags, p,
+                        print_multiline(f, n + 2, n_columns, flags, p, audit,
                                         message, message_len,
                                         highlight_shifted);
         }
@@ -583,7 +581,9 @@ static int output_verbose(
                     (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
                      && utf8_is_printable(data, length))) {
                         fprintf(f, "    %s%.*s=", on, fieldlen, (const char*)data);
-                        print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1, NULL);
+                        print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, false,
+                                        c + 1, length - fieldlen - 1,
+                                        NULL);
                         fputs(off, f);
                 } else {
                         char bytes[FORMAT_BYTES_MAX];
index bf426eb8bca4d2d3a65e13f8d3186ec4b5685182..22525d5c63303b0111f229bd18a902b2c156230a 100644 (file)
@@ -18,6 +18,7 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
 
         _cleanup_close_ int control = -1, loop = -1;
         _cleanup_free_ char *loopdev = NULL;
+        unsigned n_attempts = 0;
         struct stat st;
         LoopDevice *d;
         int nr, r;
@@ -60,19 +61,31 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) {
         if (control < 0)
                 return -errno;
 
-        nr = ioctl(control, LOOP_CTL_GET_FREE);
-        if (nr < 0)
-                return -errno;
+        /* Loop around LOOP_CTL_GET_FREE, since at the moment we attempt to open the returned device it might
+         * be gone already, taken by somebody else racing against us. */
+        for (;;) {
+                nr = ioctl(control, LOOP_CTL_GET_FREE);
+                if (nr < 0)
+                        return -errno;
 
-        if (asprintf(&loopdev, "/dev/loop%i", nr) < 0)
-                return -ENOMEM;
+                if (asprintf(&loopdev, "/dev/loop%i", nr) < 0)
+                        return -ENOMEM;
 
-        loop = open(loopdev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
-        if (loop < 0)
-                return -errno;
+                loop = open(loopdev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
+                if (loop < 0)
+                        return -errno;
+                if (ioctl(loop, LOOP_SET_FD, fd) < 0) {
+                        if (errno != EBUSY)
+                                return -errno;
 
-        if (ioctl(loop, LOOP_SET_FD, fd) < 0)
-                return -errno;
+                        if (++n_attempts >= 64) /* Give up eventually */
+                                return -EBUSY;
+                } else
+                        break;
+
+                loopdev = mfree(loopdev);
+                loop = safe_close(loop);
+        }
 
         if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0)
                 return -errno;
index 4ad112740d41eaa11fb0acc231fe0a85787976fa..55e5f08f91e44a70dbe0606a48fe9904a5f67475 100644 (file)
@@ -200,12 +200,13 @@ static int image_make(
                 const struct stat *st,
                 Image **ret) {
 
-        _cleanup_free_ char *pretty_buffer = NULL;
+        _cleanup_free_ char *pretty_buffer = NULL, *parent = NULL;
         struct stat stbuf;
         bool read_only;
         int r;
 
         assert(dfd >= 0 || dfd == AT_FDCWD);
+        assert(path || dfd == AT_FDCWD);
         assert(filename);
 
         /* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block
@@ -221,6 +222,13 @@ static int image_make(
                 st = &stbuf;
         }
 
+        if (!path) {
+                if (dfd == AT_FDCWD)
+                        (void) safe_getcwd(&parent);
+                else
+                        (void) fd_get_path(dfd, &parent);
+        }
+
         read_only =
                 (path && path_startswith(path, "/usr")) ||
                 (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS);
@@ -359,7 +367,7 @@ static int image_make(
 
                 block_fd = openat(dfd, filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
                 if (block_fd < 0)
-                        log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path, filename);
+                        log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path ?: strnull(parent), filename);
                 else {
                         /* Refresh stat data after opening the node */
                         if (fstat(block_fd, &stbuf) < 0)
@@ -373,13 +381,13 @@ static int image_make(
                                 int state = 0;
 
                                 if (ioctl(block_fd, BLKROGET, &state) < 0)
-                                        log_debug_errno(errno, "Failed to issue BLKROGET on device %s/%s, ignoring: %m", path, filename);
+                                        log_debug_errno(errno, "Failed to issue BLKROGET on device %s/%s, ignoring: %m", path ?: strnull(parent), filename);
                                 else if (state)
                                         read_only = true;
                         }
 
                         if (ioctl(block_fd, BLKGETSIZE64, &size) < 0)
-                                log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path, filename);
+                                log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path ?: strnull(parent), filename);
 
                         block_fd = safe_close(block_fd);
                 }
@@ -395,7 +403,7 @@ static int image_make(
                 if (r < 0)
                         return r;
 
-                if (size != 0 && size != UINT64_MAX)
+                if (!IN_SET(size, 0, UINT64_MAX))
                         (*ret)->usage = (*ret)->usage_exclusive = (*ret)->limit = (*ret)->limit_exclusive = size;
 
                 return 0;
index c80a67cdde45819decc52623a0cf839c767ac667..aa0423ccad73af5c70c941196ae65676d36031fc 100644 (file)
@@ -164,6 +164,8 @@ shared_sources = files('''
         uid-range.c
         uid-range.h
         utmp-wtmp.h
+        varlink.c
+        varlink.h
         verbs.c
         verbs.h
         vlan-util.c
index 44c80f60ba063327195dde416a3b6fab2d3df7a0..9129ad5f6b851e5b6ba5c07dec053b369f051834 100644 (file)
@@ -8,16 +8,13 @@
 #include <sys/statvfs.h>
 #include <unistd.h>
 
-/* Include later */
-#include <libmount.h>
-
 #include "alloc-util.h"
-#include "escape.h"
 #include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "hashmap.h"
+#include "libmount-util.h"
 #include "mount-util.h"
 #include "mountpoint-util.h"
 #include "parse-util.h"
@@ -36,52 +33,38 @@ int umount_recursive(const char *prefix, int flags) {
          * unmounting them until they are gone. */
 
         do {
-                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+                _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+                _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
 
                 again = false;
 
-                r = fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo);
+                r = libmount_parse("/proc/self/mountinfo", NULL, &table, &iter);
                 if (r < 0)
-                        return r;
+                        return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
                 for (;;) {
-                        _cleanup_free_ char *path = NULL, *p = NULL;
-                        int k;
-
-                        k = fscanf(proc_self_mountinfo,
-                                   "%*s "       /* (1) mount id */
-                                   "%*s "       /* (2) parent id */
-                                   "%*s "       /* (3) major:minor */
-                                   "%*s "       /* (4) root */
-                                   "%ms "       /* (5) mount point */
-                                   "%*s"        /* (6) mount options */
-                                   "%*[^-]"     /* (7) optional fields */
-                                   "- "         /* (8) separator */
-                                   "%*s "       /* (9) file system type */
-                                   "%*s"        /* (10) mount source */
-                                   "%*s"        /* (11) mount options 2 */
-                                   "%*[^\n]",   /* some rubbish at the end */
-                                   &path);
-                        if (k != 1) {
-                                if (k == EOF)
-                                        break;
+                        struct libmnt_fs *fs;
+                        const char *path;
 
-                                continue;
-                        }
+                        r = mnt_table_next_fs(table, iter, &fs);
+                        if (r == 1)
+                                break;
+                        if (r < 0)
+                                return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
 
-                        k = cunescape(path, UNESCAPE_RELAX, &p);
-                        if (k < 0)
-                                return k;
+                        path = mnt_fs_get_target(fs);
+                        if (!path)
+                                continue;
 
-                        if (!path_startswith(p, prefix))
+                        if (!path_startswith(path, prefix))
                                 continue;
 
-                        if (umount2(p, flags) < 0) {
-                                r = log_debug_errno(errno, "Failed to umount %s: %m", p);
+                        if (umount2(path, flags) < 0) {
+                                r = log_debug_errno(errno, "Failed to umount %s: %m", path);
                                 continue;
                         }
 
-                        log_debug("Successfully unmounted %s", p);
+                        log_debug("Successfully unmounted %s", path);
 
                         again = true;
                         n++;
@@ -91,7 +74,7 @@ int umount_recursive(const char *prefix, int flags) {
 
         } while (again);
 
-        return r < 0 ? r : n;
+        return n;
 }
 
 static int get_mount_flags(const char *path, unsigned long *flags) {
@@ -141,6 +124,8 @@ int bind_remount_recursive_with_mountinfo(
 
         for (;;) {
                 _cleanup_set_free_free_ Set *todo = NULL;
+                _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+                _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
                 bool top_autofs = false;
                 char *x;
                 unsigned long orig_flags;
@@ -151,56 +136,45 @@ int bind_remount_recursive_with_mountinfo(
 
                 rewind(proc_self_mountinfo);
 
-                for (;;) {
-                        _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
-                        int k;
-
-                        k = fscanf(proc_self_mountinfo,
-                                   "%*s "       /* (1) mount id */
-                                   "%*s "       /* (2) parent id */
-                                   "%*s "       /* (3) major:minor */
-                                   "%*s "       /* (4) root */
-                                   "%ms "       /* (5) mount point */
-                                   "%*s"        /* (6) mount options (superblock) */
-                                   "%*[^-]"     /* (7) optional fields */
-                                   "- "         /* (8) separator */
-                                   "%ms "       /* (9) file system type */
-                                   "%*s"        /* (10) mount source */
-                                   "%*s"        /* (11) mount options (bind mount) */
-                                   "%*[^\n]",   /* some rubbish at the end */
-                                   &path,
-                                   &type);
-                        if (k != 2) {
-                                if (k == EOF)
-                                        break;
+                r = libmount_parse("/proc/self/mountinfo", proc_self_mountinfo, &table, &iter);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
-                                continue;
-                        }
+                for (;;) {
+                        struct libmnt_fs *fs;
+                        const char *path, *type;
 
-                        r = cunescape(path, UNESCAPE_RELAX, &p);
+                        r = mnt_table_next_fs(table, iter, &fs);
+                        if (r == 1)
+                                break;
                         if (r < 0)
-                                return r;
+                                return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
 
-                        if (!path_startswith(p, cleaned))
+                        path = mnt_fs_get_target(fs);
+                        type = mnt_fs_get_fstype(fs);
+                        if (!path || !type)
                                 continue;
 
-                        /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall
-                         * operate on. */
-                        if (!path_equal(cleaned, p)) {
+                        if (!path_startswith(path, cleaned))
+                                continue;
+
+                        /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount
+                         * we shall operate on. */
+                        if (!path_equal(path, cleaned)) {
                                 bool blacklisted = false;
                                 char **i;
 
                                 STRV_FOREACH(i, blacklist) {
-
                                         if (path_equal(*i, cleaned))
                                                 continue;
 
                                         if (!path_startswith(*i, cleaned))
                                                 continue;
 
-                                        if (path_startswith(p, *i)) {
+                                        if (path_startswith(path, *i)) {
                                                 blacklisted = true;
-                                                log_debug("Not remounting %s blacklisted by %s, called for %s", p, *i, cleaned);
+                                                log_debug("Not remounting %s blacklisted by %s, called for %s",
+                                                          path, *i, cleaned);
                                                 break;
                                         }
                                 }
@@ -215,15 +189,12 @@ int bind_remount_recursive_with_mountinfo(
                          * already triggered, then we will find
                          * another entry for this. */
                         if (streq(type, "autofs")) {
-                                top_autofs = top_autofs || path_equal(cleaned, p);
+                                top_autofs = top_autofs || path_equal(path, cleaned);
                                 continue;
                         }
 
-                        if (!set_contains(done, p)) {
-                                r = set_consume(todo, p);
-                                p = NULL;
-                                if (r == -EEXIST)
-                                        continue;
+                        if (!set_contains(done, path)) {
+                                r = set_put_strdup(todo, path);
                                 if (r < 0)
                                         return r;
                         }
index 95e46a6aa4a7120c15379de9dc68788ddc55ed24..72920ee7df1cbce117cfe4a8ba11bafa462be237 100644 (file)
@@ -1964,3 +1964,18 @@ int seccomp_restrict_suid_sgid(void) {
 
         return 0;
 }
+
+uint32_t scmp_act_kill_process(void) {
+
+        /* Returns SCMP_ACT_KILL_PROCESS if it's supported, and SCMP_ACT_KILL_THREAD otherwise. We never
+         * actually want to use SCMP_ACT_KILL_THREAD as its semantics are nuts (killing arbitrary threads of
+         * a program is just a bad idea), but on old kernels/old libseccomp it is all we have, and at least
+         * for single-threaded apps does the right thing. */
+
+#ifdef SCMP_ACT_KILL_PROCESS
+        if (seccomp_api_get() >= 3)
+                return SCMP_ACT_KILL_PROCESS;
+#endif
+
+        return SCMP_ACT_KILL; /* same as SCMP_ACT_KILL_THREAD */
+}
index 2566d2d17f261c12873fd1eaf88994713d69c9af..1729dc1b6eeaaf5eaac3242e4a6cff709b988b52 100644 (file)
@@ -104,3 +104,5 @@ extern const uint32_t seccomp_local_archs[];
 DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
 
 int parse_syscall_archs(char **l, Set **archs);
+
+uint32_t scmp_act_kill_process(void);
index 7f23e5410239e425b65371d605ed95d99efd6e4a..0e114a7b49a94869b72844444b216e6e3ca8b626 100644 (file)
@@ -386,7 +386,7 @@ static bool can_s2h(void) {
         r = access("/sys/class/rtc/rtc0/wakealarm", W_OK);
         if (r < 0) {
                 log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
-                         "/sys/class/rct/rct0/wakealarm is not writable %m");
+                         "/sys/class/rtc/rtc0/wakealarm is not writable %m");
                 return false;
         }
 
index dbb4622312a079080ab3ae63720ce1cce4517abc..f721aff76071182940f5191f725ca6615463f1af 100644 (file)
@@ -120,10 +120,8 @@ int switch_root(const char *new_root,
 
                 if (fstat(old_root_fd, &rb) < 0)
                         log_warning_errno(errno, "Failed to stat old root directory, leaving: %m");
-                else {
-                        (void) rm_rf_children(old_root_fd, 0, &rb);
-                        old_root_fd = -1;
-                }
+                else
+                        (void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
         }
 
         return 0;
index 4b134b6c8ac6b3547a888498f03ac886148a4e67..646f449821818efe3292b67cddf44a0d8d9c2876 100644 (file)
@@ -183,16 +183,14 @@ int utmp_put_reboot(usec_t t) {
         return write_entry_both(&store);
 }
 
-_pure_ static const char *sanitize_id(const char *id) {
+static void copy_suffix(char *buf, size_t buf_size, const char *src) {
         size_t l;
 
-        assert(id);
-        l = strlen(id);
-
-        if (l <= sizeof(((struct utmpx*) NULL)->ut_id))
-                return id;
-
-        return id + l - sizeof(((struct utmpx*) NULL)->ut_id);
+        l = strlen(src);
+        if (l < buf_size)
+                strncpy(buf, src, buf_size);
+        else
+                memcpy(buf, src + l - buf_size, buf_size);
 }
 
 int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) {
@@ -207,11 +205,11 @@ int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line
 
         init_timestamp(&store, 0);
 
-        /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */
-        strncpy(store.ut_id, sanitize_id(id), sizeof(store.ut_id));
+        /* Copy the whole string if it fits, or just the suffix without the terminating NUL. */
+        copy_suffix(store.ut_id, sizeof(store.ut_id), id);
 
         if (line)
-                strncpy(store.ut_line, basename(line), sizeof(store.ut_line));
+                strncpy_exact(store.ut_line, line, sizeof(store.ut_line));
 
         r = write_entry_both(&store);
         if (r < 0)
@@ -244,8 +242,8 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
 
         setutxent();
 
-        /* ut_id needs only be nul-terminated if it is shorter than sizeof(ut_id) */
-        strncpy(lookup.ut_id, sanitize_id(id), sizeof(lookup.ut_id));
+        /* Copy the whole string if it fits, or just the suffix without the terminating NUL. */
+        copy_suffix(store.ut_id, sizeof(store.ut_id), id);
 
         found = getutxid(&lookup);
         if (!found)
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
new file mode 100644 (file)
index 0000000..3256a93
--- /dev/null
@@ -0,0 +1,2390 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/poll.h>
+
+#include "alloc-util.h"
+#include "errno-util.h"
+#include "fd-util.h"
+#include "hashmap.h"
+#include "list.h"
+#include "process-util.h"
+#include "set.h"
+#include "socket-util.h"
+#include "string-table.h"
+#include "string-util.h"
+#include "strv.h"
+#include "time-util.h"
+#include "umask-util.h"
+#include "user-util.h"
+#include "varlink.h"
+
+#define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U
+#define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U
+
+#define VARLINK_DEFAULT_TIMEOUT_USEC (45U*USEC_PER_SEC)
+#define VARLINK_BUFFER_MAX (16U*1024U*1024U)
+#define VARLINK_READ_SIZE (64U*1024U)
+
+typedef enum VarlinkState {
+        /* Client side states */
+        VARLINK_IDLE_CLIENT,
+        VARLINK_AWAITING_REPLY,
+        VARLINK_CALLING,
+        VARLINK_CALLED,
+        VARLINK_PROCESSING_REPLY,
+
+        /* Server side states */
+        VARLINK_IDLE_SERVER,
+        VARLINK_PROCESSING_METHOD,
+        VARLINK_PROCESSING_METHOD_MORE,
+        VARLINK_PROCESSING_METHOD_ONEWAY,
+        VARLINK_PROCESSED_METHOD,
+        VARLINK_PROCESSED_METHOD_MORE,
+        VARLINK_PENDING_METHOD,
+        VARLINK_PENDING_METHOD_MORE,
+
+        /* Common states (only during shutdown) */
+        VARLINK_PENDING_DISCONNECT,
+        VARLINK_PENDING_TIMEOUT,
+        VARLINK_PROCESSING_DISCONNECT,
+        VARLINK_PROCESSING_TIMEOUT,
+        VARLINK_PROCESSING_FAILURE,
+        VARLINK_DISCONNECTED,
+
+        _VARLINK_STATE_MAX,
+        _VARLINK_STATE_INVALID = -1
+} VarlinkState;
+
+/* Tests whether we are not yet disconnected. Note that this is true during all states where the connection
+ * is still good for something, and false only when it's dead for good. This means: when we are
+ * asynchronously connecting to a peer and the connect() is still pending, then this will return 'true', as
+ * the connection is still good, and we are likely to be able to properly operate on it soon. */
+#define VARLINK_STATE_IS_ALIVE(state)                   \
+        IN_SET(state,                                   \
+               VARLINK_IDLE_CLIENT,                     \
+               VARLINK_AWAITING_REPLY,                  \
+               VARLINK_CALLING,                         \
+               VARLINK_CALLED,                          \
+               VARLINK_PROCESSING_REPLY,                \
+               VARLINK_IDLE_SERVER,                     \
+               VARLINK_PROCESSING_METHOD,               \
+               VARLINK_PROCESSING_METHOD_MORE,          \
+               VARLINK_PROCESSING_METHOD_ONEWAY,        \
+               VARLINK_PROCESSED_METHOD,                \
+               VARLINK_PROCESSED_METHOD_MORE,           \
+               VARLINK_PENDING_METHOD,                  \
+               VARLINK_PENDING_METHOD_MORE)
+
+struct Varlink {
+        unsigned n_ref;
+
+        VarlinkServer *server;
+
+        VarlinkState state;
+        bool connecting; /* This boolean indicates whether the socket fd we are operating on is currently
+                          * processing an asynchronous connect(). In that state we watch the socket for
+                          * EPOLLOUT, but we refrain from calling read() or write() on the socket as that
+                          * will trigger ENOTCONN. Note that this boolean is kept separate from the
+                          * VarlinkState above on purpose: while the connect() is still not complete we
+                          * already want to allow queuing of messages and similar. Thus it's nice to keep
+                          * these two state concepts separate: the VarlinkState encodes what our own view of
+                          * the connection is, i.e. whether we think it's a server, a client, and has
+                          * something queued already, while 'connecting' tells us a detail about the
+                          * transport used below, that should have no effect on how we otherwise accept and
+                          * process operations from the user.
+                          *
+                          * Or to say this differently: VARLINK_STATE_IS_ALIVE(state) tells you whether the
+                          * connection is good to use, even if it might not be fully connected
+                          * yet. connecting=true then informs you that actually we are still connecting, and
+                          * the connection is actually not established yet and thus any requests you enqueue
+                          * now will still work fine but will be queued only, not sent yet, but that
+                          * shouldn't stop you from using the connection, since eventually whatever you queue
+                          * *will* be sent.
+                          *
+                          * Or to say this even differently: 'state' is a high-level ("application layer"
+                          * high, if you so will) state, while 'conecting' is a low-level ("transport layer"
+                          * low, if you so will) state, and while they are not entirely unrelated and
+                          * sometimes propagate effects to each other they are only asynchronously connected
+                          * at most. */
+        unsigned n_pending;
+
+        int fd;
+
+        char *input_buffer; /* valid data starts at input_buffer_index, ends at input_buffer_index+input_buffer_size */
+        size_t input_buffer_allocated;
+        size_t input_buffer_index;
+        size_t input_buffer_size;
+        size_t input_buffer_unscanned;
+
+        char *output_buffer; /* valid data starts at output_buffer_index, ends at output_buffer_index+output_buffer_size */
+        size_t output_buffer_allocated;
+        size_t output_buffer_index;
+        size_t output_buffer_size;
+
+        VarlinkReply reply_callback;
+
+        JsonVariant *current;
+        JsonVariant *reply;
+
+        struct ucred ucred;
+        bool ucred_acquired:1;
+
+        bool write_disconnected:1;
+        bool read_disconnected:1;
+        bool prefer_read_write:1;
+        bool got_pollhup:1;
+
+        usec_t timestamp;
+        usec_t timeout;
+
+        void *userdata;
+        char *description;
+
+        sd_event *event;
+        sd_event_source *io_event_source;
+        sd_event_source *time_event_source;
+        sd_event_source *quit_event_source;
+        sd_event_source *defer_event_source;
+};
+
+typedef struct VarlinkServerSocket VarlinkServerSocket;
+
+struct VarlinkServerSocket {
+        VarlinkServer *server;
+
+        int fd;
+        char *address;
+
+        sd_event_source *event_source;
+
+        LIST_FIELDS(VarlinkServerSocket, sockets);
+};
+
+struct VarlinkServer {
+        unsigned n_ref;
+        VarlinkServerFlags flags;
+
+        LIST_HEAD(VarlinkServerSocket, sockets);
+
+        Hashmap *methods;
+        VarlinkConnect connect_callback;
+
+        sd_event *event;
+        int64_t event_priority;
+
+        unsigned n_connections;
+        Hashmap *by_uid;
+
+        void *userdata;
+        char *description;
+
+        unsigned connections_max;
+        unsigned connections_per_uid_max;
+};
+
+static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
+        [VARLINK_IDLE_CLIENT]              = "idle-client",
+        [VARLINK_AWAITING_REPLY]           = "awaiting-reply",
+        [VARLINK_CALLING]                  = "calling",
+        [VARLINK_CALLED]                   = "called",
+        [VARLINK_PROCESSING_REPLY]         = "processing-reply",
+        [VARLINK_IDLE_SERVER]              = "idle-server",
+        [VARLINK_PROCESSING_METHOD]        = "processing-method",
+        [VARLINK_PROCESSING_METHOD_MORE]   = "processing-method-more",
+        [VARLINK_PROCESSING_METHOD_ONEWAY] = "processing-method-oneway",
+        [VARLINK_PROCESSED_METHOD]         = "processed-method",
+        [VARLINK_PROCESSED_METHOD_MORE]    = "processed-method-more",
+        [VARLINK_PENDING_METHOD]           = "pending-method",
+        [VARLINK_PENDING_METHOD_MORE]      = "pending-method-more",
+        [VARLINK_PENDING_DISCONNECT]       = "pending-disconnect",
+        [VARLINK_PENDING_TIMEOUT]          = "pending-timeout",
+        [VARLINK_PROCESSING_DISCONNECT]    = "processing-disconnect",
+        [VARLINK_PROCESSING_TIMEOUT]       = "processing-timeout",
+        [VARLINK_PROCESSING_FAILURE]       = "processing-failure",
+        [VARLINK_DISCONNECTED]             = "disconnected",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(varlink_state, VarlinkState);
+
+#define varlink_log_errno(v, error, fmt, ...)                           \
+        log_debug_errno(error, "%s: " fmt, varlink_description(v), ##__VA_ARGS__)
+
+#define varlink_log(v, fmt, ...)                                        \
+        log_debug("%s: " fmt, varlink_description(v), ##__VA_ARGS__)
+
+#define varlink_server_log_errno(s, error, fmt, ...) \
+        log_debug_errno(error, "%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
+
+#define varlink_server_log(s, fmt, ...) \
+        log_debug("%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
+
+static inline const char *varlink_description(Varlink *v) {
+        return strna(v ? v->description : NULL);
+}
+
+static inline const char *varlink_server_description(VarlinkServer *s) {
+        return strna(s ? s->description : NULL);
+}
+
+static void varlink_set_state(Varlink *v, VarlinkState state) {
+        assert(v);
+        assert(state >= 0 && state < _VARLINK_STATE_MAX);
+
+        if (v->state < 0)
+                varlink_log(v, "varlink: setting state %s",
+                            varlink_state_to_string(state));
+        else
+                varlink_log(v, "varlink: changing state %s → %s",
+                            varlink_state_to_string(v->state),
+                            varlink_state_to_string(state));
+
+        v->state = state;
+}
+
+static int varlink_new(Varlink **ret) {
+        Varlink *v;
+
+        assert(ret);
+
+        /* Here use new0 as the below structured initializer is nested. */
+        v = new0(Varlink, 1);
+        if (!v)
+                return -ENOMEM;
+
+        *v = (Varlink) {
+                .n_ref = 1,
+                .fd = -1,
+
+                .state = _VARLINK_STATE_INVALID,
+
+                .ucred.uid = UID_INVALID,
+                .ucred.gid = GID_INVALID,
+
+                .timestamp = USEC_INFINITY,
+                .timeout = VARLINK_DEFAULT_TIMEOUT_USEC
+        };
+
+        *ret = v;
+        return 0;
+}
+
+int varlink_connect_address(Varlink **ret, const char *address) {
+        _cleanup_(varlink_unrefp) Varlink *v = NULL;
+        union sockaddr_union sockaddr;
+        int r;
+
+        assert_return(ret, -EINVAL);
+        assert_return(address, -EINVAL);
+
+        r = sockaddr_un_set_path(&sockaddr.un, address);
+        if (r < 0)
+                return r;
+
+        r = varlink_new(&v);
+        if (r < 0)
+                return r;
+
+        v->fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (v->fd < 0)
+                return -errno;
+
+        if (connect(v->fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) {
+                if (!IN_SET(errno, EAGAIN, EINPROGRESS))
+                        return -errno;
+
+                v->connecting = true; /* We are asynchronously connecting, i.e. the connect() is being
+                                       * processed in the background. As long as that's the case the socket
+                                       * is in a special state: it's there, we can poll it for EPOLLOUT, but
+                                       * if we attempt to write() to it before we see EPOLLOUT we'll get
+                                       * ENOTCONN (and not EAGAIN, like we would for a normal connected
+                                       * socket that isn't writable at the moment). Since ENOTCONN on write()
+                                       * hence can mean two different things (i.e. connection not complete
+                                       * yet vs. already disconnected again), we store as a boolean whether
+                                       * we are still in connect(). */
+        }
+
+        varlink_set_state(v, VARLINK_IDLE_CLIENT);
+
+        *ret = TAKE_PTR(v);
+        return r;
+}
+
+int varlink_connect_fd(Varlink **ret, int fd) {
+        Varlink *v;
+        int r;
+
+        assert_return(ret, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+
+        r = fd_nonblock(fd, true);
+        if (r < 0)
+                return r;
+
+        r = varlink_new(&v);
+        if (r < 0)
+                return r;
+
+        v->fd = fd;
+        varlink_set_state(v, VARLINK_IDLE_CLIENT);
+
+        /* Note that if this function is called we assume the passed socket (if it is one) is already
+         * properly connected, i.e. any asynchronous connect() done on it already completed. Because of that
+         * we'll not set the 'connecting' boolean here, i.e. we don't need to avoid write()ing to the socket
+         * until the connection is fully set up. Behaviour here is hence a bit different from
+         * varlink_connect_address() above, as there we do handle asynchronous connections ourselves and
+         * avoid doing write() on it before we saw EPOLLOUT for the first time. */
+
+        *ret = v;
+        return 0;
+}
+
+static void varlink_detach_event_sources(Varlink *v) {
+        assert(v);
+
+        v->io_event_source = sd_event_source_disable_unref(v->io_event_source);
+
+        v->time_event_source = sd_event_source_disable_unref(v->time_event_source);
+
+        v->quit_event_source = sd_event_source_disable_unref(v->quit_event_source);
+
+        v->defer_event_source = sd_event_source_disable_unref(v->defer_event_source);
+}
+
+static void varlink_clear(Varlink *v) {
+        assert(v);
+
+        varlink_detach_event_sources(v);
+
+        v->fd = safe_close(v->fd);
+
+        v->input_buffer = mfree(v->input_buffer);
+        v->output_buffer = mfree(v->output_buffer);
+
+        v->current = json_variant_unref(v->current);
+        v->reply = json_variant_unref(v->reply);
+
+        v->event = sd_event_unref(v->event);
+}
+
+static Varlink* varlink_destroy(Varlink *v) {
+        if (!v)
+                return NULL;
+
+        /* If this is called the server object must already been unreffed here. Why that? because when we
+         * linked up the varlink connection with the server object we took one ref in each direction */
+        assert(!v->server);
+
+        varlink_clear(v);
+
+        free(v->description);
+        return mfree(v);
+}
+
+DEFINE_TRIVIAL_REF_UNREF_FUNC(Varlink, varlink, varlink_destroy);
+
+static int varlink_test_disconnect(Varlink *v) {
+        assert(v);
+
+        /* Tests whether we the the connection has been terminated. We are careful to not stop processing it
+         * prematurely, since we want to handle half-open connections as well as possible and want to flush
+         * out and read data before we close down if we can. */
+
+        /* Already disconnected? */
+        if (!VARLINK_STATE_IS_ALIVE(v->state))
+                return 0;
+
+        /* Wait until connection setup is complete, i.e. until asynchronous connect() completes */
+        if (v->connecting)
+                return 0;
+
+        /* Still something to write and we can write? Stay around */
+        if (v->output_buffer_size > 0 && !v->write_disconnected)
+                return 0;
+
+        /* Both sides gone already? Then there's no need to stick around */
+        if (v->read_disconnected && v->write_disconnected)
+                goto disconnect;
+
+        /* If we are waiting for incoming data but the read side is shut down, disconnect. */
+        if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER) && v->read_disconnected)
+                goto disconnect;
+
+        /* Similar, if are a client that hasn't written anything yet but the write side is dead, also
+         * disconnect. We also explicitly check for POLLHUP here since we likely won't notice the write side
+         * being down if we never wrote anything. */
+        if (IN_SET(v->state, VARLINK_IDLE_CLIENT) && (v->write_disconnected || v->got_pollhup))
+                goto disconnect;
+
+        return 0;
+
+disconnect:
+        varlink_set_state(v, VARLINK_PENDING_DISCONNECT);
+        return 1;
+}
+
+static int varlink_write(Varlink *v) {
+        ssize_t n;
+
+        assert(v);
+
+        if (!VARLINK_STATE_IS_ALIVE(v->state))
+                return 0;
+        if (v->connecting) /* Writing while we are still wait for a non-blocking connect() to complete will
+                            * result in ENOTCONN, hence exit early here */
+                return 0;
+        if (v->output_buffer_size == 0)
+                return 0;
+        if (v->write_disconnected)
+                return 0;
+
+        assert(v->fd >= 0);
+
+        /* We generally prefer recv()/send() (mostly because of MSG_NOSIGNAL) but also want to be compatible
+         * with non-socket IO, hence fall back automatically */
+        if (!v->prefer_read_write) {
+                n = send(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size, MSG_DONTWAIT|MSG_NOSIGNAL);
+                if (n < 0 && errno == ENOTSOCK)
+                        v->prefer_read_write = true;
+        }
+        if (v->prefer_read_write)
+                n = write(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size);
+        if (n < 0) {
+                if (errno == EAGAIN)
+                        return 0;
+
+                if (ERRNO_IS_DISCONNECT(errno)) {
+                        /* If we get informed about a disconnect on write, then let's remember that, but not
+                         * act on it just yet. Let's wait for read() to report the issue first. */
+                        v->write_disconnected = true;
+                        return 1;
+                }
+
+                return -errno;
+        }
+
+        v->output_buffer_size -= n;
+
+        if (v->output_buffer_size == 0)
+                v->output_buffer_index = 0;
+        else
+                v->output_buffer_index += n;
+
+        v->timestamp = now(CLOCK_MONOTONIC);
+        return 1;
+}
+
+static int varlink_read(Varlink *v) {
+        size_t rs;
+        ssize_t n;
+
+        assert(v);
+
+        if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER))
+                return 0;
+        if (v->connecting) /* read() on a socket while we are in connect() will fail with EINVAL, hence exit early here */
+                return 0;
+        if (v->current)
+                return 0;
+        if (v->input_buffer_unscanned > 0)
+                return 0;
+        if (v->read_disconnected)
+                return 0;
+
+        if (v->input_buffer_size >= VARLINK_BUFFER_MAX)
+                return -ENOBUFS;
+
+        assert(v->fd >= 0);
+
+        if (v->input_buffer_allocated <= v->input_buffer_index + v->input_buffer_size) {
+                size_t add;
+
+                add = MIN(VARLINK_BUFFER_MAX - v->input_buffer_size, VARLINK_READ_SIZE);
+
+                if (v->input_buffer_index == 0) {
+
+                        if (!GREEDY_REALLOC(v->input_buffer, v->input_buffer_allocated, v->input_buffer_size + add))
+                                return -ENOMEM;
+
+                } else {
+                        char *b;
+
+                        b = new(char, v->input_buffer_size + add);
+                        if (!b)
+                                return -ENOMEM;
+
+                        memcpy(b, v->input_buffer + v->input_buffer_index, v->input_buffer_size);
+
+                        free_and_replace(v->input_buffer, b);
+
+                        v->input_buffer_allocated = v->input_buffer_size + add;
+                        v->input_buffer_index = 0;
+                }
+        }
+
+        rs = v->input_buffer_allocated - (v->input_buffer_index + v->input_buffer_size);
+
+        if (!v->prefer_read_write) {
+                n = recv(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs, MSG_DONTWAIT);
+                if (n < 0 && errno == ENOTSOCK)
+                        v->prefer_read_write = true;
+        }
+        if (v->prefer_read_write)
+                n = read(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs);
+        if (n < 0) {
+                if (errno == EAGAIN)
+                        return 0;
+
+                if (ERRNO_IS_DISCONNECT(errno)) {
+                        v->read_disconnected = true;
+                        return 1;
+                }
+
+                return -errno;
+        }
+        if (n == 0) { /* EOF */
+                v->read_disconnected = true;
+                return 1;
+        }
+
+        v->input_buffer_size += n;
+        v->input_buffer_unscanned += n;
+
+        return 1;
+}
+
+static int varlink_parse_message(Varlink *v) {
+        const char *e, *begin;
+        size_t sz;
+        int r;
+
+        assert(v);
+
+        if (v->current)
+                return 0;
+        if (v->input_buffer_unscanned <= 0)
+                return 0;
+
+        assert(v->input_buffer_unscanned <= v->input_buffer_size);
+        assert(v->input_buffer_index + v->input_buffer_size <= v->input_buffer_allocated);
+
+        begin = v->input_buffer + v->input_buffer_index;
+
+        e = memchr(begin + v->input_buffer_size - v->input_buffer_unscanned, 0, v->input_buffer_unscanned);
+        if (!e) {
+                v->input_buffer_unscanned = 0;
+                return 0;
+        }
+
+        sz = e - begin + 1;
+
+        varlink_log(v, "New incoming message: %s", begin);
+
+        r = json_parse(begin, &v->current, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        v->input_buffer_size -= sz;
+
+        if (v->input_buffer_size == 0)
+                v->input_buffer_index = 0;
+        else
+                v->input_buffer_index += sz;
+
+        v->input_buffer_unscanned = v->input_buffer_size;
+        return 1;
+}
+
+static int varlink_test_timeout(Varlink *v) {
+        assert(v);
+
+        if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING))
+                return 0;
+        if (v->timeout == USEC_INFINITY)
+                return 0;
+
+        if (now(CLOCK_MONOTONIC) < usec_add(v->timestamp, v->timeout))
+                return 0;
+
+        varlink_set_state(v, VARLINK_PENDING_TIMEOUT);
+
+        return 1;
+}
+
+static int varlink_dispatch_local_error(Varlink *v, const char *error) {
+        int r;
+
+        assert(v);
+        assert(error);
+
+        if (!v->reply_callback)
+                return 0;
+
+        r = v->reply_callback(v, NULL, error, VARLINK_REPLY_ERROR|VARLINK_REPLY_LOCAL, v->userdata);
+        if (r < 0)
+                log_debug_errno(r, "Reply callback returned error, ignoring: %m");
+
+        return 1;
+}
+
+static int varlink_dispatch_timeout(Varlink *v) {
+        assert(v);
+
+        if (v->state != VARLINK_PENDING_TIMEOUT)
+                return 0;
+
+        varlink_set_state(v, VARLINK_PROCESSING_TIMEOUT);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_TIMEOUT);
+        varlink_close(v);
+
+        return 1;
+}
+
+static int varlink_dispatch_disconnect(Varlink *v) {
+        assert(v);
+
+        if (v->state != VARLINK_PENDING_DISCONNECT)
+                return 0;
+
+        varlink_set_state(v, VARLINK_PROCESSING_DISCONNECT);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_DISCONNECTED);
+        varlink_close(v);
+
+        return 1;
+}
+
+static int varlink_sanitize_parameters(JsonVariant **v) {
+        assert(v);
+
+        /* Varlink always wants a parameters list, hence make one if the caller doesn't want any */
+        if (!*v)
+                return json_variant_new_object(v, NULL, 0);
+        else if (!json_variant_is_object(*v))
+                return -EINVAL;
+
+        return 0;
+}
+
+static int varlink_dispatch_reply(Varlink *v) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        VarlinkReplyFlags flags = 0;
+        const char *error = NULL;
+        JsonVariant *e;
+        const char *k;
+        int r;
+
+        assert(v);
+
+        if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING))
+                return 0;
+        if (!v->current)
+                return 0;
+
+        assert(v->n_pending > 0);
+
+        if (!json_variant_is_object(v->current))
+                goto invalid;
+
+        JSON_VARIANT_OBJECT_FOREACH(k, e, v->current) {
+
+                if (streq(k, "error")) {
+                        if (error)
+                                goto invalid;
+                        if (!json_variant_is_string(e))
+                                goto invalid;
+
+                        error = json_variant_string(e);
+                        flags |= VARLINK_REPLY_ERROR;
+
+                } else if (streq(k, "parameters")) {
+                        if (parameters)
+                                goto invalid;
+                        if (!json_variant_is_object(e))
+                                goto invalid;
+
+                        parameters = json_variant_ref(e);
+
+                } else if (streq(k, "continues")) {
+                        if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                                goto invalid;
+
+                        if (!json_variant_is_boolean(e))
+                                goto invalid;
+
+                        if (json_variant_boolean(e))
+                                flags |= VARLINK_REPLY_CONTINUES;
+                } else
+                        goto invalid;
+        }
+
+        if (error && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                goto invalid;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                goto invalid;
+
+        if (v->state == VARLINK_AWAITING_REPLY) {
+                varlink_set_state(v, VARLINK_PROCESSING_REPLY);
+
+                if (v->reply_callback) {
+                        r = v->reply_callback(v, parameters, error, flags, v->userdata);
+                        if (r < 0)
+                                log_debug_errno(r, "Reply callback returned error, ignoring: %m");
+                }
+
+                v->current = json_variant_unref(v->current);
+
+                if (v->state == VARLINK_PROCESSING_REPLY) {
+                        assert(v->n_pending > 0);
+                        v->n_pending--;
+
+                        varlink_set_state(v, v->n_pending == 0 ? VARLINK_IDLE_CLIENT : VARLINK_AWAITING_REPLY);
+                }
+        } else {
+                assert(v->state == VARLINK_CALLING);
+
+                if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                        goto invalid;
+
+                varlink_set_state(v, VARLINK_CALLED);
+        }
+
+        return 1;
+
+invalid:
+        varlink_set_state(v, VARLINK_PROCESSING_FAILURE);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_PROTOCOL);
+        varlink_close(v);
+
+        return 1;
+}
+
+static int varlink_dispatch_method(Varlink *v) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        VarlinkMethodFlags flags = 0;
+        const char *method = NULL, *error;
+        JsonVariant *e;
+        VarlinkMethod callback;
+        const char *k;
+        int r;
+
+        assert(v);
+
+        if (v->state != VARLINK_IDLE_SERVER)
+                return 0;
+        if (!v->current)
+                return 0;
+
+        if (!json_variant_is_object(v->current))
+                goto invalid;
+
+        JSON_VARIANT_OBJECT_FOREACH(k, e, v->current) {
+
+                if (streq(k, "method")) {
+                        if (method)
+                                goto invalid;
+                        if (!json_variant_is_string(e))
+                                goto invalid;
+
+                        method = json_variant_string(e);
+
+                } else if (streq(k, "parameters")) {
+                        if (parameters)
+                                goto invalid;
+                        if (!json_variant_is_object(e))
+                                goto invalid;
+
+                        parameters = json_variant_ref(e);
+
+                } else if (streq(k, "oneway")) {
+
+                        if ((flags & (VARLINK_METHOD_ONEWAY|VARLINK_METHOD_MORE)) != 0)
+                                goto invalid;
+
+                        if (!json_variant_is_boolean(e))
+                                goto invalid;
+
+                        if (json_variant_boolean(e))
+                                flags |= VARLINK_METHOD_ONEWAY;
+
+                } else if (streq(k, "more")) {
+
+                        if ((flags & (VARLINK_METHOD_ONEWAY|VARLINK_METHOD_MORE)) != 0)
+                                goto invalid;
+
+                        if (!json_variant_is_boolean(e))
+                                goto invalid;
+
+                        if (json_variant_boolean(e))
+                                flags |= VARLINK_METHOD_MORE;
+
+                } else
+                        goto invalid;
+        }
+
+        if (!method)
+                goto invalid;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                goto fail;
+
+        varlink_set_state(v, (flags & VARLINK_METHOD_MORE)   ? VARLINK_PROCESSING_METHOD_MORE :
+                             (flags & VARLINK_METHOD_ONEWAY) ? VARLINK_PROCESSING_METHOD_ONEWAY :
+                                                               VARLINK_PROCESSING_METHOD);
+
+        assert(v->server);
+
+        if (STR_IN_SET(method, "org.varlink.service.GetInfo", "org.varlink.service.GetInterface")) {
+                /* For now, we don't implement a single of varlink's own methods */
+                callback = NULL;
+                error = VARLINK_ERROR_METHOD_NOT_IMPLEMENTED;
+        } else if (startswith(method, "org.varlink.service.")) {
+                callback = NULL;
+                error = VARLINK_ERROR_METHOD_NOT_FOUND;
+        } else {
+                callback = hashmap_get(v->server->methods, method);
+                error = VARLINK_ERROR_METHOD_NOT_FOUND;
+        }
+
+        if (callback) {
+                r = callback(v, parameters, flags, v->userdata);
+                if (r < 0) {
+                        log_debug_errno(r, "Callback for %s returned error: %m", method);
+
+                        /* We got an error back from the callback. Propagate it to the client if the method call remains unanswered. */
+                        if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) {
+                                r = varlink_errorb(v, VARLINK_ERROR_SYSTEM, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("errno", JSON_BUILD_INTEGER(-r))));
+                                if (r < 0)
+                                        return r;
+                        }
+                }
+        } else if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) {
+                assert(error);
+
+                r = varlink_errorb(v, error, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method))));
+                if (r < 0)
+                        return r;
+        }
+
+        switch (v->state) {
+
+        case VARLINK_PROCESSED_METHOD: /* Method call is fully processed */
+        case VARLINK_PROCESSING_METHOD_ONEWAY: /* ditto */
+                v->current = json_variant_unref(v->current);
+                varlink_set_state(v, VARLINK_IDLE_SERVER);
+                break;
+
+        case VARLINK_PROCESSING_METHOD: /* Method call wasn't replied to, will be replied to later */
+                varlink_set_state(v, VARLINK_PENDING_METHOD);
+                break;
+
+        case VARLINK_PROCESSED_METHOD_MORE:  /* One reply for a "more" message was sent, more to come */
+        case VARLINK_PROCESSING_METHOD_MORE: /* No reply for a "more" message was sent, more to come */
+                varlink_set_state(v, VARLINK_PENDING_METHOD_MORE);
+                break;
+
+        default:
+                assert_not_reached("Unexpected state");
+
+        }
+
+        return r;
+
+invalid:
+        r = -EINVAL;
+
+fail:
+        varlink_set_state(v, VARLINK_PROCESSING_FAILURE);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_PROTOCOL);
+        varlink_close(v);
+
+        return r;
+}
+
+int varlink_process(Varlink *v) {
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        varlink_ref(v);
+
+        r = varlink_write(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_reply(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_method(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_parse_message(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_read(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_test_disconnect(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_disconnect(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_test_timeout(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_timeout(v);
+        if (r != 0)
+                goto finish;
+
+finish:
+        if (r >= 0 && v->defer_event_source) {
+                int q;
+
+                /* If we did some processing, make sure we are called again soon */
+                q = sd_event_source_set_enabled(v->defer_event_source, r > 0 ? SD_EVENT_ON : SD_EVENT_OFF);
+                if (q < 0)
+                        r = q;
+        }
+
+        if (r < 0) {
+                if (VARLINK_STATE_IS_ALIVE(v->state))
+                        /* Initiate disconnection */
+                        varlink_set_state(v, VARLINK_PENDING_DISCONNECT);
+                else
+                        /* We failed while disconnecting, in that case close right away */
+                        varlink_close(v);
+        }
+
+        varlink_unref(v);
+        return r;
+}
+
+static void handle_revents(Varlink *v, int revents) {
+        assert(v);
+
+        if (v->connecting) {
+                /* If we have seen POLLOUT or POLLHUP on a socket we are asynchronously waiting a connect()
+                 * to complete on, we know we are ready. We don't read the connection error here though,
+                 * we'll get the error on the next read() or write(). */
+                if ((revents & (POLLOUT|POLLHUP)) == 0)
+                        return;
+
+                varlink_log(v, "Anynchronous connection completed.");
+                v->connecting = false;
+        } else {
+                /* Note that we don't care much about POLLIN/POLLOUT here, we'll just try reading and writing
+                 * what we can. However, we do care about POLLHUP to detect connection termination even if we
+                 * momentarily don't want to read nor write anything. */
+
+                if (!FLAGS_SET(revents, POLLHUP))
+                        return;
+
+                varlink_log(v, "Got POLLHUP from socket.");
+                v->got_pollhup = true;
+        }
+}
+
+int varlink_wait(Varlink *v, usec_t timeout) {
+        struct timespec ts;
+        struct pollfd pfd;
+        int r, fd, events;
+        usec_t t;
+
+        assert_return(v, -EINVAL);
+        assert_return(!v->server, -ENOTTY);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        r = varlink_get_timeout(v, &t);
+        if (r < 0)
+                return r;
+        if (t != USEC_INFINITY) {
+                usec_t n;
+
+                n = now(CLOCK_MONOTONIC);
+                if (t < n)
+                        t = 0;
+                else
+                        t = usec_sub_unsigned(t, n);
+        }
+
+        if (timeout != USEC_INFINITY &&
+            (t == USEC_INFINITY || timeout < t))
+                t = timeout;
+
+        fd = varlink_get_fd(v);
+        if (fd < 0)
+                return fd;
+
+        events = varlink_get_events(v);
+        if (events < 0)
+                return events;
+
+        pfd = (struct pollfd) {
+                .fd = fd,
+                .events = events,
+        };
+
+        r = ppoll(&pfd, 1,
+                  t == USEC_INFINITY ? NULL : timespec_store(&ts, t),
+                  NULL);
+        if (r < 0)
+                return -errno;
+
+        handle_revents(v, pfd.revents);
+
+        return r > 0 ? 1 : 0;
+}
+
+int varlink_get_fd(Varlink *v) {
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (v->fd < 0)
+                return -EBADF;
+
+        return v->fd;
+}
+
+int varlink_get_events(Varlink *v) {
+        int ret = 0;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        if (v->connecting) /* When processing an asynchronous connect(), we only wait for EPOLLOUT, which
+                            * tells us that the connection is now complete. Before that we should neither
+                            * write() or read() from the fd. */
+                return EPOLLOUT;
+
+        if (!v->read_disconnected &&
+            IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER) &&
+            !v->current &&
+            v->input_buffer_unscanned <= 0)
+                ret |= EPOLLIN;
+
+        if (!v->write_disconnected &&
+            v->output_buffer_size > 0)
+                ret |= EPOLLOUT;
+
+        return ret;
+}
+
+int varlink_get_timeout(Varlink *v, usec_t *ret) {
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING) &&
+            v->timeout != USEC_INFINITY) {
+                if (ret)
+                        *ret = usec_add(v->timestamp, v->timeout);
+                return 1;
+        } else {
+                if (ret)
+                        *ret = USEC_INFINITY;
+                return 0;
+        }
+}
+
+int varlink_flush(Varlink *v) {
+        int ret = 0, r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        for (;;) {
+                struct pollfd pfd;
+
+                if (v->output_buffer_size == 0)
+                        break;
+                if (v->write_disconnected)
+                        return -ECONNRESET;
+
+                r = varlink_write(v);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        ret = 1;
+                        continue;
+                }
+
+                pfd = (struct pollfd) {
+                        .fd = v->fd,
+                        .events = POLLOUT,
+                };
+
+                if (poll(&pfd, 1, -1) < 0)
+                        return -errno;
+
+                handle_revents(v, pfd.revents);
+        }
+
+        return ret;
+}
+
+static void varlink_detach_server(Varlink *v) {
+        assert(v);
+
+        if (!v->server)
+                return;
+
+        if (v->server->by_uid &&
+            v->ucred_acquired &&
+            uid_is_valid(v->ucred.uid)) {
+                unsigned c;
+
+                c = PTR_TO_UINT(hashmap_get(v->server->by_uid, UID_TO_PTR(v->ucred.uid)));
+                assert(c > 0);
+
+                if (c == 1)
+                        (void) hashmap_remove(v->server->by_uid, UID_TO_PTR(v->ucred.uid));
+                else
+                        (void) hashmap_replace(v->server->by_uid, UID_TO_PTR(v->ucred.uid), UINT_TO_PTR(c - 1));
+        }
+
+        assert(v->server->n_connections > 0);
+        v->server->n_connections--;
+
+        /* If this is a connection associated to a server, then let's disconnect the server and the
+         * connection from each other. This drops the dangling reference that connect_callback() set up. */
+        v->server = varlink_server_unref(v->server);
+        varlink_unref(v);
+}
+
+int varlink_close(Varlink *v) {
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return 0;
+
+        varlink_set_state(v, VARLINK_DISCONNECTED);
+
+        /* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref
+         * which would destroy us before we can call varlink_clear() */
+        varlink_ref(v);
+        varlink_detach_server(v);
+        varlink_clear(v);
+        varlink_unref(v);
+
+        return 1;
+}
+
+Varlink* varlink_flush_close_unref(Varlink *v) {
+
+        if (!v)
+                return NULL;
+
+        (void) varlink_flush(v);
+        (void) varlink_close(v);
+
+        return varlink_unref(v);
+}
+
+static int varlink_enqueue_json(Varlink *v, JsonVariant *m) {
+        _cleanup_free_ char *text = NULL;
+        int r;
+
+        assert(v);
+        assert(m);
+
+        r = json_variant_format(m, 0, &text);
+        if (r < 0)
+                return r;
+
+        if (v->output_buffer_size + r + 1 > VARLINK_BUFFER_MAX)
+                return -ENOBUFS;
+
+        varlink_log(v, "Sending message: %s", text);
+
+        if (v->output_buffer_size == 0) {
+
+                free_and_replace(v->output_buffer, text);
+
+                v->output_buffer_size = v->output_buffer_allocated = r + 1;
+                v->output_buffer_index = 0;
+
+        } else if (v->output_buffer_index == 0) {
+
+                if (!GREEDY_REALLOC(v->output_buffer, v->output_buffer_allocated, v->output_buffer_size + r + 1))
+                        return -ENOMEM;
+
+                memcpy(v->output_buffer + v->output_buffer_size, text, r + 1);
+                v->output_buffer_size += r + 1;
+
+        } else {
+                char *n;
+                const size_t new_size = v->output_buffer_size + r + 1;
+
+                n = new(char, new_size);
+                if (!n)
+                        return -ENOMEM;
+
+                memcpy(mempcpy(n, v->output_buffer + v->output_buffer_index, v->output_buffer_size), text, r + 1);
+
+                free_and_replace(v->output_buffer, n);
+                v->output_buffer_allocated = v->output_buffer_size = new_size;
+                v->output_buffer_index = 0;
+        }
+
+        return 0;
+}
+
+int varlink_send(Varlink *v, const char *method, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(method, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)),
+                                       JSON_BUILD_PAIR("oneway", JSON_BUILD_BOOLEAN(true))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        /* No state change here, this is one-way only after all */
+        v->timestamp = now(CLOCK_MONOTONIC);
+        return 0;
+}
+
+int varlink_sendb(Varlink *v, const char *method, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, method);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_send(v, method, parameters);
+}
+
+int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(method, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        varlink_set_state(v, VARLINK_AWAITING_REPLY);
+        v->n_pending++;
+        v->timestamp = now(CLOCK_MONOTONIC);
+
+        return 0;
+}
+
+int varlink_invokeb(Varlink *v, const char *method, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, method);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_invoke(v, method, parameters);
+}
+
+int varlink_call(
+                Varlink *v,
+                const char *method,
+                JsonVariant *parameters,
+                JsonVariant **ret_parameters,
+                const char **ret_error_id,
+                VarlinkReplyFlags *ret_flags) {
+
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(method, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_IDLE_CLIENT))
+                return -EBUSY;
+
+        assert(v->n_pending == 0); /* n_pending can't be > 0 if we are in VARLINK_IDLE_CLIENT state */
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        varlink_set_state(v, VARLINK_CALLING);
+        v->n_pending++;
+        v->timestamp = now(CLOCK_MONOTONIC);
+
+        while (v->state == VARLINK_CALLING) {
+
+                r = varlink_process(v);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        continue;
+
+                r = varlink_wait(v, USEC_INFINITY);
+                if (r < 0)
+                        return r;
+        }
+
+        switch (v->state) {
+
+        case VARLINK_CALLED:
+                assert(v->current);
+
+                json_variant_unref(v->reply);
+                v->reply = TAKE_PTR(v->current);
+
+                varlink_set_state(v, VARLINK_IDLE_CLIENT);
+                assert(v->n_pending == 1);
+                v->n_pending--;
+
+                if (ret_parameters)
+                        *ret_parameters = json_variant_by_key(v->reply, "parameters");
+                if (ret_error_id)
+                        *ret_error_id = json_variant_string(json_variant_by_key(v->reply, "error"));
+                if (ret_flags)
+                        *ret_flags = 0;
+
+                return 1;
+
+        case VARLINK_PENDING_DISCONNECT:
+        case VARLINK_DISCONNECTED:
+                return -ECONNRESET;
+
+        case VARLINK_PENDING_TIMEOUT:
+                return -ETIME;
+
+        default:
+                assert_not_reached("Unexpected state after method call.");
+        }
+}
+
+int varlink_callb(
+                Varlink *v,
+                const char *method,
+                JsonVariant **ret_parameters,
+                const char **ret_error_id,
+                VarlinkReplyFlags *ret_flags, ...) {
+
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, ret_flags);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_call(v, method, parameters, ret_parameters, ret_error_id, ret_flags);
+}
+
+int varlink_reply(Varlink *v, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state,
+                    VARLINK_PROCESSING_METHOD, VARLINK_PROCESSING_METHOD_MORE,
+                    VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) {
+                /* We just replied to a method call that was let hanging for a while (i.e. we were outside of
+                 * the varlink_dispatch_method() stack frame), which means with this reply we are ready to
+                 * process further messages. */
+                v->current = json_variant_unref(v->current);
+                varlink_set_state(v, VARLINK_IDLE_SERVER);
+        } else
+                /* We replied to a method call from within the varlink_dispatch_method() stack frame), which
+                 * means we should it handle the rest of the state engine. */
+                varlink_set_state(v, VARLINK_PROCESSED_METHOD);
+
+        return 1;
+}
+
+int varlink_replyb(Varlink *v, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, v);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_reply(v, parameters);
+}
+
+int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(error_id, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state,
+                    VARLINK_PROCESSING_METHOD, VARLINK_PROCESSING_METHOD_MORE,
+                    VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("error", JSON_BUILD_STRING(error_id)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) {
+                v->current = json_variant_unref(v->current);
+                varlink_set_state(v, VARLINK_IDLE_SERVER);
+        } else
+                varlink_set_state(v, VARLINK_PROCESSED_METHOD);
+
+        return 1;
+}
+
+int varlink_errorb(Varlink *v, const char *error_id, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(error_id, -EINVAL);
+
+        va_start(ap, error_id);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_error(v, error_id, parameters);
+}
+
+int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters) {
+
+        assert_return(v, -EINVAL);
+        assert_return(parameters, -EINVAL);
+
+        /* We expect to be called in one of two ways: the 'parameters' argument is a string variant in which
+         * case it is the parameter key name that is invalid. Or the 'parameters' argument is an object
+         * variant in which case we'll pull out the first key. The latter mode is useful in functions that
+         * don't expect any arguments. */
+
+        if (json_variant_is_string(parameters))
+                return varlink_error(v, VARLINK_ERROR_INVALID_PARAMETER, parameters);
+
+        if (json_variant_is_object(parameters) &&
+            json_variant_elements(parameters) > 0)
+                return varlink_error(v, VARLINK_ERROR_INVALID_PARAMETER,
+                                     json_variant_by_index(parameters, 0));
+
+        return -EINVAL;
+}
+
+int varlink_notify(Varlink *v, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_PROCESSING_METHOD_MORE, VARLINK_PENDING_METHOD_MORE))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)),
+                                       JSON_BUILD_PAIR("continues", JSON_BUILD_BOOLEAN(true))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        /* No state change, as more is coming */
+        return 1;
+}
+
+int varlink_notifyb(Varlink *v, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, v);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_notify(v, parameters);
+}
+
+int varlink_bind_reply(Varlink *v, VarlinkReply callback) {
+        assert_return(v, -EINVAL);
+
+        if (callback && v->reply_callback && callback != v->reply_callback)
+                return -EBUSY;
+
+        v->reply_callback = callback;
+
+        return 0;
+}
+
+void* varlink_set_userdata(Varlink *v, void *userdata) {
+        void *old;
+
+        assert_return(v, NULL);
+
+        old = v->userdata;
+        v->userdata = userdata;
+
+        return old;
+}
+
+void* varlink_get_userdata(Varlink *v) {
+        assert_return(v, NULL);
+
+        return v->userdata;
+}
+
+static int varlink_acquire_ucred(Varlink *v) {
+        int r;
+
+        assert(v);
+
+        if (v->ucred_acquired)
+                return 0;
+
+        r = getpeercred(v->fd, &v->ucred);
+        if (r < 0)
+                return r;
+
+        v->ucred_acquired = true;
+        return 0;
+}
+
+int varlink_get_peer_uid(Varlink *v, uid_t *ret) {
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = varlink_acquire_ucred(v);
+        if (r < 0)
+                return r;
+
+        if (!uid_is_valid(v->ucred.uid))
+                return -ENODATA;
+
+        *ret = v->ucred.uid;
+        return 0;
+}
+
+int varlink_get_peer_pid(Varlink *v, pid_t *ret) {
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = varlink_acquire_ucred(v);
+        if (r < 0)
+                return r;
+
+        if (!pid_is_valid(v->ucred.pid))
+                return -ENODATA;
+
+        *ret = v->ucred.pid;
+        return 0;
+}
+
+int varlink_set_relative_timeout(Varlink *v, usec_t timeout) {
+        assert_return(v, -EINVAL);
+        assert_return(timeout > 0, -EINVAL);
+
+        v->timeout = timeout;
+        return 0;
+}
+
+VarlinkServer *varlink_get_server(Varlink *v) {
+        assert_return(v, NULL);
+
+        return v->server;
+}
+
+int varlink_set_description(Varlink *v, const char *description) {
+        assert_return(v, -EINVAL);
+
+        return free_and_strdup(&v->description, description);
+}
+
+static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(s);
+        assert(v);
+
+        handle_revents(v, revents);
+        (void) varlink_process(v);
+
+        return 1;
+}
+
+static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(s);
+        assert(v);
+
+        (void) varlink_process(v);
+        return 1;
+}
+
+static int defer_callback(sd_event_source *s, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(s);
+        assert(v);
+
+        (void) varlink_process(v);
+        return 1;
+}
+
+static int prepare_callback(sd_event_source *s, void *userdata) {
+        Varlink *v = userdata;
+        int r, e;
+        usec_t until;
+
+        assert(s);
+        assert(v);
+
+        e = varlink_get_events(v);
+        if (e < 0)
+                return e;
+
+        r = sd_event_source_set_io_events(v->io_event_source, e);
+        if (r < 0)
+                return r;
+
+        r = varlink_get_timeout(v, &until);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                r = sd_event_source_set_time(v->time_event_source, until);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_event_source_set_enabled(v->time_event_source, r > 0 ? SD_EVENT_ON : SD_EVENT_OFF);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int quit_callback(sd_event_source *event, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(event);
+        assert(v);
+
+        varlink_flush(v);
+        varlink_close(v);
+
+        return 1;
+}
+
+int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority) {
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(!v->event, -EBUSY);
+
+        if (e)
+                v->event = sd_event_ref(e);
+        else {
+                r = sd_event_default(&v->event);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_event_add_time(v->event, &v->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->time_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->time_event_source, "varlink-time");
+
+        r = sd_event_add_exit(v->event, &v->quit_event_source, quit_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->quit_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->quit_event_source, "varlink-quit");
+
+        r = sd_event_add_io(v->event, &v->io_event_source, v->fd, 0, io_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_prepare(v->io_event_source, prepare_callback);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->io_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->io_event_source, "varlink-io");
+
+        r = sd_event_add_defer(v->event, &v->defer_event_source, defer_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->defer_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->defer_event_source, "varlink-defer");
+
+        return 0;
+
+fail:
+        varlink_detach_event(v);
+        return r;
+}
+
+
+void varlink_detach_event(Varlink *v) {
+        if (!v)
+                return;
+
+        varlink_detach_event_sources(v);
+
+        v->event = sd_event_unref(v->event);
+}
+
+sd_event *varlink_get_event(Varlink *v) {
+        assert_return(v, NULL);
+
+        return v->event;
+}
+
+int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags) {
+        VarlinkServer *s;
+
+        assert_return(ret, -EINVAL);
+        assert_return((flags & ~_VARLINK_SERVER_FLAGS_ALL) == 0, -EINVAL);
+
+        s = new(VarlinkServer, 1);
+        if (!s)
+                return -ENOMEM;
+
+        *s = (VarlinkServer) {
+                .n_ref = 1,
+                .flags = flags,
+                .connections_max = varlink_server_connections_max(NULL),
+                .connections_per_uid_max = varlink_server_connections_per_uid_max(NULL),
+        };
+
+        *ret = s;
+        return 0;
+}
+
+static VarlinkServer* varlink_server_destroy(VarlinkServer *s) {
+        char *m;
+
+        if (!s)
+                return NULL;
+
+        varlink_server_shutdown(s);
+
+        while ((m = hashmap_steal_first_key(s->methods)))
+                free(m);
+
+        hashmap_free(s->methods);
+        hashmap_free(s->by_uid);
+
+        sd_event_unref(s->event);
+
+        free(s->description);
+
+        return mfree(s);
+}
+
+DEFINE_TRIVIAL_REF_UNREF_FUNC(VarlinkServer, varlink_server, varlink_server_destroy);
+
+static int validate_connection(VarlinkServer *server, const struct ucred *ucred) {
+        int allowed = -1;
+
+        assert(server);
+        assert(ucred);
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_ROOT_ONLY))
+                allowed = ucred->uid == 0;
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_MYSELF_ONLY))
+                allowed = allowed > 0 || ucred->uid == getuid();
+
+        if (allowed == 0) { /* Allow access when it is explicitly allowed or when neither
+                             * VARLINK_SERVER_ROOT_ONLY nor VARLINK_SERVER_MYSELF_ONLY are specified. */
+                varlink_server_log(server, "Unprivileged client attempted connection, refusing.");
+                return 0;
+        }
+
+        if (server->n_connections >= server->connections_max) {
+                varlink_server_log(server, "Connection limit of %u reached, refusing.", server->connections_max);
+                return 0;
+        }
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_ACCOUNT_UID)) {
+                unsigned c;
+
+                if (!uid_is_valid(ucred->uid)) {
+                        varlink_server_log(server, "Client with invalid UID attempted connection, refusing.");
+                        return 0;
+                }
+
+                c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
+                if (c >= server->connections_per_uid_max) {
+                        varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.",
+                                           server->connections_per_uid_max);
+                        return 0;
+                }
+        }
+
+        return 1;
+}
+
+static int count_connection(VarlinkServer *server, struct ucred *ucred) {
+        unsigned c;
+        int r;
+
+        assert(server);
+        assert(ucred);
+
+        server->n_connections++;
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_ACCOUNT_UID)) {
+                r = hashmap_ensure_allocated(&server->by_uid, NULL);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to allocate UID hash table: %m");
+
+                c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
+
+                varlink_server_log(server, "Connections of user " UID_FMT ": %u (of %u max)",
+                                   ucred->uid, c, server->connections_per_uid_max);
+
+                r = hashmap_replace(server->by_uid, UID_TO_PTR(ucred->uid), UINT_TO_PTR(c + 1));
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to increment counter in UID hash table: %m");
+        }
+
+        return 0;
+}
+
+int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) {
+        _cleanup_(varlink_unrefp) Varlink *v = NULL;
+        bool ucred_acquired;
+        struct ucred ucred;
+        int r;
+
+        assert_return(server, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+
+        if ((server->flags & (VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_ACCOUNT_UID)) != 0) {
+                r = getpeercred(fd, &ucred);
+                if (r < 0)
+                        return varlink_server_log_errno(server, r, "Failed to acquire peer credentials of incoming socket, refusing: %m");
+
+                ucred_acquired = true;
+
+                r = validate_connection(server, &ucred);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -EPERM;
+        } else
+                ucred_acquired = false;
+
+        r = varlink_new(&v);
+        if (r < 0)
+                return varlink_server_log_errno(server, r, "Failed to allocate connection object: %m");
+
+        r = count_connection(server, &ucred);
+        if (r < 0)
+                return r;
+
+        v->fd = fd;
+        v->userdata = server->userdata;
+        if (ucred_acquired) {
+                v->ucred = ucred;
+                v->ucred_acquired = true;
+        }
+
+        (void) asprintf(&v->description, "%s-%i", server->description ?: "varlink", v->fd);
+
+        /* Link up the server and the connection, and take reference in both directions. Note that the
+         * reference on the connection is left dangling. It will be dropped when the connection is closed,
+         * which happens in varlink_close(), including in the event loop quit callback. */
+        v->server = varlink_server_ref(server);
+        varlink_ref(v);
+
+        varlink_set_state(v, VARLINK_IDLE_SERVER);
+
+        r = varlink_attach_event(v, server->event, server->event_priority);
+        if (r < 0) {
+                varlink_log_errno(v, r, "Failed to attach new connection: %m");
+                v->fd = -1; /* take the fd out of the connection again */
+                varlink_close(v);
+                return r;
+        }
+
+        if (ret)
+                *ret = v;
+
+        return 0;
+}
+
+static int connect_callback(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        VarlinkServerSocket *ss = userdata;
+        _cleanup_close_ int cfd = -1;
+        Varlink *v = NULL;
+        int r;
+
+        assert(source);
+        assert(ss);
+
+        varlink_server_log(ss->server, "New incoming connection.");
+
+        cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+        if (cfd < 0) {
+                if (ERRNO_IS_ACCEPT_AGAIN(errno))
+                        return 0;
+
+                return varlink_server_log_errno(ss->server, errno, "Failed to accept incoming socket: %m");
+        }
+
+        r = varlink_server_add_connection(ss->server, cfd, &v);
+        if (r < 0)
+                return 0;
+
+        TAKE_FD(cfd);
+
+        if (ss->server->connect_callback) {
+                r = ss->server->connect_callback(ss->server, v, ss->server->userdata);
+                if (r < 0) {
+                        varlink_log_errno(v, r, "Connection callback returned error, disconnecting client: %m");
+                        varlink_close(v);
+                        return 0;
+                }
+        }
+
+        return 0;
+}
+
+int varlink_server_listen_fd(VarlinkServer *s, int fd) {
+        _cleanup_free_ VarlinkServerSocket *ss = NULL;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+
+        r = fd_nonblock(fd, true);
+        if (r < 0)
+                return r;
+
+        ss = new(VarlinkServerSocket, 1);
+        if (!ss)
+                return -ENOMEM;
+
+        *ss = (VarlinkServerSocket) {
+                .server = s,
+                .fd = fd,
+        };
+
+        if (s->event) {
+                _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
+
+                r = sd_event_add_io(s->event, &es, fd, EPOLLIN, connect_callback, ss);
+                if (r < 0)
+                        return r;
+
+                r = sd_event_source_set_priority(ss->event_source, s->event_priority);
+                if (r < 0)
+                        return r;
+        }
+
+        LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
+        return 0;
+}
+
+int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t m) {
+        union sockaddr_union sockaddr;
+        _cleanup_close_ int fd = -1;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(address, -EINVAL);
+        assert_return((m & ~0777) == 0, -EINVAL);
+
+        r = sockaddr_un_set_path(&sockaddr.un, address);
+        if (r < 0)
+                return r;
+
+        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0)
+                return -errno;
+
+        (void) sockaddr_un_unlink(&sockaddr.un);
+
+        RUN_WITH_UMASK(~m & 0777)
+                if (bind(fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0)
+                        return -errno;
+
+        if (listen(fd, SOMAXCONN) < 0)
+                return -errno;
+
+        r = varlink_server_listen_fd(s, fd);
+        if (r < 0)
+                return r;
+
+        TAKE_FD(fd);
+        return 0;
+}
+
+void* varlink_server_set_userdata(VarlinkServer *s, void *userdata) {
+        void *ret;
+
+        assert_return(s, NULL);
+
+        ret = s->userdata;
+        s->userdata = userdata;
+
+        return ret;
+}
+
+void* varlink_server_get_userdata(VarlinkServer *s) {
+        assert_return(s, NULL);
+
+        return s->userdata;
+}
+
+static VarlinkServerSocket* varlink_server_socket_destroy(VarlinkServerSocket *ss) {
+        if (!ss)
+                return NULL;
+
+        if (ss->server)
+                LIST_REMOVE(sockets, ss->server->sockets, ss);
+
+        sd_event_source_disable_unref(ss->event_source);
+
+        free(ss->address);
+        safe_close(ss->fd);
+
+        return mfree(ss);
+}
+
+int varlink_server_shutdown(VarlinkServer *s) {
+        assert_return(s, -EINVAL);
+
+        while (s->sockets)
+                varlink_server_socket_destroy(s->sockets);
+
+        return 0;
+}
+
+int varlink_server_attach_event(VarlinkServer *s, sd_event *e, int64_t priority) {
+        VarlinkServerSocket *ss;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(!s->event, -EBUSY);
+
+        if (e)
+                s->event = sd_event_ref(e);
+        else {
+                r = sd_event_default(&s->event);
+                if (r < 0)
+                        return r;
+        }
+
+        LIST_FOREACH(sockets, ss, s->sockets) {
+                assert(!ss->event_source);
+
+                r = sd_event_add_io(s->event, &ss->event_source, ss->fd, EPOLLIN, connect_callback, ss);
+                if (r < 0)
+                        goto fail;
+
+                r = sd_event_source_set_priority(ss->event_source, priority);
+                if (r < 0)
+                        goto fail;
+        }
+
+        s->event_priority = priority;
+        return 0;
+
+fail:
+        varlink_server_detach_event(s);
+        return r;
+}
+
+int varlink_server_detach_event(VarlinkServer *s) {
+        VarlinkServerSocket *ss;
+
+        assert_return(s, -EINVAL);
+
+        LIST_FOREACH(sockets, ss, s->sockets) {
+
+                if (!ss->event_source)
+                        continue;
+
+                (void) sd_event_source_set_enabled(ss->event_source, SD_EVENT_OFF);
+                ss->event_source = sd_event_source_unref(ss->event_source);
+        }
+
+        sd_event_unref(s->event);
+        return 0;
+}
+
+sd_event *varlink_server_get_event(VarlinkServer *s) {
+        assert_return(s, NULL);
+
+        return s->event;
+}
+
+int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback) {
+        char *m;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(method, -EINVAL);
+        assert_return(callback, -EINVAL);
+
+        if (startswith(method, "org.varlink.service."))
+                return -EEXIST;
+
+        r = hashmap_ensure_allocated(&s->methods, &string_hash_ops);
+        if (r < 0)
+                return r;
+
+        m = strdup(method);
+        if (!m)
+                return -ENOMEM;
+
+        r = hashmap_put(s->methods, m, callback);
+        if (r < 0) {
+                free(m);
+                return r;
+        }
+
+        return 0;
+}
+
+int varlink_server_bind_method_many_internal(VarlinkServer *s, ...) {
+        va_list ap;
+        int r;
+
+        assert_return(s, -EINVAL);
+
+        va_start(ap, s);
+        for (;;) {
+                VarlinkMethod callback;
+                const char *method;
+
+                method = va_arg(ap, const char *);
+                if (!method)
+                        break;
+
+                callback = va_arg(ap, VarlinkMethod);
+
+                r = varlink_server_bind_method(s, method, callback);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect callback) {
+        assert_return(s, -EINVAL);
+
+        if (callback && s->connect_callback && callback != s->connect_callback)
+                return -EBUSY;
+
+        s->connect_callback = callback;
+        return 0;
+}
+
+unsigned varlink_server_connections_max(VarlinkServer *s) {
+        struct rlimit rl;
+
+        /* If a server is specified, return the setting for that server, otherwise the default value */
+        if (s)
+                return s->connections_max;
+
+        assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+
+        /* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
+        if (VARLINK_DEFAULT_CONNECTIONS_MAX > rl.rlim_cur / 4 * 3)
+                return rl.rlim_cur / 4 * 3;
+
+        return VARLINK_DEFAULT_CONNECTIONS_MAX;
+}
+
+unsigned varlink_server_connections_per_uid_max(VarlinkServer *s) {
+        unsigned m;
+
+        if (s)
+                return s->connections_per_uid_max;
+
+        /* Make sure to never use up more than ¾th of available connections for a single user */
+        m = varlink_server_connections_max(NULL);
+        if (VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX > m)
+                return m / 4 * 3;
+
+        return VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX;
+}
+
+int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m) {
+        assert_return(s, -EINVAL);
+        assert_return(m > 0, -EINVAL);
+
+        s->connections_per_uid_max = m;
+        return 0;
+}
+
+int varlink_server_set_connections_max(VarlinkServer *s, unsigned m) {
+        assert_return(s, -EINVAL);
+        assert_return(m > 0, -EINVAL);
+
+        s->connections_max = m;
+        return 0;
+}
+
+int varlink_server_set_description(VarlinkServer *s, const char *description) {
+        assert_return(s, -EINVAL);
+
+        return free_and_strdup(&s->description, description);
+}
diff --git a/src/shared/varlink.h b/src/shared/varlink.h
new file mode 100644 (file)
index 0000000..d96fa93
--- /dev/null
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-event.h"
+
+#include "json.h"
+#include "time-util.h"
+
+/* A minimal Varlink implementation. We only implement the minimal, obvious bits here though. No validation,
+ * no introspection, no name service, just the stuff actually needed.
+ *
+ * You might wonder why we aren't using libvarlink here? Varlink is a very simple protocol, which allows us
+ * to write our own implementation relatively easily. However, the main reasons are these:
+ *
+ * • We want to use our own JSON subsystem, with all the benefits that brings (i.e. accurate unsigned+signed
+ *   64bit integers, full fuzzing, logging during parsing and so on). If we'd want to use that with
+ *   libvarlink we'd have to serialize and deserialize all the time from its own representation which is
+ *   inefficient and nasty.
+ *
+ * • We want integration into sd-event, but also synchronous event-loop-less operation
+ *
+ * • We need proper per-UID accounting and access control, since we want to allow communication between
+ *   unprivileged clients and privileged servers.
+ *
+ * • And of course, we don't want the name service and introspection stuff for now (though that might
+ *   change).
+ */
+
+typedef struct Varlink Varlink;
+typedef struct VarlinkServer VarlinkServer;
+
+typedef enum VarlinkReplyFlags {
+        VARLINK_REPLY_ERROR     = 1 << 0,
+        VARLINK_REPLY_CONTINUES = 1 << 1,
+        VARLINK_REPLY_LOCAL     = 1 << 2,
+} VarlinkReplyFlags;
+
+typedef enum VarlinkMethodFlags {
+        VARLINK_METHOD_ONEWAY = 1 << 0,
+        VARLINK_METHOD_MORE   = 2 << 1,
+} VarlinkMethodFlags;
+
+typedef enum VarlinkServerFlags {
+        VARLINK_SERVER_ROOT_ONLY   = 1 << 0, /* Only accessible by root */
+        VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
+        VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
+
+        _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1,
+} VarlinkServerFlags;
+
+typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
+typedef int (*VarlinkReply)(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata);
+typedef int (*VarlinkConnect)(VarlinkServer *server, Varlink *link, void *userdata);
+
+int varlink_connect_address(Varlink **ret, const char *address);
+int varlink_connect_fd(Varlink **ret, int fd);
+
+Varlink* varlink_ref(Varlink *link);
+Varlink* varlink_unref(Varlink *v);
+
+int varlink_get_fd(Varlink *v);
+int varlink_get_events(Varlink *v);
+int varlink_get_timeout(Varlink *v, usec_t *ret);
+
+int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority);
+void varlink_detach_event(Varlink *v);
+sd_event *varlink_get_event(Varlink *v);
+
+int varlink_process(Varlink *v);
+int varlink_wait(Varlink *v, usec_t timeout);
+
+int varlink_flush(Varlink *v);
+int varlink_close(Varlink *v);
+
+Varlink* varlink_flush_close_unref(Varlink *v);
+
+/* Enqueue method call, not expecting a reply */
+int varlink_send(Varlink *v, const char *method, JsonVariant *parameters);
+int varlink_sendb(Varlink *v, const char *method, ...);
+
+/* Send method call and wait for reply */
+int varlink_call(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags);
+int varlink_callb(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags, ...);
+
+/* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */
+int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters);
+int varlink_invokeb(Varlink *v, const char *method, ...);
+
+/* Enqueue a final reply */
+int varlink_reply(Varlink *v, JsonVariant *parameters);
+int varlink_replyb(Varlink *v, ...);
+
+/* Enqueue a (final) error */
+int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters);
+int varlink_errorb(Varlink *v, const char *error_id, ...);
+int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters);
+
+/* Enqueue a "more" reply */
+int varlink_notify(Varlink *v, JsonVariant *parameters);
+int varlink_notifyb(Varlink *v, ...);
+
+/* Bind a disconnect, reply or timeout callback */
+int varlink_bind_reply(Varlink *v, VarlinkReply reply);
+
+void* varlink_set_userdata(Varlink *v, void *userdata);
+void* varlink_get_userdata(Varlink *v);
+
+int varlink_get_peer_uid(Varlink *v, uid_t *ret);
+int varlink_get_peer_pid(Varlink *v, pid_t *ret);
+
+int varlink_set_relative_timeout(Varlink *v, usec_t usec);
+
+VarlinkServer* varlink_get_server(Varlink *v);
+
+int varlink_set_description(Varlink *v, const char *d);
+
+/* Create a varlink server */
+int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags);
+VarlinkServer *varlink_server_ref(VarlinkServer *s);
+VarlinkServer *varlink_server_unref(VarlinkServer *s);
+
+/* Add addresses or fds to listen on */
+int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t mode);
+int varlink_server_listen_fd(VarlinkServer *s, int fd);
+int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
+
+/* Bind callbacks */
+int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);
+int varlink_server_bind_method_many_internal(VarlinkServer *s, ...);
+#define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
+int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect);
+
+void* varlink_server_set_userdata(VarlinkServer *s, void *userdata);
+void* varlink_server_get_userdata(VarlinkServer *s);
+
+int varlink_server_attach_event(VarlinkServer *v, sd_event *e, int64_t priority);
+int varlink_server_detach_event(VarlinkServer *v);
+sd_event *varlink_server_get_event(VarlinkServer *v);
+
+int varlink_server_shutdown(VarlinkServer *server);
+
+unsigned varlink_server_connections_max(VarlinkServer *s);
+unsigned varlink_server_connections_per_uid_max(VarlinkServer *s);
+
+int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m);
+int varlink_server_set_connections_max(VarlinkServer *s, unsigned m);
+
+int varlink_server_set_description(VarlinkServer *s, const char *description);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref);
+
+#define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
+#define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
+#define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
+#define VARLINK_ERROR_SYSTEM "io.systemd.System"
+
+#define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
+#define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
+#define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
+#define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
index 35b2c2aa463bb62b18de938d3e0679c6245719dd..9623fe9ea29f3cf06b57ab357507c19c9e101988 100644 (file)
@@ -212,7 +212,7 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
 }
 
 static void sync_with_progress(void) {
-        unsigned long long dirty = ULONG_LONG_MAX;
+        unsigned long long dirty = ULLONG_MAX;
         unsigned checks;
         pid_t pid;
         int r;
index e30b475c75d5cea783256ec13a9dbd75ce152954..c75be39fefc88c9a0fcf61452107e179b12630e2 100644 (file)
@@ -55,18 +55,13 @@ void mount_points_list_free(MountPoint **head) {
 }
 
 int mount_points_list_get(const char *mountinfo, MountPoint **head) {
-        _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
-        _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
+        _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
         int r;
 
         assert(head);
 
-        t = mnt_new_table();
-        i = mnt_new_iter(MNT_ITER_FORWARD);
-        if (!t || !i)
-                return log_oom();
-
-        r = mnt_table_parse_mtab(t, mountinfo);
+        r = libmount_parse(mountinfo, NULL, &table, &iter);
         if (r < 0)
                 return log_error_errno(r, "Failed to parse %s: %m", mountinfo);
 
@@ -79,7 +74,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
                 bool try_remount_ro;
                 _cleanup_free_ MountPoint *m = NULL;
 
-                r = mnt_table_next_fs(t, i, &fs);
+                r = mnt_table_next_fs(table, iter, &fs);
                 if (r == 1)
                         break;
                 if (r < 0)
index 11aabaf923d2391d284cfe9460bb92d1ab0ec2e6..ed570deaee09ba0f097eb8e42ce939151fecbf69 100644 (file)
@@ -50,7 +50,7 @@ static int write_hibernate_location_info(void) {
         if (streq(type, "partition")) {
                 r = write_string_file("/sys/power/resume", device, WRITE_STRING_FILE_DISABLE_BUFFER);
                 if (r < 0)
-                        return log_debug_errno(r, "Faileed to write partitoin device to /sys/power/resume: %m");
+                        return log_debug_errno(r, "Failed to write partition device to /sys/power/resume: %m");
 
                 return r;
         }
index bd0d429df60d657dd09597429919f083799c076f..ab62368e9cee0cee1e0d55a0f0e856259b2165ef 100644 (file)
@@ -38,6 +38,7 @@ enum {
         SD_DHCP_CLIENT_EVENT_IP_CHANGE          = 2,
         SD_DHCP_CLIENT_EVENT_EXPIRED            = 3,
         SD_DHCP_CLIENT_EVENT_RENEW              = 4,
+        SD_DHCP_CLIENT_EVENT_SELECTING          = 5,
 };
 
 enum {
@@ -98,7 +99,7 @@ enum {
 
 typedef struct sd_dhcp_client sd_dhcp_client;
 
-typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
+typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
 int sd_dhcp_client_set_callback(
                 sd_dhcp_client *client,
                 sd_dhcp_client_callback_t cb,
@@ -154,6 +155,9 @@ int sd_dhcp_client_get_client_id(
 int sd_dhcp_client_set_mtu(
                 sd_dhcp_client *client,
                 uint32_t mtu);
+int sd_dhcp_client_set_max_attempts(
+                sd_dhcp_client *client,
+                uint64_t attempt);
 int sd_dhcp_client_set_client_port(
                 sd_dhcp_client *client,
                 uint16_t port);
@@ -172,6 +176,7 @@ int sd_dhcp_client_get_lease(
 
 int sd_dhcp_client_stop(sd_dhcp_client *client);
 int sd_dhcp_client_start(sd_dhcp_client *client);
+int sd_dhcp_client_send_release(sd_dhcp_client *client);
 
 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
index 7bb8609376c43e6f42d6b1c1bcb2050ac0ff4a26..b14c92697b44803ad2d26d0409ff849de0d71684 100644 (file)
@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret);
 
 sd_event_source* sd_event_source_ref(sd_event_source *s);
 sd_event_source* sd_event_source_unref(sd_event_source *s);
+sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
 
 sd_event *sd_event_source_get_event(sd_event_source *s);
 void* sd_event_source_get_userdata(sd_event_source *s);
@@ -149,6 +150,7 @@ int sd_event_source_set_floating(sd_event_source *s, int b);
 /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref);
 
 _SD_END_DECLARATIONS;
 
index d327b27308b68d56e139cf619ce698f7ccf9f4df..d27e0ad2019cb9b5016404ab1e24d3c360777e3b 100644 (file)
 ***/
 
 #include <inttypes.h>
-#include <linux/neighbour.h>
-#include <linux/rtnetlink.h>
 #include <net/ethernet.h>
 #include <netinet/ether.h>
 #include <netinet/in.h>
+#include <linux/neighbour.h>
+#include <linux/rtnetlink.h>
 
 #include "sd-event.h"
 
index e58e1cc73d3f90729f0b1ae7e7f8d1bcfb8eebcc..ee6cdb6d54b1ce83b74ce302da3e3f5647ffec04 100644 (file)
@@ -269,6 +269,10 @@ tests += [
          [],
          []],
 
+        [['src/test/test-umask-util.c'],
+         [],
+         []],
+
         [['src/test/test-proc-cmdline.c'],
          [],
          []],
@@ -591,6 +595,10 @@ tests += [
           libmount,
           libblkid]],
 
+        [['src/test/test-varlink.c'],
+         [],
+         [threads]],
+
         [['src/test/test-cgroup-util.c'],
          [],
          []],
@@ -983,7 +991,10 @@ tests += [
 
 ]
 
-if cxx_cmd != ''
+# test-bus-vtable-cc.cc is a symlink and symlinks get lost in containers on FuzzBuzz.
+# The issue has been reported to the developers of FuzzBuzz and hopefully will be fixed soon.
+# In the meantime, let's just skip the symlink there.
+if cxx_cmd != '' and not want_fuzzbuzz
         tests += [
                 [['src/libsystemd/sd-bus/test-bus-vtable-cc.cc'],
                  [],
index ad10eb178a494b7852a60e7c61cadda18ba09e07..e6b6d96d5a91b393ba4b2e2de80535d0e76b542e 100644 (file)
@@ -1,10 +1,12 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <malloc.h>
 #include <stdint.h>
 
 #include "alloc-util.h"
 #include "macro.h"
 #include "memory-util.h"
+#include "tests.h"
 
 static void test_alloca(void) {
         static const uint8_t zero[997] = { };
@@ -21,21 +23,35 @@ static void test_alloca(void) {
 
 static void test_GREEDY_REALLOC(void) {
         _cleanup_free_ int *a = NULL, *b = NULL;
-        size_t n_allocated = 0, i;
+        size_t n_allocated = 0, i, j;
 
-        /* Give valgrind a chance to verify our realloc operations */
+        /* Give valgrind a chance to verify our realloc() operations */
 
-        for (i = 0; i < 2048; i++) {
+        for (i = 0; i < 20480; i++) {
                 assert_se(GREEDY_REALLOC(a, n_allocated, i + 1));
-                a[i] = i;
+                assert_se(n_allocated >= i + 1);
+                assert_se(malloc_usable_size(a) >= (i + 1) * sizeof(int));
+                a[i] = (int) i;
                 assert_se(GREEDY_REALLOC(a, n_allocated, i / 2));
+                assert_se(n_allocated >= i / 2);
+                assert_se(malloc_usable_size(a) >= (i / 2) * sizeof(int));
         }
 
-        for (i = 30, n_allocated = 0; i < 2048; i+=7) {
+        for (j = 0; j < i / 2; j++)
+                assert_se(a[j] == (int) j);
+
+        for (i = 30, n_allocated = 0; i < 20480; i += 7) {
                 assert_se(GREEDY_REALLOC(b, n_allocated, i + 1));
-                b[i] = i;
+                assert_se(n_allocated >= i + 1);
+                assert_se(malloc_usable_size(b) >= (i + 1) * sizeof(int));
+                b[i] = (int) i;
                 assert_se(GREEDY_REALLOC(b, n_allocated, i / 2));
+                assert_se(n_allocated >= i / 2);
+                assert_se(malloc_usable_size(b) >= (i / 2) * sizeof(int));
         }
+
+        for (j = 30; j < i / 2; j += 7)
+                assert_se(b[j] == (int) j);
 }
 
 static void test_memdup_multiply_and_greedy_realloc(void) {
@@ -91,11 +107,39 @@ static void test_bool_assign(void) {
         assert(!h);
 }
 
+static int cleanup_counter = 0;
+
+static void cleanup1(void *a) {
+        log_info("%s(%p)", __func__, a);
+        assert_se(++cleanup_counter == *(int*) a);
+}
+static void cleanup2(void *a) {
+        log_info("%s(%p)", __func__, a);
+        assert_se(++cleanup_counter == *(int*) a);
+}
+static void cleanup3(void *a) {
+        log_info("%s(%p)", __func__, a);
+        assert_se(++cleanup_counter == *(int*) a);
+}
+
+static void test_cleanup_order(void) {
+        _cleanup_(cleanup1) int x1 = 4, x2 = 3;
+        _cleanup_(cleanup3) int z = 2;
+        _cleanup_(cleanup2) int y = 1;
+        log_debug("x1: %p", &x1);
+        log_debug("x2: %p", &x2);
+        log_debug("y: %p", &y);
+        log_debug("z: %p", &z);
+}
+
 int main(int argc, char *argv[]) {
+        test_setup_logging(LOG_DEBUG);
+
         test_alloca();
         test_GREEDY_REALLOC();
         test_memdup_multiply_and_greedy_realloc();
         test_bool_assign();
+        test_cleanup_order();
 
         return 0;
 }
index 6b2de66bb7ff7f7b103098bb136914272420b079..f9fae84ddeacb14c97883dc875f5163b660dff43 100644 (file)
@@ -99,7 +99,7 @@ static int setup_tests(bool *run_ambient) {
 
         nobody = getpwnam(NOBODY_USER_NAME);
         if (!nobody)
-                return log_error_errno(errno, "Could not find nobody user: %m");
+                return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Could not find nobody user: %m");
 
         test_uid = nobody->pw_uid;
         test_gid = nobody->pw_gid;
index 7f6c0c27722195cdead667ee13005fd13bc764b2..72a6551ffd8fd42aef4615a85364dab3bfd01a8d 100644 (file)
@@ -59,7 +59,6 @@ static int test_cgroup_mask(void) {
                 m->default_tasks_accounting = false;
         m->default_tasks_max = (uint64_t) -1;
 
-        assert_se(r >= 0);
         assert_se(manager_startup(m, NULL, NULL) >= 0);
 
         /* Load units and verify hierarchy. */
index 7372f97a1c6fcdc56580c45459a02b4e3fde90a9..4fb629217f4e9eb1a1b931620e909130025deee2 100644 (file)
@@ -39,7 +39,7 @@ static int test_default_memory_low(void) {
          * 1. dml-passthrough.slice sets MemoryLow=100. This should not affect its children, as only
          *    DefaultMemoryLow is propagated, not MemoryLow. As such, all leaf services should end up with
          *    memory.low as 50, inherited from dml.slice, *except* for dml-passthrough-set-ml.service, which
-         *    should have the value of 25, as it has MemoryLow explicitly set.
+         *    should have the value of 0, as it has MemoryLow explicitly set.
          *
          *                                                  ┌───────────┐
          *                                                  │ dml.slice │
@@ -49,7 +49,7 @@ static int test_default_memory_low(void) {
          *                                            │ dml-passthrough.slice │
          *                                            └───────────┬───────────┘
          *                    ┌───────────────────────────────────┼───────────────────────────────────┐
-         *             no new settings                   DefaultMemoryLow=15                     MemoryLow=25
+         *             no new settings                   DefaultMemoryLow=15                     MemoryLow=0
          *    ┌───────────────┴───────────────┐  ┌────────────────┴────────────────┐  ┌───────────────┴────────────────┐
          *    │ dml-passthrough-empty.service │  │ dml-passthrough-set-dml.service │  │ dml-passthrough-set-ml.service │
          *    └───────────────────────────────┘  └─────────────────────────────────┘  └────────────────────────────────┘
@@ -122,7 +122,7 @@ static int test_default_memory_low(void) {
         assert_se(unit_get_ancestor_memory_low(dml_passthrough) == 100);
         assert_se(unit_get_ancestor_memory_low(dml_passthrough_empty) == dml_tree_default);
         assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_dml) == 50);
-        assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 25);
+        assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 0);
 
         assert_se(unit_get_ancestor_memory_low(dml_override) == dml_tree_default);
         assert_se(unit_get_ancestor_memory_low(dml_override_empty) == 10);
index 4ee4aa974d73272dcc845ccd62b7e7ae54cf6ad2..add17f9547dc6b803143d4cef265f1a8f54167a2 100644 (file)
@@ -6,10 +6,45 @@
 #include "tests.h"
 
 static void test_cescape(void) {
-        _cleanup_free_ char *escaped;
+        _cleanup_free_ char *t;
 
-        assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
-        assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+        assert_se(t = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
+        assert_se(streq(t, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+}
+
+static void test_xescape(void) {
+        _cleanup_free_ char *t;
+
+        assert_se(t = xescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", ""));
+        assert_se(streq(t, "abc\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb"));
+}
+
+static void test_xescape_full(bool eight_bits) {
+        const char* escaped = !eight_bits ?
+                "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb" :
+                "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\177\234\313";
+        const unsigned full_fit = !eight_bits ? 55 : 46;
+
+        for (unsigned i = 0; i < 60; i++) {
+                _cleanup_free_ char *t;
+
+                assert_se(t = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i, eight_bits));
+
+                log_info("%02d: %s", i, t);
+
+                if (i >= full_fit)
+                        assert_se(streq(t, escaped));
+                else if (i >= 3) {
+                        /* We need up to four columns, so up to three three columns may be wasted */
+                        assert_se(strlen(t) == i || strlen(t) == i - 1 || strlen(t) == i - 2 || strlen(t) == i - 3);
+                        assert_se(strneq(t, escaped, i - 3) || strneq(t, escaped, i - 4) ||
+                                  strneq(t, escaped, i - 5) || strneq(t, escaped, i - 6));
+                        assert_se(endswith(t, "..."));
+                } else {
+                        assert_se(strlen(t) == i);
+                        assert_se(strneq(t, "...", i));
+                }
+        }
 }
 
 static void test_cunescape(void) {
@@ -123,6 +158,9 @@ int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
         test_cescape();
+        test_xescape();
+        test_xescape_full(false);
+        test_xescape_full(true);
         test_cunescape();
         test_shell_escape();
         test_shell_maybe_quote();
index 9f1cb0ca38945e1a5fcaba2ab20f98a64e7d1441..7f8ea2be986209ea44a2b5c4ef1b1be93dfa3a06 100644 (file)
@@ -33,6 +33,12 @@ static bool can_unshare;
 
 typedef void (*test_function_t)(Manager *m);
 
+static int cld_dumped_to_killed(int code) {
+        /* Depending on the system, seccomp version, … some signals might result in dumping, others in plain
+         * killing. Let's ignore the difference here, and map both cases to CLD_KILLED */
+        return code == CLD_DUMPED ? CLD_KILLED : code;
+}
+
 static void check(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
         Service *service = NULL;
         usec_t ts;
@@ -62,16 +68,18 @@ static void check(const char *func, Manager *m, Unit *unit, int status_expected,
                 }
         }
         exec_status_dump(&service->main_exec_status, stdout, "\t");
-        if (service->main_exec_status.status != status_expected) {
-                log_error("%s: %s: exit status %d, expected %d",
+
+        if (cld_dumped_to_killed(service->main_exec_status.code) != cld_dumped_to_killed(code_expected)) {
+                log_error("%s: %s: exit code %d, expected %d",
                           func, unit->id,
-                          service->main_exec_status.status, status_expected);
+                          service->main_exec_status.code, code_expected);
                 abort();
         }
-        if (service->main_exec_status.code != code_expected) {
-                log_error("%s: %s: exit code %d, expected %d",
+
+        if (service->main_exec_status.status != status_expected) {
+                log_error("%s: %s: exit status %d, expected %d",
                           func, unit->id,
-                          service->main_exec_status.code, code_expected);
+                          service->main_exec_status.status, status_expected);
                 abort();
         }
 }
index fc28f27d53e6110500c533010c847a9e1926cbb1..c3395493d460b038c2f25996331a9be8384f97dc 100644 (file)
@@ -21,13 +21,10 @@ static void test_libmount_unescaping_one(
         _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
         _cleanup_fclose_ FILE *f = NULL;
 
-        assert_se(table = mnt_new_table());
-        assert_se(iter = mnt_new_iter(MNT_ITER_FORWARD));
-
         f = fmemopen((char*) string, strlen(string), "re");
         assert_se(f);
 
-        assert_se(mnt_table_parse_stream(table, f, title) >= 0);
+        assert_se(libmount_parse(title, f, &table, &iter) >= 0);
 
         struct libmnt_fs *fs;
         const char *source, *target;
index f634ca28dbdf29e49c899390e3ad849024bbe036..7878512465ed0650d4ddb94bece7e50657d29563 100644 (file)
@@ -158,7 +158,7 @@ static int enumerate_print_list(struct udev_enumerate *enumerate) {
 
                 device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
                                                       udev_list_entry_get_name(list_entry));
-                if (device != NULL) {
+                if (device) {
                         log_info("device: '%s' (%s)",
                                  udev_device_get_syspath(device),
                                  udev_device_get_subsystem(device));
@@ -249,7 +249,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
         udev_enumerate_scan_devices(udev_enumerate);
@@ -258,7 +258,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate 'net' + duplicated scan + null + zero");
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_add_match_subsystem(udev_enumerate, "net");
         udev_enumerate_scan_devices(udev_enumerate);
@@ -278,7 +278,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate 'block'");
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_add_match_subsystem(udev_enumerate,"block");
         r = udev_enumerate_add_match_is_initialized(udev_enumerate);
@@ -292,7 +292,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate 'not block'");
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block");
         udev_enumerate_scan_devices(udev_enumerate);
@@ -301,7 +301,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate 'pci, mem, vc'");
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_add_match_subsystem(udev_enumerate, "pci");
         udev_enumerate_add_match_subsystem(udev_enumerate, "mem");
@@ -312,7 +312,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate 'subsystem'");
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_scan_subsystems(udev_enumerate);
         enumerate_print_list(udev_enumerate);
@@ -320,7 +320,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
 
         log_info("enumerate 'property IF_FS_*=filesystem'");
         udev_enumerate = udev_enumerate_new(udev);
-        if (udev_enumerate == NULL)
+        if (!udev_enumerate)
                 return -1;
         udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem");
         udev_enumerate_scan_devices(udev_enumerate);
index d3dbb54ca175a7ce1073527211866df5ad1fbc60..e9233a16437e23268ec15d3a5e41ad30ee60acb0 100644 (file)
@@ -75,7 +75,8 @@ int main(int argc, char *argv[]) {
                             PROTECT_HOME_NO,
                             PROTECT_SYSTEM_NO,
                             0,
-                            0);
+                            0,
+                            NULL);
         if (r < 0) {
                 log_error_errno(r, "Failed to setup namespace: %m");
 
index 27afe36082f5a2660b78942fa0ac0a6c1ac85bb3..d0f989837866b7df170f1af597d4785f2d76db50 100644 (file)
@@ -88,7 +88,7 @@ static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
                 if (it->scopeid == 0)
                         goto numerical_index;
 
-                if (if_indextoname(it->scopeid, ifname) == NULL) {
+                if (!if_indextoname(it->scopeid, ifname)) {
                         log_warning_errno(errno, "if_indextoname(%d) failed: %m", it->scopeid);
                 numerical_index:
                         xsprintf(ifname, "%i", it->scopeid);
index 89f6618e2e85280bb1ea6a9ceb4eeae5e001fafc..9b644c09bbfc3236eebc00beb765a62b1348515a 100644 (file)
@@ -48,14 +48,14 @@ static void test_get_process_comm(pid_t pid) {
         } else
                 log_warning("%s not exist.", path);
 
-        assert_se(get_process_cmdline(pid, 0, true, &c) >= 0);
+        assert_se(get_process_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0);
         log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
 
-        assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
+        assert_se(get_process_cmdline(pid, 8, 0, &d) >= 0);
         log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
 
         free(d);
-        assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
+        assert_se(get_process_cmdline(pid, 1, 0, &d) >= 0);
         log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
 
         assert_se(get_process_ppid(pid, &e) >= 0);
@@ -107,12 +107,12 @@ static void test_get_process_comm_escape(void) {
         test_get_process_comm_escape_one("foo", "foo");
         test_get_process_comm_escape_one("012345678901234", "012345678901234");
         test_get_process_comm_escape_one("0123456789012345", "012345678901234");
-        test_get_process_comm_escape_one("äöüß", "\\303\\244\\303");
-        test_get_process_comm_escape_one("xäöüß", "x\\303\\244");
-        test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244");
-        test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244");
-        test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244");
-        test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303");
+        test_get_process_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237");
+        test_get_process_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237");
+        test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237");
+        test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237");
+        test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
+        test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
 
         assert_se(prctl(PR_SET_NAME, saved) >= 0);
 }
@@ -237,150 +237,149 @@ static void test_get_process_cmdline_harder(void) {
 
         assert_se(prctl(PR_SET_NAME, "testa") >= 0);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "[testa]"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        log_info("'%s'", line);
         assert_se(streq(line, ""));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
-        assert_se(streq(line, "["));
+        assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, ""));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
-        assert_se(streq(line, "[."));
+        assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "["));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
-        assert_se(streq(line, "[.."));
+        assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[t…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
-        assert_se(streq(line, "[..."));
+        assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[te…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
-        assert_se(streq(line, "[...]"));
+        assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[tes…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
-        assert_se(streq(line, "[t...]"));
+        assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[test…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "[testa]"));
         line = mfree(line);
 
-        assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
-
-        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
-
-        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "[testa]"));
         line = mfree(line);
 
-        assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
+        assert_se(write(fd, "foo\0bar", 8) == 8);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
+        log_info("'%s'", line);
         assert_se(streq(line, "foo bar"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "foo bar"));
         line = mfree(line);
 
         assert_se(write(fd, "quux", 4) == 4);
-        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
+        log_info("'%s'", line);
         assert_se(streq(line, "foo bar quux"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "foo bar quux"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
-        assert_se(streq(line, ""));
+        assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, ""));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
-        assert_se(streq(line, "."));
+        assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "f…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
-        assert_se(streq(line, ".."));
+        assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "fo…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
-        assert_se(streq(line, "..."));
+        assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
-        assert_se(streq(line, "f..."));
+        assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo …"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
-        assert_se(streq(line, "fo..."));
+        assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo b…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
-        assert_se(streq(line, "foo..."));
+        assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo ba…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
-        assert_se(streq(line, "foo..."));
+        assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo bar…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 9, true, &line) >= 0);
-        assert_se(streq(line, "foo b..."));
+        assert_se(get_process_cmdline(getpid_cached(), 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo bar …"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
-        assert_se(streq(line, "foo ba..."));
+        assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo bar q…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
-        assert_se(streq(line, "foo bar..."));
+        assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo bar qu…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
-        assert_se(streq(line, "foo bar..."));
+        assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "foo bar quux"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 13, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "foo bar quux"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 14, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "foo bar quux"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 1000, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "foo bar quux"));
         line = mfree(line);
 
         assert_se(ftruncate(fd, 0) >= 0);
         assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
 
-        assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
+        assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
         assert_se(streq(line, "[aaaa bbbb cccc]"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
-        assert_se(streq(line, "[aaaa...]"));
+        assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[aaaa bbb…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
-        assert_se(streq(line, "[aaaa...]"));
+        assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[aaaa bbbb…"));
         line = mfree(line);
 
-        assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
-        assert_se(streq(line, "[aaaa b...]"));
+        assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
+        assert_se(streq(line, "[aaaa bbbb …"));
         line = mfree(line);
 
         safe_close(fd);
@@ -408,8 +407,10 @@ static void test_rename_process_now(const char *p, int ret) {
         assert_se(get_process_comm(0, &comm) >= 0);
         log_info("comm = <%s>", comm);
         assert_se(strneq(comm, p, TASK_COMM_LEN-1));
+        /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the
+         * future. We'd only check the initial part, at least until we recompile, but this will still pass. */
 
-        r = get_process_cmdline(0, 0, false, &cmdline);
+        r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline);
         assert_se(r >= 0);
         /* we cannot expect cmdline to be renamed properly without privileges */
         if (geteuid() == 0) {
index 9b7307cf39308388b3c907f4958cf7a05bf257e8..a906070f9a9d45f7f3821572c25f9409215cdef0 100644 (file)
@@ -635,7 +635,7 @@ static void test_load_syscall_filter_set_raw(void) {
                 assert_se(access("/", F_OK) >= 0);
                 assert_se(poll(NULL, 0, 0) == 0);
 
-                assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL, true) >= 0);
+                assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0);
                 assert_se(access("/", F_OK) >= 0);
                 assert_se(poll(NULL, 0, 0) == 0);
 
index 96d92279fbfef4ebffaa34246be45b676d164e45..0e563f54970b8e5734d8d4eae4b703a1bd7bd553 100644 (file)
@@ -75,12 +75,45 @@ static void test_getttyname_malloc(void) {
         assert_se(PATH_IN_SET(ttyname, "ptmx", "pts/ptmx"));
 }
 
+static void test_one_color(const char *name, const char *color) {
+        printf("<%s%s%s>\n", color, name, ansi_normal());
+}
+
+static void test_colors(void) {
+        log_info("/* %s */", __func__);
+
+        test_one_color("normal", ansi_normal());
+        test_one_color("highlight", ansi_highlight());
+        test_one_color("red", ansi_red());
+        test_one_color("green", ansi_green());
+        test_one_color("yellow", ansi_yellow());
+        test_one_color("blue", ansi_blue());
+        test_one_color("megenta", ansi_magenta());
+        test_one_color("grey", ansi_grey());
+        test_one_color("highlight-red", ansi_highlight_red());
+        test_one_color("highlight-green", ansi_highlight_green());
+        test_one_color("highlight-yellow", ansi_highlight_yellow());
+        test_one_color("highlight-blue", ansi_highlight_blue());
+        test_one_color("highlight-magenta", ansi_highlight_magenta());
+        test_one_color("highlight-grey", ansi_highlight_grey());
+
+        test_one_color("underline", ansi_underline());
+        test_one_color("highlight-underline", ansi_highlight_underline());
+        test_one_color("highlight-red-underline", ansi_highlight_red_underline());
+        test_one_color("highlight-green-underline", ansi_highlight_green_underline());
+        test_one_color("highlight-yellow-underline", ansi_highlight_yellow_underline());
+        test_one_color("highlight-blue-underline", ansi_highlight_blue_underline());
+        test_one_color("highlight-magenta-underline", ansi_highlight_magenta_underline());
+        test_one_color("highlight-grey-underline", ansi_highlight_grey_underline());
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_INFO);
 
         test_default_term_for_tty();
         test_read_one_char();
         test_getttyname_malloc();
+        test_colors();
 
         return 0;
 }
diff --git a/src/test/test-umask-util.c b/src/test/test-umask-util.c
new file mode 100644 (file)
index 0000000..27f6b56
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "tests.h"
+#include "umask-util.h"
+
+int main(int argc, char *argv[]) {
+        size_t n;
+        mode_t u;
+
+        test_setup_logging(LOG_DEBUG);
+
+        u = umask(0111);
+
+        n = 0;
+        RUN_WITH_UMASK(0123) {
+                assert_se(umask(000) == 0123);
+                n++;
+        }
+
+        assert_se(n == 1);
+        assert_se(umask(u) == 0111);
+
+        RUN_WITH_UMASK(0135) {
+                assert_se(umask(000) == 0135);
+                n++;
+        }
+
+        assert_se(n == 2);
+        assert_se(umask(0111) == u);
+
+        RUN_WITH_UMASK(0315) {
+                assert_se(umask(000) == 0315);
+                n++;
+                break;
+        }
+
+        assert_se(n == 3);
+        assert_se(umask(u) == 0111);
+
+        return EXIT_SUCCESS;
+}
index d1e48da2a665d0a0a229da3963abb61461cfaedb..b5c4e3dc343c5714eb19b4bf844d7f12713b3848 100644 (file)
@@ -7,6 +7,8 @@
 #include "util.h"
 
 static void test_utf8_is_printable(void) {
+        log_info("/* %s */", __func__);
+
         assert_se(utf8_is_printable("ascii is valid\tunicode", 22));
         assert_se(utf8_is_printable("\342\204\242", 3));
         assert_se(!utf8_is_printable("\341\204", 2));
@@ -14,18 +16,24 @@ static void test_utf8_is_printable(void) {
 }
 
 static void test_utf8_is_valid(void) {
+        log_info("/* %s */", __func__);
+
         assert_se(utf8_is_valid("ascii is valid unicode"));
         assert_se(utf8_is_valid("\342\204\242"));
         assert_se(!utf8_is_valid("\341\204"));
 }
 
 static void test_ascii_is_valid(void) {
+        log_info("/* %s */", __func__);
+
         assert_se( ascii_is_valid("alsdjf\t\vbarr\nba z"));
         assert_se(!ascii_is_valid("\342\204\242"));
         assert_se(!ascii_is_valid("\341\204"));
 }
 
 static void test_ascii_is_valid_n(void) {
+        log_info("/* %s */", __func__);
+
         assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 17));
         assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 16));
         assert_se(!ascii_is_valid_n("alsdjf\t\vbarr\nba z", 18));
@@ -36,6 +44,8 @@ static void test_ascii_is_valid_n(void) {
 }
 
 static void test_utf8_encoded_valid_unichar(void) {
+        log_info("/* %s */", __func__);
+
         assert_se(utf8_encoded_valid_unichar("\342\204\242", 1) == -EINVAL); /* truncated */
         assert_se(utf8_encoded_valid_unichar("\342\204\242", 2) == -EINVAL); /* truncated */
         assert_se(utf8_encoded_valid_unichar("\342\204\242", 3) == 3);
@@ -53,9 +63,11 @@ static void test_utf8_encoded_valid_unichar(void) {
         assert_se(utf8_encoded_valid_unichar("\341\204\341\204", 5) == -EINVAL);
 }
 
-static void test_utf8_escaping(void) {
+static void test_utf8_escape_invalid(void) {
         _cleanup_free_ char *p1, *p2, *p3;
 
+        log_info("/* %s */", __func__);
+
         p1 = utf8_escape_invalid("goo goo goo");
         puts(p1);
         assert_se(utf8_is_valid(p1));
@@ -69,9 +81,11 @@ static void test_utf8_escaping(void) {
         assert_se(utf8_is_valid(p3));
 }
 
-static void test_utf8_escaping_printable(void) {
+static void test_utf8_escape_non_printable(void) {
         _cleanup_free_ char *p1, *p2, *p3, *p4, *p5, *p6;
 
+        log_info("/* %s */", __func__);
+
         p1 = utf8_escape_non_printable("goo goo goo");
         puts(p1);
         assert_se(utf8_is_valid(p1));
@@ -97,12 +111,45 @@ static void test_utf8_escaping_printable(void) {
         assert_se(utf8_is_valid(p6));
 }
 
+static void test_utf8_escape_non_printable_full(void) {
+        log_info("/* %s */", __func__);
+
+        for (size_t i = 0; i < 20; i++) {
+                _cleanup_free_ char *p;
+
+                p = utf8_escape_non_printable_full("goo goo goo", i);
+                puts(p);
+                assert_se(utf8_is_valid(p));
+                assert_se(utf8_console_width(p) <= i);
+        }
+
+        for (size_t i = 0; i < 20; i++) {
+                _cleanup_free_ char *p;
+
+                p = utf8_escape_non_printable_full("\001 \019\20\a", i);
+                puts(p);
+                assert_se(utf8_is_valid(p));
+                assert_se(utf8_console_width(p) <= i);
+        }
+
+        for (size_t i = 0; i < 20; i++) {
+                _cleanup_free_ char *p;
+
+                p = utf8_escape_non_printable_full("\xef\xbf\x30\x13", i);
+                puts(p);
+                assert_se(utf8_is_valid(p));
+                assert_se(utf8_console_width(p) <= i);
+        }
+}
+
 static void test_utf16_to_utf8(void) {
         const char16_t utf16[] = { htole16('a'), htole16(0xd800), htole16('b'), htole16(0xdc00), htole16('c'), htole16(0xd801), htole16(0xdc37) };
         static const char utf8[] = { 'a', 'b', 'c', 0xf0, 0x90, 0x90, 0xb7 };
         _cleanup_free_ char16_t *b = NULL;
         _cleanup_free_ char *a = NULL;
 
+        log_info("/* %s */", __func__);
+
         /* Convert UTF-16 to UTF-8, filtering embedded bad chars */
         a = utf16_to_utf8(utf16, sizeof(utf16));
         assert_se(a);
@@ -120,6 +167,8 @@ static void test_utf16_to_utf8(void) {
 }
 
 static void test_utf8_n_codepoints(void) {
+        log_info("/* %s */", __func__);
+
         assert_se(utf8_n_codepoints("abc") == 3);
         assert_se(utf8_n_codepoints("zażółcić gęślą jaźń") == 19);
         assert_se(utf8_n_codepoints("串") == 1);
@@ -129,6 +178,8 @@ static void test_utf8_n_codepoints(void) {
 }
 
 static void test_utf8_console_width(void) {
+        log_info("/* %s */", __func__);
+
         assert_se(utf8_console_width("abc") == 3);
         assert_se(utf8_console_width("zażółcić gęślą jaźń") == 19);
         assert_se(utf8_console_width("串") == 2);
@@ -140,6 +191,8 @@ static void test_utf8_console_width(void) {
 static void test_utf8_to_utf16(void) {
         const char *p;
 
+        log_info("/* %s */", __func__);
+
         FOREACH_STRING(p,
                        "abc",
                        "zażółcić gęślą jaźń",
@@ -165,8 +218,9 @@ int main(int argc, char *argv[]) {
         test_ascii_is_valid();
         test_ascii_is_valid_n();
         test_utf8_encoded_valid_unichar();
-        test_utf8_escaping();
-        test_utf8_escaping_printable();
+        test_utf8_escape_invalid();
+        test_utf8_escape_non_printable();
+        test_utf8_escape_non_printable_full();
         test_utf16_to_utf8();
         test_utf8_n_codepoints();
         test_utf8_console_width();
diff --git a/src/test/test-varlink.c b/src/test/test-varlink.c
new file mode 100644 (file)
index 0000000..fbfc72c
--- /dev/null
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "sd-event.h"
+
+#include "fd-util.h"
+#include "json.h"
+#include "rm-rf.h"
+#include "strv.h"
+#include "tmpfile-util.h"
+#include "user-util.h"
+#include "varlink.h"
+
+/* Let's pick some high value, that is higher than the largest listen() backlog, but leaves enough room below
+   the typical RLIMIT_NOFILE value of 1024 so that we can process both sides of each socket in our
+   process. Or in other words: "OVERLOAD_CONNECTIONS * 2 + x < 1024" should hold, for some small x that
+   should cover any auxiliary fds, the listener server fds, stdin/stdout/stderr and whatever else. */
+#define OVERLOAD_CONNECTIONS 333
+
+static int n_done = 0;
+static int block_write_fd = -1;
+
+static int method_something(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        _cleanup_(json_variant_unrefp) JsonVariant *ret = NULL;
+        JsonVariant *a, *b;
+        intmax_t x, y;
+        int r;
+
+        a = json_variant_by_key(parameters, "a");
+        if (!a)
+                return varlink_error(link, "io.test.BadParameters", NULL);
+
+        x = json_variant_integer(a);
+
+        b = json_variant_by_key(parameters, "b");
+        if (!b)
+                return varlink_error(link, "io.test.BadParameters", NULL);
+
+        y = json_variant_integer(b);
+
+        r = json_build(&ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("sum", JSON_BUILD_INTEGER(x + y))));
+        if (r < 0)
+                return r;
+
+        return varlink_reply(link, ret);
+}
+
+static int method_done(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+
+        if (++n_done == 2)
+                sd_event_exit(varlink_get_event(link), EXIT_FAILURE);
+
+        return 0;
+}
+
+static int reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+        JsonVariant *sum;
+
+        sum = json_variant_by_key(parameters, "sum");
+
+        assert_se(json_variant_integer(sum) == 7+22);
+
+        if (++n_done == 2)
+                sd_event_exit(varlink_get_event(link), EXIT_FAILURE);
+
+        return 0;
+}
+
+static int on_connect(VarlinkServer *s, Varlink *link, void *userdata) {
+        uid_t uid = UID_INVALID;
+
+        assert(s);
+        assert(link);
+
+        assert_se(varlink_get_peer_uid(link, &uid) >= 0);
+        assert_se(getuid() == uid);
+
+        return 0;
+}
+
+static int overload_reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+
+        /* This method call reply should always be called with a disconnection, since the method call should
+         * be talking to an overloaded server */
+
+        log_debug("Over reply triggered with error: %s", strna(error_id));
+        assert_se(streq(error_id, VARLINK_ERROR_DISCONNECTED));
+        sd_event_exit(varlink_get_event(link), 0);
+
+        return 0;
+}
+
+static void flood_test(const char *address) {
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        _cleanup_free_ Varlink **connections = NULL;
+        size_t k;
+        char x = 'x';
+
+        log_debug("Flooding server...");
+
+        /* Block the main event loop while we flood */
+        assert_se(write(block_write_fd, &x, sizeof(x)) == sizeof(x));
+
+        assert_se(sd_event_default(&e) >= 0);
+
+        /* Flood the server with connections */
+        assert_se(connections = new0(Varlink*, OVERLOAD_CONNECTIONS));
+        for (k = 0; k < OVERLOAD_CONNECTIONS; k++) {
+                _cleanup_free_ char *t = NULL;
+                log_debug("connection %zu", k);
+                assert_se(varlink_connect_address(connections + k, address) >= 0);
+
+                assert_se(asprintf(&t, "flood-%zu", k) >= 0);
+                assert_se(varlink_set_description(connections[k], t) >= 0);
+                assert_se(varlink_attach_event(connections[k], e, k) >= 0);
+                assert_se(varlink_sendb(connections[k], "io.test.Rubbish", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("id", JSON_BUILD_INTEGER(k)))) >= 0);
+        }
+
+        /* Then, create one more, which should fail */
+        log_debug("Creating overload connection...");
+        assert_se(varlink_connect_address(&c, address) >= 0);
+        assert_se(varlink_set_description(c, "overload-client") >= 0);
+        assert_se(varlink_attach_event(c, e, k) >= 0);
+        assert_se(varlink_bind_reply(c, overload_reply) >= 0);
+        assert_se(varlink_invokeb(c, "io.test.Overload", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("foo", JSON_BUILD_STRING("bar")))) >= 0);
+
+        /* Unblock it */
+        log_debug("Unblocking server...");
+        block_write_fd = safe_close(block_write_fd);
+
+        /* This loop will terminate as soon as the overload reply callback is called */
+        assert_se(sd_event_loop(e) >= 0);
+
+        /* And close all connections again */
+        for (k = 0; k < OVERLOAD_CONNECTIONS; k++)
+                connections[k] = varlink_unref(connections[k]);
+}
+
+static void *thread(void *arg) {
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *i = NULL;
+        JsonVariant *o = NULL;
+        const char *e;
+
+        assert_se(json_build(&i, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(88)),
+                                                   JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(99)))) >= 0);
+
+        assert_se(varlink_connect_address(&c, arg) >= 0);
+        assert_se(varlink_set_description(c, "thread-client") >= 0);
+
+        assert_se(varlink_call(c, "io.test.DoSomething", i, &o, &e, NULL) >= 0);
+        assert_se(json_variant_integer(json_variant_by_key(o, "sum")) == 88 + 99);
+        assert_se(!e);
+
+        assert_se(varlink_callb(c, "io.test.IDontExist", &o, &e, NULL, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_REAL(5.5)))) >= 0);
+        assert_se(streq_ptr(json_variant_string(json_variant_by_key(o, "method")), "io.test.IDontExist"));
+        assert_se(streq(e, VARLINK_ERROR_METHOD_NOT_FOUND));
+
+        flood_test(arg);
+
+        assert_se(varlink_send(c, "io.test.Done", NULL) >= 0);
+
+        return NULL;
+}
+
+static int block_fd_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        char c;
+
+        assert_se(fd_nonblock(fd, false) >= 0);
+
+        assert_se(read(fd, &c, sizeof(c)) == sizeof(c));
+        /* When a character is written to this pipe we'll block until the pipe is closed. */
+
+        assert_se(read(fd, &c, sizeof(c)) == 0);
+
+        assert_se(fd_nonblock(fd, true) >= 0);
+
+        assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
+
+        return 0;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *block_event = NULL;
+        _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        _cleanup_(close_pairp) int block_fds[2] = { -1, -1 };
+        pthread_t t;
+        const char *sp;
+
+        log_set_max_level(LOG_DEBUG);
+        log_open();
+
+        assert_se(mkdtemp_malloc("/tmp/varlink-test-XXXXXX", &tmpdir) >= 0);
+        sp = strjoina(tmpdir, "/socket");
+
+        assert_se(sd_event_default(&e) >= 0);
+
+        assert_se(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC) >= 0);
+        assert_se(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL) >= 0);
+        assert_se(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT) >= 0);
+        block_write_fd = TAKE_FD(block_fds[1]);
+
+        assert_se(varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID) >= 0);
+        assert_se(varlink_server_set_description(s, "our-server") >= 0);
+
+        assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
+        assert_se(varlink_server_bind_method(s, "io.test.Done", method_done) >= 0);
+        assert_se(varlink_server_bind_connect(s, on_connect) >= 0);
+        assert_se(varlink_server_listen_address(s, sp, 0600) >= 0);
+        assert_se(varlink_server_attach_event(s, e, 0) >= 0);
+        assert_se(varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS) >= 0);
+
+        assert_se(varlink_connect_address(&c, sp) >= 0);
+        assert_se(varlink_set_description(c, "main-client") >= 0);
+        assert_se(varlink_bind_reply(c, reply) >= 0);
+
+        assert_se(json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(7)),
+                                                   JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(22)))) >= 0);
+
+        assert_se(varlink_invoke(c, "io.test.DoSomething", v) >= 0);
+
+        assert_se(varlink_attach_event(c, e, 0) >= 0);
+
+        assert_se(pthread_create(&t, NULL, thread, (void*) sp) == 0);
+
+        assert_se(sd_event_loop(e) >= 0);
+
+        assert_se(pthread_join(t, NULL) == 0);
+
+        return 0;
+}
index 406ca1df6616d95b02ba84e288b78ee921a6282b..e03f1796e73f38fd2ab69b8767cafae7cb466d0f 100644 (file)
@@ -866,6 +866,7 @@ static int run(int argc, char *argv[]) {
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
index 4c00fa409f04a48bfddc0d67d8a4c4b0923f34ed..3c3a7fe69aec049ca3fac7ccb0b27a174fd81f9c 100644 (file)
@@ -1024,7 +1024,7 @@ static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t re
         sd_network_monitor_flush(m->network_monitor);
 
         /* When manager_network_read_link_servers() failed, we assume that the servers are changed. */
-        changed = !!manager_network_read_link_servers(m);
+        changed = manager_network_read_link_servers(m);
 
         /* check if the machine is online */
         online = network_is_online();
index d9d1cc1c1a1c6cd3b9da0c3aeadc4ccee680b4c2..eabc51101d992447a0cf1658a5606cab8259a3fd 100644 (file)
@@ -776,8 +776,24 @@ static bool hardlink_vulnerable(const struct stat *st) {
         return !S_ISDIR(st->st_mode) && st->st_nlink > 1 && dangerous_hardlinks();
 }
 
+static mode_t process_mask_perms(mode_t mode, mode_t current) {
+
+        if ((current & 0111) == 0)
+                mode &= ~0111;
+        if ((current & 0222) == 0)
+                mode &= ~0222;
+        if ((current & 0444) == 0)
+                mode &= ~0444;
+        if (!S_ISDIR(current))
+                mode &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
+
+        return mode;
+}
+
 static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st) {
         struct stat stbuf;
+        mode_t new_mode;
+        bool do_chown;
 
         assert(i);
         assert(fd);
@@ -797,35 +813,39 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
                                        "Refusing to set permissions on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.",
                                        path);
 
-        if (i->mode_set) {
+        /* Do we need a chown()? */
+        do_chown =
+                (i->uid_set && i->uid != st->st_uid) ||
+                (i->gid_set && i->gid != st->st_gid);
+
+        /* Calculate the mode to apply */
+        new_mode = i->mode_set ? (i->mask_perms ?
+                                  process_mask_perms(i->mode, st->st_mode) :
+                                  i->mode) :
+                                 (st->st_mode & 07777);
+
+        if (i->mode_set && do_chown) {
+                /* Before we issue the chmod() let's reduce the access mode to the common bits of the old and
+                 * the new mode. That way there's no time window where the file exists under the old owner
+                 * with more than the old access modes — and not under the new owner with more than the new
+                 * access modes either. */
+
                 if (S_ISLNK(st->st_mode))
-                        log_debug("Skipping mode fix for symlink %s.", path);
+                        log_debug("Skipping temporary mode fix for symlink %s.", path);
                 else {
-                        mode_t m = i->mode;
-
-                        if (i->mask_perms) {
-                                if (!(st->st_mode & 0111))
-                                        m &= ~0111;
-                                if (!(st->st_mode & 0222))
-                                        m &= ~0222;
-                                if (!(st->st_mode & 0444))
-                                        m &= ~0444;
-                                if (!S_ISDIR(st->st_mode))
-                                        m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
-                        }
+                        mode_t m = new_mode & st->st_mode; /* Mask new mode by old mode */
 
-                        if (m == (st->st_mode & 07777))
-                                log_debug("\"%s\" has correct mode %o already.", path, st->st_mode);
+                        if (((m ^ st->st_mode) & 07777) == 0)
+                                log_debug("\"%s\" matches temporary mode %o already.", path, m);
                         else {
-                                log_debug("Changing \"%s\" to mode %o.", path, m);
+                                log_debug("Temporarily changing \"%s\" to mode %o.", path, m);
                                 if (fchmod_opath(fd, m) < 0)
                                         return log_error_errno(errno, "fchmod() of %s failed: %m", path);
                         }
                 }
         }
 
-        if ((i->uid_set && i->uid != st->st_uid) ||
-            (i->gid_set && i->gid != st->st_gid)) {
+        if (do_chown) {
                 log_debug("Changing \"%s\" to owner "UID_FMT":"GID_FMT,
                           path,
                           i->uid_set ? i->uid : UID_INVALID,
@@ -839,6 +859,24 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
                         return log_error_errno(errno, "fchownat() of %s failed: %m", path);
         }
 
+        /* Now, apply the final mode. We do this in two cases: when the user set a mode explicitly, or after a
+         * chown(), since chown()'s mangle the access mode in regards to sgid/suid in some conditions. */
+        if (i->mode_set || do_chown) {
+                if (S_ISLNK(st->st_mode))
+                        log_debug("Skipping mode fix for symlink %s.", path);
+                else {
+                       /* Check if the chmod() is unnecessary. Note that if we did a chown() before we always
+                        * chmod() here again, since it might have mangled the bits. */
+                        if (!do_chown && ((new_mode ^ st->st_mode) & 07777) == 0)
+                                log_debug("\"%s\" matches mode %o already.", path, new_mode);
+                        else {
+                                log_debug("Changing \"%s\" to mode %o.", path, new_mode);
+                                if (fchmod_opath(fd, new_mode) < 0)
+                                        return log_error_errno(errno, "fchmod() of %s failed: %m", path);
+                        }
+                }
+        }
+
 shortcut:
         return label_fix(path, 0);
 }
@@ -2397,7 +2435,7 @@ static int specifier_expansion_from_arg(Item *i) {
 
         assert(i);
 
-        if (i->argument == NULL)
+        if (!i->argument)
                 return 0;
 
         switch (i->type) {
index 8ea2e1e327ed8e034020cb0462cd78eb0778a6da..9aca82b1fbde1e46815a84b906ae50a8a052baed 100644 (file)
@@ -381,7 +381,7 @@ static int disk_identify(int fd,
         }
 
 out:
-        if (out_is_packet_device != NULL)
+        if (out_is_packet_device)
                 *out_is_packet_device = is_packet_device;
         return ret;
 }
@@ -432,7 +432,7 @@ int main(int argc, char *argv[]) {
         }
 
         node = argv[optind];
-        if (node == NULL) {
+        if (!node) {
                 log_error("no node specified");
                 return 1;
         }
index ddcdbdaa18d6fde2b3607e36229a4dedfb4c75b1..a287901266baad43068fa335843353bcf1f0a3b1 100644 (file)
@@ -95,7 +95,7 @@ static bool is_mounted(const char *device) {
                 return false;
 
         fp = fopen("/proc/self/mountinfo", "re");
-        if (fp == NULL)
+        if (!fp)
                 return false;
         while (fscanf(fp, "%*s %*s %i:%i %*[^\n]", &maj, &min) == 2) {
                 if (makedev(maj, min) == statbuf.st_rdev) {
@@ -108,11 +108,10 @@ static bool is_mounted(const char *device) {
 }
 
 static void info_scsi_cmd_err(const char *cmd, int err) {
-        if (err == -1) {
+        if (err == -1)
                 log_debug("%s failed", cmd);
-                return;
-        }
-        log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd, SK(err), ASC(err), ASCQ(err));
+        else
+                log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd, SK(err), ASC(err), ASCQ(err));
 }
 
 struct scsi_cmd {
@@ -149,9 +148,9 @@ static int scsi_cmd_run(struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t
                 cmd->sg_io.dxferp = buf;
                 cmd->sg_io.dxfer_len = bufsize;
                 cmd->sg_io.dxfer_direction = SG_DXFER_FROM_DEV;
-        } else {
+        } else
                 cmd->sg_io.dxfer_direction = SG_DXFER_NONE;
-        }
+
         if (ioctl(fd, SG_IO, &cmd->sg_io))
                 return -1;
 
@@ -191,7 +190,7 @@ static int media_eject(int fd) {
         scsi_cmd_set(&sc, 4, 0x02);
         scsi_cmd_set(&sc, 5, 0);
         err = scsi_cmd_run(&sc, fd, NULL, 0);
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("START_STOP_UNIT", err);
                 return -1;
         }
@@ -202,10 +201,8 @@ static int cd_capability_compat(int fd) {
         int capability;
 
         capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL);
-        if (capability < 0) {
-                log_debug("CDROM_GET_CAPABILITY failed");
-                return -1;
-        }
+        if (capability < 0)
+                return log_debug_errno(errno, "CDROM_GET_CAPABILITY failed");
 
         if (capability & CDC_CD_R)
                 cd_cd_r = 1;
@@ -225,10 +222,9 @@ static int cd_capability_compat(int fd) {
 }
 
 static int cd_media_compat(int fd) {
-        if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) {
-                log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK");
-                return -1;
-        }
+        if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK)
+                return log_debug_errno(errno, "CDROM_DRIVE_STATUS != CDS_DISC_OK");
+
         cd_media = 1;
         return 0;
 }
@@ -243,15 +239,13 @@ static int cd_inquiry(int fd) {
         scsi_cmd_set(&sc, 4, 36);
         scsi_cmd_set(&sc, 5, 0);
         err = scsi_cmd_run(&sc, fd, inq, 36);
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("INQUIRY", err);
                 return -1;
         }
 
-        if ((inq[0] & 0x1F) != 5) {
-                log_debug("not an MMC unit");
-                return -1;
-        }
+        if ((inq[0] & 0x1F) != 5)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "not an MMC unit");
 
         log_debug("INQUIRY: [%.8s][%.16s][%.4s]", inq + 8, inq + 16, inq + 32);
         return 0;
@@ -465,7 +459,7 @@ static int cd_profiles_old_mmc(int fd) {
         scsi_cmd_set(&sc, 8, sizeof(header));
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, header, sizeof(header));
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("READ DISC INFORMATION", err);
                 if (cd_media == 1) {
                         log_debug("no current profile, but disc is present; assuming CD-ROM");
@@ -473,10 +467,9 @@ static int cd_profiles_old_mmc(int fd) {
                         cd_media_track_count = 1;
                         cd_media_track_count_data = 1;
                         return 0;
-                } else {
-                        log_debug("no current profile, assuming no media");
-                        return -1;
-                }
+                } else
+                        return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
+                                               "no current profile, assuming no media");
         };
 
         cd_media = 1;
@@ -512,7 +505,7 @@ static int cd_profiles(int fd) {
         scsi_cmd_set(&sc, 8, 8);
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, features, 8);
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("GET CONFIGURATION", err);
                 /* handle pre-MMC2 drives which do not support GET CONFIGURATION */
                 if (SK(err) == 0x5 && IN_SET(ASC(err), 0x20, 0x24)) {
@@ -528,9 +521,8 @@ static int cd_profiles(int fd) {
                 log_debug("current profile 0x%02x", cur_profile);
                 feature_profile_media(cur_profile);
                 ret = 0; /* we have media */
-        } else {
+        } else
                 log_debug("no current profile, assuming no media");
-        }
 
         len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3];
         log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len);
@@ -548,7 +540,7 @@ static int cd_profiles(int fd) {
         scsi_cmd_set(&sc, 8, len & 0xff);
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, features, len);
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("GET CONFIGURATION", err);
                 return -1;
         }
@@ -598,7 +590,7 @@ static int cd_media_info(int fd) {
         scsi_cmd_set(&sc, 8, sizeof(header) & 0xff);
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, header, sizeof(header));
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("READ DISC INFORMATION", err);
                 return -1;
         };
@@ -637,7 +629,7 @@ static int cd_media_info(int fd) {
                         scsi_cmd_set(&sc, 9, sizeof(dvdstruct));
                         scsi_cmd_set(&sc, 11, 0);
                         err = scsi_cmd_run(&sc, fd, dvdstruct, sizeof(dvdstruct));
-                        if ((err != 0)) {
+                        if (err != 0) {
                                 info_scsi_cmd_err("READ DVD STRUCTURE", err);
                                 return -1;
                         }
@@ -653,16 +645,15 @@ static int cd_media_info(int fd) {
                         scsi_cmd_set(&sc, 8, sizeof(format));
                         scsi_cmd_set(&sc, 9, 0);
                         err = scsi_cmd_run(&sc, fd, format, sizeof(format));
-                        if ((err != 0)) {
+                        if (err != 0) {
                                 info_scsi_cmd_err("READ DVD FORMAT CAPACITIES", err);
                                 return -1;
                         }
 
                         len = format[3];
-                        if (len & 7 || len < 16) {
-                                log_debug("invalid format capacities length");
-                                return -1;
-                        }
+                        if (len & 7 || len < 16)
+                                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "invalid format capacities length");
 
                         switch(format[8] & 3) {
                             case 1:
@@ -680,8 +671,8 @@ static int cd_media_info(int fd) {
 
                             case 3:
                                 cd_media = 0; //return no media
-                                log_debug("format capacities returned no media");
-                                return -1;
+                                return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
+                                                       "format capacities returned no media");
                         }
                 }
 
@@ -695,7 +686,7 @@ static int cd_media_info(int fd) {
                 scsi_cmd_set(&sc, 8, 32);
                 scsi_cmd_set(&sc, 9, 0);
                 err = scsi_cmd_run(&sc, fd, buffer, sizeof(buffer));
-                if ((err != 0)) {
+                if (err != 0) {
                         cd_media = 0;
                         info_scsi_cmd_err("READ FIRST 32 BLOCKS", err);
                         return -1;
@@ -748,7 +739,7 @@ static int cd_media_toc(int fd) {
         scsi_cmd_set(&sc, 8, sizeof(header) & 0xff);
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, header, sizeof(header));
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("READ TOC", err);
                 return -1;
         }
@@ -773,7 +764,7 @@ static int cd_media_toc(int fd) {
         scsi_cmd_set(&sc, 8, len & 0xff);
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, toc, len);
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("READ TOC (tracks)", err);
                 return -1;
         }
@@ -803,7 +794,7 @@ static int cd_media_toc(int fd) {
         scsi_cmd_set(&sc, 8, sizeof(header));
         scsi_cmd_set(&sc, 9, 0);
         err = scsi_cmd_run(&sc, fd, header, sizeof(header));
-        if ((err != 0)) {
+        if (err != 0) {
                 info_scsi_cmd_err("READ TOC (multi session)", err);
                 return -1;
         }
@@ -1026,7 +1017,7 @@ work:
         if (cd_media_hddvd_rw)
                 printf("ID_CDROM_MEDIA_HDDVD_RW=1\n");
 
-        if (cd_media_state != NULL)
+        if (cd_media_state)
                 printf("ID_CDROM_MEDIA_STATE=%s\n", cd_media_state);
         if (cd_media_session_next > 0)
                 printf("ID_CDROM_MEDIA_SESSION_NEXT=%u\n", cd_media_session_next);
index 7754959cdf3a53f9449bab58cb50a7d7cba67c7d..a4e10ff988b7760da1001bfd94c164ca3d106714 100644 (file)
@@ -260,7 +260,7 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
 
                                 (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
 
-                                if (name_assign_type == NET_NAME_ENUM) {
+                                if (name_assign_type == NET_NAME_ENUM && !strv_contains(link->match_name, "*")) {
                                         log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
                                                     link->filename, sysname);
                                         *ret = link;
index 324b8e679c8d8516049d72f6620d1f1ae7191a8e..4061eec99e7cdf8b8ba54ccf15d4302d387c4f59 100644 (file)
@@ -25,15 +25,16 @@ typedef enum NamingSchemeFlags {
         NAMING_SR_IOV_V        = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
         NAMING_NPAR_ARI        = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
         NAMING_INFINIBAND      = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
-        NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
+        NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Use zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
         NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
-        NAMING_NETDEVSIM       = 1 << 5, /* Allow re-renaming of netdevsim devices */
+        NAMING_NETDEVSIM       = 1 << 5, /* Generate names for netdevsim devices, see eaa9d507d85509c8bf727356e3884ec54b0fc646 */
+        NAMING_LABEL_NOPREFIX  = 1 << 6, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
 
         /* And now the masks that combine the features above */
         NAMING_V238 = 0,
         NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
         NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
-        NAMING_V243 = NAMING_V240 | NAMING_NETDEVSIM,
+        NAMING_V243 = NAMING_V240 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
 
         _NAMING_SCHEME_FLAGS_INVALID = -1,
 } NamingSchemeFlags;
index 2698cdd82fd9d8bb36103cd1601c79ced3957474..e1a8d7e3a9252819f3c8d28de8106549c738c4a9 100644 (file)
@@ -157,7 +157,7 @@ static int get_file_options(const char *vendor, const char *model,
         int retval = 0;
 
         f = fopen(config_file, "re");
-        if (f == NULL) {
+        if (!f) {
                 if (errno == ENOENT)
                         return 1;
                 else {
@@ -181,7 +181,7 @@ static int get_file_options(const char *vendor, const char *model,
                 vendor_in = model_in = options_in = NULL;
 
                 buf = fgets(buffer, MAX_BUFFER_LEN, f);
-                if (buf == NULL)
+                if (!buf)
                         break;
                 lineno++;
                 if (buf[strlen(buffer) - 1] != '\n') {
@@ -239,7 +239,7 @@ static int get_file_options(const char *vendor, const char *model,
                         break;
                 }
                 if (vendor == NULL) {
-                        if (vendor_in == NULL)
+                        if (!vendor_in)
                                 break;
                 } else if (vendor_in &&
                            startswith(vendor, vendor_in) &&
@@ -346,18 +346,18 @@ static int set_options(int argc, char **argv,
                                 default_page_code = PAGE_83;
                         else if (streq(optarg, "pre-spc3-83"))
                                 default_page_code = PAGE_83_PRE_SPC3;
-                        else {
-                                log_error("Unknown page code '%s'", optarg);
-                                return -1;
-                        }
+                        else
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Unknown page code '%s'",
+                                                       optarg);
                         break;
 
                 case 's':
                         sg_version = atoi(optarg);
-                        if (sg_version < 3 || sg_version > 4) {
-                                log_error("Unknown SG version '%s'", optarg);
-                                return -1;
-                        }
+                        if (sg_version < 3 || sg_version > 4)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Unknown SG version '%s'",
+                                                       optarg);
                         break;
 
                 case 'u':
index 7ca01858d165ba58c8bae63e371320734d3abcbe..080b027d18a74850e54f3354d8742e52b6a71b21 100644 (file)
@@ -168,10 +168,10 @@ static int scsi_dump_sense(struct scsi_id_device *dev_scsi,
          * we'll retry the command.
          */
 
-        if (sb_len < 1) {
-                log_debug("%s: sense buffer empty", dev_scsi->kernel);
-                return -1;
-        }
+        if (sb_len < 1)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s: sense buffer empty",
+                                       dev_scsi->kernel);
 
         sense_class = (sense_buffer[0] >> 4) & 0x07;
         code = sense_buffer[0] & 0xf;
@@ -181,40 +181,41 @@ static int scsi_dump_sense(struct scsi_id_device *dev_scsi,
                  * extended sense data.
                  */
                 s = sense_buffer[7] + 8;
-                if (sb_len < s) {
-                        log_debug("%s: sense buffer too small %d bytes, %d bytes too short",
-                                  dev_scsi->kernel, sb_len, s - sb_len);
-                        return -1;
-                }
+                if (sb_len < s)
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "%s: sense buffer too small %d bytes, %d bytes too short",
+                                               dev_scsi->kernel, sb_len,
+                                               s - sb_len);
+
                 if (IN_SET(code, 0x0, 0x1)) {
                         sense_key = sense_buffer[2] & 0xf;
-                        if (s < 14) {
+                        if (s < 14)
                                 /*
                                  * Possible?
                                  */
-                                log_debug("%s: sense result too" " small %d bytes",
-                                          dev_scsi->kernel, s);
-                                return -1;
-                        }
+                                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "%s: sense result too small %d bytes",
+                                                       dev_scsi->kernel, s);
+
                         asc = sense_buffer[12];
                         ascq = sense_buffer[13];
                 } else if (IN_SET(code, 0x2, 0x3)) {
                         sense_key = sense_buffer[1] & 0xf;
                         asc = sense_buffer[2];
                         ascq = sense_buffer[3];
-                } else {
-                        log_debug("%s: invalid sense code 0x%x",
-                                  dev_scsi->kernel, code);
-                        return -1;
-                }
+                } else
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "%s: invalid sense code 0x%x",
+                                               dev_scsi->kernel, code);
+
                 log_debug("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x",
                           dev_scsi->kernel, sense_key, asc, ascq);
         } else {
-                if (sb_len < 4) {
-                        log_debug("%s: sense buffer too small %d bytes, %d bytes too short",
-                                  dev_scsi->kernel, sb_len, 4 - sb_len);
-                        return -1;
-                }
+                if (sb_len < 4)
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "%s: sense buffer too small %d bytes, %d bytes too short",
+                                               dev_scsi->kernel, sb_len,
+                                               4 - sb_len);
 
                 if (sense_buffer[0] < 15)
                         log_debug("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f);
@@ -231,13 +232,13 @@ static int scsi_dump_sense(struct scsi_id_device *dev_scsi,
 
 static int scsi_dump(struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) {
         if (!io->status && !io->host_status && !io->msg_status &&
-            !io->driver_status) {
+            !io->driver_status)
                 /*
                  * Impossible, should not be called.
                  */
-                log_debug("%s: called with no error", __FUNCTION__);
-                return -1;
-        }
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s: called with no error",
+                                       __FUNCTION__);
 
         log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
                   dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
@@ -249,13 +250,13 @@ static int scsi_dump(struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) {
 
 static int scsi_dump_v4(struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) {
         if (!io->device_status && !io->transport_status &&
-            !io->driver_status) {
+            !io->driver_status)
                 /*
                  * Impossible, should not be called.
                  */
-                log_debug("%s: called with no error", __FUNCTION__);
-                return -1;
-        }
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s: called with no error",
+                                       __FUNCTION__);
 
         log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x",
                   dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status);
@@ -278,10 +279,9 @@ static int scsi_inquiry(struct scsi_id_device *dev_scsi, int fd,
         int retry = 3; /* rather random */
         int retval;
 
-        if (buflen > SCSI_INQ_BUFF_LEN) {
-                log_debug("buflen %d too long", buflen);
-                return -1;
-        }
+        if (buflen > SCSI_INQ_BUFF_LEN)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "buflen %d too long", buflen);
 
 resend:
         if (dev_scsi->use_sg == 4) {
@@ -388,7 +388,7 @@ static int do_scsi_page0_inquiry(struct scsi_id_device *dev_scsi, int fd,
                  * If the vendor id appears in the page assume the page is
                  * invalid.
                  */
-                if (strneq((char *)&buffer[VENDOR_LENGTH], dev_scsi->vendor, VENDOR_LENGTH)) {
+                if (strneq((char*) buffer + VENDOR_LENGTH, dev_scsi->vendor, VENDOR_LENGTH)) {
                         log_debug("%s: invalid page0 data", dev_scsi->kernel);
                         return 1;
                 }
@@ -396,27 +396,21 @@ static int do_scsi_page0_inquiry(struct scsi_id_device *dev_scsi, int fd,
         return 0;
 }
 
-/*
- * The caller checks that serial is long enough to include the vendor +
- * model.
- */
-static int prepend_vendor_model(struct scsi_id_device *dev_scsi, char *serial) {
-        int ind;
-
-        strncpy(serial, dev_scsi->vendor, VENDOR_LENGTH);
-        strncat(serial, dev_scsi->model, MODEL_LENGTH);
-        ind = strlen(serial);
-
-        /*
-         * This is not a complete check, since we are using strncat/cpy
-         * above, ind will never be too large.
-         */
-        if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
-                log_debug("%s: expected length %d, got length %d",
-                          dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
-                return -1;
-        }
-        return ind;
+static int append_vendor_model(
+                const struct scsi_id_device *dev_scsi,
+                char buf[static VENDOR_LENGTH + MODEL_LENGTH]) {
+
+        if (strnlen(dev_scsi->vendor, VENDOR_LENGTH) != VENDOR_LENGTH)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s: bad vendor string \"%s\"",
+                                       dev_scsi->kernel, dev_scsi->vendor);
+        if (strnlen(dev_scsi->model, MODEL_LENGTH) != MODEL_LENGTH)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "%s: bad model string \"%s\"",
+                                       dev_scsi->kernel, dev_scsi->model);
+        memcpy(buf, dev_scsi->vendor, VENDOR_LENGTH);
+        memcpy(buf + VENDOR_LENGTH, dev_scsi->model, MODEL_LENGTH);
+        return VENDOR_LENGTH + MODEL_LENGTH;
 }
 
 /*
@@ -497,7 +491,7 @@ static int check_fill_0x83_id(struct scsi_id_device *dev_scsi,
          * included in the identifier.
          */
         if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
-                if (prepend_vendor_model(dev_scsi, &serial[1]) < 0)
+                if (append_vendor_model(dev_scsi, serial + 1) < 0)
                         return 1;
 
         i = 4; /* offset to the start of the identifier */
@@ -520,12 +514,12 @@ static int check_fill_0x83_id(struct scsi_id_device *dev_scsi,
                 }
         }
 
-        strcpy(serial_short, &serial[s]);
+        strcpy(serial_short, serial + s);
 
         if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) {
-                strncpy(wwn, &serial[s], 16);
-                if (wwn_vendor_extension != NULL)
-                        strncpy(wwn_vendor_extension, &serial[s + 16], 16);
+                strncpy(wwn, serial + s, 16);
+                if (wwn_vendor_extension)
+                        strncpy(wwn_vendor_extension, serial + s + 16, 16);
         }
 
         return 0;
@@ -618,9 +612,9 @@ static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
                  * Examine each descriptor returned. There is normally only
                  * one or a small number of descriptors.
                  */
-                for (j = 4; j <= (unsigned)page_83[3] + 3; j += page_83[j + 3] + 4) {
-                        retval = check_fill_0x83_id(dev_scsi, &page_83[j],
-                                                    &id_search_list[id_ind],
+                for (j = 4; j <= ((unsigned)page_83[2] << 8) + (unsigned)page_83[3] + 3; j += page_83[j + 3] + 4) {
+                        retval = check_fill_0x83_id(dev_scsi, page_83 + j,
+                                                    id_search_list + id_ind,
                                                     serial, serial_short, len,
                                                     wwn, wwn_vendor_extension,
                                                     tgpt_group);
@@ -729,17 +723,17 @@ static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
          * specific type where we prepend '0' + vendor + model.
          */
         len = buf[3];
-        if (serial != NULL) {
+        if (serial) {
                 serial[0] = 'S';
-                ser_ind = prepend_vendor_model(dev_scsi, &serial[1]);
+                ser_ind = append_vendor_model(dev_scsi, serial + 1);
                 if (ser_ind < 0)
                         return 1;
                 ser_ind++; /* for the leading 'S' */
                 for (i = 4; i < len + 4; i++, ser_ind++)
                         serial[ser_ind] = buf[i];
         }
-        if (serial_short != NULL) {
-                memcpy(serial_short, &buf[4], len);
+        if (serial_short) {
+                memcpy(serial_short, buf + 4, len);
                 serial_short[len] = '\0';
         }
         return 0;
index 2c7dcf7d2a10ae877ac741813e19deafd717bb6f..c487bc00df23b24606b7eb0615b8d09edd1d2c9d 100644 (file)
@@ -9,86 +9,7 @@
  *
  * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
  *
- * Two character prefixes based on the type of interface:
- *   en — Ethernet
- *   ib — InfiniBand
- *   sl — serial line IP (slip)
- *   wl — wlan
- *   ww — wwan
- *
- * Type of names:
- *   b<number>                             — BCMA bus core number
- *   c<bus_id>                             — bus id of a grouped CCW or CCW device,
- *                                           with all leading zeros stripped [s390]
- *   o<index>[n<phys_port_name>|d<dev_port>]
- *                                         — on-board device index number
- *   s<slot>[f<function>][n<phys_port_name>|d<dev_port>]
- *                                         — hotplug slot index number
- *   x<MAC>                                — MAC address
- *   [P<domain>]p<bus>s<slot>[f<function>][n<phys_port_name>|d<dev_port>]
- *                                         — PCI geographical location
- *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
- *                                         — USB port number chain
- *   v<slot>                               - VIO slot number (IBM PowerVM)
- *   a<vendor><model>i<instance>           — Platform bus ACPI instance id
- *   i<addr>n<phys_port_name>             — Netdevsim bus address and port name
- *
- * All multi-function PCI devices will carry the [f<function>] number in the
- * device name, including the function 0 device.
- *
- * SR-IOV virtual devices are named based on the name of the parent interface,
- * with a suffix of "v<N>", where <N> is the virtual device number.
- *
- * When using PCI geography, The PCI domain is only prepended when it is not 0.
- *
- * For USB devices the full chain of port numbers of hubs is composed. If the
- * name gets longer than the maximum number of 15 characters, the name is not
- * exported.
- * The usual USB configuration == 1 and interface == 0 values are suppressed.
- *
- * PCI Ethernet card with firmware index "1":
- *   ID_NET_NAME_ONBOARD=eno1
- *   ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
- *
- * PCI Ethernet card in hotplug slot with firmware index number:
- *   /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
- *   ID_NET_NAME_MAC=enx000000000466
- *   ID_NET_NAME_PATH=enp5s0
- *   ID_NET_NAME_SLOT=ens1
- *
- * PCI Ethernet multi-function card with 2 ports:
- *   /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
- *   ID_NET_NAME_MAC=enx78e7d1ea46da
- *   ID_NET_NAME_PATH=enp2s0f0
- *   /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
- *   ID_NET_NAME_MAC=enx78e7d1ea46dc
- *   ID_NET_NAME_PATH=enp2s0f1
- *
- * PCI wlan card:
- *   /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
- *   ID_NET_NAME_MAC=wlx0024d7e31130
- *   ID_NET_NAME_PATH=wlp3s0
- *
- * PCI IB host adapter with 2 ports:
- *   /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/net/ibp21s0f0
- *   ID_NET_NAME_PATH=ibp21s0f0
- *   /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.1/net/ibp21s0f1
- *   ID_NET_NAME_PATH=ibp21s0f1
- *
- * USB built-in 3G modem:
- *   /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
- *   ID_NET_NAME_MAC=wwx028037ec0200
- *   ID_NET_NAME_PATH=wwp0s29u1u4i6
- *
- * USB Android phone:
- *   /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
- *   ID_NET_NAME_MAC=enxd626b3450fb5
- *   ID_NET_NAME_PATH=enp0s29u1u2
- *
- * s390 grouped CCW interface:
- *  /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0
- *  ID_NET_NAME_MAC=enx026d3c00000a
- *  ID_NET_NAME_PATH=encf5f0
+ * When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too.
  */
 
 #include <errno.h>
@@ -249,7 +170,7 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
         char *s;
         int r;
 
-        /* ACPI _DSM  — device specific method for naming a PCI or PCI Express device */
+        /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
         if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) < 0) {
                 /* SMBIOS type 41 — Onboard Devices Extended Information */
                 r = sd_device_get_sysattr_value(names->pcidev, "index", &attr);
@@ -263,10 +184,11 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
         if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
                 return -EINVAL;
 
-        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for
-         * example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary
-         * cut-off, which is somewhere beyond the realistic number of physical network interface a system might
-         * have. Ideally the kernel would already filter his crap for us, but it doesn't currently. */
+        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
+         * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
+         * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
+         * interface a system might have. Ideally the kernel would already filter his crap for us, but it
+         * doesn't currently. */
         if (idx > ONBOARD_INDEX_MAX)
                 return -ENOENT;
 
@@ -722,9 +644,8 @@ static int names_ccw(sd_device *dev, struct netnames *names) {
         if (r < 0)
                 return r;
 
-        /* Check the length of the bus-ID.  Rely on that the kernel provides
-         * a correct bus-ID; alternatively, improve this check and parse and
-         * verify each bus-ID part...
+        /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID;
+         * alternatively, improve this check and parse and verify each bus-ID part...
          */
         bus_id_len = strlen(bus_id);
         if (!IN_SET(bus_id_len, 8, 9))
@@ -960,7 +881,9 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
                         udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
 
                 if (names.pci_onboard_label &&
-                    snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_onboard_label))
+                    snprintf_ok(str, sizeof str, "%s%s",
+                                naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
+                                names.pci_onboard_label))
                         udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
 
                 if (names.pci_path[0] &&
index 7bdf6cfbb59613936cc3b9d60d5b2c245e992a89..58af63f11a6cbe8abdfb4e0c88662ef0162f93bf 100644 (file)
@@ -196,7 +196,7 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
                              desc->bInterfaceProtocol) != 7)
                         continue;
 
-                if (strstr(ifs_str, if_str) != NULL)
+                if (strstr(ifs_str, if_str))
                         continue;
 
                 memcpy(&ifs_str[strpos], if_str, 8),
index cab1b5ac0c56aa5524e035435ac797eba7096421..a0a7ac0f9e01a0c2b2d5569c04dc116a4fb73df2 100644 (file)
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include "sd-event.h"
index cfbbd7b2832da7e2f8ba5f04fa102a54e41005ed..9549a1ba442002bd966c47c985788c551c552b82 100644 (file)
@@ -98,7 +98,7 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
                 return log_device_error_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target);
 
         if (rename(slink_tmp, slink) < 0) {
-                r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s' failed: %m", slink_tmp, slink);
+                r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink);
                 (void) unlink(slink_tmp);
         }
 
index a6f7ee82bbfebf447d3251c073f6b4383a365bed..873d03bc5e51232d3cda5ea285465b8e6259fce5 100644 (file)
@@ -69,6 +69,8 @@
 #include "udev.h"
 #include "user-util.h"
 
+#define WORKER_NUM_MAX 2048U
+
 static bool arg_debug = false;
 static int arg_daemonize = false;
 static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
@@ -1745,16 +1747,18 @@ static int run(int argc, char *argv[]) {
                 return r;
 
         if (arg_children_max == 0) {
+                unsigned long cpu_limit, mem_limit;
+                unsigned long cpu_count = 1;
                 cpu_set_t cpu_set;
-                unsigned long mem_limit;
-
-                arg_children_max = 8;
 
                 if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0)
-                        arg_children_max += CPU_COUNT(&cpu_set) * 8;
+                        cpu_count = CPU_COUNT(&cpu_set);
+
+                cpu_limit = cpu_count * 2 + 16;
+                mem_limit = MAX(physical_memory() / (128UL*1024*1024), 10U);
 
-                mem_limit = physical_memory() / (128LU*1024*1024);
-                arg_children_max = MAX(10U, MIN(arg_children_max, mem_limit));
+                arg_children_max = MIN(cpu_limit, mem_limit);
+                arg_children_max = MIN(WORKER_NUM_MAX, arg_children_max);
 
                 log_debug("Set children_max to %u", arg_children_max);
         }
index 4d60ee3c85909938adb3aae69678eb4c43837704..5de26b8062377ce96c34eaa5a74a30fa47affb93 100644 (file)
@@ -56,7 +56,7 @@ int main(int argc, char *argv[]) {
                 }
 
         device = argv[optind];
-        if (device == NULL)
+        if (!device)
                 return 2;
 
         fd = open(device, O_RDONLY);
index 976dd825bcb213b28bd3880546076de12f396541..d2bc3921d281deeb1ce262298355af74325c84f4 100644 (file)
@@ -70,29 +70,19 @@ static int verify_vc_allocation_byfd(int fd) {
         return verify_vc_allocation(vcs.v_active);
 }
 
-static int verify_vc_kbmode(int fd) {
-        int curr_mode;
-
-        /*
-         * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
-         * Otherwise we would (likely) interfere with X11's processing of the
-         * key events.
-         *
-         * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
-         */
-
-        if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
-                return -errno;
-
-        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
-}
-
 static int toggle_utf8(const char *name, int fd, bool utf8) {
         int r;
         struct termios tc = {};
 
         assert(name);
 
+        r = vt_verify_kbmode(fd);
+        if (r == -EBUSY) {
+                log_warning_errno(r, "Virtual console %s is not in K_XLATE or K_UNICODE: %m", name);
+                return 0;
+        } else if (r < 0)
+                return log_warning_errno(r, "Failed to verify kbdmode on %s: %m", name);
+
         r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE);
         if (r < 0)
                 return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode on %s: %m", enable_disable(utf8), name);
@@ -290,7 +280,7 @@ static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
                         continue;
                 }
 
-                if (verify_vc_kbmode(fd_d) < 0)
+                if (vt_verify_kbmode(fd_d) < 0)
                         continue;
 
                 toggle_utf8(ttyname, fd_d, utf8);
@@ -365,7 +355,7 @@ static int find_source_vc(char **ret_path, unsigned *ret_idx) {
                                 err = -fd;
                         continue;
                 }
-                r = verify_vc_kbmode(fd);
+                r = vt_verify_kbmode(fd);
                 if (r < 0) {
                         if (!err)
                                 err = -r;
@@ -398,7 +388,7 @@ static int verify_source_vc(char **ret_path, const char *src_vc) {
         if (r < 0)
                 return log_error_errno(r, "Virtual console %s is not allocated: %m", src_vc);
 
-        r = verify_vc_kbmode(fd);
+        r = vt_verify_kbmode(fd);
         if (r < 0)
                 return log_error_errno(r, "Virtual console %s is not in K_XLATE or K_UNICODE: %m", src_vc);
 
index ace2302589f486d4febc2259dfab078c4b635148..27084f62424bf2cf3407c7a1a6bcc6bed2aa15b9 100644 (file)
@@ -40,7 +40,3 @@ fs.protected_symlinks = 1
 # Enable regular file and FIFO protection
 fs.protected_regular = 1
 fs.protected_fifos = 1
-
-# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default
-# of 2^16), to make PID collisions less likely.
-kernel.pid_max = 4194304
diff --git a/sysctl.d/50-pid-max.conf b/sysctl.d/50-pid-max.conf
new file mode 100644 (file)
index 0000000..1eff2d7
--- /dev/null
@@ -0,0 +1,16 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+# See sysctl.d(5) and core(5) for documentation.
+
+# To override settings in this file, create a local file in /etc
+# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments
+# there.
+
+# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default
+# of 2^16), to make PID collisions less likely.
+kernel.pid_max = 4194304
index 64f6ce942edd6bd6f8c9f61aaeaca0744265ba44..3f072e3db77cd85af37a7cec9d04f1c41024eee8 100644 (file)
@@ -6,6 +6,13 @@ install_data(
 
 in_files = []
 
+# Kernel determines PID_MAX_LIMIT by
+# #define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
+#         (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
+if cc.sizeof('long') > 4
+        install_data('50-pid-max.conf', install_dir : sysctldir)
+endif
+
 if conf.get('ENABLE_COREDUMP') == 1
         in_files += ['50-coredump.conf']
 endif
index 2314ec37ce5e1e91873c19688feac50a4821e1a8..0f29ad7eda727ddcdb3ecaf3a3e9c8d72f030d18 100755 (executable)
@@ -24,7 +24,7 @@ Description=Testsuite service
 After=multi-user.target
 
 [Service]
-ExecStart=/bin/sh -x -c 'systemctl --state=failed --no-legend --no-pager > /failed ; systemctl daemon-reload ; echo OK > /testok'
+ExecStart=/bin/sh -e -x -c 'systemctl --state=failed --no-legend --no-pager > /failed ; systemctl daemon-reload ; echo OK > /testok'
 Type=oneshot
 EOF
 
index bd85b92caa5cca76a7698619548b43984b87fe08..8252c4b2aaf47b6f34ce3b71c4c76227ab2eebaf 100755 (executable)
@@ -98,7 +98,7 @@ function run {
         return 0
     fi
     if [[ "$2" = "yes" && "$is_cgns_supported" = "no" ]];  then
-        printf "Cgroup namespaces are not supported. Skipping.\n" >&2
+        printf "CGroup namespaces are not supported. Skipping.\n" >&2
         return 0
     fi
 
diff --git a/test/TEST-22-TMPFILES/test-09.sh b/test/TEST-22-TMPFILES/test-09.sh
new file mode 100755 (executable)
index 0000000..b69abda
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+set -e
+set -x
+
+# Make sure that the "stat" output is not locale dependent.
+export LANG=C LC_ALL=C
+
+# first, create file without suid/sgid
+systemd-tmpfiles --create - <<EOF
+f     /tmp/xxx    0755 1 1 - -
+f     /tmp/yyy    0755 1 1 - -
+EOF
+
+test "$(stat -c %F:%u:%g:%a /tmp/xxx)" = "regular empty file:1:1:755"
+test "$(stat -c %F:%u:%g:%a /tmp/yyy)" = "regular empty file:1:1:755"
+
+# then, add suid/sgid
+systemd-tmpfiles --create - <<EOF
+f     /tmp/xxx    04755
+f     /tmp/yyy    02755
+EOF
+
+test "$(stat -c %F:%u:%g:%a /tmp/xxx)" = "regular empty file:1:1:4755"
+test "$(stat -c %F:%u:%g:%a /tmp/yyy)" = "regular empty file:1:1:2755"
+
+# then, chown the files to somebody else
+systemd-tmpfiles --create - <<EOF
+f     /tmp/xxx    - 2 2
+f     /tmp/yyy    - 2 2
+EOF
+
+test "$(stat -c %F:%u:%g:%a /tmp/xxx)" = "regular empty file:2:2:4755"
+test "$(stat -c %F:%u:%g:%a /tmp/yyy)" = "regular empty file:2:2:2755"
+
+# then, chown the files to a third user/group but also drop to a mask that has
+# both more and fewer bits set
+systemd-tmpfiles --create - <<EOF
+f     /tmp/xxx    0770 3 3
+f     /tmp/yyy    0770 3 3
+EOF
+
+test "$(stat -c %F:%u:%g:%a /tmp/xxx)" = "regular empty file:3:3:770"
+test "$(stat -c %F:%u:%g:%a /tmp/yyy)" = "regular empty file:3:3:770"
+
+# return to the beginning
+systemd-tmpfiles --create - <<EOF
+f     /tmp/xxx    0755 1 1 - -
+f     /tmp/yyy    0755 1 1 - -
+EOF
+
+test "$(stat -c %F:%u:%g:%a /tmp/xxx)" = "regular empty file:1:1:755"
+test "$(stat -c %F:%u:%g:%a /tmp/yyy)" = "regular empty file:1:1:755"
+
+# remove everything
+systemd-tmpfiles --remove - <<EOF
+r /tmp/xxx
+r /tmp/yyy
+EOF
similarity index 92%
rename from test/TEST-31-OOMPOLICY/test.sh
rename to test/TEST-32-OOMPOLICY/test.sh
index 55752e6a701d84060044c968568d6ffd67a28df9..7e9431dd11df8951a168957c427340ca5c906f12 100755 (executable)
@@ -1,6 +1,4 @@
 #!/bin/bash
-# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
-# ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
 TEST_DESCRIPTION="test OOM killer logic"
 TEST_NO_NSPAWN=1
similarity index 91%
rename from test/TEST-31-OOMPOLICY/testsuite.sh
rename to test/TEST-32-OOMPOLICY/testsuite.sh
index f0b1470d42e69df08a8eac78f79599ebbf05cb46..8aab487c6e7fb4708a45a5cf752fddcc99658bd5 100755 (executable)
@@ -1,6 +1,4 @@
 #!/bin/bash
-# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
-# ex: ts=8 sw=4 sts=4 et filetype=sh
 set -ex
 set -o pipefail
 
index 2abd591389e90f83d58f3103bdb81c29faca1e56..2e568b5deb157f3b01d2ab4357b83453a2cba2f5 100644 (file)
@@ -5,4 +5,4 @@ Description=DML passthrough set ML service
 Slice=dml-passthrough.slice
 Type=oneshot
 ExecStart=/bin/true
-MemoryLow=25
+MemoryLow=0
index 128f8b63415f3a686e7b212fe415eb7b412f24fb..be1b197024b5d46b70dfb7fd19c0e6858077c32a 100644 (file)
@@ -11,6 +11,7 @@ ListenPort=
 PrivateKey=
 PrivateKeyFile=
 FwMark=
+FirewallMark=
 [MACVTAP]
 Mode=
 [Match]
@@ -31,6 +32,7 @@ FlowLabel=
 UDP6ZeroChecksumRx=
 Remote=
 UDP6ZeroCheckSumRx=
+IPDoNotFragment=
 [Bridge]
 ForwardDelaySec=
 HelloTimeSec=
@@ -92,6 +94,7 @@ Group=
 FDBAgeingSec=
 MacLearning=
 Id=
+VNI=
 RemoteChecksumRx=
 TOS=
 L2MissNotification=
@@ -99,6 +102,7 @@ UDP6ZeroChecksumTx=
 UDP6ZeroCheckSumRx=
 UDPCheckSum=
 GroupPolicyExtension=
+GenericProtocolExtension=
 MaximumFDBEntries=
 TTL=
 DestinationPort=
@@ -106,6 +110,7 @@ ReduceARPProxy=
 PortRange=
 UDPChecksum=
 UDP6ZeroCheckSumTx=
+IPDoNotFragment=
 [VXCAN]
 Peer=
 [Bond]
@@ -135,7 +140,10 @@ DynamicTransmitLoadBalancing=
 [FooOverUDP]
 Protocol=
 Port=
+PeerPort=
 Encapsulation=
+Local=
+Peer=
 [Tap]
 MultiQueue=
 OneQueue=
@@ -146,10 +154,14 @@ VNetHeader=
 [IPVLAN]
 Mode=
 Flags=
+[IPVTAP]
+Mode=
+Flags=
 [Tun]
 OneQueue=
 MultiQueue=
 PacketInfo=
+VNetHeader=
 Group=
 User=
 [NetDev]
@@ -174,7 +186,7 @@ SessionId=
 PeerSessionId=
 Layer2SpecificHeader=
 Name=
-[MACSEC]
+[MACsec]
 Port=
 Encrypt=
 [MACsecReceiveAssociation]
index cd2031150f3a23cc5777df3fab838d99d94a2fde..bba8948d35271dcc0a8a3ed1f8d19f9722fc07c6 100644 (file)
@@ -10,6 +10,9 @@ MulticastToUnicast=
 MulticastFlood=
 NeighborSuppression=
 Learning=
+ProxyARP=
+ProxyARPWiFi=
+MulticastRouter=
 [Match]
 KernelVersion=
 Type=
@@ -32,6 +35,9 @@ MACAddress=
 [BridgeFDB]
 VLANId=
 MACAddress=
+Destination=
+VNI=
+AssociatedWith=
 [DHCP]
 UseDomains=
 UseRoutes=
@@ -57,6 +63,8 @@ ClientIdentifier=
 ListenPort=
 UseTimezone=
 RouteTable=
+BlackList=
+SendRelease=
 [Route]
 Destination=
 Protocol=
@@ -72,14 +80,17 @@ PreferredSource=
 Scope=
 MTUBytes=
 QuickAck=
+FastOpenNoCookie=
 Source=
 Metric=
+TTLPropagate=
 [Network]
 IPv6DuplicateAddressDetection=
 IPMasquerade=
 ProxyARP=
 PrimarySlave=
 IPv4LLRoute=
+DefaultRouteOnDevice=
 Address=
 IPv6ProxyNDPAddress=
 IPv6AcceptRA=
@@ -94,6 +105,7 @@ Tunnel=
 Gateway=
 IPv4LL=
 IPVLAN=
+IPVTAP=
 EmitLLDP=
 IPv6MTUBytes=
 IPv4ProxyARP=
@@ -176,7 +188,7 @@ Managed=
 OtherInformation=
 [Neighbor]
 Address=
-MacAddress=
+MACAddress=
 [IPv6AddressLabel]
 Label=
 Prefix=
@@ -186,6 +198,7 @@ RouteTable=
 UseDNS=
 UseAutonomousPrefix=
 UseOnLinkPrefix=
+BlackList=
 [DHCPServer]
 EmitNTP=
 PoolSize=
@@ -198,6 +211,7 @@ MaxLeaseTimeSec=
 DefaultLeaseTimeSec=
 EmitTimezone=
 DNS=
+MaxAttempts=
 [DHCPv4]
 UseHostname=
 UseMTU=
diff --git a/test/fuzz/fuzz-varlink/array b/test/fuzz/fuzz-varlink/array
new file mode 100644 (file)
index 0000000..f3ee40b
Binary files /dev/null and b/test/fuzz/fuzz-varlink/array differ
diff --git a/test/fuzz/fuzz-varlink/do-something b/test/fuzz/fuzz-varlink/do-something
new file mode 100644 (file)
index 0000000..3b124cb
Binary files /dev/null and b/test/fuzz/fuzz-varlink/do-something differ
diff --git a/test/fuzz/fuzz-varlink/huge-method b/test/fuzz/fuzz-varlink/huge-method
new file mode 100644 (file)
index 0000000..a480e41
--- /dev/null
@@ -0,0 +1 @@
+{"method":"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "}\0
\ No newline at end of file
diff --git a/test/fuzz/fuzz-varlink/method-call b/test/fuzz/fuzz-varlink/method-call
new file mode 100644 (file)
index 0000000..8654a7c
Binary files /dev/null and b/test/fuzz/fuzz-varlink/method-call differ
diff --git a/test/fuzz/fuzz-varlink/method-error b/test/fuzz/fuzz-varlink/method-error
new file mode 100644 (file)
index 0000000..9ce68d8
Binary files /dev/null and b/test/fuzz/fuzz-varlink/method-error differ
diff --git a/test/fuzz/fuzz-varlink/method-reply b/test/fuzz/fuzz-varlink/method-reply
new file mode 100644 (file)
index 0000000..cd4bd94
Binary files /dev/null and b/test/fuzz/fuzz-varlink/method-reply differ
diff --git a/test/fuzz/fuzz-varlink/oss-fuzz-14688 b/test/fuzz/fuzz-varlink/oss-fuzz-14688
new file mode 100644 (file)
index 0000000..9d615db
--- /dev/null
@@ -0,0 +1 @@
+                                                                                                      {"method":"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "}\0                                                                       
\ No newline at end of file
diff --git a/test/fuzz/fuzz-varlink/oss-fuzz-14708 b/test/fuzz/fuzz-varlink/oss-fuzz-14708
new file mode 100644 (file)
index 0000000..d4391cd
--- /dev/null
@@ -0,0 +1 @@
+                                                                                                                                                 {"method":"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "}\0                                                       {   "method": "         "}\0                                                                 {   "method": "         "}\0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            vvvvvvvv\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\ No newline at end of file
diff --git a/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf b/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf
new file mode 100644 (file)
index 0000000..b0d8618
Binary files /dev/null and b/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf differ
index bcebc995072c3fcd2fb7e52501dae82b430ac275..996f859217cc4bb4331706a76d5a0559a00818a4 100644 (file)
@@ -4,6 +4,7 @@ Description=Test for SystemCallFilter
 [Service]
 ExecStart=/bin/sh -c 'echo "This should not be seen"'
 Type=oneshot
+LimitCORE=0
 SystemCallFilter=ioperm
 SystemCallFilter=~ioperm
 SystemCallFilter=ioperm
index 2fdc0ed7724cc7569b58bc6400f1bed5eb7b627b..c74f42248bdf04c436f72a294d49c8ec1cdb9994 100644 (file)
@@ -4,4 +4,5 @@ Description=Test for SystemCallFilter
 [Service]
 ExecStart=/bin/sh -c 'echo "This should not be seen"'
 Type=oneshot
+LimitCORE=0
 SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST
index 50c6e9690251a6c2b5c2a347ec4e0ce5a99c7799..4a76dd70ea10cb97190bc9dbd36884d172cd86fb 100644 (file)
@@ -14,7 +14,7 @@ NSPAWN_TIMEOUT="${NSPAWN_TIMEOUT:-infinity}"
 TIMED_OUT=  # will be 1 after run_* if *_TIMEOUT is set and test timed out
 [[ "$LOOKS_LIKE_SUSE" ]] && FSTYPE="${FSTYPE:-btrfs}" || FSTYPE="${FSTYPE:-ext4}"
 UNIFIED_CGROUP_HIERARCHY="${UNIFIED_CGROUP_HIERARCHY:-default}"
-EFI_MOUNT="$(bootctl -p 2>/dev/null || echo /boot)"
+EFI_MOUNT="$(bootctl -x 2>/dev/null || echo /boot)"
 QEMU_MEM="${QEMU_MEM:-512M}"
 
 if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
@@ -50,10 +50,34 @@ IS_BUILT_WITH_ASAN=$(is_built_with_asan && echo yes || echo no)
 
 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
     STRIP_BINARIES=no
-    SKIP_INITRD=yes
+    SKIP_INITRD="${SKIP_INITRD:-yes}"
     PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan
     QEMU_MEM="1536M"
     QEMU_SMP=4
+
+    # We need to correctly distinguish between gcc's and clang's ASan DSOs.
+    if ldd $BUILD_DIR/systemd | grep -q libasan.so; then
+        ASAN_COMPILER=gcc
+    elif ldd $BUILD_DIR/systemd | grep -q libclang_rt.asan; then
+        ASAN_COMPILER=clang
+
+        # As clang's ASan DSO is usually in a non-standard path, let's check if
+        # the environment is set accordingly. If not, warn the user and exit.
+        # We're not setting the LD_LIBRARY_PATH automagically here, because
+        # user should encounter (and fix) the same issue when running the unit
+        # tests (meson test)
+        if ldd "$BUILD_DIR/systemd" | grep -q "libclang_rt.asan.*not found"; then
+            _asan_rt_name="$(ldd $BUILD_DIR/systemd | awk '/libclang_rt.asan/ {print $1; exit}')"
+            _asan_rt_path="$(find /usr/lib* /usr/local/lib* -type f -name "$_asan_rt_name" 2>/dev/null | sed 1q)"
+            echo >&2 "clang's ASan DSO ($_asan_rt_name) is not present in the runtime library path"
+            echo >&2 "Consider setting LD_LIBRARY_PATH=${_asan_rt_path%/*}"
+            exit 1
+        fi
+    else
+        echo >&2 "systemd is not linked against the ASan DSO"
+        echo >&2 "gcc does this by default, for clang compile with -shared-libasan"
+        exit 1
+    fi
 fi
 
 function find_qemu_bin() {
@@ -268,7 +292,7 @@ setup_basic_environment() {
     install_depmod_files
     generate_module_dependencies
     if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
-         create_asan_wrapper
+        create_asan_wrapper
     fi
 }
 
@@ -348,7 +372,24 @@ EOF
 
 create_asan_wrapper() {
     local _asan_wrapper=$initdir/$ROOTLIBDIR/systemd-under-asan
+    local _asan_rt_pattern
     ddebug "Create $_asan_wrapper"
+
+    case "$ASAN_COMPILER" in
+        gcc)
+            _asan_rt_pattern="*libasan*"
+            ;;
+        clang)
+            _asan_rt_pattern="libclang_rt.asan-*"
+            # Install llvm-symbolizer to generate useful reports
+            # See: https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports
+            dracut_install "llvm-symbolizer"
+            ;;
+        *)
+            dfail "Unsupported compiler: $ASAN_COMPILER"
+            exit 1
+    esac
+
     cat >$_asan_wrapper <<EOF
 #!/bin/bash
 
@@ -358,18 +399,28 @@ DEFAULT_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:chec
 DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
 DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS"
 
+# As right now bash is the PID 1, we can't expect PATH to have a sane value.
+# Let's make one to prevent unexpected "<bin> not found" issues in the future
+export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
+
 mount -t proc proc /proc
 mount -t sysfs sysfs /sys
 mount -o remount,rw /
 
-PATH_TO_ASAN=\$(find / -name '*libasan*' | sed 1q)
+PATH_TO_ASAN=\$(find / -name '$_asan_rt_pattern' | sed 1q)
 if [[ "\$PATH_TO_ASAN" ]]; then
   # A lot of services (most notably dbus) won't start without preloading libasan
   # See https://github.com/systemd/systemd/issues/5004
   DEFAULT_ENVIRONMENT="\$DEFAULT_ENVIRONMENT LD_PRELOAD=\$PATH_TO_ASAN"
+  # Let's add the ASan DSO's path to the dynamic linker's cache. This is pretty
+  # unnecessary for gcc & libasan, however, for clang this is crucial, as its
+  # runtime ASan DSO is in a non-standard (library) path.
+  echo \${PATH_TO_ASAN%/*} > /etc/ld.so.conf.d/asan-path-override.conf
+  ldconfig
 fi
 echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf
 echo DefaultTimeoutStartSec=180s >>/etc/systemd/system.conf
+echo DefaultStandardOutput=journal+console >>/etc/systemd/system.conf
 
 # ASAN and syscall filters aren't compatible with each other.
 find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\)/#\\1/'
@@ -378,7 +429,12 @@ find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\
 # But, apparently, sometimes it doesn't work: https://github.com/google/sanitizers/issues/886.
 JOURNALD_CONF_DIR=/etc/systemd/system/systemd-journald.service.d
 mkdir -p "\$JOURNALD_CONF_DIR"
-printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log\n" >"\$JOURNALD_CONF_DIR/env.conf"
+printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:log_path=/systemd-journald.ubsan.log\n" >"\$JOURNALD_CONF_DIR/env.conf"
+
+# Sometimes UBSan sends its reports to stderr regardless of what is specified in log_path
+# Let's try to catch them by redirecting stderr (and stdout just in case) to a file
+# See https://github.com/systemd/systemd/pull/12524#issuecomment-491108821
+printf "[Service]\nStandardOutput=file:/systemd-journald.out\n" >"\$JOURNALD_CONF_DIR/out.conf"
 
 # 90s isn't enough for some services to finish when literally everything is run
 # under ASan+UBSan in containers, which, in turn, are run in VMs.
@@ -386,6 +442,22 @@ printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/sys
 mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d
 printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
 
+# Let's override another hard-coded timeout that kicks in too early
+mkdir -p /etc/systemd/system/systemd-journal-flush.service.d
+printf "[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-journal-flush.service.d/timeout.conf
+
+# The 'mount' utility doesn't behave well under libasan, causing unexpected
+# fails during boot and subsequent test results check:
+# bash-5.0# mount -o remount,rw -v /
+# mount: /dev/sda1 mounted on /.
+# bash-5.0# echo \$?
+# 1
+# Let's workaround this by clearing the previously set LD_PRELOAD env variable,
+# so the libasan library is not loaded for this particular service
+REMOUNTFS_CONF_DIR=/etc/systemd/system/systemd-remount-fs.service.d
+mkdir -p "\$REMOUNTFS_CONF_DIR"
+printf "[Service]\nUnsetEnvironment=LD_PRELOAD\n" >"\$REMOUNTFS_CONF_DIR/env.conf"
+
 export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
 exec  $ROOTLIBDIR/systemd "\$@"
 EOF
@@ -454,14 +526,14 @@ get_ldpath() {
 install_missing_libraries() {
     # install possible missing libraries
     for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
-        LD_LIBRARY_PATH=$(get_ldpath $i) inst_libs $i
+        LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i)" inst_libs $i
     done
 }
 
 create_empty_image() {
     local _size=500
     if [[ "$STRIP_BINARIES" = "no" ]]; then
-        _size=$((2*_size))
+        _size=$((4*_size))
     fi
     rm -f "$TESTDIR/rootdisk.img"
     # Create the blank file to use as a root filesystem
@@ -496,9 +568,10 @@ check_asan_reports() {
             ret=$(($ret+1))
         fi
 
-        journald_report=$(find "$root" -name "systemd-journald.asan.log*" -exec cat {} \;)
+        journald_report=$(find "$root" -name "systemd-journald.*san.log*" -exec cat {} \;)
         if [[ ! -z "$journald_report" ]]; then
-            printf "%s" "$journald_report"
+            printf "%s\n" "$journald_report"
+            cat "$root/systemd-journald.out" || true
             ret=$(($ret+1))
         fi
 
@@ -684,17 +757,20 @@ install_libnss() {
 install_dbus() {
     inst $ROOTLIBDIR/system/dbus.socket
 
-    # Fedora rawhide replaced dbus.service with dbus-daemon.service
-    if [ -f $ROOTLIBDIR/system/dbus-daemon.service ]; then
+    # Newer Fedora versions use dbus-broker by default. Let's install it is available.
+    if [ -f $ROOTLIBDIR/system/dbus-broker.service ]; then
+        inst $ROOTLIBDIR/system/dbus-broker.service
+        inst_symlink /etc/systemd/system/dbus.service
+        inst /usr/bin/dbus-broker
+        inst /usr/bin/dbus-broker-launch
+    elif [ -f $ROOTLIBDIR/system/dbus-daemon.service ]; then
+        # Fedora rawhide replaced dbus.service with dbus-daemon.service
         inst $ROOTLIBDIR/system/dbus-daemon.service
         # Alias symlink
         inst_symlink /etc/systemd/system/dbus.service
     else
         inst $ROOTLIBDIR/system/dbus.service
     fi
-    # Newer Fedora versions use dbus-broker by default. Let's install it is available.
-    [ -f /usr/bin/dbus-broker ] && inst /usr/bin/dbus-broker
-    [ -f /usr/bin/dbus-broker-launch ] && inst /usr/bin/dbus-broker-launch
 
     find \
         /etc/dbus-1 /usr/share/dbus-1 -xtype f \
index 0cd901def89cbac6c34c172a97eb5be330f0b04b..3edc59e7959eddf270d7b7f74c1044c284a5d3d0 100644 (file)
@@ -4,3 +4,4 @@ Name=vlan99
 [Network]
 IPv6AcceptRA=false
 Address=192.168.23.5/24
+LinkLocalAddressing=yes
index 439ddf2809604ec780947fff28535aa2b4222438..7e6a9edc69f889120076e70bf6525a7afaa6107d 100644 (file)
@@ -1,5 +1,5 @@
 [NetDev]
-Name=bond99
+Name=bond98
 Kind=bond
 
 [Bond]
index 9921b787a13ef9f8cbc9fa45df653002dcfdf237..d0f0c9a87e0c03405e962baa143503bf9032c140 100644 (file)
@@ -1,6 +1,3 @@
 [NetDev]
 Name=ipvlan99
 Kind=ipvlan
-
-[IPVLAN]
-Mode=L2
diff --git a/test/test-network/conf/25-ipvtap.netdev b/test/test-network/conf/25-ipvtap.netdev
new file mode 100644 (file)
index 0000000..2e40adb
--- /dev/null
@@ -0,0 +1,3 @@
+[NetDev]
+Name=ipvtap99
+Kind=ipvtap
index 7037048a45b86c6502fa3dde23eff52e6034b4c6..6def92f6d5d79f47161f7c4abb8967701b661d90 100644 (file)
@@ -4,3 +4,4 @@ Name=macsec99
 [Network]
 IPv6AcceptRA=no
 Address=10.1.2.3/16
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-netdevsim.netdev b/test/test-network/conf/25-netdevsim.netdev
new file mode 100644 (file)
index 0000000..899f2d9
--- /dev/null
@@ -0,0 +1,3 @@
+[NetDev]
+Kind=netdevsim
+Name=netdevsim99
index 50b2ce0c3bc1c55ea2357c97b34f4b4d1fa7c25b..9e12480a658dd48761e0e6a9852472382077b805 100644 (file)
@@ -5,6 +5,8 @@ Name=dummy98
 IPv6AcceptRA=no
 Address=2001:1234:5:8f63::1/128
 Address=149.10.124.58/28
+DefaultRouteOnDevice=yes
+IPv4LLRoute=yes
 
 [Route]
 Destination=2001:1234:5:8fff:ff:ff:ff:ff/128
index bf5e7fe52c18f1b879e7e40a10699daf1af82709..3876075a7a62d60b0af66d1aeb1fcfb28b0289af 100644 (file)
@@ -5,3 +5,4 @@ Kind=tap
 [Tap]
 MultiQueue=true
 PacketInfo=true
+VNetHeader=true
index 380ab21552f95b2fb65e6186f91af143994138cb..37459c79701b109c47698f8b1fb953de61a6089e 100644 (file)
@@ -5,3 +5,4 @@ Kind=tun
 [Tun]
 MultiQueue=true
 PacketInfo=true
+VNetHeader=true
diff --git a/test/test-network/conf/25-tunnel-local-any.network b/test/test-network/conf/25-tunnel-local-any.network
new file mode 100644 (file)
index 0000000..8ce05ad
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=*tun98 *tap98 ip6tnl98 erspan98
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:db8:0:f102::17/64
+Address=10.3.2.4/16
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-tunnel-remote-any.network b/test/test-network/conf/25-tunnel-remote-any.network
new file mode 100644 (file)
index 0000000..becdcaa
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=*tun97 ip6tnl97
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:db8:0:f102::18/64
+Address=10.3.2.5/16
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-tunnel.network b/test/test-network/conf/25-tunnel.network
new file mode 100644 (file)
index 0000000..32c1986
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=*tun99 *tap99 ip6tnl99 erspan99
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:db8:0:f102::16/64
+Address=10.3.2.3/16
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-vxcan.netdev b/test/test-network/conf/25-vxcan.netdev
new file mode 100644 (file)
index 0000000..6d879b1
--- /dev/null
@@ -0,0 +1,6 @@
+[NetDev]
+Name=vxcan99
+Kind=vxcan
+
+[VXCAN]
+Peer=vxcan-peer
index 819a58356faa1867ae571d649ec93577fd9aeff6..d5acf48da5b56cee4aa72b40e24f04cc9c1f2534 100644 (file)
@@ -3,7 +3,7 @@ Name=vxlan99
 Kind=vxlan
 
 [VXLAN]
-Id=999
+VNI=999
 L2MissNotification=true
 L3MissNotification=true
 RouteShortCircuit=true
index 1f70c3b86d60ed3dcb9417fd4b1c6a100ffc7c31..8b2e934f7fbf94fe5df1d7f6f21bc9651b42fabc 100644 (file)
@@ -3,3 +3,4 @@ Name=veth99
 
 [Network]
 DHCP=ipv6
+IPv6Token=::1a:2b:3c:4d
diff --git a/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network b/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network
new file mode 100644 (file)
index 0000000..9ebdbb4
--- /dev/null
@@ -0,0 +1,7 @@
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+LinkLocalAddressing=fallback
+IPv6AcceptRA=no
diff --git a/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network b/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network
new file mode 100644 (file)
index 0000000..7faff5f
--- /dev/null
@@ -0,0 +1,10 @@
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+LinkLocalAddressing=fallback
+IPv6AcceptRA=no
+
+[DHCP]
+MaxAttempts=1
diff --git a/test/test-network/conf/ipvtap.network b/test/test-network/conf/ipvtap.network
new file mode 100644 (file)
index 0000000..c81ba52
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=test1
+
+[Network]
+IPVTAP=ipvtap99
index d1360a59eb6f5c972a3ae673e4f55bf4f7879577..5558547c28ae17ebf3172f2e5fe50be48aac31db 100644 (file)
@@ -6,4 +6,5 @@ MACAddress=00:50:56:c0:00:19
 
 [Network]
 IPv6AcceptRA=no
+LinkLocalAddressing=yes
 MACsec=macsec99
diff --git a/test/test-network/conf/netdev-link-local-addressing-yes.network b/test/test-network/conf/netdev-link-local-addressing-yes.network
new file mode 100644 (file)
index 0000000..2e87424
--- /dev/null
@@ -0,0 +1,17 @@
+[Match]
+Name=ipvlan99
+Name=ipvtap99
+Name=macvlan99
+Name=macvtap99
+Name=veth99
+Name=veth-peer
+Name=vcan99
+Name=vxcan99
+Name=vxcan-peer
+Name=vrf99
+Name=geneve99
+Name=ipiptun99
+
+[Network]
+LinkLocalAddressing=yes
+IPv6AcceptRA=no
diff --git a/test/test-network/conf/vxlan-test1.network b/test/test-network/conf/vxlan-test1.network
new file mode 100644 (file)
index 0000000..aaffb64
--- /dev/null
@@ -0,0 +1,7 @@
+[Match]
+Name=test1
+
+[Network]
+IPv6AcceptRA=false
+LinkLocalAddressing=yes
+VXLAN=vxlan99
index 80b405574c6bc21a97dcae640b1f5083f6c5ebb9..fc8ac47a8ad82ea5aa5839c5906e33492f04318c 100644 (file)
@@ -1,5 +1,18 @@
 [Match]
-Name=test1
+Name=vxlan99
 
 [Network]
-VXLAN=vxlan99
+IPv6AcceptRA=no
+LinkLocalAddressing=yes
+
+[BridgeFDB]
+MACAddress=00:11:22:33:44:55
+Destination=10.0.0.5
+
+[BridgeFDB]
+MACAddress=00:11:22:33:44:66
+Destination=10.0.0.6
+
+[BridgeFDB]
+MACAddress=00:11:22:33:44:77
+Destination=10.0.0.7
index 806f860eb73331712a9570e337ff3d5822d2d97d..2eda211285644348cd79ae03e941fbeaf337dee7 100755 (executable)
@@ -100,17 +100,20 @@ class Utilities():
         with open(os.path.join(path, attribute)) as f:
             return f.readline().strip()
 
-    def link_exits(self, link):
+    def link_exists(self, link):
         return os.path.exists(os.path.join('/sys/class/net', link))
 
+    def check_link_exists(self, link):
+        self.assertTrue(self.link_exists(link))
+
     def link_remove(self, links):
         for link in links:
-            if os.path.exists(os.path.join('/sys/class/net', link)):
+            if self.link_exists(link):
                 subprocess.call(['ip', 'link', 'del', 'dev', link])
         time.sleep(1)
 
     def l2tp_tunnel_remove(self, tunnel_ids):
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel'], universal_newlines=True).rstrip()
         for tid in tunnel_ids:
             words='Tunnel ' + tid + ', encap'
             if words in output:
@@ -139,8 +142,8 @@ class Utilities():
                 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
                     shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
 
-    def start_dnsmasq(self, additional_options=''):
-        dnsmasq_command = 'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20 --dhcp-range=192.168.5.10,192.168.5.200 -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
+    def start_dnsmasq(self, additional_options='', lease_time='1h'):
+        dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20,{lease_time} --dhcp-range=192.168.5.10,192.168.5.200,{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
         subprocess.check_call(dnsmasq_command, shell=True)
 
         time.sleep(10)
@@ -159,7 +162,7 @@ class Utilities():
                 contents = in_file.read()
                 if show_all:
                     print(contents)
-                for line in contents.split('\n'):
+                for line in contents.splitlines():
                     if words in line:
                         in_file.close()
                         print("%s, %s" % (words, line))
@@ -189,7 +192,26 @@ class Utilities():
         args = [wait_online_bin, f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
         if bool_any:
             args += ['--any']
-        subprocess.check_call(args)
+        try:
+            subprocess.check_call(args)
+        except subprocess.CalledProcessError:
+            for link in links_with_operstate:
+                output = subprocess.check_output(['networkctl', 'status', link.split(':')[0]], universal_newlines=True).rstrip()
+                print(output)
+            raise
+
+    def get_operstate(self, link, show_status=True, setup_state='configured'):
+        output = subprocess.check_output(['networkctl', 'status', link], universal_newlines=True).rstrip()
+        if show_status:
+            print(output)
+        for line in output.splitlines():
+            if 'State:' in line and (not setup_state or setup_state in line):
+                return line.split()[1]
+        return None
+
+    def check_operstate(self, link, expected, show_status=True, setup_state='configured'):
+        self.assertRegex(self.get_operstate(link, show_status, setup_state), expected)
+
 
 class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
@@ -222,6 +244,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         'ipiptun98',
         'ipiptun99',
         'ipvlan99',
+        'ipvtap99',
         'isataptun99',
         'macvlan99',
         'macvtap99',
@@ -242,6 +265,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         'vtitun97',
         'vtitun98',
         'vtitun99',
+        'vxcan99',
         'vxlan99',
         'wg98',
         'wg99']
@@ -289,6 +313,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '25-ipip-tunnel-remote-any.netdev',
         '25-ipip-tunnel.netdev',
         '25-ipvlan.netdev',
+        '25-ipvtap.netdev',
         '25-isatap-tunnel.netdev',
         '25-macsec.key',
         '25-macsec.netdev',
@@ -298,6 +323,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '25-sit-tunnel.netdev',
         '25-tap.netdev',
         '25-tun.netdev',
+        '25-tunnel-local-any.network',
+        '25-tunnel-remote-any.network',
+        '25-tunnel.network',
         '25-vcan.netdev',
         '25-veth.netdev',
         '25-vrf.netdev',
@@ -307,6 +335,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '25-vti-tunnel-local-any.netdev',
         '25-vti-tunnel-remote-any.netdev',
         '25-vti-tunnel.netdev',
+        '25-vxcan.netdev',
         '25-vxlan.netdev',
         '25-wireguard-23-peers.netdev',
         '25-wireguard-23-peers.network',
@@ -324,13 +353,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         'ip6tnl.network',
         'ipip.network',
         'ipvlan.network',
+        'ipvtap.network',
         'isatap.network',
         'macsec.network',
         'macvlan.network',
         'macvtap.network',
+        'netdev-link-local-addressing-yes.network',
         'sit.network',
         'vti6.network',
         'vti.network',
+        'vxlan-test1.network',
         'vxlan.network']
 
     def setUp(self):
@@ -340,37 +372,37 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.link_remove(self.links)
         self.remove_unit_from_networkd_path(self.units)
 
-    def test_dropin(self):
+    def test_dropin_and_networkctl_glob(self):
         self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('dropin-test'))
+        self.wait_online(['dropin-test:off'])
 
         # This also tests NetDev.Name= conflict and basic networkctl functionalities
 
-        output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '00:50:56:c0:00:28')
 
-        output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'list'], universal_newlines=True).rstrip()
         self.assertRegex(output, '1 lo ')
         self.assertRegex(output, 'dropin-test')
 
-        output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'list', 'dropin-test'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, '1 lo ')
         self.assertRegex(output, 'dropin-test')
 
-        output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'list', 'dropin-*'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, '1 lo ')
         self.assertRegex(output, 'dropin-test')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dropin-*']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'dropin-*'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, '1: lo ')
         self.assertRegex(output, 'dropin-test')
 
-        ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        print(ret.stdout.rstrip().decode('utf-8'))
-        if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip().decode('utf-8')) != None:
+        ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
+        print(ret.stdout.rstrip())
+        if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip()) != None:
             self.assertRegex(output, 'Driver: dummy')
         else:
             print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
@@ -380,37 +412,31 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
 
         self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
-        self.assertTrue(self.link_exits('bridge99'))
-        self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: (?:off|no-carrier) \(configuring\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: degraded \(configured\)')
+        self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring')
+        self.check_operstate('test1', 'degraded')
 
     def test_bridge(self):
         self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('bridge99'))
+        self.wait_online(['bridge99:off'])
 
-        self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
-        self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
-        self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
-        self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
-        self.assertEqual('9',   self.read_link_attr('bridge99', 'bridge','priority'))
-        self.assertEqual('1',   self.read_link_attr('bridge99', 'bridge','multicast_querier'))
-        self.assertEqual('1',   self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
-        self.assertEqual('1',   self.read_link_attr('bridge99', 'bridge','stp_state'))
+        tick = os.sysconf('SC_CLK_TCK')
+        self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
+        self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
+        self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge','forward_delay')) / tick))
+        self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge','ageing_time')) / tick))
+        self.assertEqual(9,         int(self.read_link_attr('bridge99', 'bridge','priority')))
+        self.assertEqual(1,         int(self.read_link_attr('bridge99', 'bridge','multicast_querier')))
+        self.assertEqual(1,         int(self.read_link_attr('bridge99', 'bridge','multicast_snooping')))
+        self.assertEqual(1,         int(self.read_link_attr('bridge99', 'bridge','stp_state')))
 
     def test_bond(self):
-        self.copy_unit_to_networkd_unit_path('25-bond.netdev')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('bond99'))
+        self.wait_online(['bond99:off', 'bond98:off'])
 
         self.assertEqual('802.3ad 4',         self.read_link_attr('bond99', 'bonding', 'mode'))
         self.assertEqual('layer3+4 1',        self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
@@ -424,28 +450,21 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertEqual('811',               self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
         self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
 
-    def test_bond_balanced_tlb(self):
-        self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('bond99'))
-
-        self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
-        self.assertEqual('1',             self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
+        self.assertEqual('balance-tlb 5',     self.read_link_attr('bond98', 'bonding', 'mode'))
+        self.assertEqual('1',                 self.read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
 
     def test_vlan(self):
         self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
                                              '21-vlan.network', '21-vlan-test1.network')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('vlan99'))
+        self.wait_online(['test1:degraded', 'vlan99:routable'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
-        self.assertRegex(output, ' mtu 2004 ')
+        self.assertRegex(output, ' mtu 2000 ')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, ' mtu 2000 ')
         self.assertRegex(output, 'REORDER_HDR')
@@ -454,80 +473,145 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'MVRP')
         self.assertRegex(output, ' id 99 ')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
         self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
 
     def test_macvtap(self):
-        self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('macvtap99'))
+        for mode in ['private', 'vepa', 'bridge', 'passthru']:
+            with self.subTest(mode=mode):
+                if mode != 'private':
+                    self.tearDown()
+                self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
+                                                     '11-dummy.netdev', 'macvtap.network')
+                with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
+                    f.write('[MACVTAP]\nMode=' + mode)
+                self.start_networkd(0)
+
+                self.wait_online(['macvtap99:degraded', 'test1:degraded'])
+
+                output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvtap99'], universal_newlines=True).rstrip()
+                print(output)
+                self.assertRegex(output, 'macvtap mode ' + mode + ' ')
 
     def test_macvlan(self):
-        self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('macvlan99'))
-
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, ' mtu 2000 ')
-
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, ' mtu 2000 ')
+        for mode in ['private', 'vepa', 'bridge', 'passthru']:
+            with self.subTest(mode=mode):
+                if mode != 'private':
+                    self.tearDown()
+                self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
+                                                     '11-dummy.netdev', 'macvlan.network')
+                with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
+                    f.write('[MACVLAN]\nMode=' + mode)
+                self.start_networkd(0)
+
+                self.wait_online(['macvlan99:degraded', 'test1:degraded'])
+
+                output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
+                print(output)
+                self.assertRegex(output, ' mtu 2000 ')
+
+                output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99'], universal_newlines=True).rstrip()
+                print(output)
+                self.assertRegex(output, ' mtu 2000 ')
+                self.assertRegex(output, 'macvlan mode ' + mode + ' ')
 
     @expectedFailureIfModuleIsNotAvailable('ipvlan')
     def test_ipvlan(self):
-        self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('ipvlan99'))
+        for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
+            with self.subTest(mode=mode, flag=flag):
+                if mode != 'L2':
+                    self.tearDown()
+                self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
+                                                     '11-dummy.netdev', 'ipvlan.network')
+                with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
+                    f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
+
+                self.start_networkd(0)
+                self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
+
+                output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipvlan99'], universal_newlines=True).rstrip()
+                print(output)
+                self.assertRegex(output, 'ipvlan  *mode ' + mode.lower() + ' ' + flag)
+
+    @expectedFailureIfModuleIsNotAvailable('ipvtap')
+    def test_ipvtap(self):
+        for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
+            with self.subTest(mode=mode, flag=flag):
+                if mode != 'L2':
+                    self.tearDown()
+                self.copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
+                                                     '11-dummy.netdev', 'ipvtap.network')
+                with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
+                    f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
+
+                self.start_networkd(0)
+                self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
+
+                output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipvtap99'], universal_newlines=True).rstrip()
+                print(output)
+                self.assertRegex(output, 'ipvtap  *mode ' + mode.lower() + ' ' + flag)
 
     def test_veth(self):
-        self.copy_unit_to_networkd_unit_path('25-veth.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('veth99'))
+        self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
 
-    def test_dummy(self):
-        self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
-        self.start_networkd()
+        self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
 
-        self.assertTrue(self.link_exits('test1'))
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'veth-peer'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
 
     def test_tun(self):
         self.copy_unit_to_networkd_unit_path('25-tun.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('tun99'))
+        self.wait_online(['tun99:off'])
+
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'tun99'], universal_newlines=True).rstrip()
+        print(output)
+        # Old ip command does not support IFF_ flags
+        self.assertRegex(output, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
 
     def test_tap(self):
         self.copy_unit_to_networkd_unit_path('25-tap.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
+
+        self.wait_online(['tap99:off'])
 
-        self.assertTrue(self.link_exits('tap99'))
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'tap99'], universal_newlines=True).rstrip()
+        print(output)
+        # Old ip command does not support IFF_ flags
+        self.assertRegex(output, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
 
     @expectedFailureIfModuleIsNotAvailable('vrf')
     def test_vrf(self):
-        self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('vrf99'))
+        self.wait_online(['vrf99:carrier'])
 
     @expectedFailureIfModuleIsNotAvailable('vcan')
     def test_vcan(self):
-        self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
+
+        self.wait_online(['vcan99:carrier'])
 
-        self.assertTrue(self.link_exits('vcan99'))
+    @expectedFailureIfModuleIsNotAvailable('vxcan')
+    def test_vxcan(self):
+        self.copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
+
+        self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
 
     @expectedFailureIfModuleIsNotAvailable('wireguard')
     def test_wireguard(self):
@@ -537,39 +621,36 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['wg99:carrier', 'wg98:routable'])
 
-        self.assertTrue(self.link_exits('wg99'))
-        self.assertTrue(self.link_exits('wg98'))
-
         if shutil.which('wg'):
             subprocess.call('wg')
 
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port'], universal_newlines=True).rstrip()
             self.assertRegex(output, '51820')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark'], universal_newlines=True).rstrip()
             self.assertRegex(output, '0x4d2')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
             self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=  IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
             self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=     cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
 
-            output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
 
     def test_geneve(self):
-        self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('geneve99'))
+        self.wait_online(['geneve99:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.22.1')
         self.assertRegex(output, '6082')
@@ -577,50 +658,46 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'udp6zerocsumrx')
 
     def test_ipip_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network',
-                                             '25-ipip-tunnel-local-any.netdev', '25-ipip-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ipiptun99'))
-        self.assertTrue(self.link_exits('ipiptun98'))
-        self.assertTrue(self.link_exits('ipiptun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
+                                             '25-ipip-tunnel.netdev', '25-tunnel.network',
+                                             '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
 
     def test_gre_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network',
-                                             '25-gre-tunnel-local-any.netdev', '25-gre-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('gretun99'))
-        self.assertTrue(self.link_exits('gretun98'))
-        self.assertTrue(self.link_exits('gretun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
+                                             '25-gre-tunnel.netdev', '25-tunnel.network',
+                                             '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
         self.assertRegex(output, 'ikey 1.2.3.103')
         self.assertRegex(output, 'okey 1.2.4.103')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.104')
         self.assertRegex(output, 'okey 0.0.0.104')
         self.assertNotRegex(output, 'iseq')
         self.assertNotRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.105')
@@ -629,42 +706,44 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertNotRegex(output, 'oseq')
 
     def test_ip6gre_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretun.network',
-                                             '25-ip6gre-tunnel-local-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
+                                             '25-ip6gre-tunnel.netdev', '25-tunnel.network',
+                                             '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ip6gretun99'))
-        self.assertTrue(self.link_exits('ip6gretun98'))
-        self.assertTrue(self.link_exits('ip6gretun97'))
+        # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun99']).rstrip().decode('utf-8')
+        self.check_link_exists('dummy98')
+        self.check_link_exists('ip6gretun99')
+        self.check_link_exists('ip6gretun98')
+        self.check_link_exists('ip6gretun97')
+
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
 
     def test_gretap_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network',
-                                             '25-gretap-tunnel-local-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('gretap99'))
-        self.assertTrue(self.link_exits('gretap98'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
+                                             '25-gretap-tunnel.netdev', '25-tunnel.network',
+                                             '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+        self.start_networkd(0)
+        self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.106')
         self.assertRegex(output, 'okey 0.0.0.106')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.107')
@@ -673,142 +752,127 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'oseq')
 
     def test_ip6gretap_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretap-tunnel.netdev', 'ip6gretap.network',
-                                             '25-ip6gretap-tunnel-local-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ip6gretap99'))
-        self.assertTrue(self.link_exits('ip6gretap98'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
+                                             '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
+                                             '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+        self.start_networkd(0)
+        self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
 
     def test_vti_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network',
-                                             '25-vti-tunnel-local-any.netdev', '25-vti-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('vtitun99'))
-        self.assertTrue(self.link_exits('vtitun98'))
-        self.assertTrue(self.link_exits('vtitun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
+                                             '25-vti-tunnel.netdev', '25-tunnel.network',
+                                             '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
 
     def test_vti6_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network',
-                                             '25-vti6-tunnel-local-any.netdev', '25-vti6-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('vti6tun99'))
-        self.assertTrue(self.link_exits('vti6tun98'))
-        self.assertTrue(self.link_exits('vti6tun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
+                                             '25-vti6-tunnel.netdev', '25-tunnel.network',
+                                             '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
 
     def test_ip6tnl_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network',
-                                             '25-ip6tnl-tunnel-local-any.netdev', '25-ip6tnl-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ip6tnl99'))
-        self.assertTrue(self.link_exits('ip6tnl98'))
-        self.assertTrue(self.link_exits('ip6tnl97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
+                                             '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
+                                             '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
 
     def test_sit_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network',
-                                             '25-sit-tunnel-local-any.netdev',
-                                             '25-sit-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('sittun99'))
-        self.assertTrue(self.link_exits('sittun98'))
-        self.assertTrue(self.link_exits('sittun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
+                                             '25-sit-tunnel.netdev', '25-tunnel.network',
+                                             '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
 
     def test_isatap_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('isataptun99'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
+                                             '25-isatap-tunnel.netdev', '25-tunnel.network')
+        self.start_networkd(0)
+        self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "isatap ")
 
     def test_6rd_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('sittun99'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
+                                             '25-6rd-tunnel.netdev', '25-tunnel.network')
+        self.start_networkd(0)
+        self.wait_online(['sittun99:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '6rd-prefix 2602::/24')
 
     @expectedFailureIfERSPANModuleIsNotAvailable()
     def test_erspan_tunnel(self):
         self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
-                                             '25-erspan-tunnel.netdev', '25-erspan-tunnel-local-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('erspan99'))
-        self.assertTrue(self.link_exits('erspan98'))
+                                             '25-erspan-tunnel.netdev', '25-tunnel.network',
+                                             '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+        self.start_networkd(0)
+        self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
         self.assertRegex(output, 'ikey 0.0.0.101')
         self.assertRegex(output, 'okey 0.0.0.101')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
         self.assertRegex(output, '102')
@@ -818,10 +882,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'oseq')
 
     def test_tunnel_independent(self):
-        self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('ipiptun99'))
+        self.wait_online(['ipiptun99:carrier'])
 
     @expectedFailureIfModuleIsNotAvailable('fou')
     def test_fou(self):
@@ -832,28 +896,25 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
                                              '25-fou-ipip.netdev', '25-fou-sit.netdev',
                                              '25-fou-gre.netdev', '25-fou-gretap.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('ipiptun96'))
-        self.assertTrue(self.link_exits('sittun96'))
-        self.assertTrue(self.link_exits('gretun96'))
-        self.assertTrue(self.link_exits('gretap96'))
+        self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'])
 
-        output = subprocess.check_output(['ip', 'fou', 'show']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'fou', 'show'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'port 55555 ipproto 4')
         self.assertRegex(output, 'port 55556 ipproto 47')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
 
@@ -861,14 +922,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         subprocess.call(['ip', 'fou', 'del', 'port', '55556'])
 
     def test_vxlan(self):
-        self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network', '11-dummy.netdev')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
+                                             '11-dummy.netdev', 'vxlan-test1.network')
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('vxlan99'))
+        self.wait_online(['test1:degraded', 'vxlan99:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99'], universal_newlines=True).rstrip()
         print(output)
-        self.assertRegex(output, "999")
+        self.assertRegex(output, '999')
         self.assertRegex(output, '5555')
         self.assertRegex(output, 'l2miss')
         self.assertRegex(output, 'l3miss')
@@ -879,6 +941,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'remcsumrx')
         self.assertRegex(output, 'gbp')
 
+        output = subprocess.check_output(['bridge', 'fdb', 'show', 'dev', 'vxlan99'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
+        self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
+        self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
+
     def test_macsec(self):
         self.copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
                                              'macsec.network', '12-dummy.netdev')
@@ -886,13 +954,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         self.wait_online(['dummy98:degraded', 'macsec99:routable'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macsec99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macsec99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'macsec99@dummy98')
         self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
         self.assertRegex(output, 'encrypt on')
 
-        output = subprocess.check_output(['ip', 'macsec', 'show', 'macsec99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'macsec', 'show', 'macsec99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encrypt on')
         self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
@@ -937,13 +1005,11 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
     @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
     def test_l2tp_udp(self):
         self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-udp.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('l2tp-ses1'))
-        self.assertTrue(self.link_exits('l2tp-ses2'))
+        self.wait_online(['test1:routable', 'l2tp-ses1:off', 'l2tp-ses2:off'])
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Tunnel 10, encap UDP")
         self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
@@ -951,13 +1017,13 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
         self.assertRegex(output, "UDP source / dest ports: 3000/4000")
         self.assertRegex(output, "UDP checksum: enabled")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '15']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '15'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 15 in tunnel 10")
         self.assertRegex(output, "Peer session 16, tunnel 11")
         self.assertRegex(output, "interface name: l2tp-ses1")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '17']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '17'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 17 in tunnel 10")
         self.assertRegex(output, "Peer session 18, tunnel 11")
@@ -966,25 +1032,23 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
     @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
     def test_l2tp_ip(self):
         self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-ip.netdev')
-        self.start_networkd()
+        self.start_networkd(0)
 
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('l2tp-ses3'))
-        self.assertTrue(self.link_exits('l2tp-ses4'))
+        self.wait_online(['test1:routable', 'l2tp-ses3:off', 'l2tp-ses4:off'])
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Tunnel 10, encap IP")
         self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
         self.assertRegex(output, "Peer tunnel 12")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '25']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '25'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 25 in tunnel 10")
         self.assertRegex(output, "Peer session 26, tunnel 12")
         self.assertRegex(output, "interface name: l2tp-ses3")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '27']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '27'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 27 in tunnel 10")
         self.assertRegex(output, "Peer session 28, tunnel 12")
@@ -1034,7 +1098,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.wait_online(['dummy98:routable'])
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
         self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
@@ -1044,19 +1108,19 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertNotRegex(output, '10.10.0.1/16')
         self.assertNotRegex(output, '10.10.0.2/16')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '32']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '32'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '33']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '33'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '34']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '34'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '35']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '35'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
         self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
@@ -1069,13 +1133,11 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configuring\)')
+        self.check_operstate('dummy98', 'routable', setup_state='configuring')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
         self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
@@ -1084,9 +1146,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('test1'))
+        self.check_link_exists('test1')
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.0.15')
         self.assertRegex(output, '192.168.0.1')
@@ -1099,9 +1161,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('test1'))
+        self.check_link_exists('test1')
 
-        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '111')
         self.assertRegex(output, 'from 192.168.100.18')
@@ -1123,14 +1185,14 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
             # Remove state files only first time
             self.start_networkd(remove_state_files=(trial == 0))
 
-            self.assertTrue(self.link_exits('test1'))
-            self.assertTrue(self.link_exits('dummy98'))
+            self.check_link_exists('test1')
+            self.check_link_exists('dummy98')
 
-            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7'], universal_newlines=True).rstrip()
             print(output)
             self.assertRegex(output, '111:     from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
 
-            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8'], universal_newlines=True).rstrip()
             print(output)
             self.assertRegex(output, '112:     from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
 
@@ -1145,9 +1207,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('test1'))
+        self.check_link_exists('test1')
 
-        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '111')
         self.assertRegex(output, 'from 192.168.100.18')
@@ -1166,9 +1228,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('test1'))
+        self.check_link_exists('test1')
 
-        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '111')
         self.assertRegex(output, 'not.*?from.*?192.168.100.18')
@@ -1183,34 +1245,36 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.wait_online(['dummy98:routable'])
 
-        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
         self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
 
-        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98', 'default'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
 
-        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
         self.assertRegex(output, '149.10.124.64 proto static scope link')
+        self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
         self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
         self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
 
-        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98', 'default'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
         self.assertRegex(output, 'default via 149.10.124.64 proto static')
+        self.assertRegex(output, 'default proto static')
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'blackhole']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'blackhole'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'unreachable']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'unreachable'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'prohibit']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'prohibit'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
 
@@ -1225,10 +1289,10 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('bond199'))
+        self.check_link_exists('dummy98')
+        self.check_link_exists('bond199')
 
-        output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'abcd::/16')
         self.assertRegex(output, 'src')
@@ -1238,9 +1302,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '00:01:02:aa:bb:cc')
 
@@ -1248,9 +1312,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'unmanaged')
 
@@ -1258,9 +1322,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'addrlabel', 'list'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2004:da8:1::/64')
 
@@ -1268,9 +1332,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'neigh', 'list'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
         self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
@@ -1281,25 +1345,20 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['test1:degraded', 'dummy98:carrier'])
 
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('test1')
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet .* scope link')
         self.assertRegex(output, 'inet6 .* scope link')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, 'inet6* .* scope link')
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: degraded \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: carrier \(configured\)')
+        self.check_operstate('test1', 'degraded')
+        self.check_operstate('dummy98', 'carrier')
 
         '''
         Documentation/networking/ip-sysctl.txt
@@ -1339,8 +1398,6 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['dummy98:degraded'])
 
-        self.assertTrue(self.link_exits('dummy98'))
-
         self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
         self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
         self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
@@ -1359,16 +1416,13 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['dummy98:routable'])
 
-        self.assertTrue(self.link_exits('dummy98'))
-
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, '')
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
 
@@ -1379,71 +1433,63 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['dummy98:routable'])
 
-        self.assertTrue(self.link_exits('dummy98'))
-
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet6 .* scope link')
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'routable')
 
     def test_bind_carrier(self):
         self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('test1'))
+        self.check_link_exists('test1')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'DOWN')
         self.assertNotRegex(output, '192.168.10')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: off \(configured\)')
+        self.check_operstate('test1', 'off')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
 class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
     links = [
@@ -1475,10 +1521,10 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('bond199'))
+        self.check_link_exists('dummy98')
+        self.check_link_exists('bond199')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'active_slave dummy98')
 
@@ -1486,10 +1532,10 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('bond199'))
+        self.check_link_exists('test1')
+        self.check_link_exists('bond199')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'primary test1')
 
@@ -1498,79 +1544,58 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
                                              'bond99.network','bond-slave.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('bond99'))
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('test1'))
+        self.check_link_exists('bond99')
+        self.check_link_exists('dummy98')
+        self.check_link_exists('test1')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'MASTER,UP,LOWER_UP')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'enslaved')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('bond99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
         time.sleep(2)
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: off \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: degraded-carrier \(configured\)')
+        self.check_operstate('dummy98', 'off')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('bond99', 'degraded-carrier')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
         time.sleep(2)
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'enslaved')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('bond99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
-        time.sleep(5)
+        time.sleep(2)
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: off \(configured\)')
+        self.check_operstate('dummy98', 'off')
+        self.check_operstate('test1', 'off')
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: off \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: no-carrier \(configured\)')
+        for trial in range(30):
+            if trial > 0:
+                time.sleep(1)
+            output = subprocess.check_output(['ip', 'address', 'show', 'bond99'], universal_newlines=True).rstrip()
+            print(output)
+            if self.get_operstate('bond99') == 'no-carrier':
+                break
+        else:
+            # Huh? Kernel does not recognize that all slave interfaces are down?
+            # Let's confirm that networkd's operstate is consistent with ip's result.
+            self.assertNotRegex(output, 'NO-CARRIER')
 
 class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
     links = [
@@ -1600,25 +1625,25 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
                                              'bridge99.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('bridge99'))
+        self.check_link_exists('dummy98')
+        self.check_link_exists('test1')
+        self.check_link_exists('bridge99')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'master')
         self.assertRegex(output, 'bridge')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'master')
         self.assertRegex(output, 'bridge')
 
-        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.0.15/24')
 
-        output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
         self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
@@ -1633,38 +1658,30 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
         if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
             self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('dummy98', 'enslaved')
+        self.check_operstate('bridge99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
         time.sleep(1)
 
-        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.0.16/24')
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('bridge99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
         time.sleep(3)
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: degraded-carrier \(configured\)')
+        self.check_operstate('bridge99', 'degraded-carrier')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
         time.sleep(3)
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: no-carrier \(configured\)')
+        self.check_operstate('bridge99', 'no-carrier')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'NO-CARRIER')
         self.assertNotRegex(output, '192.168.0.15/24')
@@ -1679,9 +1696,9 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
 
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('test1'))
-        self.assertTrue(self.link_exits('bridge99'))
+        self.check_link_exists('dummy98')
+        self.check_link_exists('test1')
+        self.check_link_exists('bridge99')
 
         self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
         time.sleep(1)
@@ -1690,7 +1707,7 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
         time.sleep(3)
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'NO-CARRIER')
         self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
@@ -1706,7 +1723,7 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
 
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('bridge99'))
+        self.check_link_exists('bridge99')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
@@ -1723,19 +1740,19 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
 
-        time.sleep(3)
+        for trial in range(30):
+            if trial > 0:
+                time.sleep(1)
+            if self.get_operstate('bridge99') == 'routable' and self.get_operstate('dummy98') == 'enslaved':
+                break
+        else:
+            self.assertTrue(False)
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, '0:   from all to 8.8.8.8 lookup 100')
 
@@ -1760,9 +1777,9 @@ class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
-        output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'lldp'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'veth-peer')
         self.assertRegex(output, 'veth99')
@@ -1786,9 +1803,9 @@ class NetworkdNetworkRATests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2002:da8:1:0')
 
@@ -1817,9 +1834,9 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.*')
         self.assertRegex(output, 'Gateway: 192.168.5.1')
@@ -1830,9 +1847,9 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('dummy98'))
+        self.check_link_exists('dummy98')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'Address: 192.168.42.100')
         self.assertRegex(output, 'DNS: 192.168.42.1')
@@ -1842,9 +1859,9 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'Gateway: 192.168.5.*')
         self.assertRegex(output, '192.168.5.*')
@@ -1872,6 +1889,8 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         'dhcp-client-route-metric.network',
         'dhcp-client-route-table.network',
         'dhcp-client-vrf.network',
+        'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
+        'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
         'dhcp-client.network',
         'dhcp-server-veth-peer.network',
         'dhcp-v4-server-veth-peer.network',
@@ -1890,26 +1909,31 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
     def test_dhcp_client_ipv6_only(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('veth99'))
 
+        self.start_networkd(0)
+        self.wait_online(['veth-peer:carrier'])
         self.start_dnsmasq()
+        self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2600::')
         self.assertNotRegex(output, '192.168.5')
 
+        # Confirm that ipv6 token is not set in the kernel
+        output = subprocess.check_output(['ip', 'token', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, 'token :: dev veth99')
+
     def test_dhcp_client_ipv4_only(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, '2600::')
         self.assertRegex(output, '192.168.5')
@@ -1919,11 +1943,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
                                              'dhcp-client-ipv4-only.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2600::')
         self.assertRegex(output, '192.168.5')
@@ -1932,12 +1956,12 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
         print('## ip address show dev veth99')
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
         self.assertRegex(output, '192.168.5')
@@ -1945,12 +1969,12 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         # issue #8726
         print('## ip route show table main dev veth99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, 'proto dhcp')
 
         print('## ip route show table 211 dev veth99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
         self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
@@ -1966,11 +1990,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
         self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
@@ -1979,11 +2003,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
         self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
@@ -1992,7 +2016,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
@@ -2004,11 +2028,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq('--dhcp-alternate-port=67,5555')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.* dynamic')
 
@@ -2016,11 +2040,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', '12'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'veth99 proto dhcp')
         self.assertRegex(output, '192.168.5.1')
@@ -2029,11 +2053,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'metric 24')
 
@@ -2041,11 +2065,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.*')
 
@@ -2055,7 +2079,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
         time.sleep(125)
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.*')
 
@@ -2063,11 +2087,11 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5')
         self.assertRegex(output, '2600::')
@@ -2084,14 +2108,14 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5')
         self.assertRegex(output, 'valid_lft forever preferred_lft forever')
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2600::')
         self.assertRegex(output, 'valid_lft forever preferred_lft forever')
@@ -2102,22 +2126,22 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
                                              '25-vrf.netdev', '25-vrf.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
-        self.assertTrue(self.link_exits('vrf99'))
+        self.check_link_exists('veth99')
+        self.check_link_exists('vrf99')
 
         self.start_dnsmasq()
 
         print('## ip -d link show dev vrf99')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vrf table 42')
 
         print('## ip address show vrf vrf99')
-        output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
+        output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99'], universal_newlines=True).rstrip()
         print(output_ip_vrf)
 
         print('## ip address show dev veth99')
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, output_ip_vrf)
         self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
@@ -2126,7 +2150,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'inet6 .* scope link')
 
         print('## ip route show vrf vrf99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
         self.assertRegex(output, 'default dev veth99 proto static scope link')
@@ -2136,38 +2160,88 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
 
         print('## ip route show table main dev veth99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, '')
 
-        output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: carrier \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('vrf99', 'carrier')
+        self.check_operstate('veth99', 'routable')
 
     def test_dhcp_client_gateway_onlink_implicit(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
                                              'dhcp-client-gateway-onlink-implicit.network')
         self.start_networkd()
 
-        self.assertTrue(self.link_exits('veth99'))
+        self.check_link_exists('veth99')
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5')
 
-        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'onlink')
-        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'onlink')
 
+    def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
+        self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+                                             'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
+        self.start_networkd(0)
+        self.wait_online(['veth-peer:carrier'])
+        self.start_dnsmasq(lease_time='2m')
+        self.wait_online(['veth99:routable', 'veth-peer:routable'])
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
+        self.assertRegex(output, 'inet6 .* scope link')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
+        self.assertNotRegex(output, 'inet .* scope link')
+
+        print('Wait for the dynamic address to be expired')
+        time.sleep(130)
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
+        self.assertRegex(output, 'inet6 .* scope link')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
+        self.assertNotRegex(output, 'inet .* scope link')
+
+        self.search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
+
+    def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
+        self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+                                             'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
+        self.start_networkd(0)
+        self.wait_online(['veth99:degraded', 'veth-peer:routable'])
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
+        self.assertRegex(output, 'inet6 .* scope link')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
+        self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
+        self.assertRegex(output, 'inet .* scope link')
+
 if __name__ == '__main__':
     unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
                                                      verbosity=3))
index b94a9d0f47711d40a8a1b6c519e099afff0d5809..f14b4fc6dffc6e2291a8b5b42709304eef50055a 100644 (file)
@@ -4,7 +4,7 @@ enable_tmpfiles = conf.get('ENABLE_TMPFILES') == 1
 
 tmpfiles = [['home.conf',            ''],
             ['journal-nocow.conf',   ''],
-            ['systemd-nologin.conf', ''],
+            ['systemd-nologin.conf', 'HAVE_PAM'],
             ['systemd-nspawn.conf',  'ENABLE_MACHINED'],
             ['systemd-tmp.conf',     ''],
             ['portables.conf',       'ENABLE_PORTABLED'],
index e8c6e600407ac5764f632ef24a582b0f32414790..a90fb604ae0999d6ba3a7907a7c6a50eac7d5c15 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 set -e
 
+which perl &>/dev/null || exit 77
+
 function generate_directives() {
     perl -aF'/[\s,]+/' -ne '
         if (my ($s, $d) = ($F[0] =~ /^([^\s\.]+)\.([^\s\.]+)$/)) { $d{$s}{"$d="} = 1; }
@@ -10,17 +12,23 @@ function generate_directives() {
 }
 
 ret=0
-if [[ $(generate_directives src/network/networkd-network-gperf.gperf | wc -l) -ne $(wc -l <test/fuzz/fuzz-network-parser/directives.network) ]]; then
+if ! diff \
+     <(generate_directives "$1"/src/network/networkd-network-gperf.gperf | sort) \
+     <(cat "$1"/test/fuzz/fuzz-network-parser/directives.network | sort); then
     echo "Looks like test/fuzz/fuzz-network-parser/directives.network hasn't been updated"
     ret=1
 fi
 
-if [[ $(generate_directives src/network/netdev/netdev-gperf.gperf | wc -l) -ne $(wc -l <test/fuzz/fuzz-netdev-parser/directives.netdev) ]]; then
+if ! diff \
+     <(generate_directives "$1"/src/network/netdev/netdev-gperf.gperf | sort) \
+     <(cat "$1"/test/fuzz/fuzz-netdev-parser/directives.netdev | sort); then
     echo "Looks like test/fuzz/fuzz-netdev-parser/directives.netdev hasn't been updated"
     ret=1
 fi
 
-if [[ $(generate_directives src/udev/net/link-config-gperf.gperf | wc -l) -ne $(wc -l <test/fuzz/fuzz-link-parser/directives.link) ]]; then
+if ! diff \
+     <(generate_directives "$1"/src/udev/net/link-config-gperf.gperf | sort) \
+     <(cat "$1"/test/fuzz/fuzz-link-parser/directives.link | sort) ; then
     echo "Looks like test/fuzz/fuzz-link-parser/directives.link hasn't been updated"
     ret=1
 fi
index a8605b6bc94167b6ea2df7dc265be171da1c7e53..5dc95fa8c15ad4fd61a84c5ade936010c8594482 100755 (executable)
@@ -15,4 +15,8 @@ fi
 # Apparently git describe has a bug where it always considers the work-tree
 # dirty when invoked with --git-dir (even though 'git status' is happy). Work
 # around this issue by cd-ing to the source directory.
-cd "$dir" && git describe --abbrev=7 --dirty=+ 2>/dev/null | sed 's/^v//' || echo "$fallback"
+cd "$dir"
+# 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.
+[ -e .git ] && git describe --abbrev=7 --dirty=+ 2>/dev/null | sed 's/^v//' || echo "$fallback"
index 610bb9c2353cda83c8e0cf593a076f1dc95d7cd3..6d9010ce16070d6935d5b2fbc513a24ec8d9e101 100755 (executable)
@@ -10,7 +10,7 @@ export CXX=${CXX:-clang++}
 clang_version="$($CC --version | sed -nr 's/.*version ([^ ]+?) .*/\1/p' | sed -r 's/-$//')"
 
 SANITIZER=${SANITIZER:-address -fsanitize-address-use-after-scope}
-flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize-coverage=trace-pc-guard,trace-cmp"
+flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER"
 
 clang_lib="/usr/lib64/clang/${clang_version}/lib/linux"
 [ -d "$clang_lib" ] || clang_lib="/usr/lib/clang/${clang_version}/lib/linux"
@@ -33,7 +33,7 @@ if [ -z "$FUZZING_ENGINE" ]; then
 fi
 
 meson $build -D$fuzzflag -Db_lundef=false
-ninja -C $build fuzzers
+ninja -v -C $build fuzzers
 
 # The seed corpus is a separate flat archive for each fuzzer,
 # with a fixed name ${fuzzer}_seed_corpus.zip.
index 72ffcee439b92f2ad31f154cf1bd15cfda79a00b..dd9b816c986928a872e36b1bc66f892c13977eec 100755 (executable)
@@ -15,7 +15,10 @@ CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
 DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
 DOCKER_RUN="${DOCKER_RUN:-docker run}"
 REPO_ROOT="${REPO_ROOT:-$PWD}"
-ADDITIONAL_DEPS=(python3-libevdev python3-pyparsing clang)
+ADDITIONAL_DEPS=(python3-libevdev
+                 python3-pyparsing
+                 clang
+                 perl)
 
 function info() {
     echo -e "\033[33;1m$1\033[0m"
@@ -44,10 +47,9 @@ for phase in "${PHASES[@]}"; do
             if [[ "$phase" = "RUN_CLANG" ]]; then
                 ENV_VARS="-e CC=clang -e CXX=clang++"
             fi
-            docker exec $ENV_VARS -it $CONT_NAME meson --werror -Dtests=unsafe -Dslow-tests=true -Dsplit-usr=true build
+            docker exec $ENV_VARS -it $CONT_NAME meson --werror -Dtests=unsafe -Dslow-tests=true -Dsplit-usr=true -Dman=true build
             $DOCKER_EXEC ninja -v -C build
             docker exec -e "TRAVIS=$TRAVIS" -it $CONT_NAME ninja -C build test
-            $DOCKER_EXEC tools/check-directives.sh
             ;;
         RUN_ASAN|RUN_CLANG_ASAN)
             if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
index 760ed5b1ea5d0431588f25cfe35c436a8ebe7e35..38cb3d3158454a604890fd07bab79a68a0108486 100755 (executable)
@@ -15,7 +15,15 @@ CONT_NAME="${CONT_NAME:-fedora-$FEDORA_RELEASE-$RANDOM}"
 DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
 DOCKER_RUN="${DOCKER_RUN:-docker run}"
 REPO_ROOT="${REPO_ROOT:-$PWD}"
-ADDITIONAL_DEPS=(dnf-plugins-core python2 iputils hostname libasan python3-pyparsing python3-evdev libubsan clang llvm)
+ADDITIONAL_DEPS=(dnf-plugins-core
+                 python2 iputils
+                 hostname libasan
+                 python3-pyparsing
+                 python3-evdev
+                 libubsan
+                 clang
+                 llvm
+                 perl)
 
 function info() {
     echo -e "\033[33;1m$1\033[0m"
@@ -50,10 +58,9 @@ for phase in "${PHASES[@]}"; do
             $DOCKER_EXEC meson --werror -Dtests=unsafe -Dslow-tests=true build
             $DOCKER_EXEC ninja -v -C build
             $DOCKER_EXEC ninja -C build test
-            $DOCKER_EXEC tools/check-directives.sh
             ;;
         RUN_CLANG)
-            docker exec -e CC=clang -e CXX=clang++ -it $CONT_NAME meson --werror -Dtests=unsafe -Dslow-tests=true build
+            docker exec -e CC=clang -e CXX=clang++ -it $CONT_NAME meson --werror -Dtests=unsafe -Dslow-tests=true -Dman=true build
             $DOCKER_EXEC ninja -v -C build
             $DOCKER_EXEC ninja -C build test
             ;;
diff --git a/travis-ci/managers/fuzzbuzz.sh b/travis-ci/managers/fuzzbuzz.sh
new file mode 100755 (executable)
index 0000000..0080b06
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+set -e
+set -x
+set -u
+
+REPO_ROOT=${REPO_ROOT:-$(pwd)}
+
+sudo bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
+sudo apt-get update -y
+sudo apt-get build-dep systemd -y
+sudo apt-get install -y ninja-build python3-pip python3-setuptools
+pip3 install meson
+
+cd $REPO_ROOT
+export PATH="$HOME/.local/bin/:$PATH"
+tools/oss-fuzz.sh
+timeout --preserve-status 5 ./out/fuzz-unit-file
+git clean -dxff
+
+wget https://app.fuzzbuzz.io/releases/cli/latest/linux/fuzzbuzz
+chmod +x fuzzbuzz
+./fuzzbuzz validate
+./fuzzbuzz target test fuzz-unit-file --all
+
+git clone https://github.com/google/oss-fuzz /tmp/oss-fuzz
+cd /tmp/oss-fuzz
+sudo ./infra/helper.py pull_images
+
+# docker doesn't like colons in filenames so let's create a directory
+# whose name can be consumed by the -v option.
+# https://github.com/google/oss-fuzz/issues/2428
+t=$(mktemp -d)
+sudo mount --bind "$REPO_ROOT" "$t"
+
+# helper.py is wrapped in script to trick it into thinking it's "interactive"
+# See https://github.com/systemd/systemd/pull/12542#issuecomment-491563572
+sudo script -e -c "./infra/helper.py build_fuzzers --clean --sanitizer=memory systemd $t"
+sudo script -e -c "./infra/helper.py check_build --sanitizer=memory -e ALLOWED_BROKEN_TARGETS_PERCENTAGE=0 systemd"
index 4822bdd4b73b84c7ff12b44c37c3f4e490a332fa..475a1510aa20ef3bc0faa3769e54706bd78f7316 100755 (executable)
@@ -2,21 +2,59 @@
 set -e
 set -x
 
+PACKAGES=(cryptsetup-bin
+          gettext
+          iptables-dev
+          iputils-ping
+          isc-dhcp-client
+          itstool
+          kbd
+          libblkid-dev
+          libcap-dev
+          libcurl4-gnutls-dev
+          libgpg-error-dev
+          liblz4-dev
+          liblzma-dev
+          libmicrohttpd-dev
+          libmount-dev
+          libmount-dev
+          libqrencode-dev
+          libxkbcommon-dev
+          linux-image-virtual
+          mount
+          net-tools
+          ninja-build
+          perl
+          python-lxml
+          python3-evdev
+          python3-lxml
+          python3-pip
+          python3-pyparsing
+          python3-setuptools
+          qemu-system-x86
+          strace
+          unifont
+          util-linux)
+
+bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
+
 apt-get update
 apt-get build-dep systemd -y
-apt-get install -y util-linux libmount-dev libblkid-dev liblzma-dev libqrencode-dev libmicrohttpd-dev iptables-dev liblz4-dev libcurl4-gnutls-dev unifont itstool kbd cryptsetup-bin net-tools isc-dhcp-client iputils-ping strace qemu-system-x86 linux-image-virtual mount libgpg-error-dev libxkbcommon-dev python-lxml python3-lxml python3-pip libcap-dev
-apt-get install -y gettext python3-evdev python3-pyparsing libmount-dev python3-setuptools ninja-build
+apt-get install -y "${PACKAGES[@]}"
 pip3 install meson
 
-cd $REPO_ROOT
+cd ${REPO_ROOT:-$PWD}
 
 sed -i 's/2\.30/2.27/' meson.build
 
-meson --werror -Db_sanitize=address,undefined -Dsplit-usr=true build
+meson --werror -Db_sanitize=address,undefined -Dsplit-usr=true -Dman=true build
 ninja -v -C build
-make -C test/TEST-01-BASIC clean setup run TEST_NO_QEMU=yes NSPAWN_ARGUMENTS=--keep-unit RUN_IN_UNPRIVILEGED_CONTAINER=no
+
+make -C test/TEST-01-BASIC clean setup run NSPAWN_TIMEOUT=600 TEST_NO_QEMU=yes NSPAWN_ARGUMENTS=--keep-unit RUN_IN_UNPRIVILEGED_CONTAINER=no
 
 # Now that we're more or less sure that ASan isn't going to crash systemd and cause a kernel panic
 # let's also run the test with QEMU to cover udevd, sysctl and everything else that isn't run
 # in containers.
-make -C test/TEST-01-BASIC clean setup run TEST_NO_NSPAWN=yes
+
+# This should be turned on once `journalctl --flush` isn't flaky any more
+#make -C test/TEST-01-BASIC clean setup run QEMU_TIMEOUT=900 TEST_NO_NSPAWN=yes
index 9928e3fc87ef02790f8dcd34c0d65ef99477420f..5ef30d5d3f7ddf13b75b74842d3209a96b4998a5 100644 (file)
@@ -1,4 +1,5 @@
 dnf-plugins-core
 meson
 ninja-build
+perl
 python
index a5610506d5182ead4e8a1a67633842db2f9ad0ed..52f8b7712f35b18f140dbac84e408db0c083fd4e 100644 (file)
@@ -118,7 +118,6 @@ units = [
 in_units = [
         ['debug-shell.service',                  ''],
         ['emergency.service',                    ''],
-        ['halt-local.service',                   'HAVE_SYSV_COMPAT'],
         ['initrd-cleanup.service',               ''],
         ['initrd-parse-etc.service',             ''],
         ['initrd-switch-root.service',           ''],
index d5eca2546b237e980e41b67858c0eceeb9165fa7..41abcd631c5e005eb53db402b1c168b50d4e670e 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Remove the Offline System Updates symlink
+Description=Remove the Offline System Updates Symlink
 Documentation=man:systemd.special(7) man:systemd.offline-updates(7)
 After=system-update.target
 DefaultDependencies=no
index bacfe51d6f3f450d9382a4428c8296ff13fd0eee..29b006cba5775ac2fb42859e4d4505d923dac776 100644 (file)
@@ -18,6 +18,7 @@ RequiresMountsFor=/var/log/journal
 
 [Service]
 ExecStart=@rootbindir@/journalctl --flush
+ExecStop=@rootbindir@/journalctl --smart-relinquish-var
 Type=oneshot
 RemainAfterExit=yes
 TimeoutSec=90s