summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--DISTRO_PORTING19
-rw-r--r--Makefile-man.am227
-rw-r--r--Makefile.am220
-rw-r--r--NEWS101
-rw-r--r--README18
-rw-r--r--TODO19
-rw-r--r--configure.ac46
-rw-r--r--docs/.gitignore2
-rw-r--r--hwdb/20-OUI.hwdb165
-rw-r--r--hwdb/20-bluetooth-vendor-product.hwdb66
-rw-r--r--hwdb/20-pci-vendor-model.hwdb646
-rw-r--r--hwdb/20-usb-vendor-model.hwdb7
-rw-r--r--hwdb/70-mouse.hwdb4
-rw-r--r--hwdb/70-touchpad.hwdb43
-rw-r--r--man/coredump.conf.xml2
-rw-r--r--man/custom-html.xsl186
-rw-r--r--man/journalctl.xml4
-rw-r--r--man/machinectl.xml6
-rw-r--r--man/networkctl.xml2
-rw-r--r--man/nss-mymachines.xml35
-rw-r--r--man/sd-bus-errors.xml309
-rw-r--r--man/sd_bus_creds_get_pid.xml59
-rw-r--r--man/sd_bus_creds_new_from_pid.xml150
-rw-r--r--man/sd_bus_default.xml68
-rw-r--r--man/sd_bus_error.xml344
-rw-r--r--man/sd_bus_error_add_map.xml173
-rw-r--r--man/sd_bus_message_append.xml64
-rw-r--r--man/sd_bus_message_append_array.xml125
-rw-r--r--man/sd_bus_message_append_basic.xml51
-rw-r--r--man/sd_bus_negotiate_fds.xml4
-rw-r--r--man/sd_bus_new.xml16
-rw-r--r--man/sd_bus_request_name.xml15
-rw-r--r--man/sd_notify.xml2
-rw-r--r--man/sd_pid_get_session.xml83
-rw-r--r--man/sysctl.d.xml21
-rw-r--r--man/systemctl.xml34
-rw-r--r--man/systemd-coredump.xml4
-rw-r--r--man/systemd-journald.service.xml2
-rw-r--r--man/systemd.exec.xml5
-rw-r--r--man/systemd.journal-fields.xml3
-rw-r--r--man/systemd.link.xml9
-rw-r--r--man/systemd.netdev.xml47
-rw-r--r--man/systemd.network.xml94
-rw-r--r--man/systemd.preset.xml2
-rw-r--r--man/systemd.service.xml5
-rw-r--r--man/systemd.socket.xml2
-rw-r--r--man/systemd.time.xml2
-rw-r--r--man/udev.xml9
-rw-r--r--rules/42-usb-hid-pm.rules36
-rw-r--r--rules/60-persistent-storage.rules2
-rw-r--r--rules/61-accelerometer.rules3
-rw-r--r--rules/70-touchpad.rules12
-rw-r--r--src/analyze/analyze.c240
-rw-r--r--src/backlight/backlight.c2
-rw-r--r--src/basic/bitmap.c198
-rw-r--r--src/basic/bitmap.h50
-rw-r--r--src/basic/capability.c2
-rw-r--r--src/basic/cgroup-util.c12
-rw-r--r--src/basic/copy.c6
-rw-r--r--src/basic/exit-status.c3
-rw-r--r--src/basic/fileio-label.c2
-rw-r--r--src/basic/fileio.c96
-rw-r--r--src/basic/fileio.h14
-rw-r--r--src/basic/macro.h21
-rw-r--r--src/basic/missing.h40
-rw-r--r--src/basic/path-util.c8
-rw-r--r--src/basic/process-util.c51
-rw-r--r--src/basic/smack-util.c2
-rw-r--r--src/basic/socket-label.c9
-rw-r--r--src/basic/socket-util.h1
-rw-r--r--src/basic/util.c579
-rw-r--r--src/basic/util.h12
-rw-r--r--src/basic/virt.c20
-rw-r--r--src/binfmt/binfmt.c6
-rw-r--r--src/boot/bootctl.c6
-rw-r--r--src/boot/efi/boot.c38
-rw-r--r--src/bootchart/bootchart.c16
-rw-r--r--src/bootchart/store.c30
-rw-r--r--src/bootchart/svg.c9
-rw-r--r--src/bus-proxyd/driver.c5
-rw-r--r--src/bus-proxyd/driver.h3
-rw-r--r--src/bus-proxyd/proxy.c99
-rw-r--r--src/bus-proxyd/proxy.h3
-rw-r--r--src/bus-proxyd/synthesize.c19
-rw-r--r--src/bus-proxyd/synthesize.h3
-rw-r--r--src/cgls/cgls.c10
-rw-r--r--src/cgroups-agent/cgroups-agent.c2
-rw-r--r--src/cgtop/cgtop.c1
-rw-r--r--src/core/automount.c34
-rw-r--r--src/core/busname.c3
-rw-r--r--src/core/dbus.c46
-rw-r--r--src/core/execute.c2
-rw-r--r--src/core/job.c317
-rw-r--r--src/core/kmod-setup.c2
-rw-r--r--src/core/machine-id-setup.c2
-rw-r--r--src/core/main.c48
-rw-r--r--src/core/mount-setup.c3
-rw-r--r--src/core/mount.c3
-rw-r--r--src/core/path.c2
-rw-r--r--src/core/selinux-access.c12
-rw-r--r--src/core/service.c12
-rw-r--r--src/core/slice.c1
-rw-r--r--src/core/smack-setup.c2
-rw-r--r--src/core/socket.c8
-rw-r--r--src/core/swap.c1
-rw-r--r--src/core/target.c1
-rw-r--r--src/core/unit.c81
-rw-r--r--src/core/unit.h1
-rw-r--r--src/escape/escape.c2
-rw-r--r--src/firstboot/firstboot.c4
-rw-r--r--src/fsck/fsck.c2
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c3
-rw-r--r--src/hibernate-resume/hibernate-resume.c2
-rw-r--r--src/hostname/hostnamectl.c2
-rw-r--r--src/hostname/hostnamed.c4
-rw-r--r--src/import/importd.c3
-rw-r--r--src/import/pull-dkr.c2
-rw-r--r--src/journal-remote/journal-gatewayd.c2
-rw-r--r--src/journal/journal-file.c37
-rw-r--r--src/journal/journal-file.h3
-rw-r--r--src/journal/journal-vacuum.c2
-rw-r--r--src/journal/journal-verify.c233
-rw-r--r--src/journal/journalctl.c6
-rw-r--r--src/journal/journald-server.c10
-rw-r--r--src/libsystemd-network/dhcp-lease-internal.h2
-rw-r--r--src/libsystemd-network/dhcp-protocol.h1
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c68
-rw-r--r--src/libsystemd-network/sd-lldp.c2
-rw-r--r--src/libsystemd-terminal/grdev-drm.c4
-rw-r--r--src/libsystemd/libsystemd.sym1
-rw-r--r--src/libsystemd/sd-bus/GVARIANT-SERIALIZATION4
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.h3
-rw-r--r--src/libsystemd/sd-bus/bus-control.c45
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c14
-rw-r--r--src/libsystemd/sd-bus/bus-message.c17
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c96
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c2
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c20
-rw-r--r--src/libsystemd/sd-bus/busctl.c3
-rw-r--r--src/libsystemd/sd-bus/kdbus.h1
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c11
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c4
-rw-r--r--src/libsystemd/sd-bus/test-bus-gvariant.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c21
-rw-r--r--src/libsystemd/sd-bus/test-bus-match.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c21
-rw-r--r--src/libsystemd/sd-bus/test-bus-proxy.c109
-rw-r--r--src/libsystemd/sd-device/sd-device.c8
-rw-r--r--src/libsystemd/sd-netlink/netlink-internal.h27
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c202
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c45
-rw-r--r--src/locale/localectl.c2
-rw-r--r--src/locale/localed.c4
-rw-r--r--src/login/71-seat.rules.in5
-rw-r--r--src/login/inhibit.c2
-rw-r--r--src/login/loginctl.c2
-rw-r--r--src/login/logind-core.c4
-rw-r--r--src/login/logind-dbus.c95
-rw-r--r--src/login/logind-seat.c30
-rw-r--r--src/login/logind-session.c10
-rw-r--r--src/login/logind-session.h2
-rw-r--r--src/login/logind-user-dbus.c6
-rw-r--r--src/login/logind.c6
-rw-r--r--src/login/logind.h2
-rw-r--r--src/login/org.freedesktop.login1.conf72
-rw-r--r--src/login/pam_systemd.c14
-rw-r--r--src/machine/machine-dbus.c14
-rw-r--r--src/machine/machinectl.c2
-rw-r--r--src/machine/machined-dbus.c231
-rw-r--r--src/machine/org.freedesktop.machine1.conf16
-rw-r--r--src/network/networkd-dhcp4.c41
-rw-r--r--src/network/networkd-link.c101
-rw-r--r--src/network/networkd-netdev-gperf.gperf3
-rw-r--r--src/network/networkd-netdev-tunnel.c71
-rw-r--r--src/network/networkd-netdev-tunnel.h28
-rw-r--r--src/network/networkd-netdev-tuntap.c3
-rw-r--r--src/network/networkd-netdev-tuntap.h1
-rw-r--r--src/network/networkd-netdev-vxlan.h11
-rw-r--r--src/network/networkd-netdev.c13
-rw-r--r--src/network/networkd-network-bus.c6
-rw-r--r--src/network/networkd-network-gperf.gperf137
-rw-r--r--src/network/networkd-network.c98
-rw-r--r--src/network/networkd-wait-online.c2
-rw-r--r--src/network/networkd.c2
-rw-r--r--src/network/networkd.h50
-rw-r--r--src/nspawn/nspawn.c93
-rw-r--r--src/nss-mymachines/nss-mymachines.c324
-rw-r--r--src/nss-mymachines/nss-mymachines.sym4
-rw-r--r--src/nss-resolve/nss-resolve.c6
-rw-r--r--src/python-systemd/.gitignore2
l---------src/python-systemd/Makefile1
-rw-r--r--src/python-systemd/__init__.py18
-rw-r--r--src/python-systemd/_daemon.c331
-rw-r--r--src/python-systemd/_journal.c157
-rw-r--r--src/python-systemd/_reader.c1106
-rw-r--r--src/python-systemd/daemon.py55
-rw-r--r--src/python-systemd/docs/.gitignore1
-rw-r--r--src/python-systemd/docs/conf.py279
-rw-r--r--src/python-systemd/docs/daemon.rst18
-rw-r--r--src/python-systemd/docs/default.css196
-rw-r--r--src/python-systemd/docs/id128.rst40
-rw-r--r--src/python-systemd/docs/index.rst24
-rw-r--r--src/python-systemd/docs/journal.rst64
-rw-r--r--src/python-systemd/docs/layout.html15
-rw-r--r--src/python-systemd/docs/login.rst28
-rw-r--r--src/python-systemd/id128.c163
-rw-r--r--src/python-systemd/journal.py548
-rw-r--r--src/python-systemd/login.c376
-rw-r--r--src/python-systemd/pyutil.c80
-rw-r--r--src/python-systemd/pyutil.h54
-rw-r--r--src/resolve-host/resolve-host.c6
-rw-r--r--src/resolve/dns-type.c5
-rw-r--r--src/resolve/dns-type.h1
-rw-r--r--src/resolve/resolved-dns-packet.c513
-rw-r--r--src/resolve/resolved-dns-packet.h19
-rw-r--r--src/resolve/resolved-dns-rr.c180
-rw-r--r--src/resolve/resolved-dns-rr.h32
-rw-r--r--src/resolve/resolved-dns-scope.c85
-rw-r--r--src/resolve/resolved-dns-scope.h6
-rw-r--r--src/resolve/resolved-dns-server.c44
-rw-r--r--src/resolve/resolved-dns-server.h7
-rw-r--r--src/resolve/resolved-dns-transaction.c110
-rw-r--r--src/resolve/resolved-dns-transaction.h6
-rw-r--r--src/resolve/resolved-link.c23
-rw-r--r--src/resolve/resolved-llmnr.c473
-rw-r--r--src/resolve/resolved-llmnr.h34
-rw-r--r--src/resolve/resolved-manager.c601
-rw-r--r--src/resolve/resolved-manager.h14
-rw-r--r--src/rfkill/rfkill.c2
-rw-r--r--src/run/run.c2
-rw-r--r--src/shared/bus-util.h11
-rw-r--r--src/shared/dns-domain.c95
-rw-r--r--src/shared/dns-domain.h2
-rw-r--r--src/shared/efivars.c14
-rw-r--r--src/shared/nss-util.h33
-rw-r--r--src/shared/sysctl-util.c2
-rw-r--r--src/sleep/sleep.c4
-rw-r--r--src/systemctl/systemctl.c10
-rw-r--r--src/systemd/sd-bus-vtable.h6
-rw-r--r--src/systemd/sd-bus.h3
-rw-r--r--src/systemd/sd-dhcp-lease.h2
-rw-r--r--src/sysv-generator/sysv-generator.c32
-rw-r--r--src/test/test-bitmap.c105
-rw-r--r--src/test/test-btrfs.c2
-rw-r--r--src/test/test-copy.c6
-rw-r--r--src/test/test-dns-domain.c74
-rw-r--r--src/test/test-fileio.c24
-rw-r--r--src/test/test-pty.c2
-rw-r--r--src/test/test-util.c331
-rw-r--r--src/timedate/timedatectl.c13
-rw-r--r--src/timedate/timedated.c4
-rw-r--r--src/tmpfiles/tmpfiles.c7
l---------src/udev/accelerometer/Makefile1
-rw-r--r--src/udev/accelerometer/accelerometer.c303
-rw-r--r--src/udev/ata_id/ata_id.c15
-rw-r--r--src/udev/udev-builtin-hwdb.c2
-rw-r--r--src/udev/udev-event.c50
-rw-r--r--src/udev/udev-rules.c65
-rw-r--r--src/udev/udev.h3
-rw-r--r--src/udev/udevd.c98
-rw-r--r--src/user-sessions/user-sessions.c2
-rw-r--r--src/vconsole/vconsole-setup.c4
-rw-r--r--test/rule-syntax-check.py2
-rw-r--r--test/sysv-generator-test.py19
-rw-r--r--tmpfiles.d/systemd.conf.m42
-rw-r--r--tools/make-man-rules.py12
-rw-r--r--units/emergency.service.in2
-rw-r--r--units/systemd-machined.service.in2
-rw-r--r--units/systemd-networkd.service.m4.in2
270 files changed, 8335 insertions, 7090 deletions
diff --git a/.gitignore b/.gitignore
index 1e704a872b..7659e7a645 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,7 +26,6 @@
/GRTAGS
/GSYMS
/GTAGS
-/accelerometer
/ata_id
/bootctl
/build-aux
@@ -145,6 +144,7 @@
/test-audit-type
/test-async
/test-barrier
+/test-bitmap
/test-boot-timestamp
/test-btrfs
/test-bus-benchmark
@@ -160,6 +160,7 @@
/test-bus-match
/test-bus-objects
/test-bus-policy
+/test-bus-proxy
/test-bus-server
/test-bus-signature
/test-bus-zero-copy
diff --git a/DISTRO_PORTING b/DISTRO_PORTING
index d8e9ded943..07aea865be 100644
--- a/DISTRO_PORTING
+++ b/DISTRO_PORTING
@@ -14,6 +14,7 @@ HOWTO:
--with-kbd-loadkeys=
--with-kbd-setfont=
--with-tty-gid=
+ --with-ntp-servers=
2) Try it out. Play around (as an ordinary user) with
'/usr/lib/systemd/systemd --test --system' for a test run
@@ -21,6 +22,24 @@ HOWTO:
print the initial transaction it would execute during boot-up.
This will also inform you about ordering loops and suchlike
+NTP POOL:
+
+ By default, timesyncd uses the Google NTP servers
+ time[1-4].google.com. They serve time that is not standards
+ compliant, and can be up to .5s off. Google does not
+ officially support these servers for the broader
+ audience. Distributions and vendors really should not ship
+ OSes or devices with these NTP servers configured. Instead,
+ please register your own vendor pool at ntp.org and make it
+ the built-in default by passing --with-ntp-servers= to
+ configure. Registering vendor pools is free:
+
+ http://www.pool.ntp.org/en/vendors.html
+
+ Again, if you ship your software or device with the default
+ NTP servers, then you will get served wrong time, and will
+ rely on services that might not be supported for long.
+
CONTRIBUTING UPSTREAM:
We generally do no longer accept distribution-specific
diff --git a/Makefile-man.am b/Makefile-man.am
index 734a923799..218a299e91 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -23,8 +23,8 @@ MANPAGES += \
man/localtime.5 \
man/machine-id.5 \
man/machine-info.5 \
- man/networkctl.1 \
man/os-release.5 \
+ man/sd-bus-errors.3 \
man/sd-daemon.3 \
man/sd-id128.3 \
man/sd-journal.3 \
@@ -33,6 +33,7 @@ MANPAGES += \
man/sd_bus_creds_new_from_pid.3 \
man/sd_bus_default.3 \
man/sd_bus_error.3 \
+ man/sd_bus_error_add_map.3 \
man/sd_bus_message_append.3 \
man/sd_bus_message_append_array.3 \
man/sd_bus_message_append_basic.3 \
@@ -144,7 +145,6 @@ MANPAGES += \
man/systemd.time.7 \
man/systemd.timer.5 \
man/systemd.unit.5 \
- man/sysusers.d.5 \
man/telinit.8 \
man/tmpfiles.d.5 \
man/udev.7 \
@@ -163,6 +163,40 @@ MANPAGES += \
man/udevadm.8
MANPAGES_ALIAS += \
man/SD_ALERT.3 \
+ man/SD_BUS_ERROR_ACCESS_DENIED.3 \
+ man/SD_BUS_ERROR_ADDRESS_IN_USE.3 \
+ man/SD_BUS_ERROR_AUTH_FAILED.3 \
+ man/SD_BUS_ERROR_BAD_ADDRESS.3 \
+ man/SD_BUS_ERROR_DISCONNECTED.3 \
+ man/SD_BUS_ERROR_END.3 \
+ man/SD_BUS_ERROR_FAILED.3 \
+ man/SD_BUS_ERROR_FILE_EXISTS.3 \
+ man/SD_BUS_ERROR_FILE_NOT_FOUND.3 \
+ man/SD_BUS_ERROR_INCONSISTENT_MESSAGE.3 \
+ man/SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED.3 \
+ man/SD_BUS_ERROR_INVALID_ARGS.3 \
+ man/SD_BUS_ERROR_INVALID_SIGNATURE.3 \
+ man/SD_BUS_ERROR_IO_ERROR.3 \
+ man/SD_BUS_ERROR_LIMITS_EXCEEDED.3 \
+ man/SD_BUS_ERROR_MAKE_CONST.3 \
+ man/SD_BUS_ERROR_MAP.3 \
+ man/SD_BUS_ERROR_MATCH_RULE_INVALID.3 \
+ man/SD_BUS_ERROR_MATCH_RULE_NOT_FOUND.3 \
+ man/SD_BUS_ERROR_NAME_HAS_NO_OWNER.3 \
+ man/SD_BUS_ERROR_NOT_SUPPORTED.3 \
+ man/SD_BUS_ERROR_NO_MEMORY.3 \
+ man/SD_BUS_ERROR_NO_NETWORK.3 \
+ man/SD_BUS_ERROR_NO_REPLY.3 \
+ man/SD_BUS_ERROR_NO_SERVER.3 \
+ man/SD_BUS_ERROR_NULL.3 \
+ man/SD_BUS_ERROR_PROPERTY_READ_ONLY.3 \
+ man/SD_BUS_ERROR_SERVICE_UNKNOWN.3 \
+ man/SD_BUS_ERROR_TIMEOUT.3 \
+ man/SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN.3 \
+ man/SD_BUS_ERROR_UNKNOWN_INTERFACE.3 \
+ man/SD_BUS_ERROR_UNKNOWN_METHOD.3 \
+ man/SD_BUS_ERROR_UNKNOWN_OBJECT.3 \
+ man/SD_BUS_ERROR_UNKNOWN_PROPERTY.3 \
man/SD_CRIT.3 \
man/SD_DEBUG.3 \
man/SD_EMERG.3 \
@@ -193,6 +227,7 @@ MANPAGES_ALIAS += \
man/reboot.8 \
man/sd_bus_creds_get_audit_login_uid.3 \
man/sd_bus_creds_get_audit_session_id.3 \
+ man/sd_bus_creds_get_augmented_mask.3 \
man/sd_bus_creds_get_cgroup.3 \
man/sd_bus_creds_get_cmdline.3 \
man/sd_bus_creds_get_comm.3 \
@@ -218,6 +253,7 @@ MANPAGES_ALIAS += \
man/sd_bus_creds_get_uid.3 \
man/sd_bus_creds_get_unique_name.3 \
man/sd_bus_creds_get_unit.3 \
+ man/sd_bus_creds_get_user_slice.3 \
man/sd_bus_creds_get_user_unit.3 \
man/sd_bus_creds_get_well_known_names.3 \
man/sd_bus_creds_has_bounding_cap.3 \
@@ -233,10 +269,13 @@ MANPAGES_ALIAS += \
man/sd_bus_error_get_errno.3 \
man/sd_bus_error_has_name.3 \
man/sd_bus_error_is_set.3 \
+ man/sd_bus_error_map.3 \
man/sd_bus_error_set.3 \
man/sd_bus_error_set_const.3 \
man/sd_bus_error_set_errno.3 \
man/sd_bus_error_set_errnof.3 \
+ man/sd_bus_error_set_errnofv.3 \
+ man/sd_bus_error_setf.3 \
man/sd_bus_message_append_array_iovec.3 \
man/sd_bus_message_append_array_memfd.3 \
man/sd_bus_message_append_array_space.3 \
@@ -246,7 +285,7 @@ MANPAGES_ALIAS += \
man/sd_bus_message_get_reply_cookie.3 \
man/sd_bus_message_get_seqnum.3 \
man/sd_bus_negotiate_creds.3 \
- man/sd_bus_negotiate_timestamps.3 \
+ man/sd_bus_negotiate_timestamp.3 \
man/sd_bus_open.3 \
man/sd_bus_open_system.3 \
man/sd_bus_open_system_machine.3 \
@@ -410,6 +449,40 @@ MANPAGES_ALIAS += \
man/udev_unref.3 \
man/user.conf.d.5
man/SD_ALERT.3: man/sd-daemon.3
+man/SD_BUS_ERROR_ACCESS_DENIED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_ADDRESS_IN_USE.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_AUTH_FAILED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_BAD_ADDRESS.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_DISCONNECTED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_END.3: man/sd_bus_error_add_map.3
+man/SD_BUS_ERROR_FAILED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_FILE_EXISTS.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_FILE_NOT_FOUND.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_INCONSISTENT_MESSAGE.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_INVALID_ARGS.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_INVALID_SIGNATURE.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_IO_ERROR.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_LIMITS_EXCEEDED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_MAKE_CONST.3: man/sd_bus_error.3
+man/SD_BUS_ERROR_MAP.3: man/sd_bus_error_add_map.3
+man/SD_BUS_ERROR_MATCH_RULE_INVALID.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_MATCH_RULE_NOT_FOUND.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NAME_HAS_NO_OWNER.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NOT_SUPPORTED.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NO_MEMORY.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NO_NETWORK.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NO_REPLY.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NO_SERVER.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_NULL.3: man/sd_bus_error.3
+man/SD_BUS_ERROR_PROPERTY_READ_ONLY.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_SERVICE_UNKNOWN.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_TIMEOUT.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_UNKNOWN_INTERFACE.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_UNKNOWN_METHOD.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_UNKNOWN_OBJECT.3: man/sd-bus-errors.3
+man/SD_BUS_ERROR_UNKNOWN_PROPERTY.3: man/sd-bus-errors.3
man/SD_CRIT.3: man/sd-daemon.3
man/SD_DEBUG.3: man/sd-daemon.3
man/SD_EMERG.3: man/sd-daemon.3
@@ -440,6 +513,7 @@ man/poweroff.8: man/halt.8
man/reboot.8: man/halt.8
man/sd_bus_creds_get_audit_login_uid.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_audit_session_id.3: man/sd_bus_creds_get_pid.3
+man/sd_bus_creds_get_augmented_mask.3: man/sd_bus_creds_new_from_pid.3
man/sd_bus_creds_get_cgroup.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_cmdline.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_comm.3: man/sd_bus_creds_get_pid.3
@@ -465,6 +539,7 @@ man/sd_bus_creds_get_tty.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_uid.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_unique_name.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_unit.3: man/sd_bus_creds_get_pid.3
+man/sd_bus_creds_get_user_slice.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_user_unit.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_get_well_known_names.3: man/sd_bus_creds_get_pid.3
man/sd_bus_creds_has_bounding_cap.3: man/sd_bus_creds_get_pid.3
@@ -480,10 +555,13 @@ man/sd_bus_error_free.3: man/sd_bus_error.3
man/sd_bus_error_get_errno.3: man/sd_bus_error.3
man/sd_bus_error_has_name.3: man/sd_bus_error.3
man/sd_bus_error_is_set.3: man/sd_bus_error.3
+man/sd_bus_error_map.3: man/sd_bus_error_add_map.3
man/sd_bus_error_set.3: man/sd_bus_error.3
man/sd_bus_error_set_const.3: man/sd_bus_error.3
man/sd_bus_error_set_errno.3: man/sd_bus_error.3
man/sd_bus_error_set_errnof.3: man/sd_bus_error.3
+man/sd_bus_error_set_errnofv.3: man/sd_bus_error.3
+man/sd_bus_error_setf.3: man/sd_bus_error.3
man/sd_bus_message_append_array_iovec.3: man/sd_bus_message_append_array.3
man/sd_bus_message_append_array_memfd.3: man/sd_bus_message_append_array.3
man/sd_bus_message_append_array_space.3: man/sd_bus_message_append_array.3
@@ -493,7 +571,7 @@ man/sd_bus_message_get_realtime_usec.3: man/sd_bus_message_get_monotonic_usec.3
man/sd_bus_message_get_reply_cookie.3: man/sd_bus_message_get_cookie.3
man/sd_bus_message_get_seqnum.3: man/sd_bus_message_get_monotonic_usec.3
man/sd_bus_negotiate_creds.3: man/sd_bus_negotiate_fds.3
-man/sd_bus_negotiate_timestamps.3: man/sd_bus_negotiate_fds.3
+man/sd_bus_negotiate_timestamp.3: man/sd_bus_negotiate_fds.3
man/sd_bus_open.3: man/sd_bus_default.3
man/sd_bus_open_system.3: man/sd_bus_default.3
man/sd_bus_open_system_machine.3: man/sd_bus_default.3
@@ -659,6 +737,108 @@ man/user.conf.d.5: man/systemd-system.conf.5
man/SD_ALERT.html: man/sd-daemon.html
$(html-alias)
+man/SD_BUS_ERROR_ACCESS_DENIED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_ADDRESS_IN_USE.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_AUTH_FAILED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_BAD_ADDRESS.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_DISCONNECTED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_END.html: man/sd_bus_error_add_map.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_FAILED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_FILE_EXISTS.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_FILE_NOT_FOUND.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_INCONSISTENT_MESSAGE.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_INVALID_ARGS.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_INVALID_SIGNATURE.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_IO_ERROR.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_LIMITS_EXCEEDED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_MAKE_CONST.html: man/sd_bus_error.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_MAP.html: man/sd_bus_error_add_map.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_MATCH_RULE_INVALID.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_MATCH_RULE_NOT_FOUND.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NAME_HAS_NO_OWNER.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NOT_SUPPORTED.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NO_MEMORY.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NO_NETWORK.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NO_REPLY.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NO_SERVER.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_NULL.html: man/sd_bus_error.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_PROPERTY_READ_ONLY.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_SERVICE_UNKNOWN.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_TIMEOUT.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_UNKNOWN_INTERFACE.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_UNKNOWN_METHOD.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_UNKNOWN_OBJECT.html: man/sd-bus-errors.html
+ $(html-alias)
+
+man/SD_BUS_ERROR_UNKNOWN_PROPERTY.html: man/sd-bus-errors.html
+ $(html-alias)
+
man/SD_CRIT.html: man/sd-daemon.html
$(html-alias)
@@ -749,6 +929,9 @@ man/sd_bus_creds_get_audit_login_uid.html: man/sd_bus_creds_get_pid.html
man/sd_bus_creds_get_audit_session_id.html: man/sd_bus_creds_get_pid.html
$(html-alias)
+man/sd_bus_creds_get_augmented_mask.html: man/sd_bus_creds_new_from_pid.html
+ $(html-alias)
+
man/sd_bus_creds_get_cgroup.html: man/sd_bus_creds_get_pid.html
$(html-alias)
@@ -824,6 +1007,9 @@ man/sd_bus_creds_get_unique_name.html: man/sd_bus_creds_get_pid.html
man/sd_bus_creds_get_unit.html: man/sd_bus_creds_get_pid.html
$(html-alias)
+man/sd_bus_creds_get_user_slice.html: man/sd_bus_creds_get_pid.html
+ $(html-alias)
+
man/sd_bus_creds_get_user_unit.html: man/sd_bus_creds_get_pid.html
$(html-alias)
@@ -869,6 +1055,9 @@ man/sd_bus_error_has_name.html: man/sd_bus_error.html
man/sd_bus_error_is_set.html: man/sd_bus_error.html
$(html-alias)
+man/sd_bus_error_map.html: man/sd_bus_error_add_map.html
+ $(html-alias)
+
man/sd_bus_error_set.html: man/sd_bus_error.html
$(html-alias)
@@ -881,6 +1070,12 @@ man/sd_bus_error_set_errno.html: man/sd_bus_error.html
man/sd_bus_error_set_errnof.html: man/sd_bus_error.html
$(html-alias)
+man/sd_bus_error_set_errnofv.html: man/sd_bus_error.html
+ $(html-alias)
+
+man/sd_bus_error_setf.html: man/sd_bus_error.html
+ $(html-alias)
+
man/sd_bus_message_append_array_iovec.html: man/sd_bus_message_append_array.html
$(html-alias)
@@ -908,7 +1103,7 @@ man/sd_bus_message_get_seqnum.html: man/sd_bus_message_get_monotonic_usec.html
man/sd_bus_negotiate_creds.html: man/sd_bus_negotiate_fds.html
$(html-alias)
-man/sd_bus_negotiate_timestamps.html: man/sd_bus_negotiate_fds.html
+man/sd_bus_negotiate_timestamp.html: man/sd_bus_negotiate_fds.html
$(html-alias)
man/sd_bus_open.html: man/sd_bus_default.html
@@ -1538,6 +1733,7 @@ endif
if ENABLE_NETWORKD
MANPAGES += \
+ man/networkctl.1 \
man/systemd-networkd-wait-online.service.8 \
man/systemd-networkd.service.8 \
man/systemd.netdev.5 \
@@ -1605,6 +1801,15 @@ man/systemd-rfkill.html: man/systemd-rfkill@.service.html
endif
+if ENABLE_SYSUSERS
+MANPAGES += \
+ man/sysusers.d.5
+MANPAGES_ALIAS += \
+ #
+
+
+endif
+
if ENABLE_TIMEDATED
MANPAGES += \
man/systemd-timedated.service.8 \
@@ -1732,11 +1937,13 @@ MANPAGES_ALIAS += \
man/sd_peer_get_session.3 \
man/sd_peer_get_slice.3 \
man/sd_peer_get_unit.3 \
+ man/sd_peer_get_user_slice.3 \
man/sd_peer_get_user_unit.3 \
man/sd_pid_get_machine_name.3 \
man/sd_pid_get_owner_uid.3 \
man/sd_pid_get_slice.3 \
man/sd_pid_get_unit.3 \
+ man/sd_pid_get_user_slice.3 \
man/sd_pid_get_user_unit.3 \
man/sd_seat_can_graphical.3 \
man/sd_seat_can_multi_session.3 \
@@ -1774,11 +1981,13 @@ man/sd_peer_get_owner_uid.3: man/sd_pid_get_session.3
man/sd_peer_get_session.3: man/sd_pid_get_session.3
man/sd_peer_get_slice.3: man/sd_pid_get_session.3
man/sd_peer_get_unit.3: man/sd_pid_get_session.3
+man/sd_peer_get_user_slice.3: man/sd_pid_get_session.3
man/sd_peer_get_user_unit.3: man/sd_pid_get_session.3
man/sd_pid_get_machine_name.3: man/sd_pid_get_session.3
man/sd_pid_get_owner_uid.3: man/sd_pid_get_session.3
man/sd_pid_get_slice.3: man/sd_pid_get_session.3
man/sd_pid_get_unit.3: man/sd_pid_get_session.3
+man/sd_pid_get_user_slice.3: man/sd_pid_get_session.3
man/sd_pid_get_user_unit.3: man/sd_pid_get_session.3
man/sd_seat_can_graphical.3: man/sd_seat_get_active.3
man/sd_seat_can_multi_session.3: man/sd_seat_get_active.3
@@ -1844,6 +2053,9 @@ man/sd_peer_get_slice.html: man/sd_pid_get_session.html
man/sd_peer_get_unit.html: man/sd_pid_get_session.html
$(html-alias)
+man/sd_peer_get_user_slice.html: man/sd_pid_get_session.html
+ $(html-alias)
+
man/sd_peer_get_user_unit.html: man/sd_pid_get_session.html
$(html-alias)
@@ -1859,6 +2071,9 @@ man/sd_pid_get_slice.html: man/sd_pid_get_session.html
man/sd_pid_get_unit.html: man/sd_pid_get_session.html
$(html-alias)
+man/sd_pid_get_user_slice.html: man/sd_pid_get_session.html
+ $(html-alias)
+
man/sd_pid_get_user_unit.html: man/sd_pid_get_session.html
$(html-alias)
@@ -2007,6 +2222,7 @@ EXTRA_DIST += \
man/pam_systemd.xml \
man/resolved.conf.xml \
man/runlevel.xml \
+ man/sd-bus-errors.xml \
man/sd-daemon.xml \
man/sd-id128.xml \
man/sd-journal.xml \
@@ -2016,6 +2232,7 @@ EXTRA_DIST += \
man/sd_bus_creds_new_from_pid.xml \
man/sd_bus_default.xml \
man/sd_bus_error.xml \
+ man/sd_bus_error_add_map.xml \
man/sd_bus_message_append.xml \
man/sd_bus_message_append_array.xml \
man/sd_bus_message_append_basic.xml \
diff --git a/Makefile.am b/Makefile.am
index d6e0b4ce39..d21982285f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,9 +42,9 @@ LIBUDEV_CURRENT=7
LIBUDEV_REVISION=4
LIBUDEV_AGE=6
-LIBSYSTEMD_CURRENT=8
+LIBSYSTEMD_CURRENT=9
LIBSYSTEMD_REVISION=0
-LIBSYSTEMD_AGE=8
+LIBSYSTEMD_AGE=9
# The following four libraries only exist for compatibility reasons,
# their version info should not be bumped anymore
@@ -639,7 +639,6 @@ UNINSTALL_DATA_HOOKS += units-uninstall-hook
dist_doc_DATA = \
README \
- README.md \
NEWS \
CODING_STYLE \
LICENSE.LGPL2.1 \
@@ -647,7 +646,10 @@ dist_doc_DATA = \
DISTRO_PORTING \
src/libsystemd/sd-bus/PORTING-DBUS1 \
src/libsystemd/sd-bus/DIFFERENCES \
- src/libsystemd/sd-bus/GVARIANT-SERIALIZATION \
+ src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
+
+EXTRA_DIST += \
+ README.md \
autogen.sh \
.dir-locals.el \
.vimrc \
@@ -708,10 +710,14 @@ noinst_DATA += \
CLEANFILES += \
man/index.html
+XML_GLOB = $(wildcard $(top_srcdir)/man/*.xml)
NON_INDEX_XML_FILES = $(filter-out man/systemd.index.xml,$(XML_FILES))
SOURCE_XML_FILES = ${patsubst %,$(top_srcdir)/%,$(filter-out man/systemd.directives.xml,$(NON_INDEX_XML_FILES))}
-update-man-list: $(top_srcdir)/tools/make-man-rules.py $(SOURCE_XML_FILES)
+# This target should only be run manually. It recreates Makefile-man.am
+# file in the source directory based on all man/*.xml files. Run it after
+# adding, removing, or changing the conditional in a man page.
+update-man-list: $(top_srcdir)/tools/make-man-rules.py $(XML_GLOB)
$(AM_V_GEN)$(PYTHON) $^ > $(top_srcdir)/Makefile-man.tmp
$(AM_V_at)mv $(top_srcdir)/Makefile-man.tmp $(top_srcdir)/Makefile-man.am
@echo "Makefile-man.am has been regenerated"
@@ -785,6 +791,8 @@ libbasic_la_SOURCES = \
src/basic/siphash24.h \
src/basic/set.h \
src/basic/ordered-set.h \
+ src/basic/bitmap.c \
+ src/basic/bitmap.h \
src/basic/fdset.c \
src/basic/fdset.h \
src/basic/prioq.c \
@@ -1406,6 +1414,7 @@ tests += \
test-time \
test-hashmap \
test-set \
+ test-bitmap \
test-list \
test-unaligned \
test-tables \
@@ -1762,6 +1771,12 @@ test_set_SOURCES = \
test_set_LDADD = \
libshared.la
+test_bitmap_SOURCES = \
+ src/test/test-bitmap.c
+
+test_bitmap_LDADD = \
+ libshared.la
+
test_xml_SOURCES = \
src/test/test-xml.c
@@ -2981,6 +2996,7 @@ tests += \
test-bus-cleanup \
test-bus-server \
test-bus-match \
+ test-bus-proxy \
test-bus-kernel \
test-bus-kernel-bloom \
test-bus-zero-copy \
@@ -3073,6 +3089,12 @@ test_bus_match_SOURCES = \
test_bus_match_LDADD = \
libshared.la
+test_bus_proxy_SOURCES = \
+ src/libsystemd/sd-bus/test-bus-proxy.c
+
+test_bus_proxy_LDADD = \
+ libshared.la
+
test_bus_kernel_SOURCES = \
src/libsystemd/sd-bus/test-bus-kernel.c
@@ -3486,7 +3508,6 @@ dist_network_DATA = \
network/80-container-ve.network
dist_udevrules_DATA += \
- rules/42-usb-hid-pm.rules \
rules/50-udev-default.rules \
rules/60-block.rules \
rules/60-drm.rules \
@@ -3498,7 +3519,6 @@ dist_udevrules_DATA += \
rules/60-serial.rules \
rules/64-btrfs.rules \
rules/70-mouse.rules \
- rules/70-touchpad.rules \
rules/75-net-description.rules \
rules/78-sound-card.rules \
rules/80-net-setup-link.rules
@@ -3667,8 +3687,7 @@ dist_udevhwdb_DATA = \
hwdb/60-evdev.hwdb \
hwdb/60-keyboard.hwdb \
hwdb/70-mouse.hwdb \
- hwdb/70-pointingstick.hwdb \
- hwdb/70-touchpad.hwdb
+ hwdb/70-pointingstick.hwdb
SYSINIT_TARGET_WANTS += \
systemd-hwdb-update.service
@@ -3804,19 +3823,6 @@ dist_udevrules_DATA += \
rules/60-persistent-v4l.rules
# ------------------------------------------------------------------------------
-accelerometer_SOURCES = \
- src/udev/accelerometer/accelerometer.c
-
-accelerometer_LDADD = \
- libshared.la
-
-udevlibexec_PROGRAMS += \
- accelerometer
-
-dist_udevrules_DATA += \
- rules/61-accelerometer.rules
-
-# ------------------------------------------------------------------------------
mtd_probe_SOURCES = \
src/udev/mtd_probe/mtd_probe.c \
src/udev/mtd_probe/mtd_probe.h \
@@ -5112,6 +5118,8 @@ systemd_resolved_SOURCES = \
src/resolve/resolved-bus.h \
src/resolve/resolved-link.h \
src/resolve/resolved-link.c \
+ src/resolve/resolved-llmnr.h \
+ src/resolve/resolved-llmnr.c \
src/resolve/resolved-def.h \
src/resolve/resolved-dns-rr.h \
src/resolve/resolved-dns-rr.c \
@@ -5633,164 +5641,6 @@ EXTRA_DIST += \
test/loopy.service.d/compat.conf
# ------------------------------------------------------------------------------
-if HAVE_PYTHON_DEVEL
-pkgpyexec_LTLIBRARIES = \
- _journal.la \
- id128.la \
- _daemon.la \
- _reader.la \
- login.la
-
-_journal_la_SOURCES = \
- src/python-systemd/_journal.c
-
-_journal_la_CFLAGS = \
- $(AM_CFLAGS) \
- -fvisibility=default \
- $(PYTHON_DEVEL_CFLAGS)
-
-_journal_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -shared \
- -module \
- -avoid-version
-
-_journal_la_LIBADD = \
- $(PYTHON_DEVEL_LIBS) \
- libsystemd.la
-
-id128_la_SOURCES = \
- src/python-systemd/id128.c \
- src/python-systemd/pyutil.c \
- src/python-systemd/pyutil.h
-
-nodist_id128_la_SOURCES = \
- src/python-systemd/id128-constants.h
-
-id128_la_CFLAGS = \
- $(AM_CFLAGS) \
- -fvisibility=default \
- $(PYTHON_DEVEL_CFLAGS) \
- -I$(top_builddir)/src/python-systemd
-
-id128_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -shared \
- -module \
- -avoid-version
-
-id128_la_LIBADD = \
- $(PYTHON_DEVEL_LIBS) \
- libshared.la \
- libsystemd.la
-
-_daemon_la_SOURCES = \
- src/python-systemd/_daemon.c \
- src/python-systemd/pyutil.c \
- src/python-systemd/pyutil.h
-
-_daemon_la_CFLAGS = \
- $(AM_CFLAGS) \
- -fvisibility=default \
- $(PYTHON_DEVEL_CFLAGS) \
- -I$(top_builddir)/src/python-systemd
-
-_daemon_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -shared \
- -module \
- -avoid-version
-
-_daemon_la_LIBADD = \
- $(PYTHON_DEVEL_LIBS) \
- libshared.la \
- libsystemd.la
-
-_reader_la_SOURCES = \
- src/python-systemd/_reader.c \
- src/python-systemd/pyutil.c \
- src/python-systemd/pyutil.h
-
-_reader_la_CFLAGS = \
- $(AM_CFLAGS) \
- -fvisibility=default \
- $(PYTHON_DEVEL_CFLAGS)
-
-_reader_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -shared \
- -module \
- -avoid-version
-
-_reader_la_LIBADD = \
- $(PYTHON_DEVEL_LIBS) \
- libshared.la \
- libsystemd.la
-
-login_la_SOURCES = \
- src/python-systemd/login.c \
- src/python-systemd/pyutil.c \
- src/python-systemd/pyutil.h
-
-login_la_CFLAGS = \
- $(AM_CFLAGS) \
- -fvisibility=default \
- $(PYTHON_DEVEL_CFLAGS)
-
-login_la_LDFLAGS = \
- $(AM_LDFLAGS) \
- -shared \
- -module \
- -avoid-version
-
-login_la_LIBADD = \
- $(PYTHON_DEVEL_LIBS) \
- libshared.la \
- libsystemd.la
-
-dist_pkgpyexec_PYTHON = \
- src/python-systemd/journal.py \
- src/python-systemd/daemon.py \
- src/python-systemd/__init__.py
-
-src/python-systemd/id128-constants.h: src/systemd/sd-messages.h
- $(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(SED) -n -r 's/,//g; s/#define (SD_MESSAGE_[A-Z0-9_]+)\s.*/add_id(m, "\1", \1) JOINER/p' <$< >$@
-
-BUILT_SOURCES += \
- $(nodist_id128_la_SOURCES)
-
-SPHINXOPTS = -D version=$(VERSION) -D release=$(VERSION)
-sphinx-%:
- $(AM_V_at)test -n "$(SPHINX_BUILD)" || { echo " *** sphinx-build is not available"; exit 1; }
- $(AM_V_GEN)PYTHONPATH=$(DESTDIR)$(pyexecdir) LD_LIBRARY_PATH=$(DESTDIR)$(libdir) $(SPHINX_BUILD) -b $* $(SPHINXOPTS) $(top_srcdir)/src/python-systemd/docs $(top_builddir)/docs/html/python-systemd/
- $(AM_V_at)echo Output has been generated in $(abs_top_builddir)/docs/html/python-systemd/
-
-python-shell:
- $(AM_V_at)echo "Starting python with $(DESTDIR)$(pyexecdir)"
- $(AM_V_at)PYTHONPATH=$(DESTDIR)$(pyexecdir) LD_LIBRARY_PATH=$(DESTDIR)$(libdir) $(PYTHON)
-
-destdir-sphinx: all
- dir="$$(mktemp -d /tmp/systemd-install.XXXXXX)" && \
- $(MAKE) DESTDIR="$$dir" install && \
- $(MAKE) DESTDIR="$$dir" sphinx-html && \
- rm -rf "$$dir"
-
-endif
-
-CLEAN_LOCAL_HOOKS += clean-sphinx
-
-.PHONY: python-shell destdir-sphinx clean-sphinx clean-python
-
-clean-sphinx:
- -rm -rf docs/html/python-systemd/
-
-# Remove Python stuff, e.g. to force rebuilding for a different Python version.
-clean-python:
- -rm -rf src/python-systemd/.libs src/python-systemd/*.l[ao]
- -rm -f _daemon.la id128.la _journal.la login.la _reader.la
-
-# ------------------------------------------------------------------------------
if ENABLE_COMPAT_LIBS
libsystemd-%.c: src/compat-libs/libsystemd-%.sym
$(AM_V_at)$(MKDIR_P) $(dir $@)
@@ -5962,7 +5812,6 @@ substitutions = \
'|RC_LOCAL_SCRIPT_PATH_START=$(RC_LOCAL_SCRIPT_PATH_START)|' \
'|RC_LOCAL_SCRIPT_PATH_STOP=$(RC_LOCAL_SCRIPT_PATH_STOP)|' \
'|PYTHON=$(PYTHON)|' \
- '|PYTHON_BINARY=$(PYTHON_BINARY)|' \
'|NTP_SERVERS=$(NTP_SERVERS)|' \
'|DNS_SERVERS=$(DNS_SERVERS)|' \
'|systemuidmax=$(SYSTEM_UID_MAX)|' \
@@ -6263,11 +6112,6 @@ DISTCHECK_CONFIGURE_FLAGS += \
--with-sysvrcnd-path=
endif
-if HAVE_PYTHON
-DISTCHECK_CONFIGURE_FLAGS += \
- --with-python
-endif
-
if ENABLE_SPLIT_USR
DISTCHECK_CONFIGURE_FLAGS += \
--enable-split-usr
@@ -6311,6 +6155,9 @@ hwdb-update:
http://standards.ieee.org/develop/regauth/iab/iab.txt && \
./ids-update.pl )
+.PHONY: built-sources
+built-sources: $(BUILT_SOURCES)
+
.PHONY: git-tag
git-tag:
git tag -s "v$(VERSION)" -m "systemd $(VERSION)"
@@ -6324,7 +6171,6 @@ www_target = www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd
.PHONY: doc-sync
doc-sync: all destdir-sphinx
rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times man/ $(www_target)/man/
- rsync -rlv --delete --omit-dir-times docs/html/python-systemd/ $(www_target)/python-systemd/
.PHONY: gardel
gardel: upload
diff --git a/NEWS b/NEWS
index bda8a8eb6c..8e09efcdda 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,106 @@
systemd System and Service Manager
+CHANGES WITH 223:
+
+ * The python-systemd code has been removed from the systemd repository.
+ A new repository has been created which accommodates the code from
+ now on, and we kindly ask distributions to create a separate package
+ for this: https://github.com/systemd/python-systemd
+
+ * The systemd daemon will now reload its main configuration
+ (/etc/systemd/system.conf) on daemon-reload.
+
+ * sd-dhcp now exposes vendor specific extensions via
+ sd_dhcp_lease_get_vendor_specific().
+
+ * systemd-networkd gained a number of new configuration options.
+
+ - A new boolean configuration option for TAP devices called
+ 'VNetHeader='. If set, the IFF_VNET_HDR flag is set for the
+ device, thus allowing to send and receive GSO packets.
+
+ - A new tunnel configuration option called 'CopyDSCP='.
+ If enabled, the DSCP field of ip6 tunnels is copied into the
+ decapsulated packet.
+
+ - A set of boolean bridge configuration options were added.
+ 'UseBPDU=', 'HairPin=', 'FastLeave=', 'AllowPortToBeRoot=',
+ and 'UnicastFlood=' are now parsed by networkd and applied to the
+ respective bridge link device via the respective IFLA_BRPORT_*
+ netlink attribute.
+
+ - A new string configuration option to override the hostname sent
+ to a DHCP server, called 'Hostname='. If set and 'SendHostname='
+ is true, networkd will use the configured hostname instead of the
+ system hostname when sending DHCP requests.
+
+ - A new tunnel configuration option called 'IPv6FlowLabel='. If set,
+ networkd will configure the IPv6 flow-label of the tunnel device
+ according to RFC2460.
+
+ * systemd-resolved now implements RFC5452 to improve resilience against
+ cache poisoning. Additionally, source port randomization is enabled
+ by default to further protect against DNS spoofing attacks.
+
+ * nss-mymachines now supports translating UIDs and GIDs of running
+ containers with user-namespaces enabled. If a container 'foo'
+ translates a host uid 'UID' to the container uid 'TUID', then
+ nss-mymachines will also map uid 'UID' to/from username 'vu-foo-TUID'
+ (with 'foo' and 'TUID' replaced accordingly). Similarly, groups are
+ mapped as 'vg-foo-TGID'.
+
+ Contributions from: Beniamino Galvani, cee1, Christian Hesse, Daniel
+ Buch, Daniel Mack, daurnimator, David Herrmann, Dimitri John Ledkov, Jan
+ Alexander Steffens (heftig), Johan Ouwerkerk, Jose Carlos Venegas Munoz,
+ Kay Sievers, Lennart Poettering, Lidong Zhong, Martin Pitt, Michael
+ Biebl, Michael Olbrich, Michal Schmidt, Mike Gilbert, Namhyung Kim, Nick
+ Owens, Peter Hutterer, Richard Maw, Steven Allen, Sungbae Yoo, Susant
+ Sahani, Thomas Blume, Thomas Hindoe Paaboel Andersen, Tom Gundersen,
+ Umut Tezduyar Lindskog, Vito Caputo, Vivenzio Pagliari, Zbigniew
+ Jędrzejewski-Szmek
+
+ -- Berlin, 2015-XX-XX
+
+CHANGES WITH 222:
+
+ * udev does not longer support the WAIT_FOR_SYSFS= key in udev rules.
+ There are no known issues with current sysfs, and udev does not need
+ or should be used to work around such bugs.
+
+ * udev does no longer enable USB HID power management. Several reports
+ indicate, that some devices cannot handle that setting.
+
+ * The udev accelerometer helper was removed. The functionality
+ is now fully included in iio-sensor-proxy. But this means,
+ older iio-sensor-proxy versions will no longer provide
+ accelerometer/orientation data with this systemd version.
+ Please upgrade iio-sensor-proxy to version 1.0.
+
+ * networkd gained a new configuration option IPv6PrivacyExtensions=
+ which enables IPv6 privacy extensions (RFC 4941, "Privacy Extensions
+ for Stateless Address") on selected networks.
+
+ * For the sake of fewer build-time dependencies and less code in the
+ main repository, the python bindings are about to be removed in the
+ next release. A new repository has been created which accommodates
+ the code from now on, and we kindly ask distributions to create a
+ separate package for this. The removal will take place in v223.
+
+ https://github.com/systemd/python-systemd
+
+ Contributions from: Abdo Roig-Maranges, Andrew Eikum, Bastien Nocera,
+ Cédric Delmas, Christian Hesse, Christos Trochalakis, Daniel Mack,
+ daurnimator, David Herrmann, Dimitri John Ledkov, Eric Biggers, Eric
+ Cook, Felipe Sateler, Geert Jansen, Gerd Hoffmann, Gianpaolo Macario,
+ Greg Kroah-Hartman, Iago López Galeiras, Jan Alexander Steffens
+ (heftig), Jan Engelhardt, Jay Strict, Kay Sievers, Lennart Poettering,
+ Markus Knetschke, Martin Pitt, Michael Biebl, Michael Marineau, Michal
+ Sekletar, Miguel Bernal Marin, Peter Hutterer, Richard Maw, rinrinne,
+ Susant Sahani, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein
+ Husebø, Vedran Miletić, WaLyong Cho, Zbigniew Jędrzejewski-Szmek
+
+ -- Berlin, 2015-07-07
+
CHANGES WITH 221:
* The sd-bus.h and sd-event.h APIs have now been declared
diff --git a/README b/README
index 53220ff3f2..7595949765 100644
--- a/README
+++ b/README
@@ -82,11 +82,11 @@ REQUIREMENTS:
CONFIG_SECCOMP
CONFIG_CHECKPOINT_RESTORE (for the kcmp() syscall)
- Required for CPUShares in resource control unit settings
+ Required for CPUShares= in resource control unit settings
CONFIG_CGROUP_SCHED
CONFIG_FAIR_GROUP_SCHED
- Required for CPUQuota in resource control unit settings
+ Required for CPUQuota= in resource control unit settings
CONFIG_CFS_BANDWIDTH
For systemd-bootchart, several proc debug interfaces are required:
@@ -97,6 +97,15 @@ REQUIREMENTS:
CONFIG_EFIVAR_FS
CONFIG_EFI_PARTITION
+ We recommend to turn off Real-Time group scheduling in the
+ kernel when using systemd. RT group scheduling effectively
+ makes RT scheduling unavailable for most userspace, since it
+ requires explicit assignment of RT budgets to each unit whose
+ processes making use of RT. As there's no sensible way to
+ assign these budgets automatically this cannot really be
+ fixed, and it's best to disable group scheduling hence.
+ CONFIG_RT_GROUP_SCHED=n
+
Note that kernel auditing is broken when used with systemd's
container code. When using systemd in conjunction with
containers, please make sure to either turn off auditing at
@@ -261,6 +270,11 @@ WARNINGS:
false positives will be triggered by code which violates
some rules but is actually safe.
+ Currently, systemd-timesyncd defaults to use the Google NTP
+ servers if not specified otherwise at configure time. You
+ really should not ship an OS or device with this default
+ setting. See DISTRO_PORTING for details.
+
ENGINEERING AND CONSULTING SERVICES:
ENDOCODE <https://endocode.com/> offers professional
engineering and consulting services for systemd. Please
diff --git a/TODO b/TODO
index 386599bc10..9514af5a90 100644
--- a/TODO
+++ b/TODO
@@ -26,6 +26,8 @@ External:
Features:
+* consider throwing a warning if a service declares it wants to be "Before=" a .device unit.
+
* "systemctl edit" should know a mode to create a new unit file
* there's probably something wrong with having user mounts below /sys,
@@ -49,10 +51,6 @@ Features:
* install: include generator dirs in unit file search paths
-* networkd: add support for configuring ipv6 privacy extensions
-
-* introduce an NSS module that uses machined info to give container UIDs pretty names when user namespacing is used.
-
* stop using off_t, it's a crazy type. Use uint64_t instead.
* logind: follow PropertiesChanged state more closely, to deal with quick logouts and relogins
@@ -71,8 +69,6 @@ Features:
* log accumulated resource usage after each service invocation
-* networkd: dhcp server: try to assign stable IP addresses based on client's MAC address
-
* nspawn: a nice way to boot up without machine id set, so that it is set at boot automatically for supporting --ephemeral. Maybe hash the host machine id together with the machine name to generate the machine id for the container
* logind: rename session scope so that it includes the UID. THat way
@@ -98,8 +94,6 @@ Features:
* nspawn: as soon as networkd has a bus interface, hook up --network-interface=, --network-bridge= with networkd, to trigger netdev creation should an interface be missing
-* networkd: make DHCP server IP range configurable, including only with a single IP address
-
* rework C11 utf8.[ch] to use char32_t instead of uint32_t when referring
to unicode chars, to make things more expressive.
@@ -318,11 +312,11 @@ Features:
(throughout the codebase, not only PID1)
* networkd:
+ - make DHCP server IP range configurable, including only with a single IP address
+ - dhcp server: try to assign stable IP addresses based on client's MAC address
- add LLDP client side support
- the DHCP lease data (such as NTP/DNS) is still made available when
a carrier is lost on a link. It should be removed instantly.
- - .network setting that allows overriding of the hostname to send to the dhcp server
- http://lists.freedesktop.org/archives/systemd-devel/2014-July/021550.html
- expose in the API the following bits:
- option 15, domain name and/or option 119, search list
- option 12, host name and/or option 81, fqdn
@@ -337,14 +331,13 @@ Features:
- allow Name= to be specified repeatedly in the [Match] section. Maybe also
support Name=foo*|bar*|baz ?
- duplicate address check for static IPs (like ARPCHECK in network-scripts)
+ - allow DUID/IAID to be customized, see issue #394.
* resolved:
- put networkd events and rtnl events at a higher priority, so that
we always process them before we process client requests
- DNSSEC
- - use base64 for key presentation?
- add display of private key types (http://tools.ietf.org/html/rfc4034#appendix-A.1.1)?
- - add nice formatting of DNS timestamps
- DNS
- search paths
- mDNS/DNS-SD
@@ -353,8 +346,6 @@ Features:
- edns0
- dname
- cname on PTR (?)
- - maybe randomize DNS UDP source ports
- - maybe compare query section of DNS replies
* Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely
diff --git a/configure.ac b/configure.ac
index 88b52c45fe..2fddf29f36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
AC_PREREQ([2.64])
AC_INIT([systemd],
- [221],
+ [222],
[http://github.com/systemd/systemd/issues],
[systemd],
[http://www.freedesktop.org/wiki/Software/systemd])
@@ -38,6 +38,11 @@ AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-di
AM_SILENT_RULES([yes])
AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
+
+AC_CHECK_TOOLS([AR], [gcc-ar ar], [:])
+AC_CHECK_TOOLS([NM], [gcc-nm nm], [:])
+AC_CHECK_TOOLS([RANLIB], [gcc-ranlib ranlib], [:])
+
LT_PREREQ(2.2)
LT_INIT([disable-static])
@@ -196,7 +201,7 @@ AS_CASE([$CC], [*clang*],
AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
[CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
- -flto -ffat-lto-objects])],
+ -flto])],
[AC_MSG_RESULT([skipping -flto, optimization not enabled])])
AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags")
@@ -238,7 +243,7 @@ AC_CHECK_SIZEOF(rlim_t,,[
])
# ------------------------------------------------------------------------------
-# we use python to build the man page index, and for systemd-python
+# we use python to build the man page index
have_python=no
AC_ARG_WITH([python],
[AS_HELP_STRING([--without-python], [Disable building the man page index and systemd-python (default: test)])])
@@ -260,30 +265,7 @@ AS_IF([test "$have_python" != "yes"], [
AS_IF([test "$with_python" != "no"],
[AC_MSG_WARN([*** python support not found, some documentation cannot be built])])
])
-
AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"])
-AS_IF([test "x$PYTHON_BINARY" = "x"],
- [AS_IF([test "x$have_python" = "xyes"],
- [PYTHON_BINARY="$(which "$PYTHON")"],
- [PYTHON_BINARY=/usr/bin/python])])
-AC_ARG_VAR(PYTHON_BINARY, [Python binary used to launch installed scripts])
-
-AS_IF([test "x$have_python" != "xyes" -a "x$enable_python_devel" = "xyes"],
- [AC_MSG_ERROR([*** python-devel support requires --with-python])])
-
-have_python_devel=no
-AC_ARG_ENABLE(python_devel, AS_HELP_STRING([--disable-python-devel], [Do not build python modules]))
-AS_IF([test "x$have_python" = "xyes" -a "x$enable_python_devel" != "xno"], [
- PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}],
- [have_python_devel=yes],
- [PKG_CHECK_MODULES([PYTHON_DEVEL], [python],
- [have_python_devel=yes],
- [have_python_devel=no])])
- AS_IF([test "x$have_python_devel" = xno -a "x$enable_python_devel" = xyes],
- [AC_MSG_ERROR([*** python-devel support requested but libraries not found])])
- AC_PATH_PROGS(SPHINX_BUILD, sphinx-build-${PYTHON_VERSION} sphinx-build)
-])
-AM_CONDITIONAL([HAVE_PYTHON_DEVEL], [test "$have_python_devel" = "yes"])
# ------------------------------------------------------------------------------
@@ -322,9 +304,10 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
IFLA_BOND_AD_INFO,
IFLA_VLAN_PROTOCOL,
IFLA_VXLAN_REMCSUM_NOPARTIAL,
- IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+ IFLA_IPTUN_ENCAP_DPORT,
+ IFLA_GRE_ENCAP_DPORT,
IFLA_BRIDGE_VLAN_INFO,
- IFLA_BRPORT_UNICAST_FLOOD,
+ IFLA_BRPORT_LEARNING_SYNC,
NDA_IFINDEX,
IFA_FLAGS],
[], [], [[
@@ -1032,7 +1015,8 @@ AC_ARG_WITH(ntp-servers,
AS_HELP_STRING([--with-ntp-servers=NTPSERVERS],
[Space-separated list of default NTP servers]),
[NTP_SERVERS="$withval"],
- [NTP_SERVERS="time1.google.com time2.google.com time3.google.com time4.google.com"])
+ [NTP_SERVERS="time1.google.com time2.google.com time3.google.com time4.google.com"
+ AC_MSG_WARN([*** Using Google NTP servers. Please do not ship OSes or devices with these default settings. See DISTRO_PORTING for details!])])
AC_DEFINE_UNQUOTED(NTP_SERVERS, ["$NTP_SERVERS"], [Default NTP Servers])
AC_SUBST(NTP_SERVERS)
@@ -1566,7 +1550,6 @@ AC_MSG_RESULT([
terminal: ${have_terminal}
kdbus: ${have_kdbus}
Python: ${have_python}
- Python Headers: ${have_python_devel}
man pages: ${have_manpages}
test coverage: ${have_coverage}
Split /usr: ${enable_split_usr}
@@ -1587,7 +1570,6 @@ AC_MSG_RESULT([
SysV init scripts: ${SYSTEM_SYSVINIT_PATH}
SysV rc?.d directories: ${SYSTEM_SYSVRCND_PATH}
Build Python: ${PYTHON}
- Installation Python: ${PYTHON_BINARY}
sphinx binary: ${SPHINX_BUILD}
PAM modules dir: ${with_pamlibdir}
PAM configuration dir: ${with_pamconfdir}
@@ -1608,6 +1590,4 @@ AC_MSG_RESULT([
CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
- PYTHON_CFLAGS: ${PYTHON_DEVEL_CFLAGS}
- PYTHON_LIBS: ${PYTHON_DEVEL_LIBS}
])
diff --git a/docs/.gitignore b/docs/.gitignore
index ac7af2e80e..35b5e99aee 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1 +1 @@
-/html/
+/html
diff --git a/hwdb/20-OUI.hwdb b/hwdb/20-OUI.hwdb
index 51f591c77a..cbf70da880 100644
--- a/hwdb/20-OUI.hwdb
+++ b/hwdb/20-OUI.hwdb
@@ -51871,6 +51871,9 @@ OUI:0463E0*
OUI:046785*
ID_OUI_FROM_DATABASE=scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH
+OUI:0469F8*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:046D42*
ID_OUI_FROM_DATABASE=Bryston Ltd.
@@ -52516,6 +52519,9 @@ OUI:080090*
OUI:080371*
ID_OUI_FROM_DATABASE=KRG CORPORATE
+OUI:080581*
+ ID_OUI_FROM_DATABASE=Roku, Inc
+
OUI:0805CD*
ID_OUI_FROM_DATABASE=DongGuang EnMai Electronic Product Co.Ltd.
@@ -54466,6 +54472,9 @@ OUI:1C1D67*
OUI:1C1D86*
ID_OUI_FROM_DATABASE=Cisco
+OUI:1C21D1*
+ ID_OUI_FROM_DATABASE=IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information.
+
OUI:1C334D*
ID_OUI_FROM_DATABASE=ITS Telecom
@@ -54994,6 +55003,9 @@ OUI:209AE9*
OUI:209BA5*
ID_OUI_FROM_DATABASE=JIAXING GLEAD Electronics Co.,Ltd
+OUI:209BCD*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:20A2E4*
ID_OUI_FROM_DATABASE=Apple
@@ -55042,6 +55054,9 @@ OUI:20C1AF*
OUI:20C38F*
ID_OUI_FROM_DATABASE=Texas Instruments Inc
+OUI:20C3A4*
+ ID_OUI_FROM_DATABASE=RetailNext
+
OUI:20C60D*
ID_OUI_FROM_DATABASE=Shanghai annijie Information technology Co.,LTD
@@ -55876,6 +55891,9 @@ OUI:2C0623*
OUI:2C073C*
ID_OUI_FROM_DATABASE=DEVLINE LIMITED
+OUI:2C081C*
+ ID_OUI_FROM_DATABASE=OVH
+
OUI:2C10C1*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
@@ -56503,6 +56521,9 @@ OUI:30D6C9*
OUI:30DE86*
ID_OUI_FROM_DATABASE=Cedac Software S.r.l.
+OUI:30E090*
+ ID_OUI_FROM_DATABASE=Linctronix Ltd,
+
OUI:30E48E*
ID_OUI_FROM_DATABASE=Vodafone UK
@@ -57025,6 +57046,9 @@ OUI:38192F*
OUI:381C1A*
ID_OUI_FROM_DATABASE=Cisco
+OUI:381C23*
+ ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD
+
OUI:381C4A*
ID_OUI_FROM_DATABASE=SIMCom Wireless Solutions Co.,Ltd.
@@ -57085,6 +57109,9 @@ OUI:38484C*
OUI:384B76*
ID_OUI_FROM_DATABASE=AIRTAME ApS
+OUI:384C90*
+ ID_OUI_FROM_DATABASE=ARRIS GROUP, INC.
+
OUI:384FF0*
ID_OUI_FROM_DATABASE=Azurewave Technologies, Inc.
@@ -57103,6 +57130,9 @@ OUI:3859F9*
OUI:385AA8*
ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co.
+OUI:385F66*
+ ID_OUI_FROM_DATABASE=Cisco SPVTG
+
OUI:385FC3*
ID_OUI_FROM_DATABASE=Yu Jeong System, Co.Ltd
@@ -57232,6 +57262,9 @@ OUI:38CA97*
OUI:38D135*
ID_OUI_FROM_DATABASE=EasyIO Corporation Sdn. Bhd.
+OUI:38D40B*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:38D82F*
ID_OUI_FROM_DATABASE=zte corporation
@@ -57496,12 +57529,18 @@ OUI:3C754A*
OUI:3C77E6*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+OUI:3C7A8A*
+ ID_OUI_FROM_DATABASE=ARRIS GROUP, INC.
+
OUI:3C7DB1*
ID_OUI_FROM_DATABASE=Texas Instruments
OUI:3C81D8*
ID_OUI_FROM_DATABASE=SAGEMCOM SAS
+OUI:3C831E*
+ ID_OUI_FROM_DATABASE=CKD Corporation
+
OUI:3C8375*
ID_OUI_FROM_DATABASE=Microsoft Corporation
@@ -57562,6 +57601,9 @@ OUI:3CA315*
OUI:3CA31A*
ID_OUI_FROM_DATABASE=Oilfind International LLC
+OUI:3CA348*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
OUI:3CA72B*
ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD
@@ -57796,6 +57838,9 @@ OUI:404022*
OUI:40406B*
ID_OUI_FROM_DATABASE=Icomera
+OUI:4040A7*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
OUI:4045DA*
ID_OUI_FROM_DATABASE=Spreadtrum Communications (Shanghai) Co., Ltd.
@@ -58477,6 +58522,9 @@ OUI:480FCF*
OUI:481249*
ID_OUI_FROM_DATABASE=Luxcom Technologies Inc.
+OUI:48137E*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:4813F3*
ID_OUI_FROM_DATABASE=BBK Electronics Corp., Ltd.
@@ -59584,6 +59632,9 @@ OUI:544A05*
OUI:544A16*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:544E90*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:545146*
ID_OUI_FROM_DATABASE=AMG Systems Ltd.
@@ -59725,6 +59776,9 @@ OUI:54B753*
OUI:54B80A*
ID_OUI_FROM_DATABASE=D-Link International
+OUI:54BE53*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:54BEF7*
ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
@@ -60022,6 +60076,9 @@ OUI:58874C*
OUI:5887E2*
ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd.
+OUI:588BF3*
+ ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation
+
OUI:588D09*
ID_OUI_FROM_DATABASE=CISCO SYSTEMS, INC.
@@ -61090,6 +61147,9 @@ OUI:6459F8*
OUI:645A04*
ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd.
+OUI:645D92*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD
+
OUI:645DD7*
ID_OUI_FROM_DATABASE=Shenzhen Lifesense Medical Electronics Co., Ltd.
@@ -61705,6 +61765,9 @@ OUI:68DFDD*
OUI:68E41F*
ID_OUI_FROM_DATABASE=Unglaube Identech GmbH
+OUI:68E8EB*
+ ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd
+
OUI:68EBAE*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -62077,6 +62140,9 @@ OUI:6CE907*
OUI:6CE983*
ID_OUI_FROM_DATABASE=Gastron Co., LTD.
+OUI:6CEBB2*
+ ID_OUI_FROM_DATABASE=Dongguan Sen DongLv Electronics Co.,Ltd
+
OUI:6CECA1*
ID_OUI_FROM_DATABASE=SHENZHEN CLOU ELECTRONICS CO. LTD.
@@ -62434,6 +62500,9 @@ OUI:70B921*
OUI:70BAEF*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+OUI:70BF3E*
+ ID_OUI_FROM_DATABASE=Charles River Laboratories
+
OUI:70C6AC*
ID_OUI_FROM_DATABASE=Bosch Automotive Aftermarket
@@ -63037,6 +63106,9 @@ OUI:78521A*
OUI:785262*
ID_OUI_FROM_DATABASE=Shenzhen Hojy Software Co., Ltd.
+OUI:7853F2*
+ ID_OUI_FROM_DATABASE=ROXTON Ltd.
+
OUI:78542E*
ID_OUI_FROM_DATABASE=D-Link International
@@ -63577,6 +63649,9 @@ OUI:7C8D91*
OUI:7C8EE4*
ID_OUI_FROM_DATABASE=Texas Instruments
+OUI:7C9122*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:7C94B2*
ID_OUI_FROM_DATABASE=Philips Healthcare PCCI
@@ -63934,6 +64009,9 @@ OUI:80618F*
OUI:806459*
ID_OUI_FROM_DATABASE=Nimbus Inc.
+OUI:80656D*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:8065E9*
ID_OUI_FROM_DATABASE=BenQ Corporation
@@ -64930,6 +65008,9 @@ OUI:8C0CA3*
OUI:8C0EE3*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD.
+OUI:8C10D4*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
OUI:8C11CB*
ID_OUI_FROM_DATABASE=ABUS Security-Center GmbH & Co. KG
@@ -65620,6 +65701,9 @@ OUI:90DB46*
OUI:90DFB7*
ID_OUI_FROM_DATABASE=s.m.s smart microwave sensors GmbH
+OUI:90DFFB*
+ ID_OUI_FROM_DATABASE=HOMERIDER SYSTEMS
+
OUI:90E0F0*
ID_OUI_FROM_DATABASE=IEEE 1722a Working Group
@@ -65776,6 +65860,9 @@ OUI:9451BF*
OUI:945493*
ID_OUI_FROM_DATABASE=Rigado, LLC
+OUI:9457A5*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
OUI:94592D*
ID_OUI_FROM_DATABASE=EKE Building Technology Systems Ltd
@@ -65893,6 +65980,9 @@ OUI:94BA31*
OUI:94BA56*
ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd.
+OUI:94BBAE*
+ ID_OUI_FROM_DATABASE=Husqvarna AB
+
OUI:94BF1E*
ID_OUI_FROM_DATABASE=eflow Inc. / Smart Device Planning and Development Division
@@ -66397,6 +66487,9 @@ OUI:9C28BF*
OUI:9C28EF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+OUI:9C293F*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
OUI:9C2A70*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
@@ -66517,6 +66610,9 @@ OUI:9C77AA*
OUI:9C79AC*
ID_OUI_FROM_DATABASE=Suntec Software(Shanghai) Co., Ltd.
+OUI:9C7A03*
+ ID_OUI_FROM_DATABASE=Ciena Corporation
+
OUI:9C7BD2*
ID_OUI_FROM_DATABASE=NEOLAB Convergence
@@ -66766,6 +66862,9 @@ OUI:A01C05*
OUI:A01D48*
ID_OUI_FROM_DATABASE=Hewlett Packard
+OUI:A01E0B*
+ ID_OUI_FROM_DATABASE=MINIX Technology Limited
+
OUI:A02195*
ID_OUI_FROM_DATABASE=Samsung Electronics Digital Imaging
@@ -66781,6 +66880,9 @@ OUI:A02BB8*
OUI:A02EF3*
ID_OUI_FROM_DATABASE=United Integrated Services Co., Led.
+OUI:A03299*
+ ID_OUI_FROM_DATABASE=Lenovo (Beijing) Co., Ltd.
+
OUI:A0369F*
ID_OUI_FROM_DATABASE=Intel Corporate
@@ -67594,6 +67696,9 @@ OUI:A84041*
OUI:A84481*
ID_OUI_FROM_DATABASE=Nokia Corporation
+OUI:A845CD*
+ ID_OUI_FROM_DATABASE=Siselectron Technology LTD.
+
OUI:A845E9*
ID_OUI_FROM_DATABASE=Firich Enterprises CO., LTD.
@@ -67645,6 +67750,9 @@ OUI:A86A6F*
OUI:A870A5*
ID_OUI_FROM_DATABASE=UniComm Inc.
+OUI:A87285*
+ ID_OUI_FROM_DATABASE=IDT, INC.
+
OUI:A8741D*
ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH
@@ -67762,6 +67870,9 @@ OUI:A8BD3A*
OUI:A8C222*
ID_OUI_FROM_DATABASE=TM-Research Inc.
+OUI:A8C87F*
+ ID_OUI_FROM_DATABASE=Roqos, Inc.
+
OUI:A8CB95*
ID_OUI_FROM_DATABASE=EAST BEST CO., LTD.
@@ -67990,6 +68101,9 @@ OUI:AC6123*
OUI:AC620D*
ID_OUI_FROM_DATABASE=Jabil Circuit (Wuxi) Co. LTD
+OUI:AC6462*
+ ID_OUI_FROM_DATABASE=zte corporation
+
OUI:AC6706*
ID_OUI_FROM_DATABASE=Ruckus Wireless
@@ -68128,6 +68242,9 @@ OUI:ACB74F*
OUI:ACB859*
ID_OUI_FROM_DATABASE=Uniband Electronic Corp,
+OUI:ACBC32*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:ACBD0B*
ID_OUI_FROM_DATABASE=IMAC CO.,LTD
@@ -68242,6 +68359,9 @@ OUI:ACEC80*
OUI:ACEE3B*
ID_OUI_FROM_DATABASE=6harmonics Inc
+OUI:ACEE9E*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:ACF0B2*
ID_OUI_FROM_DATABASE=Becker Electronics Taiwan Ltd.
@@ -69052,6 +69172,9 @@ OUI:B8415F*
OUI:B843E4*
ID_OUI_FROM_DATABASE=Vlatacom
+OUI:B844D9*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:B847C6*
ID_OUI_FROM_DATABASE=SanJet Technology Corp.
@@ -69064,6 +69187,9 @@ OUI:B85510*
OUI:B856BD*
ID_OUI_FROM_DATABASE=ITT LLC
+OUI:B857D8*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:B85810*
ID_OUI_FROM_DATABASE=NUMERA, INC.
@@ -69721,6 +69847,9 @@ OUI:BCE09D*
OUI:BCE59F*
ID_OUI_FROM_DATABASE=WATERWORLD Technology Co.,LTD
+OUI:BCE63F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:BCE767*
ID_OUI_FROM_DATABASE=Quanzhou TDX Electronics Co., Ltd
@@ -69769,6 +69898,9 @@ OUI:C005C2*
OUI:C00D7E*
ID_OUI_FROM_DATABASE=Additech, Inc.
+OUI:C01173*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:C011A6*
ID_OUI_FROM_DATABASE=Fort-Telecom ltd.
@@ -69796,6 +69928,9 @@ OUI:C0255C*
OUI:C02567*
ID_OUI_FROM_DATABASE=Nexxt Solutions
+OUI:C025A2*
+ ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
+
OUI:C027B9*
ID_OUI_FROM_DATABASE=Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd.
@@ -69868,6 +70003,9 @@ OUI:C0493D*
OUI:C04A00*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+OUI:C04A09*
+ ID_OUI_FROM_DATABASE=Zhejiang Everbright Communication Equip. Co,. Ltd
+
OUI:C04DF7*
ID_OUI_FROM_DATABASE=SERELEC
@@ -69934,6 +70072,9 @@ OUI:C0830A*
OUI:C0847A*
ID_OUI_FROM_DATABASE=Apple
+OUI:C08488*
+ ID_OUI_FROM_DATABASE=Finis Inc
+
OUI:C0885B*
ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd.
@@ -71308,6 +71449,9 @@ OUI:D023DB*
OUI:D02516*
ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+OUI:D02544*
+ ID_OUI_FROM_DATABASE=Samsung Electro Mechanics co., LTD.
+
OUI:D02598*
ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -71563,6 +71707,9 @@ OUI:D0BF9C*
OUI:D0C0BF*
ID_OUI_FROM_DATABASE=Actions Microelectronics Co., Ltd
+OUI:D0C193*
+ ID_OUI_FROM_DATABASE=SKYBELL, INC
+
OUI:D0C1B1*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -71875,6 +72022,9 @@ OUI:D481CA*
OUI:D4823E*
ID_OUI_FROM_DATABASE=Argosy Technologies, Ltd.
+OUI:D48304*
+ ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+
OUI:D48564*
ID_OUI_FROM_DATABASE=Hewlett-Packard Company
@@ -72526,6 +72676,9 @@ OUI:DC2008*
OUI:DC2A14*
ID_OUI_FROM_DATABASE=Shanghai Longjing Technology Co.
+OUI:DC2B2A*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:DC2B61*
ID_OUI_FROM_DATABASE=Apple
@@ -73579,6 +73732,9 @@ OUI:E83935*
OUI:E839DF*
ID_OUI_FROM_DATABASE=Askey Computer
+OUI:E83A12*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:E83A97*
ID_OUI_FROM_DATABASE=OCZ Technology Group
@@ -74239,6 +74395,9 @@ OUI:F00786*
OUI:F008F1*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:F00D5C*
+ ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd.
+
OUI:F013C3*
ID_OUI_FROM_DATABASE=SHENZHEN FENDA TECHNOLOGY CO., LTD
@@ -74479,6 +74638,9 @@ OUI:F0AE51*
OUI:F0B052*
ID_OUI_FROM_DATABASE=Ruckus Wireless
+OUI:F0B0E7*
+ ID_OUI_FROM_DATABASE=Apple
+
OUI:F0B2E5*
ID_OUI_FROM_DATABASE=Cisco Systems
@@ -74644,6 +74806,9 @@ OUI:F40B93*
OUI:F40E11*
ID_OUI_FROM_DATABASE=IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information.
+OUI:F40E22*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
OUI:F40F1B*
ID_OUI_FROM_DATABASE=Cisco
diff --git a/hwdb/20-bluetooth-vendor-product.hwdb b/hwdb/20-bluetooth-vendor-product.hwdb
index b737e6b308..dccced77da 100644
--- a/hwdb/20-bluetooth-vendor-product.hwdb
+++ b/hwdb/20-bluetooth-vendor-product.hwdb
@@ -1706,3 +1706,69 @@ bluetooth:v0235*
bluetooth:v0236*
ID_VENDOR_FROM_DATABASE=Pitpatpet Ltd
+
+bluetooth:v0237*
+ ID_VENDOR_FROM_DATABASE=MSHeli s.r.l.
+
+bluetooth:v0238*
+ ID_VENDOR_FROM_DATABASE=Trakm8 Ltd
+
+bluetooth:v0239*
+ ID_VENDOR_FROM_DATABASE=JIN CO, Ltd
+
+bluetooth:v023A*
+ ID_VENDOR_FROM_DATABASE=Alatech Technology
+
+bluetooth:v023B*
+ ID_VENDOR_FROM_DATABASE=Beijing CarePulse Electronic Technology Co, Ltd
+
+bluetooth:v023C*
+ ID_VENDOR_FROM_DATABASE=Awarepoint
+
+bluetooth:v023D*
+ ID_VENDOR_FROM_DATABASE=ViCentra B.V.
+
+bluetooth:v023E*
+ ID_VENDOR_FROM_DATABASE=Raven Industries
+
+bluetooth:v023F*
+ ID_VENDOR_FROM_DATABASE=WaveWare Technologies
+
+bluetooth:v0240*
+ ID_VENDOR_FROM_DATABASE=Argenox Technologies
+
+bluetooth:v0241*
+ ID_VENDOR_FROM_DATABASE=Bragi GmbH
+
+bluetooth:v0242*
+ ID_VENDOR_FROM_DATABASE=16Lab Inc
+
+bluetooth:v0243*
+ ID_VENDOR_FROM_DATABASE=Masimo Corp
+
+bluetooth:v0244*
+ ID_VENDOR_FROM_DATABASE=Iotera Inc.
+
+bluetooth:v0245*
+ ID_VENDOR_FROM_DATABASE=Endress+Hauser
+
+bluetooth:v0246*
+ ID_VENDOR_FROM_DATABASE=ACKme Networks, Inc.
+
+bluetooth:v0247*
+ ID_VENDOR_FROM_DATABASE=FiftyThree Inc.
+
+bluetooth:v0248*
+ ID_VENDOR_FROM_DATABASE=Parker Hannifin Corp
+
+bluetooth:v0249*
+ ID_VENDOR_FROM_DATABASE=Transcranial Ltd
+
+bluetooth:v024A*
+ ID_VENDOR_FROM_DATABASE=Uwatec AG
+
+bluetooth:v024B*
+ ID_VENDOR_FROM_DATABASE=Orlan LLC
+
+bluetooth:v024C*
+ ID_VENDOR_FROM_DATABASE=Blue Clover Devices
diff --git a/hwdb/20-pci-vendor-model.hwdb b/hwdb/20-pci-vendor-model.hwdb
index 065f8988ba..8316bc979e 100644
--- a/hwdb/20-pci-vendor-model.hwdb
+++ b/hwdb/20-pci-vendor-model.hwdb
@@ -4266,34 +4266,34 @@ pci:v00001002d00006608*
ID_MODEL_FROM_DATABASE=Oland GL [FirePro W2100]
pci:v00001002d00006610*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X]
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350]
pci:v00001002d00006610sv00001019sd00000030*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon HD 8670)
-
-pci:v00001002d00006610sv00001028sd00000081*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon R7 350X)
-
-pci:v00001002d00006610sv00001028sd00000083*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon R5 340X)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670)
pci:v00001002d00006610sv00001028sd00002120*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon R7 250)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 250)
pci:v00001002d00006610sv00001028sd00002322*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon R7 250)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 250)
pci:v00001002d00006610sv00001462sd00002910*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon HD 8670)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670)
pci:v00001002d00006610sv00001462sd00002911*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon HD 8670)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670)
+
+pci:v00001002d00006610sv0000148Csd00007350*
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350)
pci:v00001002d00006610sv00001642sd00003C81*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon HD 8670)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670)
pci:v00001002d00006610sv00001642sd00003C91*
- ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R5 340X / R7 250/350X] (Radeon HD 8670)
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670)
+
+pci:v00001002d00006610sv00001642sd00003F09*
+ ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350)
pci:v00001002d00006611*
ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM]
@@ -4314,10 +4314,13 @@ pci:v00001002d00006611sv00001B0Asd000090D3*
ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM)
pci:v00001002d00006613*
- ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240]
+ ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340]
+
+pci:v00001002d00006613sv0000148Csd00007340*
+ ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] (Radeon R7 340)
pci:v00001002d00006613sv00001682sd00007240*
- ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240] (R7 240 2048 MB)
+ ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] (R7 240 2048 MB)
pci:v00001002d00006620*
ID_MODEL_FROM_DATABASE=Mars
@@ -4353,40 +4356,73 @@ pci:v00001002d00006651*
ID_MODEL_FROM_DATABASE=Bonaire
pci:v00001002d00006658*
- ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X]
+ ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360]
+
+pci:v00001002d00006658sv0000148Csd00000907*
+ ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360)
+
+pci:v00001002d00006658sv00001682sd00000907*
+ ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360)
+
+pci:v00001002d00006658sv00001682sd00007360*
+ ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360)
pci:v00001002d0000665C*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM]
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM]
pci:v00001002d0000665Csv00001043sd00000452*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon HD 7790 DirectCU II OC)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 DirectCU II OC)
pci:v00001002d0000665Csv00001462sd00002930*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon HD 7790 OC)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 OC)
pci:v00001002d0000665Csv00001462sd00002932*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon HD 8770)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 8770)
pci:v00001002d0000665Csv00001462sd00002934*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon R9 260 OEM)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 260 OEM)
+
+pci:v00001002d0000665Csv00001462sd00002938*
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 360 OEM)
+
+pci:v00001002d0000665Csv0000148Csd00000907*
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R7 360)
pci:v00001002d0000665Csv0000148Csd00009260*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon R9 260 OEM)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 260 OEM)
+
+pci:v00001002d0000665Csv0000148Csd00009360*
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 360 OEM)
+
+pci:v00001002d0000665Csv00001682sd00000907*
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R7 360)
pci:v00001002d0000665Csv00001682sd00003310*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon HD 7790 Black Edition 2 GB)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 Black Edition 2 GB)
pci:v00001002d0000665Csv0000174Bsd0000E253*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon HD 7790 Dual-X OC)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 Dual-X OC)
pci:v00001002d0000665Csv00001787sd00002329*
- ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R9 260 OEM] (Radeon HD 7790 TurboDuo)
+ ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 TurboDuo)
pci:v00001002d0000665D*
ID_MODEL_FROM_DATABASE=Bonaire [Radeon R7 200 Series]
pci:v00001002d0000665F*
- ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R9 360]
+ ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM]
+
+pci:v00001002d0000665Fsv00001028sd00000B04*
+ ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM)
+
+pci:v00001002d0000665Fsv00001462sd00002938*
+ ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM)
+
+pci:v00001002d0000665Fsv00001462sd00003271*
+ ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM)
+
+pci:v00001002d0000665Fsv00001682sd00007360*
+ ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R7 360)
pci:v00001002d00006660*
ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330]
@@ -6144,13 +6180,40 @@ pci:v00001002d00006809*
ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000]
pci:v00001002d00006810*
- ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R9 270X]
+ ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R7 370 / R9 270X/370 OEM]
+
+pci:v00001002d00006810sv0000148Csd00000908*
+ ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R7 370 / R9 270X/370 OEM] (Radeon R9 370 OEM)
+
+pci:v00001002d00006810sv00001682sd00007370*
+ ID_MODEL_FROM_DATABASE=Curacao XT [Radeon R7 370 / R9 270X/370 OEM] (Radeon R7 370)
pci:v00001002d00006811*
- ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R9 270/370]
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM]
pci:v00001002d00006811sv00001028sd00000B00*
- ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R9 270/370] (Trinidad PRO [Radeon R9 370])
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
+
+pci:v00001002d00006811sv00001043sd00002016*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
+
+pci:v00001002d00006811sv00001458sd00002016*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
+
+pci:v00001002d00006811sv00001462sd00002016*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
+
+pci:v00001002d00006811sv0000148Csd00002016*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
+
+pci:v00001002d00006811sv00001682sd00002015*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R7 370])
+
+pci:v00001002d00006811sv0000174Bsd00002016*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
+
+pci:v00001002d00006811sv00001787sd00002016*
+ ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM])
pci:v00001002d00006816*
ID_MODEL_FROM_DATABASE=Pitcairn
@@ -6168,10 +6231,19 @@ pci:v00001002d00006818sv0000174Bsd00008B04*
ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] (Radeon HD 8860)
pci:v00001002d00006819*
- ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850]
+ ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP]
+
+pci:v00001002d00006819sv00001682sd00007269*
+ ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP)
+
+pci:v00001002d00006819sv00001682sd00009278*
+ ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP)
+
+pci:v00001002d00006819sv0000174Bsd0000A008*
+ ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP)
pci:v00001002d00006819sv0000174Bsd0000E221*
- ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850] (Radeon HD 7850 2GB GDDR5 DVI-I/DVI-D/HDMI/DP)
+ ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon HD 7850 2GB GDDR5 DVI-I/DVI-D/HDMI/DP)
pci:v00001002d00006820*
ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X]
@@ -8058,7 +8130,10 @@ pci:v00001002d00006938*
ID_MODEL_FROM_DATABASE=Amethyst XT [Radeon R9 M295X Mac Edition]
pci:v00001002d00006939*
- ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285]
+ ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380]
+
+pci:v00001002d00006939sv0000148Csd00009380*
+ ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380)
pci:v00001002d0000700F*
ID_MODEL_FROM_DATABASE=RS100 AGP Bridge
@@ -8420,6 +8495,9 @@ pci:v00001002d000072B1*
pci:v00001002d000072B3*
ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 GT] (Secondary)
+pci:v00001002d00007300*
+ ID_MODEL_FROM_DATABASE=Fiji XT [Radeon R9 FURY X]
+
pci:v00001002d00007833*
ID_MODEL_FROM_DATABASE=RS350 Host Bridge
@@ -28562,6 +28640,9 @@ pci:v000010DEd00001022*
pci:v000010DEd00001023*
ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40m]
+pci:v000010DEd00001023sv000010DEsd0000097E*
+ ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40m] (12GB Computational Accelerator)
+
pci:v000010DEd00001024*
ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40c]
@@ -29921,6 +30002,9 @@ pci:v000010DEd000011C7*
pci:v000010DEd000011C8*
ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 OEM]
+pci:v000010DEd000011CB*
+ ID_MODEL_FROM_DATABASE=GK106 [GeForce GT 740]
+
pci:v000010DEd000011E0*
ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 770M]
@@ -30203,6 +30287,9 @@ pci:v000010DEd00001341sv000017AAsd00003699*
pci:v000010DEd00001341sv000017AAsd0000369C*
ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A)
+pci:v000010DEd00001344*
+ ID_MODEL_FROM_DATABASE=GM108M [GeForce 845M]
+
pci:v000010DEd00001346*
ID_MODEL_FROM_DATABASE=GM108M [GeForce 930M]
@@ -30212,6 +30299,9 @@ pci:v000010DEd00001347*
pci:v000010DEd0000137A*
ID_MODEL_FROM_DATABASE=GM108GLM [Quadro K620M]
+pci:v000010DEd0000137D*
+ ID_MODEL_FROM_DATABASE=GM108M [GeForce 940A]
+
pci:v000010DEd00001380*
ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 750 Ti]
@@ -30255,7 +30345,13 @@ pci:v000010DEd0000139C*
ID_MODEL_FROM_DATABASE=GM107M [GeForce 940M]
pci:v000010DEd000013B0*
- ID_MODEL_FROM_DATABASE=GM107GLM [N16P-Q3]
+ ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M2000M]
+
+pci:v000010DEd000013B1*
+ ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M1000M]
+
+pci:v000010DEd000013B2*
+ ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M600M]
pci:v000010DEd000013B3*
ID_MODEL_FROM_DATABASE=GM107GLM [Quadro K2200M]
@@ -30296,6 +30392,12 @@ pci:v000010DEd000013D8*
pci:v000010DEd000013D9*
ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M]
+pci:v000010DEd000013F0*
+ ID_MODEL_FROM_DATABASE=GM204GL [Quadro M5000]
+
+pci:v000010DEd000013F1*
+ ID_MODEL_FROM_DATABASE=GM204GL [Quadro M4000]
+
pci:v000010DEd000013F2*
ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60]
@@ -30896,6 +30998,9 @@ pci:v000010ECd00008139sv000010F7sd00008338*
pci:v000010ECd00008139sv00001113sd0000EC01*
ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LevelOne FNC-0107TX/FNC-0109TX)
+pci:v000010ECd00008139sv00001186sd00001104*
+ ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DFE-520TX Fast Ethernet PCI Adapter (rev. D1))
+
pci:v000010ECd00008139sv00001186sd00001300*
ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DFE-538TX)
@@ -32367,7 +32472,7 @@ pci:v00001106d00003043sv00001106sd00000100*
ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (VT86C100A Fast Ethernet Adapter)
pci:v00001106d00003043sv00001186sd00001400*
- ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (DFE-530TX rev A)
+ ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (DFE-530TX PCI Fast Ethernet Adapter (rev. A))
pci:v00001106d00003044*
ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller
@@ -32417,6 +32522,9 @@ pci:v00001106d00003051*
pci:v00001106d00003053*
ID_MODEL_FROM_DATABASE=VT6105M [Rhine-III]
+pci:v00001106d00003053sv00001186sd00001404*
+ ID_MODEL_FROM_DATABASE=VT6105M [Rhine-III] (DFE-530TX PCI Fast Ethernet Adapter (rev. D))
+
pci:v00001106d00003057*
ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI]
@@ -32589,10 +32697,13 @@ pci:v00001106d00003065sv00001106sd00000102*
ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (VT6102/6103 [Rhine II] Ethernet Controller)
pci:v00001106d00003065sv00001186sd00001400*
- ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX rev A)
+ ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. A))
pci:v00001106d00003065sv00001186sd00001401*
- ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX rev B)
+ ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. B))
+
+pci:v00001106d00003065sv00001186sd00001402*
+ ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. B))
pci:v00001106d00003065sv000013B9sd00001421*
ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (LD-10/100AL PCI Fast Ethernet Adapter (rev.B))
@@ -32712,7 +32823,7 @@ pci:v00001106d00003106sv00001106sd00000105*
ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (VT6106S [Rhine-III])
pci:v00001106d00003106sv00001186sd00001403*
- ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-530TX rev C)
+ ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-530TX PCI Fast Ethernet Adapter (rev. C))
pci:v00001106d00003106sv00001186sd00001405*
ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-520TX Fast Ethernet PCI Adapter)
@@ -37262,6 +37373,9 @@ pci:v00001186d00004200sv00001186sd00001103*
pci:v00001186d00004300*
ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter
+pci:v00001186d00004300sv00001186sd00004300*
+ ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter (DGE-528T PCI Gigabit Ethernet Adapter)
+
pci:v00001186d00004300sv00001186sd00004B10*
ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter (DGE-560T PCI Express (x1) Gigabit Ethernet Adapter)
@@ -45659,6 +45773,12 @@ pci:v00001425d00005014*
pci:v00001425d00005015*
ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller
+pci:v00001425d00005016*
+ ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller
+
+pci:v00001425d00005017*
+ ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller
+
pci:v00001425d00005080*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
@@ -45692,6 +45812,12 @@ pci:v00001425d00005089*
pci:v00001425d00005090*
ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller
+pci:v00001425d00005091*
+ ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller
+
+pci:v00001425d00005092*
+ ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller
+
pci:v00001425d00005401*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -45755,6 +45881,12 @@ pci:v00001425d00005414*
pci:v00001425d00005415*
ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller
+pci:v00001425d00005416*
+ ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller
+
+pci:v00001425d00005417*
+ ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller
+
pci:v00001425d00005480*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller
@@ -45788,6 +45920,12 @@ pci:v00001425d00005489*
pci:v00001425d00005490*
ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller
+pci:v00001425d00005491*
+ ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller
+
+pci:v00001425d00005492*
+ ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller
+
pci:v00001425d00005501*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
@@ -45851,6 +45989,12 @@ pci:v00001425d00005514*
pci:v00001425d00005515*
ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Storage Controller
+pci:v00001425d00005516*
+ ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Storage Controller
+
+pci:v00001425d00005517*
+ ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Storage Controller
+
pci:v00001425d00005580*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller
@@ -45884,6 +46028,12 @@ pci:v00001425d00005589*
pci:v00001425d00005590*
ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Storage Controller
+pci:v00001425d00005591*
+ ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Storage Controller
+
+pci:v00001425d00005592*
+ ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Storage Controller
+
pci:v00001425d00005601*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
@@ -45947,6 +46097,12 @@ pci:v00001425d00005614*
pci:v00001425d00005615*
ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Storage Controller
+pci:v00001425d00005616*
+ ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Storage Controller
+
+pci:v00001425d00005617*
+ ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Storage Controller
+
pci:v00001425d00005680*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller
@@ -45980,6 +46136,12 @@ pci:v00001425d00005689*
pci:v00001425d00005690*
ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Storage Controller
+pci:v00001425d00005691*
+ ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Storage Controller
+
+pci:v00001425d00005692*
+ ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Storage Controller
+
pci:v00001425d00005701*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
@@ -46076,6 +46238,12 @@ pci:v00001425d00005789*
pci:v00001425d00005790*
ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller
+pci:v00001425d00005791*
+ ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller
+
+pci:v00001425d00005792*
+ ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller
+
pci:v00001425d00005801*
ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller [VF]
@@ -46139,6 +46307,12 @@ pci:v00001425d00005814*
pci:v00001425d00005815*
ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller [VF]
+pci:v00001425d00005816*
+ ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d00005817*
+ ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller [VF]
+
pci:v00001425d00005880*
ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller [VF]
@@ -46172,6 +46346,12 @@ pci:v00001425d00005889*
pci:v00001425d00005890*
ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller [VF]
+pci:v00001425d00005891*
+ ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d00005892*
+ ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller [VF]
+
pci:v00001425d0000A000*
ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller
@@ -46385,6 +46565,21 @@ pci:v0000144Dd0000A820sv00001028sd00001F96*
pci:v0000144Dd0000A820sv00001028sd00001F97*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 1600GB)
+pci:v0000144Dd0000A820sv00001028sd00001FA4*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 3.2TB SFF)
+
+pci:v0000144Dd0000A820sv00001028sd00001FA6*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 3.2TB AIC)
+
+pci:v0000144Dd0000A820sv00001028sd00001FBA*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 800GB SFF)
+
+pci:v0000144Dd0000A820sv00001028sd00001FBB*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 1.6TB SFF)
+
+pci:v0000144Dd0000A820sv00001028sd00001FBC*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 1.6TB AIC)
+
pci:v0000144Dd0000A821*
ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X
@@ -55883,6 +56078,12 @@ pci:v000019AEd00000520*
pci:v000019AEd00000521*
ID_MODEL_FROM_DATABASE=Decimator
+pci:v000019BA*
+ ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corp.
+
+pci:v000019BAd00002330*
+ ID_MODEL_FROM_DATABASE=ZyWALL Turbo Card
+
pci:v000019C1*
ID_VENDOR_FROM_DATABASE=Exegy Inc.
@@ -56324,6 +56525,12 @@ pci:v00001AE9d00000302*
pci:v00001AE9d00000310*
ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter
+pci:v00001AEA*
+ ID_VENDOR_FROM_DATABASE=Alcor Micro
+
+pci:v00001AEAd00006601*
+ ID_MODEL_FROM_DATABASE=AU6601 PCI-E Flash card reader controller
+
pci:v00001AEC*
ID_VENDOR_FROM_DATABASE=Wolfson Microelectronics
@@ -56819,6 +57026,30 @@ pci:v00001BBFd00000003*
pci:v00001BBFd00000004*
ID_MODEL_FROM_DATABASE=MAX4
+pci:v00001BD0*
+ ID_VENDOR_FROM_DATABASE=Astronics Corporation
+
+pci:v00001BD0d00001001*
+ ID_MODEL_FROM_DATABASE=Mx5 PMC/XMC Databus Interface Card
+
+pci:v00001BD0d00001002*
+ ID_MODEL_FROM_DATABASE=PM1553-5 (PC/104+ MIL-STD-1553 Interface Card)
+
+pci:v00001BD0d00001004*
+ ID_MODEL_FROM_DATABASE=AB3000 Series Rugged Computer
+
+pci:v00001BD0d00001005*
+ ID_MODEL_FROM_DATABASE=PE1000 (Multi-Protocol PCIe/104 Interface Card)
+
+pci:v00001BD0d00001101*
+ ID_MODEL_FROM_DATABASE=OmniBus II PCIe Multi-Protocol Interface Card
+
+pci:v00001BD0d00001102*
+ ID_MODEL_FROM_DATABASE=OmniBusBox II Multi-Protocol Interface Core
+
+pci:v00001BD0d00001103*
+ ID_MODEL_FROM_DATABASE=OmniBus II cPCIe/PXIe Multi-Protocol Interface Card
+
pci:v00001BEE*
ID_VENDOR_FROM_DATABASE=IXXAT Automation GmbH
@@ -60372,16 +60603,16 @@ pci:v00008086d00000C4E*
ID_MODEL_FROM_DATABASE=Atom Processor S1200 NTB Primary
pci:v00008086d00000C50*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QuickData Technology Device
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device
pci:v00008086d00000C51*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QuickData Technology Device
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device
pci:v00008086d00000C52*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QuickData Technology Device
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device
pci:v00008086d00000C53*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QuickData Technology Device
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device
pci:v00008086d00000C54*
ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal
@@ -67220,6 +67451,12 @@ pci:v00008086d000024DF*
pci:v00008086d000024DFsv00001028sd00000168*
ID_MODEL_FROM_DATABASE=82801ER (ICH5R) SATA Controller (Precision Workstation 670 Mainboard)
+pci:v00008086d000024F0*
+ ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete]
+
+pci:v00008086d000024F1*
+ ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [integrated]
+
pci:v00008086d000024F3*
ID_MODEL_FROM_DATABASE=Wireless 8260
@@ -75090,487 +75327,487 @@ pci:v00008086d000065FF*
ID_MODEL_FROM_DATABASE=5100 Chipset DMA Engine
pci:v00008086d00006F00*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DMI2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2
pci:v00008086d00006F01*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 0
pci:v00008086d00006F02*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1
pci:v00008086d00006F03*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1
pci:v00008086d00006F04*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2
pci:v00008086d00006F05*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2
pci:v00008086d00006F06*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2
pci:v00008086d00006F07*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2
pci:v00008086d00006F08*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 3
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3
pci:v00008086d00006F09*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 3
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3
pci:v00008086d00006F0A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 3
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3
pci:v00008086d00006F0B*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon PCI Express Root Port 3
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3
pci:v00008086d00006F10*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F11*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F12*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F13*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F14*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F15*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F16*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F17*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F18*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F19*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F1A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F1B*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F1C*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug
pci:v00008086d00006F1D*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R2PCIe Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent
pci:v00008086d00006F1E*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Ubox
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox
pci:v00008086d00006F1F*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Ubox
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox
pci:v00008086d00006F20*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 0
pci:v00008086d00006F21*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 1
pci:v00008086d00006F22*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 2
pci:v00008086d00006F23*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 3
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 3
pci:v00008086d00006F24*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 4
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 4
pci:v00008086d00006F25*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 5
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 5
pci:v00008086d00006F26*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 6
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 6
pci:v00008086d00006F27*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Crystal Beach DMA Channel 7
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 7
pci:v00008086d00006F28*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Map/VTd_Misc/System Management
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management
pci:v00008086d00006F29*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO Hot Plug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug
pci:v00008086d00006F2A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IIO RAS/Control Status/Global Errors
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors
pci:v00008086d00006F2C*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon I/O APIC
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC
pci:v00008086d00006F30*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Home Agent 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0
pci:v00008086d00006F32*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0
pci:v00008086d00006F33*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1
pci:v00008086d00006F34*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R2PCIe Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent
pci:v00008086d00006F36*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link 0/1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1
pci:v00008086d00006F37*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link 0/1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1
pci:v00008086d00006F38*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Home Agent 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1
pci:v00008086d00006F39*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon IO Performance Monitoring
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IO Performance Monitoring
pci:v00008086d00006F3A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2
pci:v00008086d00006F3E*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2
pci:v00008086d00006F3F*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2
pci:v00008086d00006F40*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2
pci:v00008086d00006F41*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2
pci:v00008086d00006F43*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 2
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2
pci:v00008086d00006F45*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 2 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug
pci:v00008086d00006F46*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 2 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug
pci:v00008086d00006F47*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 2 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug
pci:v00008086d00006F60*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Home Agent 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1
pci:v00008086d00006F68*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Target Address/Thermal/RAS
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS
pci:v00008086d00006F6A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder
pci:v00008086d00006F6B*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder
pci:v00008086d00006F6C*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder
pci:v00008086d00006F6D*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder
pci:v00008086d00006F6E*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 2/3 Broadcast
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Broadcast
pci:v00008086d00006F6F*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Global Broadcast
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast
pci:v00008086d00006F70*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Home Agent 0 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 Debug
pci:v00008086d00006F71*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Target Address/Thermal/RAS
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS
pci:v00008086d00006F76*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug
pci:v00008086d00006F78*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Home Agent 1 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 Debug
pci:v00008086d00006F79*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Target Address/Thermal/RAS
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS
pci:v00008086d00006F7D*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Ubox
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox
pci:v00008086d00006F7E*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug
pci:v00008086d00006F80*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0
pci:v00008086d00006F81*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon R3 QPI Link 0/1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1
pci:v00008086d00006F83*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0
pci:v00008086d00006F85*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 0 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug
pci:v00008086d00006F86*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 0 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug
pci:v00008086d00006F87*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 0 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug
pci:v00008086d00006F88*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006F8A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006F90*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1
pci:v00008086d00006F93*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 1
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1
pci:v00008086d00006F95*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 1 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug
pci:v00008086d00006F96*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon QPI Link 1 Debug
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug
pci:v00008086d00006F98*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006F99*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006F9A*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006F9C*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FA0*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Home Agent 0
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0
pci:v00008086d00006FA8*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Target Address/Thermal/RAS
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS
pci:v00008086d00006FAA*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder
pci:v00008086d00006FAB*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder
pci:v00008086d00006FAC*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder
pci:v00008086d00006FAD*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel Target Address Decoder
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder
pci:v00008086d00006FAE*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 0/1 Broadcast
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Broadcast
pci:v00008086d00006FAF*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Global Broadcast
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast
pci:v00008086d00006FB0*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 0 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Thermal Control
pci:v00008086d00006FB1*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 1 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Thermal Control
pci:v00008086d00006FB2*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 0 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Error
pci:v00008086d00006FB3*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 1 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Error
pci:v00008086d00006FB4*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 2 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Thermal Control
pci:v00008086d00006FB5*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 3 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Thermal Control
pci:v00008086d00006FB6*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 2 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Error
pci:v00008086d00006FB7*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 0 - Channel 3 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Error
pci:v00008086d00006FB8*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 2/3 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface
pci:v00008086d00006FB9*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 2/3 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface
pci:v00008086d00006FBA*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 2/3 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface
pci:v00008086d00006FBB*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 2/3 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface
pci:v00008086d00006FBC*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 0/1 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface
pci:v00008086d00006FBD*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 0/1 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface
pci:v00008086d00006FBE*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 0/1 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface
pci:v00008086d00006FBF*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon DDRIO Channel 0/1 Interface
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface
pci:v00008086d00006FC0*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC1*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC2*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC3*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC4*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC5*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC6*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC7*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC8*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FC9*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FCA*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FCB*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FCC*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FCD*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FCE*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FCF*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Power Control Unit
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit
pci:v00008086d00006FD0*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 0 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Thermal Control
pci:v00008086d00006FD1*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 1 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Thermal Control
pci:v00008086d00006FD2*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 0 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Error
pci:v00008086d00006FD3*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 1 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Error
pci:v00008086d00006FD4*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 2 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Thermal Control
pci:v00008086d00006FD5*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 3 Thermal Control
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Thermal Control
pci:v00008086d00006FD6*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 2 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Error
pci:v00008086d00006FD7*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Memory Controller 1 - Channel 3 Error
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Error
pci:v00008086d00006FE0*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE1*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE2*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE3*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE4*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE5*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE6*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE7*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE8*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FE9*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FEA*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FEB*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FEC*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FED*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FEE*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FEF*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FF0*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FF1*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FF8*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FF9*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FFA*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FFB*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FFC*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FFD*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00006FFE*
- ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon Caching Agent
+ ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent
pci:v00008086d00007000*
ID_MODEL_FROM_DATABASE=82371SB PIIX3 ISA [Natoma/Triton II]
@@ -77363,6 +77600,9 @@ pci:v00008086d0000A1FC*
pci:v00008086d0000A620*
ID_MODEL_FROM_DATABASE=6400/6402 Advanced Memory Buffer (AMB)
+pci:v00008086d0000ABC0*
+ ID_MODEL_FROM_DATABASE=Omni-Path Fabric Switch Silicon 100 Series
+
pci:v00008086d0000B152*
ID_MODEL_FROM_DATABASE=21152 PCI-to-PCI Bridge
diff --git a/hwdb/20-usb-vendor-model.hwdb b/hwdb/20-usb-vendor-model.hwdb
index 151ba5ce04..87dad3a0ea 100644
--- a/hwdb/20-usb-vendor-model.hwdb
+++ b/hwdb/20-usb-vendor-model.hwdb
@@ -44943,7 +44943,7 @@ usb:v152Dp0539*
ID_MODEL_FROM_DATABASE=JMS539/567 SuperSpeed SATA II/III 3.0G/6.0G Bridge
usb:v152Dp0567*
- ID_MODEL_FROM_DATABASE=JMS567 SATA 6.0Gb/s bridge
+ ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge
usb:v152Dp0770*
ID_MODEL_FROM_DATABASE=Alienware Integrated Webcam
@@ -44978,8 +44978,11 @@ usb:v152Dp2551*
usb:v152Dp2566*
ID_MODEL_FROM_DATABASE=JMS566 SATA 3Gb/s bridge
+usb:v152Dp2590*
+ ID_MODEL_FROM_DATABASE=Seatay ATA/ATAPI Bridge
+
usb:v152Dp3562*
- ID_MODEL_FROM_DATABASE=JMS567 SATA 6.0Gb/s bridge
+ ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge
usb:v152Dp3569*
ID_MODEL_FROM_DATABASE=JMS566 SATA 3Gb/s bridge
diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb
index 1633321502..bc4b597bbf 100644
--- a/hwdb/70-mouse.hwdb
+++ b/hwdb/70-mouse.hwdb
@@ -247,6 +247,10 @@ mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:
mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:
MOUSE_DPI=1000@125
+# Logitech MX Master
+mouse:usb:v046dp4041:name:Logitech MX Master:
+ MOUSE_DPI=1000@166
+
# Logitech MK260 Wireless Combo Receiver aka M-R0011
mouse:usb:v046dpc52e:name:Logitech USB Receiver:
MOUSE_DPI=1000@200
diff --git a/hwdb/70-touchpad.hwdb b/hwdb/70-touchpad.hwdb
deleted file mode 100644
index 8a324466b3..0000000000
--- a/hwdb/70-touchpad.hwdb
+++ /dev/null
@@ -1,43 +0,0 @@
-# This file is part of systemd.
-#
-# The lookup keys are composed in:
-# 70-touchpad.rules
-#
-# Note: The format of the "touchpad:" prefix match key is a
-# contract between the rules file and the hardware data, it might
-# change in later revisions to support more or better matches, it
-# is not necessarily expected to be a stable ABI.
-#
-# Match string format:
-# touchpad:pnpid:<pnpid>:
-#
-# To add local entries, create a new file
-# /etc/udev/hwdb.d/71-touchpad-local.hwdb
-# and add your rules there. To load the new rules execute (as root):
-# udevadm hwdb --update
-# udevadm trigger /dev/input/eventXX
-# where /dev/input/eventXX is the touchpad in question. If in
-# doubt, simply use /dev/input/event* to reload all input rules.
-#
-# If your changes are generally applicable, open a bug report on
-# http://bugs.freedesktop.org/enter_bug.cgi?product=systemd
-# and include your new rules, a description of the device, and the
-# output of
-# udevadm info /dev/input/eventXX
-# (or /dev/input/event*).
-#
-# Allowed properties are:
-# TOUCHPAD_HAS_TRACKPOINT_BUTTONS=1
-#
-# If the TOUCHPAD_HAS_TRACKPOINT_BUTTONS property is set, this
-# device has # the trackpoint buttons wired up to the touchpad as
-# BTN_0, BTN_1 and BTN_2. This affects the Lenovo X1 Carbon 3rd
-# and the *50 series (T450, T550, etc.)
-
-# Lenovo X1 Carbon 3rd
-touchpad:pnpid:*LEN0048*:
-# Lenovo W541
-touchpad:pnpid:*LEN004a*:
-# Lenovo T450s
-touchpad:pnpid:*LEN200f*:
- TOUCHPAD_HAS_TRACKPOINT_BUTTONS=1
diff --git a/man/coredump.conf.xml b/man/coredump.conf.xml
index fd54c59e6b..8e71f7d4ec 100644
--- a/man/coredump.conf.xml
+++ b/man/coredump.conf.xml
@@ -58,7 +58,7 @@
<refsect1>
<title>Description</title>
- <para>These files configure the behaviour of
+ <para>These files configure the behavior of
<citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
a handler for core dumps invoked by the kernel.</para>
</refsect1>
diff --git a/man/custom-html.xsl b/man/custom-html.xsl
index b298c216b1..3e266e4a7f 100644
--- a/man/custom-html.xsl
+++ b/man/custom-html.xsl
@@ -22,6 +22,16 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
+<!--
+ - The docbook stylesheet injects empty anchor tags into generated HTML, identified by an auto-generated ID.
+ - Ask the docbook stylesheet to generate reproducible output when generating (these) ID values.
+ - This makes the output of this stylesheet reproducible across identical invocations on the same input,
+ - which is an easy and significant win for achieving reproducible builds.
+ -
+ - It may be even better to strip the empty anchors from the document output in addition to turning on consistent IDs,
+ - for this stylesheet contains its own custom ID logic (for generating permalinks) already.
+ -->
+<xsl:param name="generate.consistent.ids" select="1"/>
<!-- translate man page references to links to html pages -->
<xsl:template match="citerefentry[not(@project)]">
@@ -113,80 +123,122 @@
</a>
</xsl:template>
-<xsl:template match="refsect1/title|refsect1/info/title">
- <!-- the ID is output in the block.object call for refsect1 -->
- <h2>
+<!--
+ - helper template to do conflict resolution between various headings with the same inferred ID attribute/tag from the headerlink template
+ - this conflict resolution is necessary to prevent malformed HTML output (multiple id attributes with the same value)
+ - and it fixes xsltproc warnings during compilation of HTML man pages
+ -
+ - A simple top-to-bottom numbering scheme is implemented for nodes with the same ID value to derive unique ID values for HTML output.
+ - It uses two parameters:
+ templateID the proposed ID string to use which must be checked for conflicts
+ keyNode the context node which 'produced' the given templateID.
+ -
+ - Conflicts are detected solely based on keyNode, templateID is not taken into account for that purpose.
+ -->
+<xsl:template name="generateID">
+ <!-- node which generatedID needs to assume as the 'source' of the ID -->
+ <xsl:param name="keyNode"/>
+ <!-- suggested value for generatedID output, a contextually meaningful ID string -->
+ <xsl:param name="templateID"/>
+ <xsl:variable name="conflictSource" select="preceding::refsect1/title|preceding::refsect1/info/title|
+ preceding::refsect2/title|preceding::refsect2/info/title|
+ preceding::varlistentry/term[1]"/>
+ <xsl:variable name="conflictCount" select="count($conflictSource[. = $keyNode])"/>
+ <xsl:choose>
+ <!-- special case conflictCount = 0 to preserve compatibility with URLs generated by previous versions of this XSL stylesheet where possible -->
+ <xsl:when test="$conflictCount = 0">
+ <xsl:value-of select="$templateID"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($templateID, $conflictCount)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--
+ - a helper template to abstract over the structure of generated subheading + permalink HTML output
+ - It helps reduce tedious repetition and groups all actual markup output (as opposed to URL/ID logic) in a single location.
+ -->
+<xsl:template name="permalink">
+ <xsl:param name="nodeType"/> <!-- local name of the element node to generate, e.g. 'h2' for <h2></h2> -->
+ <xsl:param name="nodeContent"/> <!-- nodeset to apply further templates to obtain the content of the subheading/term -->
+ <xsl:param name="linkTitle"/> <!-- value for title attribute of generated permalink, e.g. 'this is a permalink' -->
+
+ <!-- parameters passed to generateID template, otherwise unused. -->
+ <xsl:param name="keyNode"/>
+ <xsl:param name="templateID"/>
+
+ <!--
+ - If stable URLs with fragment markers (references to the ID) turn out not to be important:
+ - generatedID could simply take the value of generate-id(), and various other helper templates may be dropped entirely.
+ - Alternatively if xsltproc is patched to generate reproducible generate-id() output the same simplifications can be
+ - applied at the cost of breaking compatibility with URLs generated from output of previous versions of this stylesheet.
+ -->
+ <xsl:variable name="generatedID">
+ <xsl:call-template name="generateID">
+ <xsl:with-param name="keyNode" select="$keyNode"/>
+ <xsl:with-param name="templateID" select="$templateID"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:element name="{$nodeType}">
<xsl:attribute name="id">
- <xsl:call-template name="inline.charseq"/>
+ <xsl:value-of select="$generatedID"/>
</xsl:attribute>
- <xsl:apply-templates/>
- <a>
- <xsl:attribute name="class">
- <xsl:text>headerlink</xsl:text>
- </xsl:attribute>
- <xsl:attribute name="title">
- <xsl:text>Permalink to this headline</xsl:text>
- </xsl:attribute>
- <xsl:attribute name="href">
- <xsl:text>#</xsl:text>
- <xsl:call-template name="inline.charseq"/>
- </xsl:attribute>
- <xsl:text>¶</xsl:text>
- </a>
- </h2>
+ <xsl:apply-templates select="$nodeContent"/>
+ <a class="headerlink" title="{$linkTitle}" href="#{$generatedID}">¶</a>
+ </xsl:element>
</xsl:template>
-<xsl:template match="refsect2/title|refsect2/info/title">
- <h3>
- <xsl:attribute name="id">
+<!-- simple wrapper around permalink to avoid repeating common info for each level of subheading covered by the permalink logic (h2, h3) -->
+<xsl:template name="headerlink">
+ <xsl:param name="nodeType"/>
+ <xsl:call-template name="permalink">
+ <xsl:with-param name="nodeType" select="$nodeType"/>
+ <xsl:with-param name="linkTitle" select="'Permalink to this headline'"/>
+ <xsl:with-param name="nodeContent" select="node()"/>
+ <xsl:with-param name="keyNode" select="."/>
+ <!--
+ - To retain compatibility with IDs generated by previous versions of the template, inline.charseq must be called.
+ - The purpose of that template is to generate markup (according to docbook documentation its purpose is to mark/format something as plain text).
+ - The only reason to call this template is to get the auto-generated text such as brackets ([]) before flattening it.
+ -->
+ <xsl:with-param name="templateID">
<xsl:call-template name="inline.charseq"/>
- </xsl:attribute>
- <xsl:apply-templates/>
- <a>
- <xsl:attribute name="class">
- <xsl:text>headerlink</xsl:text>
- </xsl:attribute>
- <xsl:attribute name="title">
- <xsl:text>Permalink to this headline</xsl:text>
- </xsl:attribute>
- <xsl:attribute name="href">
- <xsl:text>#</xsl:text>
- <xsl:call-template name="inline.charseq"/>
- </xsl:attribute>
- <xsl:text>¶</xsl:text>
- </a>
- </h3>
+ </xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="refsect1/title|refsect1/info/title">
+ <!-- the ID is output in the block.object call for refsect1 -->
+ <xsl:call-template name="headerlink">
+ <xsl:with-param name="nodeType" select="'h2'"/>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="refsect2/title|refsect2/info/title">
+ <xsl:call-template name="headerlink">
+ <xsl:with-param name="nodeType" select="'h3'"/>
+ </xsl:call-template>
</xsl:template>
<xsl:template match="varlistentry">
- <dt>
- <xsl:attribute name="id">
+ <xsl:call-template name="permalink">
+ <xsl:with-param name="nodeType" select="'dt'"/>
+ <xsl:with-param name="linkTitle" select="'Permalink to this term'"/>
+ <xsl:with-param name="nodeContent" select="term"/>
+ <xsl:with-param name="keyNode" select="term[1]"/>
+ <!--
+ - To retain compatibility with IDs generated by previous versions of the template, inline.charseq must be called.
+ - The purpose of that template is to generate markup (according to docbook documentation its purpose is to mark/format something as plain text).
+ - The only reason to call this template is to get the auto-generated text such as brackets ([]) before flattening it.
+ -->
+ <xsl:with-param name="templateID">
<xsl:call-template name="inline.charseq">
- <xsl:with-param name="content">
- <xsl:copy-of select="term[position()=1]" />
- </xsl:with-param>
+ <xsl:with-param name="content" select="term[1]"/>
</xsl:call-template>
- </xsl:attribute>
- <xsl:apply-templates select="term"/>
- <a>
- <xsl:attribute name="class">
- <xsl:text>headerlink</xsl:text>
- </xsl:attribute>
- <xsl:attribute name="title">
- <xsl:text>Permalink to this term</xsl:text>
- </xsl:attribute>
- <xsl:attribute name="href">
- <!-- <xsl:call-template name="href.target.uri" /> -->
- <xsl:text>#</xsl:text>
- <xsl:call-template name="inline.charseq">
- <xsl:with-param name="content">
- <xsl:copy-of select="term[position()=1]" />
- </xsl:with-param>
- </xsl:call-template>
- </xsl:attribute>
- <xsl:text>¶</xsl:text>
- </a>
- </dt>
+ </xsl:with-param>
+ </xsl:call-template>
<dd>
<xsl:apply-templates select="listitem"/>
</dd>
@@ -225,12 +277,6 @@
<xsl:text>systemd.directives.html</xsl:text>
</xsl:attribute>
<xsl:text>Directives </xsl:text>
- </a>·
- <a>
- <xsl:attribute name="href">
- <xsl:text>../python-systemd/index.html</xsl:text>
- </xsl:attribute>
- <xsl:text>Python </xsl:text>
</a>
<span style="float:right">
diff --git a/man/journalctl.xml b/man/journalctl.xml
index 08de0ff068..ca933645a9 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -111,9 +111,9 @@
<para>All users are granted access to their private per-user
journals. However, by default, only root and users who are
members of a few special groups are granted access to the system
- journal and the journals of other users. Members of the the
+ journal and the journals of other users. Members of the groups
<literal>systemd-journal</literal>, <literal>adm</literal>, and
- <literal>wheel</literal> groups can read all journal files. Note
+ <literal>wheel</literal> can read all journal files. Note
that the two latter groups traditionally have additional
privileges specified by the distribution. Members of the
<literal>wheel</literal> group can often perform administrative
diff --git a/man/machinectl.xml b/man/machinectl.xml
index cf17349a6c..a5eb3f08e4 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -593,7 +593,7 @@
<filename>/var/lib/machines/</filename>, that is named after
the specified URL and its HTTP etag. A writable snapshot is
then taken from this subvolume, and named after the specified
- local name. This behaviour ensures that creating multiple
+ local name. This behavior ensures that creating multiple
container instances of the same URL is efficient, as multiple
downloads are not necessary. In order to create only the
read-only image, and avoid creating its writable snapshot,
@@ -628,7 +628,7 @@
<para>Image verification is identical for raw and tar images
(see above).</para>
- <para>If the the downloaded image is in
+ <para>If the downloaded image is in
<filename>.qcow2</filename> format it is converted into a raw
image file before it is made available.</para>
@@ -639,7 +639,7 @@
machine name. To omit creation of the local, writable copy
pass <literal>-</literal> as local machine name.</para>
- <para>Similar to the behaviour of <command>pull-tar</command>,
+ <para>Similar to the behavior of <command>pull-tar</command>,
the read-only image is prefixed with
<filename>.raw-</filename>, and thus not shown by
<command>list-images</command>, unless <option>--all</option>
diff --git a/man/networkctl.xml b/man/networkctl.xml
index 884d2005c4..388afbed93 100644
--- a/man/networkctl.xml
+++ b/man/networkctl.xml
@@ -64,7 +64,7 @@
state of the network links as seen by
<command>systemd-networkd</command>. Please refer to
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for an introduction to the the basic concepts, functionality, and
+ for an introduction to the basic concepts, functionality, and
configuration syntax.</para>
</refsect1>
diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml
index eb1ed2592b..41ec458e4b 100644
--- a/man/nss-mymachines.xml
+++ b/man/nss-mymachines.xml
@@ -59,21 +59,26 @@
<para><command>nss-mymachines</command> is a plugin for the GNU
Name Service Switch (NSS) functionality of the GNU C Library
(<command>glibc</command>) providing hostname resolution for
- containers running locally, that are registered with
+ container names of containers running locally, that are registered
+ with
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
- The container names are resolved to IP addresses of the specific
- container, ordered by their scope.</para>
+ The container names are resolved to the IP addresses of the
+ specific container, ordered by their scope.</para>
+
+ <para>The module also resolves user IDs used by containers to user
+ names indicating the container name, and back.</para>
<para>To activate the NSS modules, <literal>mymachines</literal>
- has to be added to the line starting with
- <literal>hosts:</literal> in
+ has to be added to the lines starting with
+ <literal>hosts:</literal>, <literal>passwd:</literal> and
+ <literal>group:</literal> in
<filename>/etc/nsswitch.conf</filename>.</para>
<para>It is recommended to place <literal>mymachines</literal>
- near the end of the <filename>nsswitch.conf</filename> line to
- make sure that this mapping is only used as fallback, and any DNS
- or <filename>/etc/hosts</filename> based mapping takes
- precedence.</para>
+ near the end of the <filename>nsswitch.conf</filename> lines to
+ make sure that its mappings are only used as fallback, and any
+ other mappings, such as DNS or <filename>/etc/hosts</filename>
+ based mappings take precedence.</para>
</refsect1>
<refsect1>
@@ -82,17 +87,17 @@
<para>Here's an example <filename>/etc/nsswitch.conf</filename>
file, that enables <command>mymachines</command> correctly:</para>
-<programlisting>passwd: compat
-group: compat
-shadow: compat
+ <programlisting>passwd: compat <command>mymachines</command>
+group: compat <command>mymachines</command>
+shadow: compat
-hosts: files dns <command>mymachines</command> myhostname
+hosts: files dns <command>mymachines</command> myhostname
networks: files
protocols: db files
services: db files
-ethers: db files
-rpc: db files
+ethers: db files
+rpc: db files
netgroup: nis</programlisting>
diff --git a/man/sd-bus-errors.xml b/man/sd-bus-errors.xml
new file mode 100644
index 0000000000..a1e8462858
--- /dev/null
+++ b/man/sd-bus-errors.xml
@@ -0,0 +1,309 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2015 Lennart Poettering
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd-bus-errors">
+
+ <refentryinfo>
+ <title>sd-bus-errors</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd-bus-errors</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd-bus-errors</refname>
+ <refname>SD_BUS_ERROR_FAILED</refname>
+ <refname>SD_BUS_ERROR_NO_MEMORY</refname>
+ <refname>SD_BUS_ERROR_SERVICE_UNKNOWN</refname>
+ <refname>SD_BUS_ERROR_NAME_HAS_NO_OWNER</refname>
+ <refname>SD_BUS_ERROR_NO_REPLY</refname>
+ <refname>SD_BUS_ERROR_IO_ERROR</refname>
+ <refname>SD_BUS_ERROR_BAD_ADDRESS</refname>
+ <refname>SD_BUS_ERROR_NOT_SUPPORTED</refname>
+ <refname>SD_BUS_ERROR_LIMITS_EXCEEDED</refname>
+ <refname>SD_BUS_ERROR_ACCESS_DENIED</refname>
+ <refname>SD_BUS_ERROR_AUTH_FAILED</refname>
+ <refname>SD_BUS_ERROR_NO_SERVER</refname>
+ <refname>SD_BUS_ERROR_TIMEOUT</refname>
+ <refname>SD_BUS_ERROR_NO_NETWORK</refname>
+ <refname>SD_BUS_ERROR_ADDRESS_IN_USE</refname>
+ <refname>SD_BUS_ERROR_DISCONNECTED</refname>
+ <refname>SD_BUS_ERROR_INVALID_ARGS</refname>
+ <refname>SD_BUS_ERROR_FILE_NOT_FOUND</refname>
+ <refname>SD_BUS_ERROR_FILE_EXISTS</refname>
+ <refname>SD_BUS_ERROR_UNKNOWN_METHOD</refname>
+ <refname>SD_BUS_ERROR_UNKNOWN_OBJECT</refname>
+ <refname>SD_BUS_ERROR_UNKNOWN_INTERFACE</refname>
+ <refname>SD_BUS_ERROR_UNKNOWN_PROPERTY</refname>
+ <refname>SD_BUS_ERROR_PROPERTY_READ_ONLY</refname>
+ <refname>SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN</refname>
+ <refname>SD_BUS_ERROR_INVALID_SIGNATURE</refname>
+ <refname>SD_BUS_ERROR_INCONSISTENT_MESSAGE</refname>
+ <refname>SD_BUS_ERROR_MATCH_RULE_NOT_FOUND</refname>
+ <refname>SD_BUS_ERROR_MATCH_RULE_INVALID</refname>
+ <refname>SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED</refname>
+
+ <refpurpose>Standard D-Bus error names</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+<funcsynopsisinfo>#define SD_BUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed"
+#define SD_BUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory"
+#define SD_BUS_ERROR_SERVICE_UNKNOWN "org.freedesktop.DBus.Error.ServiceUnknown"
+#define SD_BUS_ERROR_NAME_HAS_NO_OWNER "org.freedesktop.DBus.Error.NameHasNoOwner"
+#define SD_BUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply"
+#define SD_BUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError"
+#define SD_BUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress"
+#define SD_BUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported"
+#define SD_BUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded"
+#define SD_BUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied"
+#define SD_BUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed"
+#define SD_BUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer"
+#define SD_BUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout"
+#define SD_BUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork"
+#define SD_BUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse"
+#define SD_BUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected"
+#define SD_BUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs"
+#define SD_BUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound"
+#define SD_BUS_ERROR_FILE_EXISTS "org.freedesktop.DBus.Error.FileExists"
+#define SD_BUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod"
+#define SD_BUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
+#define SD_BUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
+#define SD_BUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
+#define SD_BUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
+#define SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
+#define SD_BUS_ERROR_INVALID_SIGNATURE "org.freedesktop.DBus.Error.InvalidSignature"
+#define SD_BUS_ERROR_INCONSISTENT_MESSAGE "org.freedesktop.DBus.Error.InconsistentMessage"
+#define SD_BUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound"
+#define SD_BUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid"
+#define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \
+ "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"</funcsynopsisinfo>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>In addition to the error names user programs define, D-Bus
+ knows a number of generic, standardized error names, that are
+ listed below.</para>
+
+ <para>In addition to this list, in sd-bus the special error
+ namespace <literal>System.Error.</literal> is used to map
+ arbitrary Linux system errors (as defined by <citerefentry
+ project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+ to D-Bus errors and back. For example, the error
+ <constant>EUCLEAN</constant> is mapped to
+ <literal>System.Error.EUCLEAN</literal> and back.</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_FAILED</varname></term>
+ <listitem><para>A generic error indication. See the error
+ message for further details. This error name should be
+ avoided, in favor of a more expressive error
+ name.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_NO_MEMORY</varname></term>
+ <listitem><para>A memory allocation failed, and the requested
+ operation could not be completed.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_SERVICE_UNKNOWN</varname></term>
+ <listitem><para>The contacted bus service is unknown and
+ cannot be activated.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_NAME_HAS_NO_OWNER</varname></term>
+ <listitem><para>The specified bus service name currently has
+ no owner.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_NO_REPLY</varname></term>
+ <listitem><para>A message did not receive a reply. This error
+ is usually generated after a timeout.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_IO_ERROR</varname></term>
+ <listitem><para>Generic input/output error, for example when
+ accessing a socket or other IO context.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_BAD_ADDRESS</varname></term>
+ <listitem><para>The specified D-Bus bus address string is
+ malformed.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_NOT_SUPPORTED</varname></term>
+ <listitem><para>The requested operation is not supported on
+ the local system.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_LIMITS_EXCEEDED</varname></term>
+ <listitem><para>Some limited resource has been
+ exhausted.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_ACCESS_DENIED</varname></term>
+ <listitem><para>Access to a resource has been denied, due to security restrictions.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_AUTH_FAILED</varname></term>
+ <listitem><para>Authentication did not complete successfully.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_NO_SERVER</varname></term>
+ <listitem><para>Unable to connect to the specified server.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_TIMEOUT</varname></term>
+ <listitem><para>An operation timed out. Note that method calls
+ which timeout generate a
+ <varname>SD_BUS_ERROR_NO_REPLY</varname>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_NO_NETWORK</varname></term>
+ <listitem><para>No network available to execute requested network operation on.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_ADDRESS_IN_USE</varname></term>
+ <listitem><para>The specified network address is already being listened on.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_DISCONNECTED</varname></term>
+ <listitem><para>The connection has been terminated.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_INVALID_ARGS</varname></term>
+ <listitem><para>One or more invalid arguments have been passed.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_FILE_NOT_FOUND</varname></term>
+ <listitem><para>The requested file could not be found.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_FILE_EXISTS</varname></term>
+ <listitem><para>The requested file exists already.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_UNKNOWN_METHOD</varname></term>
+ <listitem><para>The requested method does not exist in the selected interface.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_UNKNOWN_OBJECT</varname></term>
+ <listitem><para>The requested object does not exist in the selected service.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_UNKNOWN_INTERFACE</varname></term>
+ <listitem><para>The requested interface does not exist on the selected object.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_UNKNOWN_PROPERTY</varname></term>
+ <listitem><para>The requested property does not exist in the selected interface.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_PROPERTY_READ_ONLY</varname></term>
+ <listitem><para>A write operation was requested on a read-only property.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN</varname></term>
+ <listitem><para>The requested PID is not known.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_INVALID_SIGNATURE</varname></term>
+ <listitem><para>The specified message signature is not
+ valid.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_INCONSISTENT_MESSAGE</varname></term>
+ <listitem><para>The passed message does not validate
+ correctly.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_MATCH_RULE_NOT_FOUND</varname></term>
+ <listitem><para>The specified match rule does not exist.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_MATCH_RULE_INVALID</varname></term>
+ <listitem><para>The specified match rule is invalid.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED</varname></term>
+ <listitem><para>Access to the requested operation is not
+ permitted, however, it might be available after interactive
+ authentication. This is usually returned by method calls
+ supporting a framework for additional interactive
+ authorization, when interactive authorization was not enabled
+ with the
+ <citerefentry><refentrytitle>sd_bus_message_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for the method call message.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para>The various error definitions described here are available
+ as a shared library, which can be compiled and linked to with the
+ <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='die-net'><refentrytitle>strerror</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml
index 13f885cd5d..4162fab065 100644
--- a/man/sd_bus_creds_get_pid.xml
+++ b/man/sd_bus_creds_get_pid.xml
@@ -61,8 +61,9 @@
<refname>sd_bus_creds_get_cmdline</refname>
<refname>sd_bus_creds_get_cgroup</refname>
<refname>sd_bus_creds_get_unit</refname>
- <refname>sd_bus_creds_get_user_unit</refname>
<refname>sd_bus_creds_get_slice</refname>
+ <refname>sd_bus_creds_get_user_unit</refname>
+ <refname>sd_bus_creds_get_user_slice</refname>
<refname>sd_bus_creds_get_session</refname>
<refname>sd_bus_creds_get_owner_uid</refname>
<refname>sd_bus_creds_has_effective_cap</refname>
@@ -193,13 +194,19 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_bus_creds_get_slice</function></funcdef>
+ <paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
+ <paramdef>const char **<parameter>slice</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_bus_creds_get_user_unit</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
<paramdef>const char **<parameter>unit</parameter></paramdef>
</funcprototype>
<funcprototype>
- <funcdef>int <function>sd_bus_creds_get_slice</function></funcdef>
+ <funcdef>int <function>sd_bus_creds_get_user_slice</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
<paramdef>const char **<parameter>slice</parameter></paramdef>
</funcprototype>
@@ -288,9 +295,9 @@
<refsect1>
<title>Description</title>
- <para>These functions return information from an
- <parameter>sd_bus_creds</parameter> credential object. Credential
- objects may be created with
+ <para>These functions return credential information from an
+ <parameter>sd_bus_creds</parameter> object. Credential objects may
+ be created with
<citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
in which case they describe the credentials of the process
identified by the specified PID, with
@@ -301,7 +308,13 @@
in which case they describe the credentials of the creator of a
bus, or with
<citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- in which case they describe the credentials of the sender of the message.</para>
+ in which case they describe the credentials of the sender of the
+ message.</para>
+
+ <para>Not all credential fields are part of every
+ <literal>sd_bus_creds</literal> object. Use
+ <citerefentry><refentrytitle>sd_bus_creds_get_mask</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ to determine the mask of fields available.</para>
<para><function>sd_bus_creds_get_pid()</function> will retrieve
the PID (process identifier). Similar,
@@ -374,19 +387,22 @@
<para><function>sd_bus_creds_get_slice()</function> will retrieve
the systemd slice (a unit in the system instance of systemd) that
the process is part of. See
- <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Similar,
+ <function>sd_bus_creds_get_user_slice()</function> retrieves the
+ systemd slice of the process, in the user instance of systemd.
</para>
<para><function>sd_bus_creds_get_session()</function> will
- retrieve the logind session that the process is part of. See
+ retrieve the identifier of the login session that the process is
+ part of. See
<citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>. For
processes that are not part of a session returns -ENXIO.
</para>
<para><function>sd_bus_creds_get_owner_uid()</function> will
retrieve the numeric UID (user identifier) of the user who owns
- the session that the process is part of. See
- <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ the login session that the process is part of. See
+ <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
For processes that are not part of a session returns -ENXIO.
</para>
@@ -395,7 +411,7 @@
<parameter>capability</parameter> was set in the effective
capabilities mask. A positive return value means that is was
set, zero means that it was not set, and a negative return
- value signifies an error. See
+ value indicates an error. See
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
and <varname>Capabilities=</varname> and
<varname>CapabilityBoundingSet=</varname> settings in
@@ -427,8 +443,8 @@
processes that are not part of an audit session.</para>
<para><function>sd_bus_creds_get_tty()</function> will retrieve
- the controlling TTY. Returns -ENXIO for processes that have no
- controlling TTY.</para>
+ the controlling TTY, without the prefixing "/dev/". Returns -ENXIO
+ for processes that have no controlling TTY.</para>
<para><function>sd_bus_creds_get_unique_name()</function> will
retrieve the D-Bus unique name. See <ulink
@@ -489,8 +505,9 @@
<listitem><para>Given field is not specified for the described
process or peer. This will be returned by
<function>sd_bus_get_unit()</function>,
- <function>sd_bus_get_user_unit()</function>,
<function>sd_bus_get_slice()</function>,
+ <function>sd_bus_get_user_unit()</function>,
+ <function>sd_bus_get_user_slice()</function>,
<function>sd_bus_get_session()</function>, and
<function>sd_bus_get_owner_uid()</function> if the process is
not part of a systemd system unit, systemd user unit, systemd
@@ -526,10 +543,11 @@
<refsect1>
<title>Notes</title>
- <para><function>sd_bus_open_user()</function> and other functions
- described here are available as a shared library, which can be
- compiled and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <para><function>sd_bus_creds_get_pid()</function> and the other
+ functions described here are available as a shared library, which
+ can be compiled and linked to with the
+ <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
@@ -539,8 +557,9 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>fork</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>fork</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>credentials</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
diff --git a/man/sd_bus_creds_new_from_pid.xml b/man/sd_bus_creds_new_from_pid.xml
index 8c054a5905..a78d3f5717 100644
--- a/man/sd_bus_creds_new_from_pid.xml
+++ b/man/sd_bus_creds_new_from_pid.xml
@@ -45,6 +45,7 @@
<refnamediv>
<refname>sd_bus_creds_new_from_pid</refname>
<refname>sd_bus_creds_get_mask</refname>
+ <refname>sd_bus_creds_get_augmented_mask</refname>
<refname>sd_bus_creds_ref</refname>
<refname>sd_bus_creds_unref</refname>
@@ -68,6 +69,11 @@
</funcprototype>
<funcprototype>
+ <funcdef>uint64_t <function>sd_bus_creds_get_augmented_mask</function></funcdef>
+ <paramdef>const sd_bus_creds *<parameter>c</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>sd_bus_creds *<function>sd_bus_creds_ref</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
</funcprototype>
@@ -80,17 +86,26 @@
<para>
<constant>SD_BUS_CREDS_PID</constant>,
+ <constant>SD_BUS_CREDS_PPID</constant>,
<constant>SD_BUS_CREDS_TID</constant>,
<constant>SD_BUS_CREDS_UID</constant>,
+ <constant>SD_BUS_CREDS_EUID</constant>,
+ <constant>SD_BUS_CREDS_SUID</constant>,
+ <constant>SD_BUS_CREDS_FSUID</constant>,
<constant>SD_BUS_CREDS_GID</constant>,
+ <constant>SD_BUS_CREDS_EGID</constant>,
+ <constant>SD_BUS_CREDS_SGID</constant>,
+ <constant>SD_BUS_CREDS_FSGID</constant>,
+ <constant>SD_BUS_CREDS_SUPPLEMENTARY_GIDS</constant>,
<constant>SD_BUS_CREDS_COMM</constant>,
<constant>SD_BUS_CREDS_TID_COMM</constant>,
<constant>SD_BUS_CREDS_EXE</constant>,
<constant>SD_BUS_CREDS_CMDLINE</constant>,
<constant>SD_BUS_CREDS_CGROUP</constant>,
<constant>SD_BUS_CREDS_UNIT</constant>,
- <constant>SD_BUS_CREDS_USER_UNIT</constant>,
<constant>SD_BUS_CREDS_SLICE</constant>,
+ <constant>SD_BUS_CREDS_USER_UNIT</constant>,
+ <constant>SD_BUS_CREDS_USER_SLICE</constant>,
<constant>SD_BUS_CREDS_SESSION</constant>,
<constant>SD_BUS_CREDS_OWNER_UID</constant>,
<constant>SD_BUS_CREDS_EFFECTIVE_CAPS</constant>,
@@ -100,8 +115,11 @@
<constant>SD_BUS_CREDS_SELINUX_CONTEXT</constant>,
<constant>SD_BUS_CREDS_AUDIT_SESSION_ID</constant>,
<constant>SD_BUS_CREDS_AUDIT_LOGIN_UID</constant>,
+ <constant>SD_BUS_CREDS_TTY</constant>,
<constant>SD_BUS_CREDS_UNIQUE_NAME</constant>,
<constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant>,
+ <constant>SD_BUS_CREDS_DESCRIPTION</constant>,
+ <constant>SD_BUS_CREDS_AUGMENT</constant>,
<constant>_SD_BUS_CREDS_ALL</constant>
</para>
</refsynopsisdiv>
@@ -109,25 +127,39 @@
<refsect1>
<title>Description</title>
- <para><function>sd_bus_creds_new_from_pid()</function> creates a new
- credentials object and fills it with information about the process
- <parameter>pid</parameter>. This pointer to this object will
- be stored in <parameter>ret</parameter> pointer.</para>
+ <para><function>sd_bus_creds_new_from_pid()</function> creates a
+ new credentials object and fills it with information about the
+ process <parameter>pid</parameter>. The pointer to this object
+ will be stored in <parameter>ret</parameter> pointer. Note that
+ credential objects may also be created and retrieved via
+ <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>The information that will be stored is determined by
<parameter>creds_mask</parameter>. It may contain a subset of ORed
constants <constant>SD_BUS_CREDS_PID</constant>,
+ <constant>SD_BUS_CREDS_PPID</constant>,
<constant>SD_BUS_CREDS_TID</constant>,
<constant>SD_BUS_CREDS_UID</constant>,
+ <constant>SD_BUS_CREDS_EUID</constant>,
+ <constant>SD_BUS_CREDS_SUID</constant>,
+ <constant>SD_BUS_CREDS_FSUID</constant>,
<constant>SD_BUS_CREDS_GID</constant>,
+ <constant>SD_BUS_CREDS_EGID</constant>,
+ <constant>SD_BUS_CREDS_SGID</constant>,
+ <constant>SD_BUS_CREDS_FSGID</constant>,
+ <constant>SD_BUS_CREDS_SUPPLEMENTARY_GIDS</constant>,
<constant>SD_BUS_CREDS_COMM</constant>,
<constant>SD_BUS_CREDS_TID_COMM</constant>,
<constant>SD_BUS_CREDS_EXE</constant>,
<constant>SD_BUS_CREDS_CMDLINE</constant>,
<constant>SD_BUS_CREDS_CGROUP</constant>,
<constant>SD_BUS_CREDS_UNIT</constant>,
- <constant>SD_BUS_CREDS_USER_UNIT</constant>,
<constant>SD_BUS_CREDS_SLICE</constant>,
+ <constant>SD_BUS_CREDS_USER_UNIT</constant>,
+ <constant>SD_BUS_CREDS_USER_SLICE</constant>,
<constant>SD_BUS_CREDS_SESSION</constant>,
<constant>SD_BUS_CREDS_OWNER_UID</constant>,
<constant>SD_BUS_CREDS_EFFECTIVE_CAPS</constant>,
@@ -137,34 +169,71 @@
<constant>SD_BUS_CREDS_SELINUX_CONTEXT</constant>,
<constant>SD_BUS_CREDS_AUDIT_SESSION_ID</constant>,
<constant>SD_BUS_CREDS_AUDIT_LOGIN_UID</constant>,
+ <constant>SD_BUS_CREDS_TTY</constant>,
<constant>SD_BUS_CREDS_UNIQUE_NAME</constant>,
<constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant>,
- or <constant>_SD_BUS_CREDS_ALL</constant> to indicate
- all known fields.</para>
+ <constant>SD_BUS_CREDS_DESCRIPTION</constant>. Use the special
+ value <constant>_SD_BUS_CREDS_ALL</constant> to request all
+ supported fields. The <constant>SD_BUS_CREDS_AUGMENT</constant>
+ may not be ORed into the mask for invocations of
+ <function>sd_bus_creds_new_from_pid()</function>.</para>
<para>Fields can be retrieved from the credentials object using
<citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and other functions which correspond directly to the constants
listed above.</para>
- <para>A mask of fields which were actually successfully set
- (acquired from <filename>/proc</filename>, etc.) can be retrieved
- with <function>sd_bus_creds_get_mask()</function>. If the
- credentials object was created with
+ <para>A mask of fields which were actually successfully retrieved
+ can be retrieved with
+ <function>sd_bus_creds_get_mask()</function>. If the credentials
+ object was created with
<function>sd_bus_creds_new_from_pid()</function>, this will be a
subset of fields requested in <parameter>creds_mask</parameter>.
</para>
- <para><function>sd_bus_creds_ref</function> creates a new
+ <para>Similar to <function>sd_bus_creds_get_mask()</function> the
+ function <function>sd_bus_creds_get_augmented_mask()</function>
+ returns a bitmask of field constants. The mask indicates which
+ credential fields have been retrieved in a non-atomic fashion. For
+ credential objects created via
+ <function>sd_bus_creds_new_from_pid()</function> this mask will be
+ identical to the mask returned by
+ <function>sd_bus_creds_get_mask()</function>. However, for
+ credential objects retrieved via
+ <function>sd_bus_get_name_creds()</function> this mask will be set
+ for the credential fields that could not be determined atomically
+ at peer connection time, and which were later added by reading
+ augmenting credential data from
+ <filename>/proc</filename>. Similar, for credential objects
+ retrieved via <function>sd_bus_get_owner_creds()</function> the
+ mask is set for the fields that could not be determined atomically
+ at bus creation time, but have been augmented. Similar, for
+ credential objects retrieved via
+ <function>sd_bus_message_get_creds()</function> the mask is set
+ for the fields that could not be determined atomically at message
+ send time, but have been augmented. The mask returned by
+ <function>sd_bus_creds_get_augmented_mask()</function> is always a
+ subset of (or identical to) the mask returned by
+ <function>sd_bus_creds_get_mask()</function> for the same
+ object. The latter call hence returns all credential fields
+ available in the credential object, the former then marks the
+ subset of those that have been augmented. Note that augmented
+ fields are unsuitable for authorization decisions as they may be
+ retrieved at different times, thus being subject to races. Hence
+ augmented fields should be used exclusively for informational
+ purposes.
+ </para>
+
+ <para><function>sd_bus_creds_ref()</function> creates a new
reference to the credentials object <parameter>c</parameter>. This
object will not be destroyed until
- <function>sd_bus_creds_unref</function> has been called as many
+ <function>sd_bus_creds_unref()</function> has been called as many
times plus once more. Once the reference count has dropped to zero,
<parameter>c</parameter> cannot be used anymore, so further
calls to <function>sd_bus_creds_ref(c)</function> or
<function>sd_bus_creds_unref(c)</function> are illegal.</para>
- <para><function>sd_bus_creds_unref</function> destroys a reference
+ <para><function>sd_bus_creds_unref()</function> destroys a reference
to <parameter>c</parameter>.</para>
</refsect1>
@@ -178,10 +247,15 @@
<para><function>sd_bus_creds_get_mask()</function> returns the
mask of successfully acquired fields.</para>
- <para><function>sd_bus_creds_ref</function> always returns the
+ <para><function>sd_bus_creds_get_augmented_mask()</function>
+ returns the mask of fields that have been augmented from data in
+ <filename>/proc</filename>, and are thus not suitable for
+ authorization decisions.</para>
+
+ <para><function>sd_bus_creds_ref()</function> always returns the
argument.</para>
- <para><function>sd_bus_creds_unref</function> always returns
+ <para><function>sd_bus_creds_unref()</function> always returns
<constant>NULL</constant>.</para>
</refsect1>
@@ -222,16 +296,23 @@
<listitem><para>Memory allocation failed.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><constant>-EOPNOTSUPP</constant></term>
+
+ <listitem><para>One of the requested fields is unknown to the local system.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Notes</title>
- <para><function>sd_bus_creds_new_from_pid()</function> is
- available as a shared library, which can be compiled and linked to
- with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <para><function>sd_bus_creds_new_from_pid()</function> and the
+ other calls described here are available as a shared library,
+ which can be compiled and linked to with the
+ <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
</refsect1>
@@ -241,31 +322,10 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_tid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_gid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_comm</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_tid_comm</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_exe</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_cmdline</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_cgroup</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_unit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_user_unit</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_slice</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_session</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_owner_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_has_effective_cap</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_has_permitted_cap</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_has_inheritable_cap</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_has_bounding_cap</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_selinux_context</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_audit_session_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_audit_login_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_unique_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_creds_get_well_known_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_default.xml b/man/sd_bus_default.xml
index c5a1b530f9..1cf2cb8f9a 100644
--- a/man/sd_bus_default.xml
+++ b/man/sd_bus_default.xml
@@ -111,9 +111,9 @@
<para><function>sd_bus_default()</function> acquires a bus
connection object to the user bus when invoked in user context, or
to the system bus otherwise. The connection object is associated
- to the calling thread. Each time the function is invoked from the
- same thread the same object is returned, but its reference count
- is increased by one, as long as at least one reference is
+ with the calling thread. Each time the function is invoked from
+ the same thread the same object is returned, but its reference
+ count is increased by one, as long as at least one reference is
kept. When the last reference to the connection is dropped (using
the
<citerefentry><refentrytitle>sd_bus_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -121,10 +121,11 @@
not automatically terminated when the associated thread ends. It
is important to drop the last reference to the bus connection
explicitly before the thread ends or otherwise the connection will
- be leaked.</para>
+ be leaked. Also, queued but unread or unwritten messages keep the
+ bus referenced, see below.</para>
<para><function>sd_bus_default_user()</function> returns a user
- bus connection object associated to the calling thread.
+ bus connection object associated with the calling thread.
<function>sd_bus_default_system()</function> is similar, but
connects to the system bus. Note that
<function>sd_bus_default()</function> is identical to these two
@@ -182,7 +183,7 @@
processes at this time.</para>
<para>These calls allocate a bus connection object and initiate
- the connection ot a well-known bus of some form. An alternative to
+ the connection to a well-known bus of some form. An alternative to
using these high-level calls is to create an unconnected bus
object with
<citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
@@ -193,32 +194,63 @@
</refsect1>
<refsect1>
- <title>Return Value</title>
-
- <para>On success, these calls return 0 or a positive
- integer. On failure, these calls return a negative
- errno-style error code.</para>
- </refsect1>
-
- <refsect1>
<title>Reference ownership</title>
<para>The functions <function>sd_bus_open()</function>,
<function>sd_bus_open_user()</function>,
<function>sd_bus_open_system()</function>,
<function>sd_bus_open_system_remote()</function>, and
<function>sd_bus_open_system_machine()</function> return a new
- object and the caller owns the sole reference. When not needed
- anymore, this reference should be destroyed with
+ connection object and the caller owns the sole reference. When not
+ needed anymore, this reference should be destroyed with
<citerefentry><refentrytitle>sd_bus_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
<para>The functions <function>sd_bus_default()</function>,
<function>sd_bus_default_user()</function> and
<function>sd_bus_default_system()</function> do not necessarily
- create a new object, but increase the connection reference by
- one. Use
+ create a new object, but increase the connection reference of an
+ existing connection object by one. Use
<citerefentry><refentrytitle>sd_bus_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
to drop the reference.</para>
+
+ <para>Queued but unwritten/unread messages also keep a reference
+ to their bus connection object. For this reason, even if an
+ application dropped all references to a bus connection it might
+ not get destroyed right-away. Until all incoming queued
+ messages are read, and until all outgoing unwritten messages are
+ written, the bus object will stay
+ alive. <function>sd_bus_flush()</function> may be used to write
+ all outgoing queued messages so they drop their references. To
+ flush the unread incoming messages use
+ <function>sd_bus_close()</function>, which will also close the bus
+ connection. When using the default bus logic it is a good idea to
+ first invoke <function>sd_bus_flush()</function> followed by
+ <function>sd_bus_close()</function> when a thread or process
+ terminates, and thus its bus connection object should be
+ freed.</para>
+
+ <para>The life-cycle of the default bus connection should be the
+ responsibility of the code that creates/owns the thread the
+ default bus connection object is associated with. Library code
+ should neither call <function>sd_bus_flush()</function> nor
+ <function>sd_bus_close()</function> on default bus objects unless
+ it does so in its own private, self-allocated thread. Library code
+ should not use the default bus object in other threads unless it
+ is clear that the program using it will life-cycle the bus
+ connection object and flush and close it before exiting from the
+ thread. In libraries where it is not clear that the calling
+ program will life-cycle the bus connection object it is hence
+ recommended to use <function>sd_bus_open_system()</function>
+ instead of <function>sd_bus_default_system()</function> and
+ related calls.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, these calls return 0 or a positive
+ integer. On failure, these calls return a negative
+ errno-style error code.</para>
</refsect1>
<refsect1>
diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml
index b8cb339cec..6dc4541eb1 100644
--- a/man/sd_bus_error.xml
+++ b/man/sd_bus_error.xml
@@ -44,11 +44,15 @@
<refnamediv>
<refname>sd_bus_error</refname>
+ <refname>SD_BUS_ERROR_MAKE_CONST</refname>
+ <refname>SD_BUS_ERROR_NULL</refname>
<refname>sd_bus_error_free</refname>
<refname>sd_bus_error_set</refname>
+ <refname>sd_bus_error_setf</refname>
<refname>sd_bus_error_set_const</refname>
<refname>sd_bus_error_set_errno</refname>
<refname>sd_bus_error_set_errnof</refname>
+ <refname>sd_bus_error_set_errnofv</refname>
<refname>sd_bus_error_get_errno</refname>
<refname>sd_bus_error_copy</refname>
<refname>sd_bus_error_is_set</refname>
@@ -75,7 +79,7 @@
</para>
<funcprototype>
- <funcdef>int <function>sd_bus_error_free</function></funcdef>
+ <funcdef>void <function>sd_bus_error_free</function></funcdef>
<paramdef>sd_bus_error *<parameter>e</parameter></paramdef>
</funcprototype>
@@ -116,6 +120,14 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_bus_error_set_errnofv</function></funcdef>
+ <paramdef>sd_bus_error *<parameter>e</parameter></paramdef>
+ <paramdef>int <parameter>error</parameter></paramdef>
+ <paramdef>const char *<parameter>format</parameter></paramdef>
+ <paramdef>va_list ap</paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_bus_error_get_errno</function></funcdef>
<paramdef>const sd_bus_error *<parameter>e</parameter></paramdef>
</funcprototype>
@@ -138,234 +150,194 @@
</funcprototype>
</funcsynopsis>
- <para>
- <constant>SD_BUS_ERROR_FAILED</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_NO_MEMORY</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_SERVICE_UNKNOWN</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_NAME_HAS_NO_OWNER</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_NO_REPLY</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_IO_ERROR</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_BAD_ADDRESS</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_NOT_SUPPORTED</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_LIMITS_EXCEEDED</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_ACCESS_DENIED</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_AUTH_FAILED</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_NO_SERVER</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_TIMEOUT</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_NO_NETWORK</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_ADDRESS_IN_USE</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_DISCONNECTED</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_INVALID_ARGS</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_FILE_NOT_FOUND</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_FILE_EXISTS</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_UNKNOWN_METHOD</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_UNKNOWN_OBJECT</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_UNKNOWN_INTERFACE</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_UNKNOWN_PROPERTY</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_PROPERTY_READ_ONLY</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_INVALID_SIGNATURE</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_INCONSISTENT_MESSAGE</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_MATCH_RULE_NOT_FOUND</constant>
- </para>
- <para>
- <constant>SD_BUS_ERROR_MATCH_RULE_INVALID</constant>
- </para>
-
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>The <structname>sd_bus_error</structname> structure carries
- information for a <filename>sd-bus</filename> error. The
- functions described below can be used to set and query fields in
- this structure. The <structfield>name</structfield> field contains a
- short identifier of an error. It should follow the rules for error
- names described in the D-Bus specification, subsection <ulink
+ information about a D-Bus error condition. The functions described
+ below may be used to set and query fields in this structure. The
+ <structfield>name</structfield> field contains a short identifier
+ of an error. It should follow the rules for error names described
+ in the D-Bus specification, subsection <ulink
url="http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names">Valid
- Names</ulink>. The <structfield>message</structfield> is a human
- readable string describing the details. When no longer necessary,
- resources held by this structure should be destroyed with
- <function>sd_bus_error_free</function>.</para>
-
- <para><function>sd_bus_error_set</function> will return an
- errno-like negative value returned based on parameter
- <parameter>name</parameter> (see
- <citerefentry project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
- Various well-known D-Bus errors are converted to specific values,
- and the remaining ones to <constant>-ENXIO</constant>. Well-known
- D-Bus error names are available as constants
- <constant>SD_BUS_ERROR_FAILED</constant>, etc., listed above. If
+ Names</ulink>. A number of common, standardized error names are
+ described in
+ <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ but additional domain-specific errors may be defined by
+ applications. The <structfield>message</structfield> field usually
+ contains a human readable string describing the details, but might
+ be NULL. An unset <structname>sd_bus_error</structname> structure
+ should have both fields initialized to NULL. Set an error
+ structure to <constant>SD_BUS_ERROR_NULL</constant> in order to
+ reset both fields to NULL. When no longer necessary, resources
+ held by the <structname>sd_bus_error</structname>structure should
+ be destroyed with <function>sd_bus_error_free()</function>.</para>
+
+ <para><function>sd_bus_error_set()</function> sets an error
+ structure to the specified name and message strings. The strings
+ will be copied into internal, newly allocated memory. It is
+ essential to free the error structure again when it is not
+ required anymore (see above). The function will return an
+ <varname>errno</varname>-like negative value (see <citerefentry
+ project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>)
+ determined from the specified error name. Various well-known
+ D-Bus errors are converted to well-known <varname>errno</varname>
+ counterparts, and the other ones to <constant>-EIO</constant>. See
+ <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for a list of well-known error names. Additional error mappings
+ may be defined with
+ <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
+ <parameter>e</parameter> is NULL no error structure is initialized
+ but the error is still converted into an
+ <varname>errno</varname>-style error. If
<parameter>name</parameter> is <constant>NULL</constant>, it is
assumed that no error occurred, and 0 is returned. This means that
this function may be conveniently used in a
- <function>return</function> statement.</para>
-
- <para>If <parameter>e</parameter> is not
- <constant>NULL</constant>, <structfield>name</structfield> and
- <structfield>message</structfield> in the
- <structname>sd_bus_error</structname> structure
- <parameter>e</parameter> points at will be filled in. As described above,
- <parameter>name</parameter> may be <constant>NULL</constant>,
- which is treated as no error. Parameter
- <parameter>message</parameter> may also be
- <constant>NULL</constant>, in which case no message is specified.
- <function>sd_bus_error_set</function> will make internal copies of
- specified strings.</para>
-
- <para><function>sd_bus_error_setf</function> is similar to
- <function>sd_bus_error_set</function>, but takes a
- <citerefentry project='man-pages'><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- format string and corresponding arguments to generate
- <structname>message</structname>.</para>
-
- <para><function>sd_bus_error_set_const</function> is similar to
- <function>sd_bus_error_set</function>, but string parameters are
- not copied internally, and must remain valid for the lifetime of
- <parameter>e</parameter>.</para>
-
- <para><function>sd_bus_error_set_errno</function> will set
- <structfield>name</structfield> based on an errno-like value.
- <citerefentry project='die-net'><refentrytitle>strerror</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <function>return</function> statement. If
+ <parameter>message</parameter> is NULL no message is set. This
+ call can fail if no memory may be allocated for the name and
+ message strings, in which case an
+ <constant>SD_BUS_ERROR_NO_MEMORY</constant> error might be set
+ instead and -ENOMEM returned. Do not use this call on error
+ structures that are already initialized. If you intend to reuse an
+ error structure free the old data stored in it with
+ <function>sd_bus_error_free()</function> first.</para>
+
+ <para><function>sd_bus_error_setf()</function> is similar to
+ <function>sd_bus_error_set()</function>, but takes a <citerefentry
+ project='man-pages'><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ format string and corresponding arguments to generate the
+ <structfield>message</structfield> field.</para>
+
+ <para><function>sd_bus_error_set_const()</function> is similar to
+ <function>sd_bus_error_set()</function>, but the string parameters
+ are not copied internally, and must hence remain constant and
+ valid for the lifetime of <parameter>e</parameter>. Use this call
+ to avoid memory allocations when setting error structures. Since
+ this call does not allocate memory it will not fail with an
+ out-of-memory condition, as
+ <function>sd_bus_error_set()</function> can, as described
+ above. Alternatively, the
+ <constant>SD_BUS_ERROR_MAKE_CONST()</constant> macro may be used
+ to generate a literal, constant bus error structure
+ on-the-fly.</para>
+
+ <para><function>sd_bus_error_set_errno()</function> will set
+ <structfield>name</structfield> from an
+ <varname>errno</varname>-like value that is converted to a D-Bus
+ error. <citerefentry
+ project='die-net'><refentrytitle>strerror_r</refentrytitle><manvolnum>3</manvolnum></citerefentry>
will be used to set <structfield>message</structfield>. Well-known
D-Bus error names will be used for <structfield>name</structfield>
- if available, otherwise a name in the
- <literal>System.Error</literal> namespace will be generated.
- </para>
-
- <para><function>sd_bus_error_set_errnof</function> is similar to
- <function>sd_bus_error_set_errno</function>, but in addition to
- <parameter>name</parameter>, takes a
- <citerefentry project='man-pages'><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- format and corresponding arguments.
- <structfield>name</structfield> will be generated from
+ if applicable, otherwise a name in the
+ <literal>System.Error.</literal> namespace will be generated. The
+ sign of the specified error number is ignored. The absolute value
+ is used implicitly. The call always returns a negative value, for
+ convenient usage in <function>return</function> statements. This
+ call might fail due to lack of memory, in which case an
+ <constant>SD_BUS_ERROR_NO_MEMORY</constant> error is set instead,
+ and -ENOMEM returned.</para>
+
+ <para><function>sd_bus_error_set_errnof()</function> is similar to
+ <function>sd_bus_error_set_errno()</function>, but in addition to
+ <parameter>error</parameter>, takes a <citerefentry
+ project='man-pages'><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ format string and corresponding arguments. The
+ <structfield>message</structfield> field will be generated from
<parameter>format</parameter> and the arguments.</para>
- <para><function>sd_bus_error_get_errno</function> will convert
- <structname>e-&gt;name</structname> to an errno-like value using the
- same rules as <function>sd_bus_error_set</function>. If
+ <para><function>sd_bus_error_set_errnofv()</function> is similar to
+ <function>sd_bus_error_set_errnof()</function> but takes the
+ format string parameters as <citerefentry
+ project='man-pages'><refentrytitle>va_arg</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ parameter list.</para>
+
+ <para><function>sd_bus_error_get_errno()</function> converts the
+ <structfield>name</structfield> field of an error structure to an
+ <varname>errno</varname>-like (positive) value using the same
+ rules as <function>sd_bus_error_set()</function>. If
<parameter>e</parameter> is <constant>NULL</constant>, 0 will be
returned.</para>
- <para><function>sd_bus_error_copy</function> will initialize
+ <para><function>sd_bus_error_copy()</function> will initialize
<parameter>dst</parameter> using the values in
<parameter>e</parameter>. If the strings in
<parameter>e</parameter> were set using
- <function>sd_bus_set_error_const</function>, they will be shared.
- Otherwise, they will be copied.</para>
+ <function>sd_bus_set_error_const()</function>, they will be shared.
+ Otherwise, they will be copied. Returns a converted
+ <varname>errno</varname>-like, negative error code.</para>
- <para><function>sd_bus_error_is_set</function> will return
- <constant>true</constant> if <parameter>e</parameter> is
+ <para><function>sd_bus_error_is_set()</function> will return a
+ non-zero value if <parameter>e</parameter> is
non-<constant>NULL</constant> and an error has been set,
<constant>false</constant> otherwise.</para>
- <para><function>sd_bus_error_has_name</function> will return true
- if <parameter>e</parameter> is non-<constant>NULL</constant> and
- an error with the same <parameter>name</parameter> has been set,
+ <para><function>sd_bus_error_has_name()</function> will return a
+ non-zero value if <parameter>e</parameter> is
+ non-<constant>NULL</constant> and an error with the same
+ <parameter>name</parameter> has been set,
<constant>false</constant> otherwise.</para>
- <para><function>sd_bus_error_free</function> will destroy resources
- held by <parameter>e</parameter>. The parameter itself will not
- be deallocated, and must be
- <citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>d
- by the caller if necessary.</para>
+ <para><function>sd_bus_error_free()</function> will destroy
+ resources held by <parameter>e</parameter>. The parameter itself
+ will not be deallocated, and must be <citerefentry
+ project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>d
+ by the caller if necessary. The function may also be called safely
+ on unset errors (error structures with both fields set to NULL),
+ in which case it performs no operation. This call will reset the
+ error structure after freeing the data, so that all fields are set
+ to NULL. The structure may be reused afterwards.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
- <para>Functions <function>sd_bus_error_set</function>,
- <function>sd_bus_error_setf</function>,
- <function>sd_bus_error_set_const</function>, when successful,
+ <para>The functions <function>sd_bus_error_set()</function>,
+ <function>sd_bus_error_setf()</function>,
+ <function>sd_bus_error_set_const()</function>, when successful,
return the negative errno value corresponding to the
<parameter>name</parameter> parameter. Functions
- <function>sd_bus_error_set_errno</function> and
- <function>sd_bus_error_set_errnof</function>, when successful,
- return the value of the <parameter>errno</parameter> parameter. If
- an error occurs, one of the negative error values listed below
- will be returned.</para>
-
- <para><function>sd_bus_error_get_errno</function> returns
+ <function>sd_bus_error_set_errno()</function>,
+ <function>sd_bus_error_set_errnof()</function> and
+ <function>sd_bus_error_set_errnofv()</function>, when successful,
+ return the negative value of the <parameter>error</parameter>
+ parameter. If an error occurs, one of the negative error values
+ listed below will be returned.</para>
+
+ <para><function>sd_bus_error_get_errno()</function> returns
<constant>false</constant> when <parameter>e</parameter> is
<constant>NULL</constant>, and a positive errno value mapped from
<parameter>e-&gt;name</parameter> otherwise.</para>
- <para><function>sd_bus_error_copy</function> returns 0 or a
- positive integer on success, and one of the negative error values
- listed below otherwise.</para>
+ <para><function>sd_bus_error_copy()</function> returns 0 or a
+ positive integer on success, and a negative error value converted
+ from the error name otherwise.</para>
- <para><function>sd_bus_error_is_set</function> returns
- <constant>true</constant> when <parameter>e</parameter> and
- <parameter>e-&gt;name</parameter> are non-<constant>NULL</constant>,
- <constant>false</constant> otherwise.</para>
+ <para><function>sd_bus_error_is_set()</function> returns a
+ non-zero value when <parameter>e</parameter> and the
+ <structfield>name</structfield> field are
+ non-<constant>NULL</constant>, zero otherwise.</para>
- <para><function>sd_bus_error_has_name</function> returns
- <constant>true</constant> when <parameter>e</parameter> is
- non-<constant>NULL</constant> and <parameter>e-&gt;name</parameter>
- is equal to <parameter>name</parameter>,
- <constant>false</constant> otherwise.</para>
+ <para><function>sd_bus_error_has_name()</function> returns a
+ non-zero value when <parameter>e</parameter> is
+ non-<constant>NULL</constant> and the
+ <structfield>name</structfield> field is equal to
+ <parameter>name</parameter>, zero otherwise.</para>
</refsect1>
<refsect1>
<title>Reference ownership</title>
<para><structname>sd_bus_error</structname> is not reference
counted. Users should destroy resources held by it by calling
- <function>sd_bus_error_free</function>.</para>
+ <function>sd_bus_error_free()</function>. Usually error structures
+ are allocated on the stack or passed in as function parameters,
+ but they may also be allocated dynamically, in which case it is
+ the duty of the caller to <citerefentry
+ project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ the memory held by the structure itself after freeing its contents
+ with <function>sd_bus_error_free()</function>.</para>
</refsect1>
<refsect1>
@@ -407,8 +379,10 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry project='die-net'><refentrytitle>strerror</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry project='die-net'><refentrytitle>strerror_r</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_error_add_map.xml b/man/sd_bus_error_add_map.xml
new file mode 100644
index 0000000000..3fca63be4a
--- /dev/null
+++ b/man/sd_bus_error_add_map.xml
@@ -0,0 +1,173 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2015 Lennart Poettering
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_bus_error_add_map">
+
+ <refentryinfo>
+ <title>sd_bus_error_add_map</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_error_add_map</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_error_add_map</refname>
+ <refname>sd_bus_error_map</refname>
+ <refname>SD_BUS_ERROR_MAP</refname>
+ <refname>SD_BUS_ERROR_END</refname>
+
+ <refpurpose>Additional sd-dbus error mappings</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcsynopsisinfo>typedef struct {
+ const char *name;
+ int code;
+ ...
+} sd_bus_error_map;</funcsynopsisinfo>
+
+ </funcsynopsis>
+
+ <para>
+ <constant>SD_BUS_ERROR_MAP(<replaceable>name</replaceable>, <replaceable>code</replaceable>)</constant>
+ </para>
+ <para>
+ <constant>SD_BUS_ERROR_MAP_END</constant>
+ </para>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_error_add_map</function></funcdef>
+ <paramdef>const sd_bus_map *<parameter>map</parameter></paramdef>
+ </funcprototype>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>The <function>sd_bus_error_add_map()</function> call may be
+ used to register additional mappings for converting D-Bus errors
+ to Linux <varname>errno</varname>-style errors. The mappings
+ defined with this call are consulted by calls such as
+ <citerefentry><refentrytitle>sd_bus_error_set</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ or
+ <citerefentry><refentrytitle>sd_bus_error_get_errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>. By
+ default a number of generic, standardized mappings are known, as
+ documented in
+ <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Use
+ this call to add further, application-specific mappings.</para>
+
+ <para>The function takes a pointer to an array of
+ <structname>sd_bus_error_map</structname> structures. A reference
+ to the specified array is added to the lookup tables for error
+ mappings. Note that the structure is not copied, it is hence
+ essential that the array stays available and constant during the
+ entire remaining runtime of the process.</para>
+
+ <para>The mapping array should be put together with a series of
+ <constant>SD_BUS_ERROR_MAP()</constant> macro invocations, that
+ take a literal name string and a (positive)
+ <varname>errno</varname>-style error number. The last entry of the
+ array should be an invocation of the
+ <constant>SD_BUS_ERROR_MAP_END</constant> macro. The array should not be
+ put together without use of these two macros.</para>
+
+ <para>Note that the call is idempotent: it is safe to invoke it
+ multiple times with the parameter, which will only add the passed
+ mapping array once.</para>
+
+ <para>Note that the memory allocated by this call is not intended
+ to be freed during the lifetime of the process. It should not be
+ freed explicitly.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para><function>sd_bus_error_add_map()</function> returns a
+ positive value when the new array was added to the lookup
+ tables. It returns zero when the same array was already added
+ before. On error, a negative <varname>errno</varname>-style error
+ code is returned. See below for known error codes.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>The specified mapping array is invalid.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Memory allocation failed.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para>The various error definitions described here are available
+ as a shared library, which can be compiled and linked to with the
+ <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='die-net'><refentrytitle>strerror_r</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd_bus_message_append.xml b/man/sd_bus_message_append.xml
index 7a4bfa4bc4..0ee849dca7 100644
--- a/man/sd_bus_message_append.xml
+++ b/man/sd_bus_message_append.xml
@@ -46,7 +46,8 @@
<refnamediv>
<refname>sd_bus_message_append</refname>
- <refpurpose>Attach parts of message based on a format string</refpurpose>
+ <refpurpose>Attach fields to a D-Bus message based on a type
+ string</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -65,17 +66,20 @@
<refsect1>
<title>Description</title>
- <para>The <function>sd_bus_message_append</function> function appends
- a sequence of items to message <parameter>m</parameter>. The
- format string <parameter>types</parameter> describes the types of
- arguments that follow.</para>
+ <para>The <function>sd_bus_message_append()</function> function
+ appends a sequence of fields to the D-Bus message object
+ <parameter>m</parameter>. The type string
+ <parameter>types</parameter> describes the types of the field
+ arguments that follow. For each type specified in the type string
+ one or more arguments need to be specified, in the same order as
+ declared in the type string.</para>
- <para>The format string is composed of the elements shown in the
+ <para>The type string is composed of the elements shown in the
table below. It contains zero or more single "complete types".
Each complete type may be one of the basic types or a fully
- described container type. A container type may be a structure, a
- variant type code, an array with its element type, or a dictionary
- with its entry type. The format string is
+ described container type. A container type may be a structure with
+ the contained types, a variant, an array with its element type, or
+ a dictionary entry with the contained types. The type string is
<constant>NUL</constant>-terminated.</para>
<para>In case of a basic type, one argument of the corresponding
@@ -88,27 +92,32 @@
rules as if they were not nested.</para>
<para>A variant is denoted by <literal>v</literal>. Corresponding
- arguments must include a format string denoting a complete type,
+ arguments must begin with a type string denoting a complete type,
and following that, arguments corresponding to the specified type.
</para>
<para>An array is denoted by <literal>a</literal> followed by a
- complete type. Corresponding arguments must include the size of
- the array, and then repeated this number of times, arguments
- corresponding to the nested type.</para>
+ complete type. Corresponding arguments must begin with the number of
+ entries in the array, followed by the entries themselves,
+ matching the element type of the array.</para>
<para>A dictionary is an array of dictionary entries, denoted by
<literal>a</literal> followed by a pair of complete types between
<literal>{</literal> and <literal>}</literal>. The first of those
- types must be a basic type. Corresponding arguments must include
- the size of the dictionary, and then repeated this number of
- times, arguments corresponding to each of the two nested
- types.</para>
+ types must be a basic type. Corresponding arguments must begin
+ with the number of dictionary entries, followed by a pair of
+ values for each entry matching the element type of
+ the dictionary entries.</para>
+
+ <para>For further details on the D-Bus type system, please consult
+ the <ulink
+ url="http://dbus.freedesktop.org/doc/dbus-specification.html#type-system">D-Bus
+ Specification</ulink>.</para>
<table>
- <title>Item format specifiers</title>
+ <title>Item type specifiers</title>
- <tgroup cols='4'>
+ <tgroup cols='5'>
<xi:include href="sd_bus_message_append_basic.xml" xpointer="xpointer(//table[@id='format-specifiers'])//colspec" />
<xi:include href="sd_bus_message_append_basic.xml" xpointer="xpointer(//table[@id='format-specifiers']//thead)" />
@@ -120,6 +129,7 @@
<entry><constant>SD_BUS_TYPE_ARRAY</constant></entry>
<entry>array</entry>
<entry>determined by array type and size</entry>
+ <entry>int, followed by array contents</entry>
</row>
<row>
@@ -127,6 +137,7 @@
<entry><constant>SD_BUS_TYPE_VARIANT</constant></entry>
<entry>variant</entry>
<entry>determined by the type argument</entry>
+ <entry>signature string, followed by variant contents</entry>
</row>
<row>
@@ -134,6 +145,7 @@
<entry><constant>SD_BUS_TYPE_STRUCT_BEGIN</constant></entry>
<entry>array start</entry>
<entry morerows="1">determined by the nested types</entry>
+ <entry morerows="1">structure contents</entry>
</row>
<row>
<entry><literal>)</literal></entry>
@@ -146,6 +158,7 @@
<entry><constant>SD_BUS_TYPE_DICT_ENTRY_BEGIN</constant></entry>
<entry>dictionary entry start</entry>
<entry morerows="1">determined by the nested types</entry>
+ <entry morerows="1">dictionary contents</entry>
</row>
<row>
<entry><literal>}</literal></entry>
@@ -155,10 +168,11 @@
</tbody>
</tgroup>
</table>
+
</refsect1>
<refsect1>
- <title>Types string grammar</title>
+ <title>Types String Grammar</title>
<programlisting>types ::= complete_type*
complete_type ::= basic_type | variant | structure | array | dictionary
@@ -194,7 +208,7 @@ uint32_t t = 7;
double d = 8.0;
sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d);</programlisting>
- <para>Append a structure composed of string and a D-Bus path:</para>
+ <para>Append a structure composed of a string and a D-Bus path:</para>
<programlisting>sd_bus_message_append(m, "(so)", "a string", "/a/path");
</programlisting>
@@ -242,12 +256,8 @@ sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d);</programlisting>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry project='die-net'><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append_array</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_bus_message_append_array.xml b/man/sd_bus_message_append_array.xml
index c2adc6f43d..37cadb9d0f 100644
--- a/man/sd_bus_message_append_array.xml
+++ b/man/sd_bus_message_append_array.xml
@@ -49,7 +49,8 @@
<refname>sd_bus_message_append_array_iovec</refname>
<refname>sd_bus_message_append_array_space</refname>
- <refpurpose>Attach an array of items to a message</refpurpose>
+ <refpurpose>Append an array of fields to a D-Bus
+ message</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -69,6 +70,8 @@
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
<paramdef>char <parameter>type</parameter></paramdef>
<paramdef>int <parameter>memfd</parameter></paramdef>
+ <paramdef>uint64_t <parameter>offset</parameter></paramdef>
+ <paramdef>uint64_t <parameter>size</parameter></paramdef>
</funcprototype>
<funcprototype>
@@ -83,7 +86,7 @@
<funcdef>int sd_bus_message_append_array_space</funcdef>
<paramdef>char <parameter>type</parameter></paramdef>
<paramdef>size_t <parameter>size</parameter></paramdef>
- <paramdef>char void **<parameter>ptr</parameter></paramdef>
+ <paramdef>void **<parameter>ptr</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -91,18 +94,19 @@
<refsect1>
<title>Description</title>
- <para>The <function>sd_bus_message_append_array</function> functionc
- appends items to message <parameter>m</parameter> as the single
- array. A container will be opened, items appended, and the
- container closed. Parameter <parameter>type</parameter> determines
- how pointer <parameter>p</parameter> is interpreted.
+ <para>The <function>sd_bus_message_append_array()</function>
+ function appends an array to a D-Bus message
+ <parameter>m</parameter>. A container will be opened, the array
+ contents appended, and the container closed. The parameter
+ <parameter>type</parameter> determines how the pointer
+ <parameter>p</parameter> is interpreted.
<parameter>type</parameter> must be one of the "trivial" types
<literal>y</literal>, <literal>n</literal>, <literal>q</literal>,
<literal>i</literal>, <literal>u</literal>, <literal>x</literal>,
<literal>t</literal>, <literal>d</literal> (but not
- <literal>b</literal>), as defined by the
- <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#basic-types">Basic Types</ulink>
- section of the D-Bus specification, and listed in
+ <literal>b</literal>), as defined by the <ulink
+ url="http://dbus.freedesktop.org/doc/dbus-specification.html#basic-types">Basic
+ Types</ulink> section of the D-Bus specification, and listed in
<citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Pointer <parameter>p</parameter> must point to an array of size
<parameter>size</parameter> bytes containing items of the
@@ -110,57 +114,75 @@
multiple of the size of the type <parameter>type</parameter>. As a
special case, <parameter>p</parameter> may be
<constant>NULL</constant>, if <parameter>size</parameter> is 0.
- </para>
-
- <para>The memory pointed at by <parameter>p</parameter> is copied
- into the memory area containing the message and may be changed
- after this call.</para>
-
- <para>The
- <function>sd_bus_message_append_array_memfd</function> function appends
- items to message <parameter>m</parameter>, similarly to
- <function>sd_bus_message_append_array</function>. Contents of the
- memory file descriptor <parameter>memfd</parameter> are used as
- the contents of the array. Their size must be a multiple of the
- size of the type <parameter>type</parameter>.</para>
-
- <para>The descriptor specified with <parameter>memfd</parameter>
- will be sealed and cannot be modified after this call.</para>
-
- <para>The
- <function>sd_bus_message_append_array_iovec</function> function appends
- items to message <parameter>m</parameter>, similarly to
- <function>sd_bus_message_append_array</function>. Contents of the
- iovec <parameter>iov</parameter> are used as the contents of the
- array. The total size of <parameter>iov</parameter> payload (the
- sum of <structfield>iov_len</structfield> fields) must be a multiple
- of the size of the type <parameter>type</parameter>.</para>
-
- <para>The <parameter>iov</parameter> argument must point to
- <parameter>n</parameter> <structname>struct iovec</structname>
- structures. Each structure may have the
- <structname>iov_base</structname> field set, in which case the
- memory pointed to will be copied into the message, or unset, in
- which case a block of zeros of length
+ The memory pointed to by <parameter>p</parameter> is copied into
+ the memory area containing the message and stays in possession of
+ the caller. The caller may hence freely change the data after this
+ call without affecting the message the array was appended
+ to.</para>
+
+ <para>The <function>sd_bus_message_append_array_memfd()</function>
+ function appends an array of a trivial type to message
+ <parameter>m</parameter>, similar to
+ <function>sd_bus_message_append_array()</function>. The contents
+ of the memory file descriptor <parameter>memfd</parameter>
+ starting at the specified offset and of the specified size is
+ used as the contents of the array. The offset and size must be a
+ multiple of the size of the type
+ <parameter>type</parameter>. However, as a special exception, if
+ the offset is specified as zero and the size specified as
+ UINT64_MAX the full memory file descriptor contents is used. The
+ memory file descriptor is sealed by this call if it hasn't been
+ sealed yet, and cannot be modified a after this call. See
+ <citerefentry
+ project='man-pages'><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+ for details about memory file descriptors. Appending arrays with
+ memory file descriptors enables efficient zero-copy data transfer,
+ as the memory file descriptor may be passed as-is to the
+ destination, without copying the memory in it to the destination
+ process. Not all protocol transports support passing memory file
+ descriptors between participants, in which case this call will
+ automatically fall back to copying. Also, as memory file
+ descriptor passing is inefficient for smaller amounts of data
+ copying might still be enforced even where memory file descriptor
+ passing is supported.</para>
+
+ <para>The <function>sd_bus_message_append_array_iovec()</function>
+ function appends an array of a trivial type to the message
+ <parameter>m</parameter>, similar to
+ <function>sd_bus_message_append_array()</function>. Contents of
+ the IO vector array <parameter>iov</parameter> are used as the
+ contents of the array. The total size of
+ <parameter>iov</parameter> payload (the sum of
+ <structfield>iov_len</structfield> fields) must be a multiple of
+ the size of the type <parameter>type</parameter>. The
+ <parameter>iov</parameter> argument must point to
+ <parameter>n</parameter> IO vector structures. Each structure may
+ have the <structname>iov_base</structname> field set, in which
+ case the memory pointed to will be copied into the message, or
+ unset (set to zero), in which case a block of zeros of length
<structname>iov_len</structname> bytes will be inserted. The
memory pointed at by <parameter>iov</parameter> may be changed
after this call.</para>
- <para>The
- <function>sd_bus_message_append_array_space</function> function appends
- space for an array of items to message <parameter>m</parameter>.
- It behaves the same as
- <function>sd_bus_message_append_array</function>, but instead
- of copying items to the message, it returns a pointer to the
- destination area to the caller in pointer <parameter>p</parameter>.
- </para>
+ <para>The <function>sd_bus_message_append_array_space()</function>
+ function appends space for an array of a trivial type to message
+ <parameter>m</parameter>. It behaves the same as
+ <function>sd_bus_message_append_array()</function>, but instead of
+ copying items to the message, it returns a pointer to the
+ destination area to the caller in pointer
+ <parameter>p</parameter>. The caller should subsequently write the
+ array contents to this memory. Modifications of the memory
+ pointed to should only occur until the next operation on the bus
+ message is invoked, most importantly the memory should not be
+ altered anymore when another field has been added to the message
+ or the message has been sealed.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, these calls return 0 or a positive integer. On
- failure, they returns a negative errno-style error code.</para>
+ failure, they return a negative errno-style error code.</para>
</refsect1>
<xi:include href="sd_bus_message_append_basic.xml" xpointer="errors" />
@@ -183,6 +205,7 @@
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
<ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html">The D-Bus specification</ulink>
</para>
</refsect1>
diff --git a/man/sd_bus_message_append_basic.xml b/man/sd_bus_message_append_basic.xml
index 91eaf87530..276953af69 100644
--- a/man/sd_bus_message_append_basic.xml
+++ b/man/sd_bus_message_append_basic.xml
@@ -45,7 +45,7 @@
<refnamediv>
<refname>sd_bus_message_append_basic</refname>
- <refpurpose>Attach a single part to a message</refpurpose>
+ <refpurpose>Attach a single field to a message</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -56,7 +56,7 @@
<funcdef>int sd_bus_message_append_basic</funcdef>
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
<paramdef>char <parameter>type</parameter></paramdef>
- <paramdef>char void *<parameter>p</parameter></paramdef>
+ <paramdef>const void *<parameter>p</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -64,31 +64,33 @@
<refsect1>
<title>Description</title>
- <para><function>sd_bus_message_append_basic</function> appends a
- single item to the message <parameter>m</parameter>. Parameter
- <parameter>type</parameter> determines how pointer
+ <para><function>sd_bus_message_append_basic()</function> appends a
+ single field to the message <parameter>m</parameter>. The
+ parameter <parameter>type</parameter> determines how the pointer
<parameter>p</parameter> is interpreted.
- <parameter>type</parameter> must be one of the basic types
- as defined by the
-
- <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#basic-types">Basic Types</ulink>
- section of the D-Bus specification, and listed in the table below.
+ <parameter>type</parameter> must be one of the basic types as
+ defined by the <ulink
+ url="http://dbus.freedesktop.org/doc/dbus-specification.html#basic-types">Basic
+ Types</ulink> section of the D-Bus specification, and listed in
+ the table below.
</para>
<table id='format-specifiers'>
- <title>Item format specifiers</title>
+ <title>Item type specifiers</title>
- <tgroup cols='4'>
+ <tgroup cols='5'>
<colspec colname='specifier' />
<colspec colname='constant' />
<colspec colname='description' />
<colspec colname='size' />
+ <colspec colname='ctype' />
<thead>
<row>
<entry>Specifier</entry>
<entry>Constant</entry>
<entry>Description</entry>
<entry>Size</entry>
+ <entry>Expected C Type</entry>
</row>
</thead>
<tbody>
@@ -97,6 +99,7 @@
<entry><constant>SD_BUS_TYPE_BYTE</constant></entry>
<entry>unsigned integer</entry>
<entry>1 byte</entry>
+ <entry>uint8_t</entry>
</row>
<row>
@@ -104,6 +107,7 @@
<entry><constant>SD_BUS_TYPE_BOOLEAN</constant></entry>
<entry>boolean</entry>
<entry>4 bytes</entry>
+ <entry>int</entry>
</row>
<row>
@@ -111,6 +115,7 @@
<entry><constant>SD_BUS_TYPE_INT16</constant></entry>
<entry>signed integer</entry>
<entry>2 bytes</entry>
+ <entry>int16_t</entry>
</row>
<row>
@@ -118,6 +123,7 @@
<entry><constant>SD_BUS_TYPE_UINT16</constant></entry>
<entry>unsigned integer</entry>
<entry>2 bytes</entry>
+ <entry>uint16_t</entry>
</row>
<row>
@@ -125,6 +131,7 @@
<entry><constant>SD_BUS_TYPE_INT32</constant></entry>
<entry>signed integer</entry>
<entry>4 bytes</entry>
+ <entry>int32_t</entry>
</row>
<row>
@@ -132,6 +139,7 @@
<entry><constant>SD_BUS_TYPE_UINT32</constant></entry>
<entry>unsigned integer</entry>
<entry>4 bytes</entry>
+ <entry>uint32_t</entry>
</row>
<row>
@@ -139,6 +147,7 @@
<entry><constant>SD_BUS_TYPE_INT64</constant></entry>
<entry>signed integer</entry>
<entry>8 bytes</entry>
+ <entry>int64_t</entry>
</row>
<row>
@@ -146,6 +155,7 @@
<entry><constant>SD_BUS_TYPE_UINT64</constant></entry>
<entry>unsigned integer</entry>
<entry>8 bytes</entry>
+ <entry>uint64_t</entry>
</row>
<row>
@@ -153,6 +163,7 @@
<entry><constant>SD_BUS_TYPE_DOUBLE</constant></entry>
<entry>floating-point</entry>
<entry>8 bytes</entry>
+ <entry>double</entry>
</row>
<row>
@@ -160,6 +171,7 @@
<entry><constant>SD_BUS_TYPE_STRING</constant></entry>
<entry>Unicode string</entry>
<entry>variable</entry>
+ <entry>char[]</entry>
</row>
<row>
@@ -167,6 +179,7 @@
<entry><constant>SD_BUS_TYPE_OBJECT_PATH</constant></entry>
<entry>object path</entry>
<entry>variable</entry>
+ <entry>char[]</entry>
</row>
<row>
@@ -174,6 +187,7 @@
<entry><constant>SD_BUS_TYPE_SIGNATURE</constant></entry>
<entry>signature</entry>
<entry>variable</entry>
+ <entry>char[]</entry>
</row>
<row>
@@ -181,16 +195,19 @@
<entry><constant>SD_BUS_TYPE_UNIX_FD</constant></entry>
<entry>UNIX file descriptor</entry>
<entry>4 bytes</entry>
+ <entry>int</entry>
</row>
</tbody>
</tgroup>
</table>
- <para>The value of the parameter is copied into the memory area
- containing the message and may be changed after this call. If
- <parameter>type</parameter> is <literal>h</literal> (UNIX file
- descriptor), it is always "consumed" by this call, and either
- successfully appended to the message or closed.</para>
+ <para>The value of the parameter is copied into a memory area held
+ by the message object, stays in the possession of the caller and
+ may hence be freely changed after this call without affecting the
+ bus message it has been added to. If <parameter>type</parameter>
+ is <literal>h</literal> (UNIX file descriptor), the descriptor is
+ duplicated by this call and the passed descriptor stays in
+ possession of the caller.</para>
<para>For types <literal>s</literal>, <literal>o</literal>, and
<literal>g</literal>, the parameter <parameter>p</parameter> is
diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml
index 04042f2136..f53ea9e41a 100644
--- a/man/sd_bus_negotiate_fds.xml
+++ b/man/sd_bus_negotiate_fds.xml
@@ -44,7 +44,7 @@
<refnamediv>
<refname>sd_bus_negotiate_fds</refname>
- <refname>sd_bus_negotiate_timestamps</refname>
+ <refname>sd_bus_negotiate_timestamp</refname>
<refname>sd_bus_negotiate_creds</refname>
<refpurpose>Control feature negotiation on bus connections</refpurpose>
@@ -152,7 +152,7 @@
<refsect1>
<title>Return Value</title>
- <para>On success, these functions returns 0 or a
+ <para>On success, these functions return 0 or a
positive integer. On failure, they return a negative errno-style
error code.</para>
</refsect1>
diff --git a/man/sd_bus_new.xml b/man/sd_bus_new.xml
index 44744a0029..aff2ed2e83 100644
--- a/man/sd_bus_new.xml
+++ b/man/sd_bus_new.xml
@@ -77,8 +77,8 @@
<para><function>sd_bus_new()</function> creates a new bus
object. This object is reference-counted, and will be destroyed
when all references are gone. Initially, the caller of this
- function owns the sole reference. The bus object will not be
- connected to any bus initially. To connect it to a bus, make sure
+ function owns the sole reference and the bus object will not be
+ connected to any bus. To connect it to a bus, make sure
to set an address with
<citerefentry><refentrytitle>sd_bus_set_address</refentrytitle><manvolnum>3</manvolnum></citerefentry>
or a related call, and then start the connection with
@@ -94,15 +94,13 @@
well-known bus in a single function invocation.</para>
<para><function>sd_bus_ref()</function> creates a new reference to
- <parameter>bus</parameter>. This bus object will not be destroyed
- until <function>sd_bus_unref()</function> has been called as many
- times plus once more. Once the reference count has dropped to
- zero, <parameter>bus</parameter> cannot be used anymore, so
- further calls to <function>sd_bus_ref()</function> or
- <function>sd_bus_unref()</function> are illegal.</para>
+ <parameter>bus</parameter>.</para>
<para><function>sd_bus_unref()</function> destroys a reference to
- <parameter>bus</parameter>.</para>
+ <parameter>bus</parameter>. Once the reference count has dropped
+ to zero, <parameter>bus</parameter> cannot be used anymore, so
+ further calls to <function>sd_bus_ref()</function> or
+ <function>sd_bus_unref()</function> are illegal.</para>
</refsect1>
<refsect1>
diff --git a/man/sd_bus_request_name.xml b/man/sd_bus_request_name.xml
index 9b0a93d888..f07ae09555 100644
--- a/man/sd_bus_request_name.xml
+++ b/man/sd_bus_request_name.xml
@@ -45,7 +45,7 @@
<refnamediv>
<refname>sd_bus_request_name</refname>
<refname>sd_bus_release_name</refname>
- <refpurpose>Request or release a well-known name on a bus</refpurpose>
+ <refpurpose>Request or release a well-known service name on a bus</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -71,9 +71,9 @@
<title>Description</title>
<para><function>sd_bus_request_name()</function> requests a
- well-known 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>
+ 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>
<variablelist>
<varlistentry>
@@ -166,8 +166,11 @@
<varlistentry>
<term><constant>-EINVAL</constant></term>
- <listitem><para>A specified parameter is
- invalid.</para></listitem>
+ <listitem><para>A specified parameter is invalid. This is also
+ generated when the requested name is a special service name
+ reserved by the D-Bus specification, or when the operation is
+ requested on a connection that does not refer to a
+ bus.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index 87e59c9cc2..14030f56b1 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -197,7 +197,7 @@
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for information how to enable this functionality and
<citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- for the details of how the service can check if the the
+ for the details of how the service can check whether the
watchdog is enabled. </para></listitem>
</varlistentry>
diff --git a/man/sd_pid_get_session.xml b/man/sd_pid_get_session.xml
index b46d47101b..9c6706caf8 100644
--- a/man/sd_pid_get_session.xml
+++ b/man/sd_pid_get_session.xml
@@ -49,15 +49,17 @@
<refname>sd_pid_get_owner_uid</refname>
<refname>sd_pid_get_machine_name</refname>
<refname>sd_pid_get_slice</refname>
+ <refname>sd_pid_get_user_slice</refname>
<refname>sd_peer_get_session</refname>
<refname>sd_peer_get_unit</refname>
<refname>sd_peer_get_user_unit</refname>
<refname>sd_peer_get_owner_uid</refname>
<refname>sd_peer_get_machine_name</refname>
<refname>sd_peer_get_slice</refname>
- <refpurpose>Determine session, service, owner of a
- session, container/VM or slice of a specific
- PID or socket peer</refpurpose>
+ <refname>sd_peer_get_user_slice</refname>
+ <refpurpose>Determine session, unit, owner of a session,
+ container/VM or slice of a specific PID or socket
+ peer</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -101,6 +103,12 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_pid_get_user_slice</function></funcdef>
+ <paramdef>pid_t <parameter>pid</parameter></paramdef>
+ <paramdef>char **<parameter>slice</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_peer_get_session</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>char **<parameter>session</parameter></paramdef>
@@ -135,6 +143,12 @@
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>char **<parameter>slice</parameter></paramdef>
</funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_peer_get_user_slice</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>char **<parameter>slice</parameter></paramdef>
+ </funcprototype>
</funcsynopsis>
</refsynopsisdiv>
@@ -155,30 +169,29 @@
call after use.</para>
<para><function>sd_pid_get_unit()</function> may be used to
- determine the systemd system unit (i.e. system service) identifier
- of a process identified by the specified PID. The unit name is a
- short string, suitable for usage in file system paths. Note that
- not all processes are part of a system unit/service (e.g. user
- processes, or kernel threads). For processes not being part of a
- systemd system unit this function will fail with -ENXIO (More
- specifically: this call will not work for processes that are part
- of user units, use <function>sd_pid_get_user_unit()</function> for
- that.) The returned string needs to be freed with the libc
- <citerefentry
+ determine the systemd system unit (i.e. system service or scope
+ unit) identifier of a process identified by the specified PID. The
+ unit name is a short string, suitable for usage in file system
+ paths. Note that not all processes are part of a system
+ unit/service (e.g. user processes, or kernel threads). For
+ processes not being part of a systemd system unit this function
+ will fail with -ENXIO (More specifically: this call will not work
+ for kernel threads.) The returned string needs to be freed with
+ the libc <citerefentry
project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
<para><function>sd_pid_get_user_unit()</function> may be used to
- determine the systemd user unit (i.e. user service) identifier of
- a process identified by the specified PID. This is similar to
- <function>sd_pid_get_unit()</function> but applies to user units
- instead of system units.</para>
+ determine the systemd user unit (i.e. user service or scope unit)
+ identifier of a process identified by the specified PID. This is
+ similar to <function>sd_pid_get_unit()</function> but applies to
+ user units instead of system units.</para>
<para><function>sd_pid_get_owner_uid()</function> may be used to
- determine the Unix user identifier of the owner of the session of
- a process identified the specified PID. Note that this function
- will succeed for user processes which are shared between multiple
- login sessions of the same user, where
+ determine the Unix UID (user identifier) of the owner of the
+ session of a process identified the specified PID. Note that this
+ function will succeed for user processes which are shared between
+ multiple login sessions of the same user, where
<function>sd_pid_get_session()</function> will fail. For processes
not being part of a login session and not being a shared process
of a user this function will fail with -ENXIO.</para>
@@ -200,6 +213,10 @@
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call after use.</para>
+ <para>Similar, <function>sd_pid_get_user_slice()</function>
+ returns the user slice (as managed by the user's systemd instance)
+ of a process.</para>
+
<para>If the <varname>pid</varname> parameter of any of these
functions is passed as 0, the operation is executed for the
calling process.</para>
@@ -208,10 +225,14 @@
<function>sd_peer_get_unit()</function>,
<function>sd_peer_get_user_unit()</function>,
<function>sd_peer_get_owner_uid()</function>,
- <function>sd_peer_get_machine_name()</function> and
- <function>sd_peer_get_slice()</function> calls operate similar to
- their PID counterparts, but operate on a connected AF_UNIX socket
- and retrieve information about the connected peer process.</para>
+ <function>sd_peer_get_machine_name()</function>,
+ <function>sd_peer_get_slice()</function> and
+ <function>sd_peer_get_user_slice()</function> calls operate
+ similar to their PID counterparts, but operate on a connected
+ AF_UNIX socket and retrieve information about the connected peer
+ process. Note that these fields are retrieved via
+ <filename>/proc</filename>, and hence are not suitable for
+ authorization purposes, as they are subject to races.</para>
</refsect1>
<refsect1>
@@ -262,15 +283,17 @@
<function>sd_pid_get_owner_uid()</function>,
<function>sd_pid_get_machine_name()</function>,
<function>sd_pid_get_slice()</function>,
+ <function>sd_pid_get_user_slice()</function>,
<function>sd_peer_get_session()</function>,
<function>sd_peer_get_unit()</function>,
<function>sd_peer_get_user_unit()</function>,
<function>sd_peer_get_owner_uid()</function>,
- <function>sd_peer_get_machine_name()</function> and
- <function>sd_peer_get_slice()</function> interfaces are
- available as a shared library, which can be compiled
- and linked to with the
- <constant>libsystemd</constant> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <function>sd_peer_get_machine_name()</function>,
+ <function>sd_peer_get_slice()</function> and
+ <function>sd_peer_get_user_slice()</function> interfaces are
+ available as a shared library, which can be compiled and linked to
+ with the <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
file.</para>
<para>Note that the login session identifier as
diff --git a/man/sysctl.d.xml b/man/sysctl.d.xml
index 8a131791a5..e5b2bc0ac9 100644
--- a/man/sysctl.d.xml
+++ b/man/sysctl.d.xml
@@ -123,11 +123,12 @@
</example>
<example>
- <title>Disable packet filter on bridged packets (method one)</title>
+ <title>Apply settings available only when a certain module is loaded (method one)</title>
<para><filename>/etc/udev/rules.d/99-bridge.rules</filename>:
</para>
- <programlisting>ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/net/bridge"
+ <programlisting>ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", \
+ RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/net/bridge"
</programlisting>
<para><filename>/etc/sysctl.d/bridge.conf</filename>:
@@ -137,14 +138,20 @@
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
</programlisting>
+
+ <para>This method applies settings when the module is
+ loaded. Please note that unless the <filename>br_netfilter</filename>
+ module is loaded, bridged packets will not be filtered by
+ netfilter (starting with kernel 3.18), so simply not loading the
+ module is suffient to avoid filtering.</para>
</example>
<example>
- <title>Disable packet filter on bridged packets (method two)</title>
+ <title>Apply settings available only when a certain module is loaded (method two)</title>
<para><filename>/etc/modules-load.d/bridge.conf</filename>:
</para>
- <programlisting>bridge</programlisting>
+ <programlisting>br_netfilter</programlisting>
<para><filename>/etc/sysctl.d/bridge.conf</filename>:
</para>
@@ -153,6 +160,12 @@ net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
</programlisting>
+
+ <para>This method forces the module to be always loaded. Please
+ note that unless the <filename>br_netfilter</filename> module is
+ loaded, bridged packets will not be filtered with netfilter
+ (starting with kernel 3.18), so simply not loading the module is
+ suffient to avoid filtering.</para>
</example>
</refsect1>
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 409b6f0895..66a090049d 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -114,12 +114,30 @@
<listitem>
<para>When showing unit/job/manager properties with the
- <command>show</command> command, limit display to certain
- properties as specified as argument. If not specified, all
- set properties are shown. The argument should be a
+ <command>show</command> command, limit display to properties
+ specified in the argument. The argument should be a
comma-separated list of property names, such as
- <literal>MainPID</literal>. If specified more than once, all
- properties with the specified names are shown.</para>
+ <literal>MainPID</literal>. Unless specified, all known
+ properties are shown. If specified more than once, all
+ properties with the specified names are shown. Shell
+ completion is implemented for property names.</para>
+
+ <para>For the manager itself,
+ <command>systemctl show</command> will show all available
+ properties. Those properties are documented in
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
+
+ <para>Properties for units vary by unit type, so showing any
+ unit (even a non-existent one) is a way to list properties
+ pertaining to this type. Similarly showing any job will list
+ properties pertaining to all jobs. Properties for units are
+ documented in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ and the pages for individual unit types
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ etc.</para>
</listitem>
</varlistentry>
@@ -1181,9 +1199,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<replaceable>NAME</replaceable>...</command></term>
<listitem>
- <para>Adds <literal>Wants=</literal> resp. <literal>Requires=</literal>
- dependency to the specified <replaceable>TARGET</replaceable> for
- one or more units. </para>
+ <para>Adds <literal>Wants=</literal> or <literal>Requires=</literal>
+ dependency, respectively, to the specified
+ <replaceable>TARGET</replaceable> for one or more units. </para>
<para>This command honors <option>--system</option>,
<option>--user</option>, <option>--runtime</option> and
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
index 5da3857c08..cb46d41902 100644
--- a/man/systemd-coredump.xml
+++ b/man/systemd-coredump.xml
@@ -67,7 +67,7 @@
overridden to use a different setting following normal
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> rules.</para>
- <para>The behaviour of a specific program upon reception of a
+ <para>The behavior of a specific program upon reception of a
signal is governed by a few factors which are described in detail
in <citerefentry project='man-pages'><refentrytitle>core</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
In particular, the coredump will only be processed when the
@@ -81,7 +81,7 @@
including a backtrace if possible, and store the core (contents of
process' memory contents) in an external file on disk in
<filename>/var/lib/systemd/coredump</filename>, or directly in
- the journal. This behaviour may be modified using
+ the journal. This behavior may be modified using
<citerefentry><refentrytitle>coredump.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>Apart from the
diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml
index 8280d6c874..dae6ee6042 100644
--- a/man/systemd-journald.service.xml
+++ b/man/systemd-journald.service.xml
@@ -203,7 +203,7 @@
<listitem><para>Configure
<command>systemd-journald</command>
- behaviour. See
+ behavior. See
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 64877720bc..45a4422dc3 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -858,9 +858,10 @@
<listitem><para>Takes a boolean argument or
<literal>read-only</literal>. If true, the directories
- <filename>/home</filename> and <filename>/run/user</filename>
+ <filename>/home</filename>, <filename>/root</filename> and
+ <filename>/run/user</filename>
are made inaccessible and empty for processes invoked by this
- unit. If set to <literal>read-only</literal>, the two
+ unit. If set to <literal>read-only</literal>, the three
directories are made read-only instead. It is recommended to
enable this setting for all long-running services (in
particular network-facing ones), to ensure they cannot get
diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml
index a101006a7e..49f44d2922 100644
--- a/man/systemd.journal-fields.xml
+++ b/man/systemd.journal-fields.xml
@@ -73,7 +73,7 @@
<para>The human-readable message string for this entry. This
is supposed to be the primary text shown to the user. It is
usually not translated (but might be in some cases), and is
- not supposed to be parsed for meta data.</para>
+ not supposed to be parsed for metadata.</para>
</listitem>
</varlistentry>
@@ -440,7 +440,6 @@
</varlistentry>
</variablelist>
-
</refsect1>
<refsect1>
diff --git a/man/systemd.link.xml b/man/systemd.link.xml
index d9b1879c59..b630ef7a17 100644
--- a/man/systemd.link.xml
+++ b/man/systemd.link.xml
@@ -68,11 +68,10 @@
in <filename>/etc</filename> have the highest priority, files in
<filename>/run</filename> take precedence over files with the same
name in <filename>/usr/lib</filename>. This can be used to
- override a system-supplied link file with a local file if needed;
- a symlink in <filename>/etc</filename> with the same name as a
- link file in <filename>/usr/lib</filename>, pointing to
- <filename>/dev/null</filename>, disables the link file
- entirely.</para>
+ override a system-supplied link file with a local file if needed.
+ As a special case, an empty file (file size 0) or symlink with the
+ same name pointing to <filename>/dev/null</filename>, disable the
+ configuration file entirely (it is "masked").</para>
<para>The link file contains a <literal>[Match]</literal> section,
which determines if a given link file may be applied to a given
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 01c31c5ef5..298cf0eb84 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -80,11 +80,9 @@
<filename>/run</filename> take precedence over files with the same
name in <filename>/usr/lib</filename>. This can be used to
override a system-supplied configuration file with a local file if
- needed; a symlink in <filename>/etc</filename> with the same name
- as a configuration file in <filename>/usr/lib</filename>, pointing
- to <filename>/dev/null</filename>, disables the configuration file
- entirely.</para>
-
+ needed. As a special case, an empty file (file size 0) or symlink
+ with the same name pointing to <filename>/dev/null</filename>,
+ disable the configuration file entirely (it is "masked").</para>
</refsect1>
<refsect1>
@@ -491,6 +489,31 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>IPv6FlowLabel=</varname></term>
+ <listitem>
+ <para>Configures The 20-bit Flow Label (see <ulink url="https://tools.ietf.org/html/rfc6437">
+ RFC 6437</ulink>) field in the IPv6 header (see <ulink url="https://tools.ietf.org/html/rfc2460">
+ RFC 2460</ulink>), is used by a node to label packets of a flow.
+ It's only used for IPv6 Tunnels.
+ A Flow Label of zero is used to indicate packets that have
+ not been labeled. Takes following values.
+ When <literal>inherit</literal> it uses the original flowlabel,
+ or can be configured to any value between 0 to 0xFFFFF.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>CopyDSCP=</varname></term>
+ <listitem>
+ <para>A boolean. When true, the Differentiated Service Code
+ Point (DSCP) field will be copied to the inner header from
+ outer header during the decapsulation of an IPv6 tunnel
+ packet. DSCP is a field in an IP packet that enables different
+ levels of service to be assigned to network traffic.
+ Defaults to <literal>no</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>Mode=</varname></term>
<listitem>
<para>An <literal>ip6tnl</literal> tunnels can have three
@@ -563,6 +586,16 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>VNetHeader=</varname></term>
+ <listitem><para>Takes a boolean argument. Configures
+ IFF_VNET_HDR flag for a tap device. It allows sending
+ and receiving larger Generic Segmentation Offload (GSO)
+ packets. This may increase throughput significantly.
+ Defaults to
+ <literal>no</literal>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>User=</varname></term>
<listitem><para>User to grant access to the
<filename>/dev/net/tun</filename> device.</para>
@@ -644,7 +677,7 @@
<listitem>
<para>Specifies the frequency that Media Independent
Interface link monitoring will occur. A value of zero
- disables MII link monitoring. This values is rounded down to
+ disables MII link monitoring. This value is rounded down to
the nearest millisecond. The default value is 0.</para>
</listitem>
</varlistentry>
@@ -788,7 +821,7 @@
<listitem>
<para> Specify the number of packets to transmit through a slave before
moving to the next one. When set to 0 then a slave is chosen at
- random.The valid range is (0 - 65535). Defaults to 1. This option
+ random. The valid range is (0 - 65535). Defaults to 1. This option
has effect only in balance-rr mode.
</para>
</listitem>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 1a2699a47f..e44491cc2e 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -76,11 +76,9 @@
<filename>/run</filename> take precedence over files with the same
name in <filename>/usr/lib</filename>. This can be used to
override a system-supplied configuration file with a local file if
- needed; a symlink in <filename>/etc</filename> with the same name
- as a configuration file in <filename>/usr/lib</filename>, pointing
- to <filename>/dev/null</filename>, disables the configuration file
- entirely.</para>
-
+ needed. As a special case, an empty file (file size 0) or symlink
+ with the same name pointing to <filename>/dev/null</filename>,
+ disable the configuration file entirely (it is "masked").</para>
</refsect1>
<refsect1>
@@ -288,7 +286,7 @@
<term><varname>BindCarrier=</varname></term>
<listitem>
<para>A port or a list of ports. When set, controls the
- behaviour of the current interface. When all ports in the list
+ behavior of the current interface. When all ports in the list
are in an operational down state, the current interface is brought
down. When at least one port has carrier, the current interface
is brought up.
@@ -376,8 +374,9 @@
<para>Note: unless this option is turned on, or set to <literal>kernel</literal>,
no IP forwarding is done on this interface, even if this is
globally turned on in the kernel, with the
- <filename>net.ipv4.ip_forward</filename> and
- <filename>net.ipv4.ip_forward</filename> sysctl
+ <filename>net.ipv4.ip_forward</filename>,
+ <filename>net.ipv4.conf.all.forwarding</filename>, and
+ <filename>net.ipv6.conf.all.forwarding</filename> sysctl
options.</para>
</listitem>
</varlistentry>
@@ -391,6 +390,23 @@
<literal>no</literal>.</para></listitem>
</varlistentry>
<varlistentry>
+ <term><varname>IPv6PrivacyExtensions=</varname></term>
+ <listitem><para>Configures use of stateless temporary
+ addresses that change over time (see <ulink
+ url="https://tools.ietf.org/html/rfc4941">RFC 4941</ulink>,
+ Privacy Extensions for Stateless Address Autoconfiguration
+ in IPv6). Takes a boolean or the special values
+ <literal>prefer-public</literal> and
+ <literal>kernel</literal>. When true enables the privacy
+ extensions and prefers temporary addresses over public
+ addresses. When <literal>prefer-public</literal> enables the
+ privacy extensions, but prefers public addresses over
+ temporary addresses. When false, the privacy extensions
+ remain disabled. When <literal>kernel</literal> the kernel's
+ default setting will be left in place. Defaults to
+ <literal>no</literal>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>Bridge=</varname></term>
<listitem>
<para>The name of the bridge to add the link to.</para>
@@ -558,19 +574,26 @@
<varlistentry>
<term><varname>SendHostname=</varname></term>
<listitem>
- <para>When true (the default), the machine's hostname will be sent to the DHCP
- server</para>
+ <para>When true (the default), the machine's hostname will
+ be sent to the DHCP server.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseHostname=</varname></term>
<listitem>
<para>When true (the default), the hostname received from
- the DHCP server will be used as the transient
- hostname.</para>
+ the DHCP server will be used as the transient hostname.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>Hostname=</varname></term>
+ <listitem>
+ <para>Use this value for the hostname which is sent to the
+ DHCP server, instead of machine's hostname.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>UseDomains=</varname></term>
<listitem>
<para>When true (not the default), the domain name
@@ -645,16 +668,57 @@
following keys.</para>
<variablelist class='network-directives'>
<varlistentry>
+ <term><varname>UnicastFlood=</varname></term>
+ <listitem>
+ <para>A boolean. Controls whether the bridge should flood
+ traffic for which an FDB entry is missing and the destination
+ is unknown through this port. Defaults to on.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>HairPin=</varname></term>
+ <listitem>
+ <para>A boolean. Configures whether traffic may be sent back
+ out of the port on which it was received. By default, this
+ flag is false, and the bridge will not forward traffic back
+ out of the receiving port.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>UseBPDU=</varname></term>
+ <listitem>
+ <para>A boolean. Configures whether STP Bridge Protocol Data Units will be
+ processed by the bridge port. Defaults to yes.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>FastLeave=</varname></term>
+ <listitem>
+ <para>A boolean. This flag allows the bridge to immediately stop multicast
+ traffic on a port that receives IGMP Leave message. It is only used with
+ IGMP snooping if enabled on the bridge. Defaults to off.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>AllowPortToBeRoot=</varname></term>
+ <listitem>
+ <para>A boolean. Configures whether a given port is allowed to
+ become a root port. Only used when STP is enabled on the bridge.
+ Defaults to on.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>Cost=</varname></term>
<listitem>
- <para>Each port in a bridge may have different speed. Cost
+ <para>Sets the "cost" of sending packets of this interface.
+ Each port in a bridge may have different speed and the cost
is used to decide which link to use. Faster interfaces
- should have lower costs</para>
+ should have lower costs.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
-
<refsect1>
<title>[BridgeFDB] Section Options</title>
<para>The <literal>[BridgeFDB]</literal> section manages the
diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml
index 2f9add8d6c..b7164014f0 100644
--- a/man/systemd.preset.xml
+++ b/man/systemd.preset.xml
@@ -106,7 +106,7 @@
one takes precedence over all others.</para>
<para>Each preset file shall be named in the style of
- <filename>&lt;priority&gt;-&lt;program&gt;.conf</filename>. Files
+ <filename>&lt;priority&gt;-&lt;policy-name&gt;.preset</filename>. Files
in <filename>/etc/</filename> override files with the same name in
<filename>/usr/lib/</filename> and <filename>/run/</filename>.
Files in <filename>/run/</filename> override files with the same
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 1e949f0c52..4368ca8a19 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -226,7 +226,10 @@
services where <varname>Type=</varname> is set to
<option>forking</option>. systemd will read the PID of the
main process of the daemon after start-up of the service.
- systemd will not write to the file configured here.</para>
+ systemd will not write to the file configured here, although
+ it will remove the file after the service has shut down if it
+ still exists.
+ </para>
</listitem>
</varlistentry>
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index 1e9778bc2a..36fa3a86be 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -462,7 +462,7 @@
and the kernel will ignore initial ACK packets without any
data. The argument specifies the approximate amount of time
the kernel should wait for incoming data before falling back
- to the normal behaviour of honouring empty ACK packets. This
+ to the normal behavior of honouring empty ACK packets. This
option is beneficial for protocols where the client sends the
data first (e.g. HTTP, in contrast to SMTP), because the
server process will not be woken up unnecessarily before it
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index da0729725d..64358351d5 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -125,7 +125,7 @@
(<literal>Wednesday</literal>) English language form (case does
not matter), and is not subject to the locale choice of the user.
Either the date, or the time part may be omitted, in which case
- the current date or 00:00:00, resp., is assumed. The seconds
+ the current date or 00:00:00, respectively, is assumed. The seconds
component of the time may also be omitted, in which case ":00" is
assumed. Year numbers may be specified in full or may be
abbreviated (omitting the century).</para>
diff --git a/man/udev.xml b/man/udev.xml
index 4c2e13ee7b..2e1655bf55 100644
--- a/man/udev.xml
+++ b/man/udev.xml
@@ -522,15 +522,6 @@
</varlistentry>
<varlistentry>
- <term><varname>WAIT_FOR</varname></term>
- <listitem>
- <para>Wait for a file to become available or until a timeout of
- 10 seconds expires. The path is relative to the sysfs device;
- if no path is specified, this waits for an attribute to appear.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
<term><varname>OPTIONS</varname></term>
<listitem>
<para>Rule and device options:</para>
diff --git a/rules/42-usb-hid-pm.rules b/rules/42-usb-hid-pm.rules
deleted file mode 100644
index 3721219098..0000000000
--- a/rules/42-usb-hid-pm.rules
+++ /dev/null
@@ -1,36 +0,0 @@
-# do not edit this file, it will be overwritten on update
-#
-# Enable autosuspend for qemu emulated usb hid devices
-
-# Note that there are buggy qemu versions (0.13 & older) which
-# advertise remote wakeup support but don't actually implement
-# it correctly. This is the reason why we need a match for the
-# serial number here. Old, broken versions have serial "1".
-# It has been changed to "42" after fixing the bug to indicate
-# remote wakeup is working.
-ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Mouse", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto"
-ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Tablet", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto"
-ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Keyboard", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto"
-
-# Dell DRAC 4
-ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="413c", ATTR{idProduct}=="2500", TEST=="power/control", ATTR{power/control}="auto"
-
-# Dell DRAC 5
-ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="413c", ATTR{idProduct}=="0000", TEST=="power/control", ATTR{power/control}="auto"
-
-# IBM remote access
-ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="04b3", ATTR{idProduct}=="4001", TEST=="power/control", ATTR{power/control}="auto"
-ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="04b3", ATTR{idProduct}=="4002", TEST=="power/control", ATTR{power/control}="auto"
-ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="04b3", ATTR{idProduct}=="4012", TEST=="power/control", ATTR{power/control}="auto"
-
-# Raritan Computer, Inc KVM.
-ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="14dd", ATTR{idProduct}=="0002", TEST=="power/control", ATTR{power/control}="auto"
-
-# USB HID devices that are internal to the machine should also be safe to autosuspend
-
-ACTION=="add", SUBSYSTEM=="usb", SUBSYSTEMS=="usb", ATTR{../removable}=="removable", GOTO="usb_hid_pm_end"
-ACTION=="add", SUBSYSTEM=="usb", SUBSYSTEMS=="usb", ATTR{../removable}=="unknown", GOTO="usb_hid_pm_end"
-
-ACTION=="add", SUBSYSTEM=="usb", ATTR{bInterfaceClass}=="03", ATTR{../removable}=="fixed", TEST=="../power/control", ATTR{../power/control}="auto"
-
-LABEL="usb_hid_pm_end"
diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
index 71b8e46ae8..5ab03fc278 100644
--- a/rules/60-persistent-storage.rules
+++ b/rules/60-persistent-storage.rules
@@ -6,7 +6,7 @@
ACTION=="remove", GOTO="persistent_storage_end"
SUBSYSTEM!="block", GOTO="persistent_storage_end"
-KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*", GOTO="persistent_storage_end"
+KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*", GOTO="persistent_storage_end"
# ignore partitions that span the entire disk
TEST=="whole_disk", GOTO="persistent_storage_end"
diff --git a/rules/61-accelerometer.rules b/rules/61-accelerometer.rules
deleted file mode 100644
index a6a2bfd088..0000000000
--- a/rules/61-accelerometer.rules
+++ /dev/null
@@ -1,3 +0,0 @@
-# do not edit this file, it will be overwritten on update
-
-SUBSYSTEM=="input", ACTION!="remove", ENV{ID_INPUT_ACCELEROMETER}=="1", IMPORT{program}="accelerometer %p"
diff --git a/rules/70-touchpad.rules b/rules/70-touchpad.rules
deleted file mode 100644
index 88e6fd2f25..0000000000
--- a/rules/70-touchpad.rules
+++ /dev/null
@@ -1,12 +0,0 @@
-# do not edit this file, it will be overwritten on update
-
-ACTION=="remove", GOTO="touchpad_end"
-KERNEL!="event*", GOTO="touchpad_end"
-ENV{ID_INPUT_TOUCHPAD}=="", GOTO="touchpad_end"
-
-# touchpad:pnpid:<pnpid>:*
-KERNELS=="serio1", \
- IMPORT{builtin}="hwdb 'touchpad:pnpid:$attr{firmware_id}:'", \
- GOTO="touchpad_end"
-
-LABEL="touchpad_end"
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 9583458f72..db1e7f3f37 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -88,6 +88,18 @@ struct boot_times {
usec_t generators_finish_time;
usec_t unitsload_start_time;
usec_t unitsload_finish_time;
+
+ /*
+ * If we're analyzing the user instance, all timestamps will be offset
+ * by its own start-up timestamp, which may be arbitrarily big.
+ * With "plot", this causes arbitrarily wide output SVG files which almost
+ * completely consist of empty space. Thus we cancel out this offset.
+ *
+ * This offset is subtracted from times above by acquire_boot_times(),
+ * but it still needs to be subtracted from unit-specific timestamps
+ * (so it is stored here for reference).
+ */
+ usec_t reverse_offset;
};
struct unit_times {
@@ -188,95 +200,13 @@ static void free_unit_times(struct unit_times *t, unsigned n) {
free(t);
}
-static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- int r, c = 0;
- struct unit_times *unit_times = NULL;
- size_t size = 0;
- UnitInfo u;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "ListUnits",
- &error, &reply,
- NULL);
- if (r < 0) {
- log_error("Failed to list units: %s", bus_error_message(&error, -r));
- goto fail;
- }
+static void subtract_timestamp(usec_t *a, usec_t b) {
+ assert(a);
- r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
- if (r < 0) {
- bus_log_parse_error(r);
- goto fail;
+ if (*a > 0) {
+ assert(*a >= b);
+ *a -= b;
}
-
- while ((r = bus_parse_unit_info(reply, &u)) > 0) {
- struct unit_times *t;
-
- if (!GREEDY_REALLOC(unit_times, size, c+1)) {
- r = log_oom();
- goto fail;
- }
-
- t = unit_times+c;
- t->name = NULL;
-
- assert_cc(sizeof(usec_t) == sizeof(uint64_t));
-
- if (bus_get_uint64_property(bus, u.unit_path,
- "org.freedesktop.systemd1.Unit",
- "InactiveExitTimestampMonotonic",
- &t->activating) < 0 ||
- bus_get_uint64_property(bus, u.unit_path,
- "org.freedesktop.systemd1.Unit",
- "ActiveEnterTimestampMonotonic",
- &t->activated) < 0 ||
- bus_get_uint64_property(bus, u.unit_path,
- "org.freedesktop.systemd1.Unit",
- "ActiveExitTimestampMonotonic",
- &t->deactivating) < 0 ||
- bus_get_uint64_property(bus, u.unit_path,
- "org.freedesktop.systemd1.Unit",
- "InactiveEnterTimestampMonotonic",
- &t->deactivated) < 0) {
- r = -EIO;
- goto fail;
- }
-
- if (t->activated >= t->activating)
- t->time = t->activated - t->activating;
- else if (t->deactivated >= t->activating)
- t->time = t->deactivated - t->activating;
- else
- t->time = 0;
-
- if (t->activating == 0)
- continue;
-
- t->name = strdup(u.id);
- if (t->name == NULL) {
- r = log_oom();
- goto fail;
- }
- c++;
- }
- if (r < 0) {
- bus_log_parse_error(r);
- goto fail;
- }
-
- *out = unit_times;
- return c;
-
-fail:
- if (unit_times)
- free_unit_times(unit_times, (unsigned) c);
- return r;
}
static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
@@ -355,10 +285,30 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
return -EINPROGRESS;
}
- if (times.initrd_time)
- times.kernel_done_time = times.initrd_time;
- else
- times.kernel_done_time = times.userspace_time;
+ if (arg_user) {
+ /*
+ * User-instance-specific timestamps processing
+ * (see comment to reverse_offset in struct boot_times).
+ */
+ times.reverse_offset = times.userspace_time;
+
+ times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = times.userspace_time = 0;
+ subtract_timestamp(&times.finish_time, times.reverse_offset);
+
+ subtract_timestamp(&times.security_start_time, times.reverse_offset);
+ subtract_timestamp(&times.security_finish_time, times.reverse_offset);
+
+ subtract_timestamp(&times.generators_start_time, times.reverse_offset);
+ subtract_timestamp(&times.generators_finish_time, times.reverse_offset);
+
+ subtract_timestamp(&times.unitsload_start_time, times.reverse_offset);
+ subtract_timestamp(&times.unitsload_finish_time, times.reverse_offset);
+ } else {
+ if (times.initrd_time)
+ times.kernel_done_time = times.initrd_time;
+ else
+ times.kernel_done_time = times.userspace_time;
+ }
cached = true;
@@ -378,6 +328,107 @@ static void free_host_info(struct host_info *hi) {
free(hi);
}
+static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
+ _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r, c = 0;
+ struct boot_times *boot_times = NULL;
+ struct unit_times *unit_times = NULL;
+ size_t size = 0;
+ UnitInfo u;
+
+ r = acquire_boot_times(bus, &boot_times);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "ListUnits",
+ &error, &reply,
+ NULL);
+ if (r < 0) {
+ log_error("Failed to list units: %s", bus_error_message(&error, -r));
+ goto fail;
+ }
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
+ if (r < 0) {
+ bus_log_parse_error(r);
+ goto fail;
+ }
+
+ while ((r = bus_parse_unit_info(reply, &u)) > 0) {
+ struct unit_times *t;
+
+ if (!GREEDY_REALLOC(unit_times, size, c+1)) {
+ r = log_oom();
+ goto fail;
+ }
+
+ t = unit_times+c;
+ t->name = NULL;
+
+ assert_cc(sizeof(usec_t) == sizeof(uint64_t));
+
+ if (bus_get_uint64_property(bus, u.unit_path,
+ "org.freedesktop.systemd1.Unit",
+ "InactiveExitTimestampMonotonic",
+ &t->activating) < 0 ||
+ bus_get_uint64_property(bus, u.unit_path,
+ "org.freedesktop.systemd1.Unit",
+ "ActiveEnterTimestampMonotonic",
+ &t->activated) < 0 ||
+ bus_get_uint64_property(bus, u.unit_path,
+ "org.freedesktop.systemd1.Unit",
+ "ActiveExitTimestampMonotonic",
+ &t->deactivating) < 0 ||
+ bus_get_uint64_property(bus, u.unit_path,
+ "org.freedesktop.systemd1.Unit",
+ "InactiveEnterTimestampMonotonic",
+ &t->deactivated) < 0) {
+ r = -EIO;
+ goto fail;
+ }
+
+ subtract_timestamp(&t->activating, boot_times->reverse_offset);
+ subtract_timestamp(&t->activated, boot_times->reverse_offset);
+ subtract_timestamp(&t->deactivating, boot_times->reverse_offset);
+ subtract_timestamp(&t->deactivated, boot_times->reverse_offset);
+
+ if (t->activated >= t->activating)
+ t->time = t->activated - t->activating;
+ else if (t->deactivated >= t->activating)
+ t->time = t->deactivated - t->activating;
+ else
+ t->time = 0;
+
+ if (t->activating == 0)
+ continue;
+
+ t->name = strdup(u.id);
+ if (t->name == NULL) {
+ r = log_oom();
+ goto fail;
+ }
+ c++;
+ }
+ if (r < 0) {
+ bus_log_parse_error(r);
+ goto fail;
+ }
+
+ *out = unit_times;
+ return c;
+
+fail:
+ if (unit_times)
+ free_unit_times(unit_times, (unsigned) c);
+ return r;
+}
+
static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
int r;
struct host_info *host;
@@ -450,10 +501,7 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC));
size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
- if (t->kernel_time > 0)
- strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
- else
- strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
+ strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
ptr = strdup(buf);
if (!ptr)
@@ -1331,7 +1379,7 @@ int main(int argc, char *argv[]) {
arg_user ? MANAGER_USER : MANAGER_SYSTEM,
arg_man);
else {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
if (r < 0) {
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
index c79ad6520c..c8961de946 100644
--- a/src/backlight/backlight.c
+++ b/src/backlight/backlight.c
@@ -415,7 +415,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- r = write_string_file(saved, value);
+ r = write_string_file(saved, value, WRITE_STRING_FILE_CREATE);
if (r < 0) {
log_error_errno(r, "Failed to write %s: %m", saved);
return EXIT_FAILURE;
diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c
new file mode 100644
index 0000000000..bf9d8d4d7c
--- /dev/null
+++ b/src/basic/bitmap.c
@@ -0,0 +1,198 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Tom Gundersen
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "util.h"
+
+#include "bitmap.h"
+
+struct Bitmap {
+ uint64_t *bitmaps;
+ size_t n_bitmaps;
+ size_t bitmaps_allocated;
+};
+
+/* Bitmaps are only meant to store relatively small numbers
+ * (corresponding to, say, an enum), so it is ok to limit
+ * the max entry. 64k should be plenty. */
+#define BITMAPS_MAX_ENTRY 0xffff
+
+/* This indicates that we reached the end of the bitmap */
+#define BITMAP_END ((unsigned) -1)
+
+#define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8))
+#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
+#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
+
+Bitmap *bitmap_new(void) {
+ return new0(Bitmap, 1);
+}
+
+void bitmap_free(Bitmap *b) {
+ if (!b)
+ return;
+
+ free(b->bitmaps);
+ free(b);
+}
+
+int bitmap_ensure_allocated(Bitmap **b) {
+ Bitmap *a;
+
+ assert(b);
+
+ if (*b)
+ return 0;
+
+ a = bitmap_new();
+ if (!a)
+ return -ENOMEM;
+
+ *b = a;
+
+ return 0;
+}
+
+int bitmap_set(Bitmap *b, unsigned n) {
+ uint64_t bitmask;
+ unsigned offset;
+
+ assert(b);
+
+ /* we refuse to allocate huge bitmaps */
+ if (n > BITMAPS_MAX_ENTRY)
+ return -ERANGE;
+
+ offset = BITMAP_NUM_TO_OFFSET(n);
+
+ if (offset >= b->n_bitmaps) {
+ if (!GREEDY_REALLOC0(b->bitmaps, b->bitmaps_allocated, offset + 1))
+ return -ENOMEM;
+
+ b->n_bitmaps = offset + 1;
+ }
+
+ bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n);
+
+ b->bitmaps[offset] |= bitmask;
+
+ return 0;
+}
+
+void bitmap_unset(Bitmap *b, unsigned n) {
+ uint64_t bitmask;
+ unsigned offset;
+
+ if (!b)
+ return;
+
+ offset = BITMAP_NUM_TO_OFFSET(n);
+
+ if (offset >= b->n_bitmaps)
+ return;
+
+ bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n);
+
+ b->bitmaps[offset] &= ~bitmask;
+}
+
+bool bitmap_isset(Bitmap *b, unsigned n) {
+ uint64_t bitmask;
+ unsigned offset;
+
+ if (!b)
+ return false;
+
+ offset = BITMAP_NUM_TO_OFFSET(n);
+
+ if (offset >= b->n_bitmaps)
+ return false;
+
+ bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n);
+
+ return !!(b->bitmaps[offset] & bitmask);
+}
+
+bool bitmap_isclear(Bitmap *b) {
+ unsigned i;
+
+ assert(b);
+
+ for (i = 0; i < b->n_bitmaps; i++)
+ if (b->bitmaps[i] != 0)
+ return false;
+
+ return true;
+}
+
+void bitmap_clear(Bitmap *b) {
+ assert(b);
+
+ b->n_bitmaps = 0;
+}
+
+bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) {
+ uint64_t bitmask;
+ unsigned offset, rem;
+
+ assert(i);
+ assert(n);
+
+ if (!b || i->idx == BITMAP_END)
+ return false;
+
+ offset = BITMAP_NUM_TO_OFFSET(i->idx);
+ rem = BITMAP_NUM_TO_REM(i->idx);
+ bitmask = UINT64_C(1) << rem;
+
+ for (; offset < b->n_bitmaps; offset ++) {
+ if (b->bitmaps[offset]) {
+ for (; bitmask; bitmask <<= 1, rem ++) {
+ if (b->bitmaps[offset] & bitmask) {
+ *n = BITMAP_OFFSET_TO_NUM(offset, rem);
+ i->idx = *n + 1;
+
+ return true;
+ }
+ }
+ }
+
+ rem = 0;
+ bitmask = 1;
+ }
+
+ i->idx = BITMAP_END;
+
+ return false;
+}
+
+bool bitmap_equal(Bitmap *a, Bitmap *b) {
+
+ if (!a ^ !b)
+ return false;
+
+ if (!a)
+ return true;
+
+ if (a->n_bitmaps != b->n_bitmaps)
+ return false;
+
+ return memcmp(a->bitmaps, b->bitmaps, sizeof(uint64_t) * a->n_bitmaps) == 0;
+}
diff --git a/src/basic/bitmap.h b/src/basic/bitmap.h
new file mode 100644
index 0000000000..2874bc99f7
--- /dev/null
+++ b/src/basic/bitmap.h
@@ -0,0 +1,50 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Tom Gundersen
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+#include "hashmap.h"
+
+typedef struct Bitmap Bitmap;
+
+Bitmap *bitmap_new(void);
+
+void bitmap_free(Bitmap *b);
+
+int bitmap_ensure_allocated(Bitmap **b);
+
+int bitmap_set(Bitmap *b, unsigned n);
+void bitmap_unset(Bitmap *b, unsigned n);
+bool bitmap_isset(Bitmap *b, unsigned n);
+bool bitmap_isclear(Bitmap *b);
+void bitmap_clear(Bitmap *b);
+
+bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n);
+
+bool bitmap_equal(Bitmap *a, Bitmap *b);
+
+#define BITMAP_FOREACH(n, b, i) \
+ for ((i).idx = 0; bitmap_iterate((b), &(i), (unsigned*)&(n)); )
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Bitmap*, bitmap_free);
+
+#define _cleanup_bitmap_free_ _cleanup_(bitmap_freep)
diff --git a/src/basic/capability.c b/src/basic/capability.c
index 58f00e6dae..8dbe4da5bb 100644
--- a/src/basic/capability.c
+++ b/src/basic/capability.c
@@ -204,7 +204,7 @@ static int drop_from_file(const char *fn, uint64_t drop) {
if (asprintf(&p, "%u %u", lo, hi) < 0)
return -ENOMEM;
- r = write_string_file(fn, p);
+ r = write_string_file(fn, p, WRITE_STRING_FILE_CREATE);
free(p);
return r;
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 439c5516dc..34a3060509 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -646,7 +646,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
snprintf(c, sizeof(c), PID_FMT"\n", pid);
- return write_string_file_no_create(fs, c);
+ return write_string_file(fs, c, 0);
}
int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
@@ -820,7 +820,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
sc = strstrip(contents);
if (sc[0] == 0) {
- r = write_string_file_no_create(fs, agent);
+ r = write_string_file(fs, agent, 0);
if (r < 0)
return r;
} else if (!streq(sc, agent))
@@ -840,7 +840,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
sc = strstrip(contents);
if (streq(sc, "0")) {
- r = write_string_file_no_create(fs, "1");
+ r = write_string_file(fs, "1", 0);
if (r < 0)
return r;
@@ -861,7 +861,7 @@ int cg_uninstall_release_agent(const char *controller) {
if (r < 0)
return r;
- r = write_string_file_no_create(fs, "0");
+ r = write_string_file(fs, "0", 0);
if (r < 0)
return r;
@@ -872,7 +872,7 @@ int cg_uninstall_release_agent(const char *controller) {
if (r < 0)
return r;
- r = write_string_file_no_create(fs, "");
+ r = write_string_file(fs, "", 0);
if (r < 0)
return r;
@@ -1708,7 +1708,7 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri
if (r < 0)
return r;
- return write_string_file_no_create(p, value);
+ return write_string_file(p, value, 0);
}
int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 230e7e4d3f..e2d356d676 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -24,6 +24,7 @@
#include "util.h"
#include "btrfs-util.h"
+#include "strv.h"
#include "copy.h"
#define COPY_BUFFER_SIZE (16*1024)
@@ -262,10 +263,13 @@ static int fd_copy_directory(
(void) copy_xattr(dirfd(d), fdt);
}
- FOREACH_DIRENT(de, d, return -errno) {
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
struct stat buf;
int q;
+ if (STR_IN_SET(de->d_name, ".", ".."))
+ continue;
+
if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) {
r = -errno;
continue;
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
index 5ab36825c0..fcff753ada 100644
--- a/src/basic/exit-status.c
+++ b/src/basic/exit-status.c
@@ -151,6 +151,9 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
case EXIT_BUS_ENDPOINT:
return "BUS_ENDPOINT";
+
+ case EXIT_SMACK_PROCESS_LABEL:
+ return "SMACK_PROCESS_LABEL";
}
}
diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c
index bec988ca78..f596f1d11f 100644
--- a/src/basic/fileio-label.c
+++ b/src/basic/fileio-label.c
@@ -31,7 +31,7 @@ int write_string_file_atomic_label(const char *fn, const char *line) {
if (r < 0)
return r;
- r = write_string_file_atomic(fn, line);
+ r = write_string_file(fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
mac_selinux_create_file_clear();
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index ff6b1a7ed7..2216853777 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -27,14 +27,14 @@
#include "ctype.h"
#include "fileio.h"
-int write_string_stream(FILE *f, const char *line) {
+int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
assert(f);
assert(line);
errno = 0;
fputs(line, f);
- if (!endswith(line, "\n"))
+ if (enforce_newline && !endswith(line, "\n"))
fputc('\n', f);
fflush(f);
@@ -45,42 +45,7 @@ int write_string_stream(FILE *f, const char *line) {
return 0;
}
-int write_string_file(const char *fn, const char *line) {
- _cleanup_fclose_ FILE *f = NULL;
-
- assert(fn);
- assert(line);
-
- f = fopen(fn, "we");
- if (!f)
- return -errno;
-
- return write_string_stream(f, line);
-}
-
-int write_string_file_no_create(const char *fn, const char *line) {
- _cleanup_fclose_ FILE *f = NULL;
- int fd;
-
- assert(fn);
- assert(line);
-
- /* We manually build our own version of fopen(..., "we") that
- * works without O_CREAT */
- fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- f = fdopen(fd, "we");
- if (!f) {
- safe_close(fd);
- return -errno;
- }
-
- return write_string_stream(f, line);
-}
-
-int write_string_file_atomic(const char *fn, const char *line) {
+static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
@@ -94,7 +59,7 @@ int write_string_file_atomic(const char *fn, const char *line) {
fchmod_umask(fileno(f), 0644);
- r = write_string_stream(f, line);
+ r = write_string_stream(f, line, enforce_newline);
if (r >= 0) {
if (rename(p, fn) < 0)
r = -errno;
@@ -106,6 +71,41 @@ int write_string_file_atomic(const char *fn, const char *line) {
return r;
}
+int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
+ _cleanup_fclose_ FILE *f = NULL;
+
+ assert(fn);
+ assert(line);
+
+ if (flags & WRITE_STRING_FILE_ATOMIC) {
+ assert(flags & WRITE_STRING_FILE_CREATE);
+
+ return write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ }
+
+ if (flags & WRITE_STRING_FILE_CREATE) {
+ f = fopen(fn, "we");
+ if (!f)
+ return -errno;
+ } else {
+ int fd;
+
+ /* We manually build our own version of fopen(..., "we") that
+ * works without O_CREAT */
+ fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
+ if (fd < 0)
+ return -errno;
+
+ f = fdopen(fd, "we");
+ if (!f) {
+ safe_close(fd);
+ return -errno;
+ }
+ }
+
+ return write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+}
+
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
char t[LINE_MAX], *c;
@@ -134,6 +134,17 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
+int verify_one_line_file(const char *fn, const char *line) {
+ _cleanup_free_ char *value = NULL;
+ int r;
+
+ r = read_one_line_file(fn, &value);
+ if (r < 0)
+ return r;
+
+ return streq(value, line);
+}
+
int read_full_stream(FILE *f, char **contents, size_t *size) {
size_t n, l;
_cleanup_free_ char *buf = NULL;
@@ -775,7 +786,7 @@ int executable_is_script(const char *path, char **interpreter) {
*/
int get_status_field(const char *filename, const char *pattern, char **field) {
_cleanup_free_ char *status = NULL;
- char *t;
+ char *t, *f;
size_t len;
int r;
@@ -809,9 +820,10 @@ int get_status_field(const char *filename, const char *pattern, char **field) {
len = strcspn(t, WHITESPACE);
- *field = strndup(t, len);
- if (!*field)
+ f = strndup(t, len);
+ if (!f)
return -ENOMEM;
+ *field = f;
return 0;
}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 5ae51c1e28..2e8148ff24 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -25,15 +25,21 @@
#include "macro.h"
-int write_string_stream(FILE *f, const char *line);
-int write_string_file(const char *fn, const char *line);
-int write_string_file_no_create(const char *fn, const char *line);
-int write_string_file_atomic(const char *fn, const char *line);
+typedef enum {
+ WRITE_STRING_FILE_CREATE = 1,
+ WRITE_STRING_FILE_ATOMIC = 2,
+ WRITE_STRING_FILE_AVOID_NEWLINE = 4,
+} WriteStringFileFlags;
+
+int write_string_stream(FILE *f, const char *line, bool enforce_newline);
+int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags);
int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
+int verify_one_line_file(const char *fn, const char *line);
+
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l);
diff --git a/src/basic/macro.h b/src/basic/macro.h
index 5fa17ed208..627d768b76 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/uio.h>
#include <inttypes.h>
+#include <stdbool.h>
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
@@ -406,12 +407,12 @@ do { \
#define IN_SET(x, y, ...) \
({ \
- const typeof(y) _y = (y); \
- const typeof(_y) _x = (x); \
+ static const typeof(y) _array[] = { (y), __VA_ARGS__ }; \
+ const typeof(y) _x = (x); \
unsigned _i; \
bool _found = false; \
- for (_i = 0; _i < 1 + sizeof((const typeof(_x)[]) { __VA_ARGS__ })/sizeof(const typeof(_x)); _i++) \
- if (((const typeof(_x)[]) { _y, __VA_ARGS__ })[_i] == _x) { \
+ for (_i = 0; _i < ELEMENTSOF(_array); _i++) \
+ if (_array[_i] == _x) { \
_found = true; \
break; \
} \
@@ -461,6 +462,18 @@ do { \
#define GID_INVALID ((gid_t) -1)
#define MODE_INVALID ((mode_t) -1)
+static inline bool UID_IS_INVALID(uid_t uid) {
+ /* We consider both the old 16bit -1 user and the newer 32bit
+ * -1 user invalid, since they are or used to be incompatible
+ * with syscalls such as setresuid() or chown(). */
+
+ return uid == (uid_t) ((uint32_t) -1) || uid == (uid_t) ((uint16_t) -1);
+}
+
+static inline bool GID_IS_INVALID(gid_t gid) {
+ return gid == (gid_t) ((uint32_t) -1) || gid == (gid_t) ((uint16_t) -1);
+}
+
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
diff --git a/src/basic/missing.h b/src/basic/missing.h
index be7f6186fc..ed6cd80c75 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -772,7 +772,7 @@ static inline int setns(int fd, int nstype) {
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_IPTUN_6RD_RELAY_PREFIXLEN
+#if !HAVE_DECL_IFLA_IPTUN_ENCAP_DPORT
#define IFLA_IPTUN_UNSPEC 0
#define IFLA_IPTUN_LINK 1
#define IFLA_IPTUN_LOCAL 2
@@ -788,11 +788,41 @@ static inline int setns(int fd, int nstype) {
#define IFLA_IPTUN_6RD_RELAY_PREFIX 12
#define IFLA_IPTUN_6RD_PREFIXLEN 13
#define IFLA_IPTUN_6RD_RELAY_PREFIXLEN 14
-#define __IFLA_IPTUN_MAX 15
+#define IFLA_IPTUN_ENCAP_TYPE 15
+#define IFLA_IPTUN_ENCAP_FLAGS 16
+#define IFLA_IPTUN_ENCAP_SPORT 17
+#define IFLA_IPTUN_ENCAP_DPORT 18
+
+#define __IFLA_IPTUN_MAX 19
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
#endif
+#if !HAVE_DECL_IFLA_GRE_ENCAP_DPORT
+#define IFLA_GRE_UNSPEC 0
+#define IFLA_GRE_LINK 1
+#define IFLA_GRE_IFLAGS 2
+#define IFLA_GRE_OFLAGS 3
+#define IFLA_GRE_IKEY 4
+#define IFLA_GRE_OKEY 5
+#define IFLA_GRE_LOCAL 6
+#define IFLA_GRE_REMOTE 7
+#define IFLA_GRE_TTL 8
+#define IFLA_GRE_TOS 9
+#define IFLA_GRE_PMTUDISC 10
+#define IFLA_GRE_ENCAP_LIMIT 11
+#define IFLA_GRE_FLOWINFO 12
+#define IFLA_GRE_FLAGS 13
+#define IFLA_GRE_ENCAP_TYPE 14
+#define IFLA_GRE_ENCAP_FLAGS 15
+#define IFLA_GRE_ENCAP_SPORT 16
+#define IFLA_GRE_ENCAP_DPORT 17
+
+#define __IFLA_GRE_MAX 18
+
+#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1)
+#endif
+
#if !HAVE_DECL_IFLA_BRIDGE_VLAN_INFO
#define IFLA_BRIDGE_FLAGS 0
#define IFLA_BRIDGE_MODE 1
@@ -802,7 +832,7 @@ static inline int setns(int fd, int nstype) {
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_BRPORT_UNICAST_FLOOD
+#if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC
#define IFLA_BRPORT_UNSPEC 0
#define IFLA_BRPORT_STATE 1
#define IFLA_BRPORT_PRIORITY 2
@@ -813,7 +843,9 @@ static inline int setns(int fd, int nstype) {
#define IFLA_BRPORT_FAST_LEAVE 7
#define IFLA_BRPORT_LEARNING 8
#define IFLA_BRPORT_UNICAST_FLOOD 9
-#define __IFLA_BRPORT_MAX 10
+#define IFLA_BRPORT_PROXYARP 10
+#define IFLA_BRPORT_LEARNING_SYNC 11
+#define __IFLA_BRPORT_MAX 12
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
#endif
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 537705446a..5cbfc145a4 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -528,7 +528,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
*
* If that didn't work we will try to read the mount id from
* /proc/self/fdinfo/<fd>. This is almost as good as
- * name_to_handle_at(), however, does not return the the
+ * name_to_handle_at(), however, does not return the
* opaque file handle. The opaque file handle is pretty useful
* to detect the root directory, which we should always
* consider a mount point. Hence we use this only as
@@ -656,9 +656,11 @@ int path_is_mount_point(const char *t, int flags) {
canonical = canonicalize_file_name(t);
if (!canonical)
return -errno;
+
+ t = canonical;
}
- r = path_get_parent(canonical ?: t, &parent);
+ r = path_get_parent(t, &parent);
if (r < 0)
return r;
@@ -666,7 +668,7 @@ int path_is_mount_point(const char *t, int flags) {
if (fd < 0)
return -errno;
- return fd_is_mount_point(fd, basename(canonical ?: t), flags);
+ return fd_is_mount_point(fd, basename(t), flags);
}
int path_is_read_only_fs(const char *path) {
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index cfc876567d..61f188467f 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -43,7 +43,10 @@ int get_process_state(pid_t pid) {
assert(pid >= 0);
p = procfs_file_alloca(pid, "stat");
+
r = read_one_line_file(p, &line);
+ if (r == -ENOENT)
+ return -ESRCH;
if (r < 0)
return r;
@@ -87,8 +90,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
p = procfs_file_alloca(pid, "cmdline");
f = fopen(p, "re");
- if (!f)
+ if (!f) {
+ if (errno == ENOENT)
+ return -ESRCH;
return -errno;
+ }
if (max_length == 0) {
size_t len = 0, allocated = 0;
@@ -182,8 +188,11 @@ int is_kernel_thread(pid_t pid) {
p = procfs_file_alloca(pid, "cmdline");
f = fopen(p, "re");
- if (!f)
+ if (!f) {
+ if (errno == ENOENT)
+ return -ESRCH;
return -errno;
+ }
count = fread(&c, 1, 1, f);
eof = feof(f);
@@ -199,13 +208,18 @@ int is_kernel_thread(pid_t pid) {
int get_process_capeff(pid_t pid, char **capeff) {
const char *p;
+ int r;
assert(capeff);
assert(pid >= 0);
p = procfs_file_alloca(pid, "status");
- return get_status_field(p, "\nCapEff:", capeff);
+ r = get_status_field(p, "\nCapEff:", capeff);
+ if (r == -ENOENT)
+ return -ESRCH;
+
+ return r;
}
static int get_process_link_contents(const char *proc_file, char **name) {
@@ -215,8 +229,10 @@ static int get_process_link_contents(const char *proc_file, char **name) {
assert(name);
r = readlink_malloc(proc_file, name);
+ if (r == -ENOENT)
+ return -ESRCH;
if (r < 0)
- return r == -ENOENT ? -ESRCH : r;
+ return r;
return 0;
}
@@ -253,8 +269,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
p = procfs_file_alloca(pid, "status");
f = fopen(p, "re");
- if (!f)
+ if (!f) {
+ if (errno == ENOENT)
+ return -ESRCH;
return -errno;
+ }
FOREACH_LINE(line, f, return -errno) {
char *l;
@@ -316,8 +335,11 @@ int get_process_environ(pid_t pid, char **env) {
p = procfs_file_alloca(pid, "environ");
f = fopen(p, "re");
- if (!f)
+ if (!f) {
+ if (errno == ENOENT)
+ return -ESRCH;
return -errno;
+ }
while ((c = fgetc(f)) != EOF) {
if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
@@ -329,7 +351,13 @@ int get_process_environ(pid_t pid, char **env) {
sz += cescape_char(c, outcome + sz);
}
- outcome[sz] = '\0';
+ if (!outcome) {
+ outcome = strdup("");
+ if (!outcome)
+ return -ENOMEM;
+ } else
+ outcome[sz] = '\0';
+
*env = outcome;
outcome = NULL;
@@ -352,6 +380,8 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
p = procfs_file_alloca(pid, "stat");
r = read_one_line_file(p, &line);
+ if (r == -ENOENT)
+ return -ESRCH;
if (r < 0)
return r;
@@ -472,8 +502,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
path = procfs_file_alloca(pid, "environ");
f = fopen(path, "re");
- if (!f)
+ if (!f) {
+ if (errno == ENOENT)
+ return -ESRCH;
return -errno;
+ }
l = strlen(field);
r = 0;
@@ -532,7 +565,7 @@ bool pid_is_alive(pid_t pid) {
return false;
r = get_process_state(pid);
- if (r == -ENOENT || r == 'Z')
+ if (r == -ESRCH || r == 'Z')
return false;
return true;
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index 2e24b1ea99..047aa294f4 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -139,7 +139,7 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
return 0;
p = procfs_file_alloca(pid, "attr/current");
- r = write_string_file(p, label);
+ r = write_string_file(p, label, 0);
if (r < 0)
return r;
#endif
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index cbe3ff216e..144e6fd86e 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -38,6 +38,7 @@ int socket_address_listen(
int backlog,
SocketAddressBindIPv6Only only,
const char *bind_to_device,
+ bool reuse_port,
bool free_bind,
bool transparent,
mode_t directory_mode,
@@ -83,6 +84,12 @@ int socket_address_listen(
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
return -errno;
+ if (reuse_port) {
+ one = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
+ log_warning_errno(errno, "SO_REUSEPORT failed: %m");
+ }
+
if (free_bind) {
one = 1;
if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
@@ -146,7 +153,7 @@ int make_socket_fd(int log_level, const char* address, int flags) {
}
fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
- NULL, false, false, 0755, 0644, NULL);
+ NULL, false, false, false, 0755, 0644, NULL);
if (fd < 0 || log_get_max_level() >= log_level) {
_cleanup_free_ char *p = NULL;
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 538cf59174..6b0ce7836f 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -80,6 +80,7 @@ int socket_address_listen(
int backlog,
SocketAddressBindIPv6Only only,
const char *bind_to_device,
+ bool reuse_port,
bool free_bind,
bool transparent,
mode_t directory_mode,
diff --git a/src/basic/util.c b/src/basic/util.c
index 727be56f58..1c15fbc172 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -916,32 +916,573 @@ char *hexmem(const void *p, size_t l) {
return r;
}
-void *unhexmem(const char *p, size_t l) {
- uint8_t *r, *z;
+int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
+ _cleanup_free_ uint8_t *r = NULL;
+ uint8_t *z;
const char *x;
+ assert(mem);
+ assert(len);
assert(p);
z = r = malloc((l + 1) / 2 + 1);
if (!r)
- return NULL;
+ return -ENOMEM;
for (x = p; x < p + l; x += 2) {
int a, b;
a = unhexchar(x[0]);
- if (x+1 < p + l)
+ if (a < 0)
+ return a;
+ else if (x+1 < p + l) {
b = unhexchar(x[1]);
- else
+ if (b < 0)
+ return b;
+ } else
b = 0;
*(z++) = (uint8_t) a << 4 | (uint8_t) b;
}
*z = 0;
+
+ *mem = r;
+ r = NULL;
+ *len = (l + 1) / 2;
+
+ return 0;
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-6
+ * Notice that base32hex differs from base32 in the alphabet it uses.
+ * The distinction is that the base32hex representation preserves the
+ * order of the underlying data when compared as bytestrings, this is
+ * useful when representing NSEC3 hashes, as one can then verify the
+ * order of hashes directly from their representation. */
+char base32hexchar(int x) {
+ static const char table[32] = "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUV";
+
+ return table[x & 31];
+}
+
+int unbase32hexchar(char c) {
+ unsigned offset;
+
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ offset = '9' - '0' + 1;
+
+ if (c >= 'A' && c <= 'V')
+ return c - 'A' + offset;
+
+ return -EINVAL;
+}
+
+char *base32hexmem(const void *p, size_t l, bool padding) {
+ char *r, *z;
+ const uint8_t *x;
+ size_t len;
+
+ if (padding)
+ /* five input bytes makes eight output bytes, padding is added so we must round up */
+ len = 8 * (l + 4) / 5;
+ else {
+ /* same, but round down as there is no padding */
+ len = 8 * l / 5;
+
+ switch (l % 5) {
+ case 4:
+ len += 7;
+ break;
+ case 3:
+ len += 5;
+ break;
+ case 2:
+ len += 4;
+ break;
+ case 1:
+ len += 2;
+ break;
+ }
+ }
+
+ z = r = malloc(len + 1);
+ if (!r)
+ return NULL;
+
+ for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
+ /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
+ x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
+ *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
+ *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
+ *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
+ *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
+ }
+
+ switch (l % 5) {
+ case 4:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
+ *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
+ *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
+ *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
+ if (padding)
+ *(z++) = '=';
+
+ break;
+
+ case 3:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
+ *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
+ if (padding) {
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ }
+
+ break;
+
+ case 2:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
+ if (padding) {
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ }
+
+ break;
+
+ case 1:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
+ if (padding) {
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ }
+
+ break;
+ }
+
+ *z = 0;
+ return r;
+}
+
+int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
+ _cleanup_free_ uint8_t *r = NULL;
+ int a, b, c, d, e, f, g, h;
+ uint8_t *z;
+ const char *x;
+ size_t len;
+ unsigned pad = 0;
+
+ assert(p);
+
+ /* padding ensures any base32hex input has input divisible by 8 */
+ if (padding && l % 8 != 0)
+ return -EINVAL;
+
+ if (padding) {
+ /* strip the padding */
+ while (l > 0 && p[l - 1] == '=' && pad < 7) {
+ pad ++;
+ l --;
+ }
+ }
+
+ /* a group of eight input bytes needs five output bytes, in case of
+ padding we need to add some extra bytes */
+ len = (l / 8) * 5;
+
+ switch (l % 8) {
+ case 7:
+ len += 4;
+ break;
+ case 5:
+ len += 3;
+ break;
+ case 4:
+ len += 2;
+ break;
+ case 2:
+ len += 1;
+ break;
+ case 0:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ z = r = malloc(len + 1);
+ if (!r)
+ return -ENOMEM;
+
+ for (x = p; x < p + (l / 8) * 8; x += 8) {
+ /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
+ e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ e = unbase32hexchar(x[4]);
+ if (e < 0)
+ return -EINVAL;
+
+ f = unbase32hexchar(x[5]);
+ if (f < 0)
+ return -EINVAL;
+
+ g = unbase32hexchar(x[6]);
+ if (g < 0)
+ return -EINVAL;
+
+ h = unbase32hexchar(x[7]);
+ if (h < 0)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
+ *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
+ *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
+ }
+
+ switch (l % 8) {
+ case 7:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ e = unbase32hexchar(x[4]);
+ if (e < 0)
+ return -EINVAL;
+
+ f = unbase32hexchar(x[5]);
+ if (f < 0)
+ return -EINVAL;
+
+ g = unbase32hexchar(x[6]);
+ if (g < 0)
+ return -EINVAL;
+
+ /* g == 000VV000 */
+ if (g & 7)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
+ *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
+
+ break;
+ case 5:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ e = unbase32hexchar(x[4]);
+ if (e < 0)
+ return -EINVAL;
+
+ /* e == 000SSSS0 */
+ if (e & 1)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
+
+ break;
+ case 4:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ /* d == 000W0000 */
+ if (d & 15)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+
+ break;
+ case 2:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ /* b == 000YYY00 */
+ if (b & 3)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+
+ break;
+ case 0:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *z = 0;
+
+ *mem = r;
+ r = NULL;
+ *_len = len;
+
+ return 0;
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-4 */
+char base64char(int x) {
+ static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ return table[x & 63];
+}
+
+int unbase64char(char c) {
+ unsigned offset;
+
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A';
+
+ offset = 'Z' - 'A' + 1;
+
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + offset;
+
+ offset += 'z' - 'a' + 1;
+
+ if (c >= '0' && c <= '9')
+ return c - '0' + offset;
+
+ offset += '9' - '0' + 1;
+
+ if (c == '+')
+ return offset;
+
+ offset ++;
+
+ if (c == '/')
+ return offset;
+
+ return -EINVAL;
+}
+
+char *base64mem(const void *p, size_t l) {
+ char *r, *z;
+ const uint8_t *x;
+
+ /* three input bytes makes four output bytes, padding is added so we must round up */
+ z = r = malloc(4 * (l + 2) / 3 + 1);
+ if (!r)
+ return NULL;
+
+ for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
+ /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
+ *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
+ *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
+ }
+
+ switch (l % 3) {
+ case 2:
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
+ *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
+ *(z++) = '=';
+
+ break;
+ case 1:
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
+ *(z++) = '=';
+ *(z++) = '=';
+
+ break;
+ }
+
+ *z = 0;
return r;
}
+int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
+ _cleanup_free_ uint8_t *r = NULL;
+ int a, b, c, d;
+ uint8_t *z;
+ const char *x;
+ size_t len;
+
+ assert(p);
+
+ /* padding ensures any base63 input has input divisible by 4 */
+ if (l % 4 != 0)
+ return -EINVAL;
+
+ /* strip the padding */
+ if (l > 0 && p[l - 1] == '=')
+ l --;
+ if (l > 0 && p[l - 1] == '=')
+ l --;
+
+ /* a group of four input bytes needs three output bytes, in case of
+ padding we need to add two or three extra bytes */
+ len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
+
+ z = r = malloc(len + 1);
+ if (!r)
+ return -ENOMEM;
+
+ for (x = p; x < p + (l / 4) * 4; x += 4) {
+ /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
+ a = unbase64char(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase64char(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase64char(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase64char(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
+ }
+
+ switch (l % 4) {
+ case 3:
+ a = unbase64char(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase64char(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase64char(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ /* c == 00ZZZZ00 */
+ if (c & 3)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+
+ break;
+ case 2:
+ a = unbase64char(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase64char(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ /* b == 00YY0000 */
+ if (b & 15)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
+
+ break;
+ case 0:
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *z = 0;
+
+ *mem = r;
+ r = NULL;
+ *_len = len;
+
+ return 0;
+}
+
char octchar(int x) {
return '0' + (x & 7);
}
@@ -2533,8 +3074,9 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
f = fdopen(fd, "we");
if (!f) {
- unlink(t);
+ unlink_noerrno(t);
free(t);
+ safe_close(fd);
return -errno;
}
@@ -3627,7 +4169,7 @@ bool string_is_safe(const char *p) {
if (*t > 0 && *t < ' ')
return false;
- if (strchr("\\\"\'\0x7f", *t))
+ if (strchr("\\\"\'\x7f", *t))
return false;
}
@@ -4716,7 +5258,7 @@ int update_reboot_param_file(const char *param) {
if (param) {
- r = write_string_file(REBOOT_PARAM_FILE, param);
+ r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
if (r < 0)
log_error("Failed to write reboot param to "
REBOOT_PARAM_FILE": %s", strerror(-r));
@@ -5192,13 +5734,19 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
case VALUE:
if (c == 0)
goto finish;
- else if (c == '\'')
+ else if (c == '\'') {
+ if (!GREEDY_REALLOC(s, allocated, sz+1))
+ return -ENOMEM;
+
state = SINGLE_QUOTE;
- else if (c == '\\')
+ } else if (c == '\\')
state = VALUE_ESCAPE;
- else if (c == '\"')
+ else if (c == '\"') {
+ if (!GREEDY_REALLOC(s, allocated, sz+1))
+ return -ENOMEM;
+
state = DOUBLE_QUOTE;
- else if (strchr(WHITESPACE, c))
+ } else if (strchr(WHITESPACE, c))
state = SPACE;
else {
if (!GREEDY_REALLOC(s, allocated, sz+2))
@@ -5925,10 +6473,9 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
if (ret >= 0)
return 0;
- /* Even though renameat2() exists since Linux 3.15, btrfs added
- * support for it later. If it is not implemented, fallback to another
- * method. */
- if (errno != EINVAL)
+ /* renameat2() exists since Linux 3.15, btrfs added support for it later.
+ * If it is not implemented, fallback to another method. */
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
/* The link()/unlink() fallback does not work on directories. But
diff --git a/src/basic/util.h b/src/basic/util.h
index a1d1dd15c3..c2e5cc610b 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -240,6 +240,10 @@ char octchar(int x) _const_;
int unoctchar(char c) _const_;
char decchar(int x) _const_;
int undecchar(char c) _const_;
+char base32hexchar(int x) _const_;
+int unbase32hexchar(char c) _const_;
+char base64char(int x) _const_;
+int unbase64char(char c) _const_;
char *cescape(const char *s);
size_t cescape_char(char c, char *buf);
@@ -614,7 +618,13 @@ static inline void *mempset(void *s, int c, size_t n) {
}
char *hexmem(const void *p, size_t l);
-void *unhexmem(const char *p, size_t l);
+int unhexmem(const char *p, size_t l, void **mem, size_t *len);
+
+char *base32hexmem(const void *p, size_t l, bool padding);
+int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
+
+char *base64mem(const void *p, size_t l);
+int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
char *strextend(char **x, ...) _sentinel_;
char *strrep(const char *s, unsigned n);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 1299a75ed5..a8d26716a1 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -188,7 +188,7 @@ int detect_vm(const char **id) {
_cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
static thread_local int cached_found = -1;
static thread_local const char *cached_id = NULL;
- const char *_id = NULL;
+ const char *_id = NULL, *_id_cpuid = NULL;
int r;
if (_likely_(cached_found >= 0)) {
@@ -234,10 +234,26 @@ int detect_vm(const char **id) {
/* this will set _id to "other" and return 0 for unknown hypervisors */
r = detect_vm_cpuid(&_id);
- if (r != 0)
+
+ /* finish when found a known hypervisor other than kvm */
+ if (r < 0 || (r > 0 && !streq(_id, "kvm")))
goto finish;
+ _id_cpuid = _id;
+
r = detect_vm_dmi(&_id);
+
+ /* kvm with and without Virtualbox */
+ if (streq_ptr(_id_cpuid, "kvm")) {
+ if (r > 0 && streq(_id, "oracle"))
+ goto finish;
+
+ _id = _id_cpuid;
+ r = 1;
+ goto finish;
+ }
+
+ /* information from dmi */
if (r != 0)
goto finish;
diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
index 6028ed68c0..1e216f52bd 100644
--- a/src/binfmt/binfmt.c
+++ b/src/binfmt/binfmt.c
@@ -53,7 +53,7 @@ static int delete_rule(const char *rule) {
if (!fn)
return log_oom();
- return write_string_file(fn, "-1");
+ return write_string_file(fn, "-1", 0);
}
static int apply_rule(const char *rule) {
@@ -61,7 +61,7 @@ static int apply_rule(const char *rule) {
delete_rule(rule);
- r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule);
+ r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
if (r < 0)
return log_error_errno(r, "Failed to add binary format: %m");
@@ -191,7 +191,7 @@ int main(int argc, char *argv[]) {
}
/* Flush out all rules */
- write_string_file("/proc/sys/fs/binfmt_misc/status", "-1");
+ write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
STRV_FOREACH(f, files) {
k = apply_file(*f, true);
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 1e65597acf..091ea375d3 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -294,6 +294,8 @@ static int status_binaries(const char *esp_path, sd_id128_t partition) {
else if (r < 0)
return r;
+ printf("\n");
+
return 0;
}
@@ -888,7 +890,7 @@ static int install_loader_config(const char *esp_path) {
f = fopen("/etc/machine-id", "re");
if (!f)
- return -errno;
+ return errno == ENOENT ? 0 : -errno;
if (fgets(line, sizeof(line), f) != NULL) {
char *s;
@@ -918,7 +920,7 @@ static int install_loader_config(const char *esp_path) {
static int help(void) {
printf("%s [COMMAND] [OPTIONS...]\n"
"\n"
- "Install, update or remove the sdboot EFI boot manager.\n\n"
+ "Install, update or remove the systemd-boot EFI boot manager.\n\n"
" -h --help Show this help\n"
" --version Print version\n"
" --path=PATH Path to the EFI System Partition (ESP)\n"
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index eb1a4e3b66..e8cd8abd26 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -1495,6 +1495,7 @@ static VOID config_entry_add_osx(Config *config) {
static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_image, EFI_FILE *root_dir) {
EFI_FILE_HANDLE linux_dir;
EFI_STATUS err;
+ ConfigEntry *entry;
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL);
if (!EFI_ERROR(err)) {
@@ -1504,6 +1505,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
EFI_FILE_INFO *f;
CHAR8 *sections[] = {
(UINT8 *)".osrel",
+ (UINT8 *)".cmdline",
NULL
};
UINTN offs[ELEMENTSOF(sections)-1] = {};
@@ -1517,6 +1519,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
CHAR16 *os_name = NULL;
CHAR16 *os_id = NULL;
CHAR16 *os_version = NULL;
+ CHAR16 *os_build = NULL;
bufsize = sizeof(buf);
err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf);
@@ -1534,7 +1537,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
if (StriCmp(f->FileName + len - 4, L".efi") != 0)
continue;
- /* look for an .osrel section in the .efi binary */
+ /* look for .osrel and .cmdline sections in the .efi binary */
err = pefile_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
if (EFI_ERROR(err))
continue;
@@ -1547,35 +1550,56 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
line = content;
while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) {
+ FreePool(os_name);
os_name = stra_to_str(value);
continue;
}
if (strcmpa((CHAR8 *)"ID", key) == 0) {
+ FreePool(os_id);
os_id = stra_to_str(value);
continue;
}
if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) {
+ FreePool(os_version);
os_version = stra_to_str(value);
continue;
}
+
+ if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) {
+ FreePool(os_build);
+ os_build = stra_to_str(value);
+ continue;
+ }
}
- if (os_name && os_id && os_version) {
+ if (os_name && os_id && (os_version || os_build)) {
CHAR16 *conf;
CHAR16 *path;
+ CHAR16 *cmdline;
- conf = PoolPrint(L"%s-%s", os_id, os_version);
+ conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build);
path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
- config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
+ entry = config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
+
+ FreePool(content);
+ /* read the embedded cmdline file */
+ len = file_read(linux_dir, f->FileName, offs[1], szs[1] - 1 , &content);
+ if (len > 0) {
+ cmdline = stra_to_str(content);
+ entry->options = cmdline;
+ cmdline = NULL;
+ }
+ FreePool(cmdline);
FreePool(conf);
FreePool(path);
- FreePool(os_name);
- FreePool(os_id);
- FreePool(os_version);
}
+ FreePool(os_name);
+ FreePool(os_id);
+ FreePool(os_version);
+ FreePool(os_build);
FreePool(content);
}
uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 3360bc85be..1625d51fa8 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -387,9 +387,6 @@ int main(int argc, char *argv[]) {
for (samples = 0; !exiting && samples < arg_samples_len; samples++) {
int res;
double sample_stop;
- struct timespec req;
- time_t newint_s;
- long newint_ns;
double elapsed;
double timeleft;
@@ -427,18 +424,17 @@ int main(int argc, char *argv[]) {
elapsed = (sample_stop - sampledata->sampletime) * 1000000000.0;
timeleft = interval - elapsed;
- newint_s = (time_t)(timeleft / 1000000000.0);
- newint_ns = (long)(timeleft - (newint_s * 1000000000.0));
-
/*
* check if we have not consumed our entire timeslice. If we
* do, don't sleep and take a new sample right away.
* we'll lose all the missed samples and overrun our total
* time
*/
- if (newint_ns > 0 || newint_s > 0) {
- req.tv_sec = newint_s;
- req.tv_nsec = newint_ns;
+ if (timeleft > 0) {
+ struct timespec req;
+
+ req.tv_sec = (time_t)(timeleft / 1000000000.0);
+ req.tv_nsec = (long)(timeleft - (req.tv_sec * 1000000000.0));
res = nanosleep(&req, NULL);
if (res) {
@@ -452,7 +448,7 @@ int main(int argc, char *argv[]) {
} else {
overrun++;
/* calculate how many samples we lost and scrap them */
- arg_samples_len -= (int)(newint_ns / interval);
+ arg_samples_len -= (int)(-timeleft / interval);
}
LIST_PREPEND(link, head, sampledata);
}
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index 00439f0409..caa97b97fc 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -37,6 +37,7 @@
#include "store.h"
#include "bootchart.h"
#include "cgroup-util.h"
+#include "fileio.h"
/*
* Alloc a static 4k buffer for stdio - primarily used to increase
@@ -97,13 +98,14 @@ int log_sample(DIR *proc,
int *cpus) {
static int vmstat = -1;
- static int schedstat = -1;
+ _cleanup_free_ char *buf_schedstat = NULL;
char buf[4096];
char key[256];
char val[256];
char rt[256];
char wt[256];
char *m;
+ int r;
int c;
int p;
int mod;
@@ -156,27 +158,13 @@ vmstat_next:
break;
}
- if (schedstat < 0) {
- /* overall CPU utilization */
- schedstat = openat(procfd, "schedstat", O_RDONLY|O_CLOEXEC);
- if (schedstat < 0)
- return log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
- }
+ /* Parse "/proc/schedstat" for overall CPU utilization */
+ r = read_full_file("/proc/schedstat", &buf_schedstat, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Unable to read schedstat: %m");
- n = pread(schedstat, buf, sizeof(buf) - 1, 0);
- if (n <= 0) {
- schedstat = safe_close(schedstat);
- if (n < 0)
- return -errno;
- return -ENODATA;
- }
-
- buf[n] = '\0';
-
- m = buf;
+ m = buf_schedstat;
while (m) {
- int r;
-
if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3)
goto schedstat_next;
@@ -238,7 +226,6 @@ schedstat_next:
_cleanup_fclose_ FILE *st = NULL;
char t[32];
struct ps_struct *parent;
- int r;
ps->next_ps = new0(struct ps_struct, 1);
if (!ps->next_ps)
@@ -427,7 +414,6 @@ schedstat_next:
return -errno;
}
FOREACH_DIRENT(ent, taskdir, break) {
- int r;
int tid = -1;
_cleanup_close_ int tid_schedstat = -1;
long long delta_rt;
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index f442200b66..a7ef653d5d 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -76,8 +76,6 @@ static void svg_header(FILE *of, struct list_sample_data *head, double graph_sta
assert(head);
- sampledata = head;
- LIST_FIND_TAIL(link, sampledata, head);
sampledata_last = head;
LIST_FOREACH_BEFORE(link, sampledata, head) {
sampledata_last = sampledata;
@@ -174,7 +172,7 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start,
r = read_one_line_file(filename, &model);
if (r < 0)
- log_warning("Error reading disk model for %s: %m\n", rootbdev);
+ log_info("Error reading disk model for %s: %m\n", rootbdev);
}
/* various utsname parameters */
@@ -210,7 +208,8 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start,
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
uts.sysname, uts.release, uts.version, uts.machine);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu);
- fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
+ if (model)
+ fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build);
fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
@@ -1296,6 +1295,8 @@ int svg_do(FILE *of,
double offset = 7;
int r, c;
+ sampledata = head;
+ LIST_FIND_TAIL(link, sampledata, head);
ps = ps_first;
/* count initcall thread count first */
diff --git a/src/bus-proxyd/driver.c b/src/bus-proxyd/driver.c
index 4ac955da41..1cb5ea5008 100644
--- a/src/bus-proxyd/driver.c
+++ b/src/bus-proxyd/driver.c
@@ -33,6 +33,7 @@
#include "strv.h"
#include "set.h"
#include "driver.h"
+#include "proxy.h"
#include "synthesize.h"
static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
@@ -70,7 +71,7 @@ static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, s
return get_creds_by_name(bus, name, mask, _creds, error);
}
-int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
+int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
int r;
assert(a);
@@ -189,7 +190,7 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
- r = sd_bus_add_match(a, NULL, match, NULL, NULL);
+ r = sd_bus_add_match(a, NULL, match, proxy_match, p);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
diff --git a/src/bus-proxyd/driver.h b/src/bus-proxyd/driver.h
index b8cedf5ce5..da3834f8b0 100644
--- a/src/bus-proxyd/driver.h
+++ b/src/bus-proxyd/driver.h
@@ -23,5 +23,6 @@
#include "sd-bus.h"
#include "bus-xml-policy.h"
+#include "proxy.h"
-int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names);
+int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names);
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c
index 28ab1c97fc..c37b09b9c0 100644
--- a/src/bus-proxyd/proxy.c
+++ b/src/bus-proxyd/proxy.c
@@ -45,7 +45,7 @@
#include "formats-util.h"
static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
- _cleanup_bus_close_unref_ sd_bus *b = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
int r;
r = sd_bus_new(&b);
@@ -101,7 +101,7 @@ static int proxy_create_destination(Proxy *p, const char *destination, const cha
}
static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) {
- _cleanup_bus_close_unref_ sd_bus *b = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
sd_id128_t server_id;
int r;
@@ -144,6 +144,18 @@ static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fd
return 0;
}
+static int proxy_match_synthetic(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ Proxy *p = userdata;
+
+ p->synthetic_matched = true;
+ return 0; /* make sure to continue processing it in further handlers */
+}
+
+/*
+ * We always need NameOwnerChanged so we can synthesize NameLost and
+ * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
+ * subscribe unconditionally.
+ */
static int proxy_prepare_matches(Proxy *p) {
_cleanup_free_ char *match = NULL;
const char *unique;
@@ -168,7 +180,7 @@ static int proxy_prepare_matches(Proxy *p) {
if (!match)
return log_oom();
- r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL);
+ r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
if (r < 0)
return log_error_errno(r, "Failed to add match for NameLost: %m");
@@ -185,10 +197,24 @@ static int proxy_prepare_matches(Proxy *p) {
if (!match)
return log_oom();
- r = sd_bus_add_match(p->destination_bus, NULL, match, NULL, NULL);
+ r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
if (r < 0)
return log_error_errno(r, "Failed to add match for NameAcquired: %m");
+ free(match);
+ match = strjoin("type='signal',"
+ "destination='",
+ unique,
+ "'",
+ NULL);
+ if (!match)
+ return log_oom();
+
+ r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
+ if (r < 0)
+ log_error_errno(r, "Failed to add match for directed signals: %m");
+ /* FIXME: temporarily ignore error to support older kdbus versions */
+
return 0;
}
@@ -238,8 +264,8 @@ Proxy *proxy_free(Proxy *p) {
if (!p)
return NULL;
- sd_bus_close_unrefp(&p->local_bus);
- sd_bus_close_unrefp(&p->destination_bus);
+ sd_bus_flush_close_unref(p->local_bus);
+ sd_bus_flush_close_unref(p->destination_bus);
set_free_free(p->owned_names);
free(p);
@@ -494,7 +520,16 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m,
}
/* First check if we (the sender) can send to this name */
- if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
+ if (sd_bus_message_is_signal(m, NULL, NULL)) {
+ /* If we forward a signal from dbus-1 to kdbus, we have
+ * no idea who the recipient is. Therefore, we cannot
+ * apply any dbus-1 policies that match on receiver
+ * credentials. We know sd-bus always sets
+ * KDBUS_MSG_SIGNAL, so the kernel applies policies to
+ * the message. Therefore, skip policy checks in this
+ * case. */
+ return 0;
+ } else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
if (n) {
/* If we made a receiver decision, then remember which
* name's policy we used, and to which unique ID it
@@ -512,19 +547,8 @@ static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m,
return r;
}
- if (sd_bus_message_is_signal(m, NULL, NULL)) {
- /* If we forward a signal from dbus-1 to kdbus,
- * we have no idea who the recipient is.
- * Therefore, we cannot apply any dbus-1
- * receiver policies that match on receiver
- * credentials. We know sd-bus always sets
- * KDBUS_MSG_SIGNAL, so the kernel applies
- * receiver policies to the message. Therefore,
- * skip policy checks in this case. */
+ if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
return 0;
- } else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) {
- return 0;
- }
}
/* Return an error back to the caller */
@@ -663,11 +687,28 @@ static int patch_sender(sd_bus *a, sd_bus_message *m) {
static int proxy_process_destination_to_local(Proxy *p) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ bool matched, matched_synthetic;
int r;
assert(p);
+ /*
+ * Usually, we would just take any message that the bus passes to us
+ * and forward it to the local connection. However, there are actually
+ * applications that fail if they receive broadcasts that they didn't
+ * subscribe to. Therefore, we actually emulate a real broadcast
+ * matching here, and discard any broadcasts that weren't matched. Our
+ * match-handlers remembers whether a message was matched by any rule,
+ * by marking it in @p->message_matched.
+ */
+
r = sd_bus_process(p->destination_bus, &m);
+
+ matched = p->message_matched;
+ matched_synthetic = p->synthetic_matched;
+ p->message_matched = false;
+ p->synthetic_matched = false;
+
if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
return r;
if (r < 0) {
@@ -683,12 +724,21 @@ static int proxy_process_destination_to_local(Proxy *p) {
if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
return -ECONNRESET;
- r = synthesize_name_acquired(p->destination_bus, p->local_bus, m);
+ r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
return log_error_errno(r, "Failed to synthesize message: %m");
+ /* discard broadcasts that were not matched by any MATCH rule */
+ if (!matched && !sd_bus_message_get_destination(m)) {
+ if (!matched_synthetic)
+ log_debug("Dropped unmatched broadcast: uid=" UID_FMT " gid=" GID_FMT " pid=" PID_FMT " message=%s path=%s interface=%s member=%s sender=%s destination=%s",
+ p->local_creds.uid, p->local_creds.gid, p->local_creds.pid, bus_message_type_to_string(m->header->type),
+ strna(m->path), strna(m->interface), strna(m->member), strna(m->sender), strna(m->destination));
+ return 1;
+ }
+
patch_sender(p->destination_bus, m);
if (p->policy) {
@@ -772,7 +822,7 @@ static int proxy_process_local_to_destination(Proxy *p) {
if (r > 0)
return 1;
- r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
+ r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
if (r == -ECONNRESET || r == -ENOTCONN)
return r;
if (r < 0)
@@ -818,6 +868,13 @@ static int proxy_process_local_to_destination(Proxy *p) {
return 1;
}
+int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ Proxy *p = userdata;
+
+ p->message_matched = true;
+ return 0; /* make sure to continue processing it in further handlers */
+}
+
int proxy_run(Proxy *p) {
int r;
diff --git a/src/bus-proxyd/proxy.h b/src/bus-proxyd/proxy.h
index ff278a2465..ccb951c109 100644
--- a/src/bus-proxyd/proxy.h
+++ b/src/bus-proxyd/proxy.h
@@ -39,6 +39,8 @@ struct Proxy {
bool got_hello : 1;
bool queue_overflow : 1;
+ bool message_matched : 1;
+ bool synthetic_matched : 1;
};
int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest);
@@ -46,6 +48,7 @@ Proxy *proxy_free(Proxy *p);
int proxy_set_policy(Proxy *p, SharedPolicy *policy, char **configuration);
int proxy_hello_policy(Proxy *p, uid_t original_uid);
+int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error);
int proxy_run(Proxy *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(Proxy*, proxy_free);
diff --git a/src/bus-proxyd/synthesize.c b/src/bus-proxyd/synthesize.c
index 67bcc7a242..3ecedfd575 100644
--- a/src/bus-proxyd/synthesize.c
+++ b/src/bus-proxyd/synthesize.c
@@ -28,6 +28,7 @@
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
+#include "bus-match.h"
#include "synthesize.h"
int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
@@ -152,11 +153,12 @@ int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
return synthetic_driver_send(call->bus, m);
}
-int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
+int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) {
_cleanup_bus_message_unref_ sd_bus_message *n = NULL;
const char *name, *old_owner, *new_owner;
int r;
+ assert(p);
assert(a);
assert(b);
assert(m);
@@ -216,5 +218,18 @@ int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
if (r < 0)
return r;
- return sd_bus_send(b, n, NULL);
+ /*
+ * Make sure to only forward NameLost/NameAcquired messages if they
+ * match an installed MATCH rule of the local client. We really must
+ * not send messages the client doesn't expect.
+ */
+
+ r = bus_match_run(b, &b->match_callbacks, n);
+ if (r >= 0 && p->message_matched)
+ r = sd_bus_send(b, n, NULL);
+
+ p->message_matched = false;
+ p->synthetic_matched = false;
+
+ return r;
}
diff --git a/src/bus-proxyd/synthesize.h b/src/bus-proxyd/synthesize.h
index e850350bc5..b596daddf2 100644
--- a/src/bus-proxyd/synthesize.h
+++ b/src/bus-proxyd/synthesize.h
@@ -22,6 +22,7 @@
***/
#include "sd-bus.h"
+#include "proxy.h"
int synthetic_driver_send(sd_bus *b, sd_bus_message *m);
@@ -33,4 +34,4 @@ int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const
int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p);
int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4);
-int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m);
+int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m);
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index c6f5485716..b8d1d2ccaf 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -127,7 +127,7 @@ int main(int argc, char *argv[]) {
int r = 0, retval = EXIT_FAILURE;
int output_flags;
_cleanup_free_ char *root = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
log_parse_environment();
log_open();
@@ -197,19 +197,19 @@ int main(int argc, char *argv[]) {
if (arg_machine) {
char *m;
const char *cgroup;
- _cleanup_free_ char *scope = NULL;
+ _cleanup_free_ char *unit = NULL;
_cleanup_free_ char *path = NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
m = strjoina("/run/systemd/machines/", arg_machine);
- r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL);
+ r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
if (r < 0) {
log_error_errno(r, "Failed to get machine path: %m");
goto finish;
}
- path = unit_dbus_path_from_name(scope);
+ path = unit_dbus_path_from_name(unit);
if (!path) {
log_oom();
goto finish;
@@ -219,7 +219,7 @@ int main(int argc, char *argv[]) {
bus,
"org.freedesktop.systemd1",
path,
- "org.freedesktop.systemd1.Scope",
+ endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
"ControlGroup",
&error,
&reply,
diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c
index 529e843030..612bc8fdec 100644
--- a/src/cgroups-agent/cgroups-agent.c
+++ b/src/cgroups-agent/cgroups-agent.c
@@ -26,7 +26,7 @@
#include "bus-util.h"
int main(int argc, char *argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
if (argc != 2) {
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index d630e35882..f953c9e624 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <alloca.h>
#include <getopt.h>
+#include <signal.h>
#include "path-util.h"
#include "terminal-util.h"
diff --git a/src/core/automount.c b/src/core/automount.c
index d847dc1629..4af381b4b6 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -471,13 +471,20 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) {
return r;
}
+static int automount_start_expire(Automount *a);
+
int automount_update_mount(Automount *a, MountState old_state, MountState state) {
+ int r;
+
assert(a);
switch (state) {
case MOUNT_MOUNTED:
case MOUNT_REMOUNTING:
automount_send_ready(a, a->tokens, 0);
+ r = automount_start_expire(a);
+ if (r < 0)
+ log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
break;
case MOUNT_DEAD:
case MOUNT_UNMOUNTING:
@@ -490,6 +497,7 @@ int automount_update_mount(Automount *a, MountState old_state, MountState state)
case MOUNT_FAILED:
if (old_state != state)
automount_send_ready(a, a->tokens, -ENODEV);
+ (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
break;
default:
break;
@@ -633,8 +641,6 @@ static void *expire_thread(void *p) {
return NULL;
}
-static int automount_start_expire(Automount *a);
-
static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
Automount *a = AUTOMOUNT(userdata);
_cleanup_(expire_data_freep) struct expire_data *data = NULL;
@@ -672,7 +678,10 @@ static int automount_start_expire(Automount *a) {
assert(a);
- timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/10, USEC_PER_SEC);
+ if (a->timeout_idle_usec == 0)
+ return 0;
+
+ timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC);
if (a->expire_event_source) {
r = sd_event_source_set_time(a->expire_event_source, timeout);
@@ -730,10 +739,6 @@ static void automount_enter_runnning(Automount *a) {
}
}
- r = automount_start_expire(a);
- if (r < 0)
- log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
-
automount_set_state(a, AUTOMOUNT_RUNNING);
return;
@@ -904,6 +909,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
union autofs_v5_packet_union packet;
Automount *a = AUTOMOUNT(userdata);
+ struct stat st;
int r;
assert(a);
@@ -963,6 +969,19 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
goto fail;
}
+
+ /* Before we do anything, let's see if somebody is playing games with us? */
+ if (lstat(a->where, &st) < 0) {
+ log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
+ goto fail;
+ }
+
+ if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
+ log_unit_info(UNIT(a), "Automount point already unmounted?");
+ automount_send_ready(a, a->expire_tokens, 0);
+ break;
+ }
+
r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
@@ -1066,7 +1085,6 @@ const UnitVTable automount_vtable = {
.finished_start_job = {
[JOB_DONE] = "Set up automount %s.",
[JOB_FAILED] = "Failed to set up automount %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Unset automount %s.",
diff --git a/src/core/busname.c b/src/core/busname.c
index 2085721546..9530a87311 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -1065,13 +1065,10 @@ const UnitVTable busname_vtable = {
.finished_start_job = {
[JOB_DONE] = "Listening on %s.",
[JOB_FAILED] = "Failed to listen on %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- [JOB_TIMEOUT] = "Timed out starting %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Closed %s.",
[JOB_FAILED] = "Failed stopping %s.",
- [JOB_TIMEOUT] = "Timed out stopping %s.",
},
},
};
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 86886e6d2c..057653a8b5 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -69,13 +69,37 @@ int bus_send_queued_message(Manager *m) {
}
static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ const char *cgroup, *me;
Manager *m = userdata;
- const char *cgroup;
+ uid_t sender_uid;
+ sd_bus *bus;
int r;
assert(message);
assert(m);
+ /* ignore recursive events sent by us on the system/user bus */
+ bus = sd_bus_message_get_bus(message);
+ if (!sd_bus_is_server(bus)) {
+ r = sd_bus_get_unique_name(bus, &me);
+ if (r < 0)
+ return r;
+
+ if (streq_ptr(sd_bus_message_get_sender(message), me))
+ return 0;
+ }
+
+ /* only accept org.freedesktop.systemd1.Agent from UID=0 */
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_creds_get_euid(creds, &sender_uid);
+ if (r < 0 || sender_uid != 0)
+ return 0;
+
+ /* parse 'cgroup-empty' notification */
r = sd_bus_message_read(message, "s", &cgroup);
if (r < 0) {
bus_log_parse_error(r);
@@ -84,19 +108,15 @@ static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus
manager_notify_cgroup_empty(m, cgroup);
- /* only forward to system bus if running as system instance */
- if (m->running_as != MANAGER_SYSTEM || !m->system_bus)
- return 0;
-
- r = sd_bus_message_rewind(message, 1);
- if (r < 0)
- goto exit;
-
- r = sd_bus_send(m->system_bus, message, NULL);
+ /* if running as system-instance, forward under our name */
+ if (m->running_as == MANAGER_SYSTEM && m->system_bus) {
+ r = sd_bus_message_rewind(message, 1);
+ if (r >= 0)
+ r = sd_bus_send(m->system_bus, message, NULL);
+ if (r < 0)
+ log_warning_errno(r, "Failed to forward Released message: %m");
+ }
-exit:
- if (r < 0)
- log_warning_errno(r, "Failed to forward Released message: %m");
return 0;
}
diff --git a/src/core/execute.c b/src/core/execute.c
index c92db51330..21721dc240 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1446,7 +1446,7 @@ static int exec_child(
* shouldn't trip up over that. */
sprintf(t, "%i", context->oom_score_adjust);
- r = write_string_file("/proc/self/oom_score_adj", t);
+ r = write_string_file("/proc/self/oom_score_adj", t, 0);
if (r == -EPERM || r == -EACCES) {
log_open();
log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
diff --git a/src/core/job.c b/src/core/job.c
index 8a047df0c3..15f5cc0cc9 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -452,7 +452,7 @@ static bool job_is_runnable(Job *j) {
j->type == JOB_RELOAD) {
/* Immediate result is that the job is or might be
- * started. In this case lets wait for the
+ * started. In this case let's wait for the
* dependencies, regardless whether they are
* starting or stopping something. */
@@ -462,7 +462,7 @@ static bool job_is_runnable(Job *j) {
}
/* Also, if something else is being stopped and we should
- * change state after it, then lets wait. */
+ * change state after it, then let's wait. */
SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
if (other->job &&
@@ -495,10 +495,48 @@ static void job_change_type(Job *j, JobType newtype) {
j->type = newtype;
}
+static int job_perform_on_unit(Job **j) {
+ /* While we execute this operation the job might go away (for
+ * example: because it finishes immediately or is replaced by a new,
+ * conflicting job.) To make sure we don't access a freed job later on
+ * we store the id here, so that we can verify the job is still
+ * valid. */
+ Manager *m = (*j)->manager;
+ Unit *u = (*j)->unit;
+ JobType t = (*j)->type;
+ uint32_t id = (*j)->id;
+ int r;
+
+ switch (t) {
+ case JOB_START:
+ r = unit_start(u);
+ break;
+
+ case JOB_RESTART:
+ t = JOB_STOP;
+ case JOB_STOP:
+ r = unit_stop(u);
+ break;
+
+ case JOB_RELOAD:
+ r = unit_reload(u);
+ break;
+
+ default:
+ assert_not_reached("Invalid job type");
+ }
+
+ /* Log if the job still exists and the start/stop/reload function
+ * actually did something. */
+ *j = manager_get_job(m, id);
+ if (*j && r > 0)
+ unit_status_emit_starting_stopping_reloading(u, t);
+
+ return r;
+}
+
int job_run_and_invalidate(Job *j) {
int r;
- uint32_t id;
- Manager *m = j->manager;
assert(j);
assert(j->installed);
@@ -517,23 +555,9 @@ int job_run_and_invalidate(Job *j) {
job_set_state(j, JOB_RUNNING);
job_add_to_dbus_queue(j);
- /* While we execute this operation the job might go away (for
- * example: because it is replaced by a new, conflicting
- * job.) To make sure we don't access a freed job later on we
- * store the id here, so that we can verify the job is still
- * valid. */
- id = j->id;
switch (j->type) {
- case JOB_START:
- r = unit_start(j->unit);
-
- /* If this unit cannot be started, then simply wait */
- if (r == -EBADR)
- r = 0;
- break;
-
case JOB_VERIFY_ACTIVE: {
UnitActiveState t = unit_active_state(j->unit);
if (UNIT_IS_ACTIVE_OR_RELOADING(t))
@@ -545,17 +569,19 @@ int job_run_and_invalidate(Job *j) {
break;
}
+ case JOB_START:
case JOB_STOP:
case JOB_RESTART:
- r = unit_stop(j->unit);
+ r = job_perform_on_unit(&j);
- /* If this unit cannot stopped, then simply wait. */
+ /* If the unit type does not support starting/stopping,
+ * then simply wait. */
if (r == -EBADR)
r = 0;
break;
case JOB_RELOAD:
- r = unit_reload(j->unit);
+ r = job_perform_on_unit(&j);
break;
case JOB_NOP:
@@ -566,7 +592,6 @@ int job_run_and_invalidate(Job *j) {
assert_not_reached("Unknown job type");
}
- j = manager_get_job(m, id);
if (j) {
if (r == -EALREADY)
r = job_finish_and_invalidate(j, JOB_DONE, true);
@@ -588,161 +613,110 @@ int job_run_and_invalidate(Job *j) {
}
_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
+ const char *format;
const UnitStatusMessageFormats *format_table;
+ static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = "Started %s.",
+ [JOB_TIMEOUT] = "Timed out starting %s.",
+ [JOB_FAILED] = "Failed to start %s.",
+ [JOB_DEPENDENCY] = "Dependency failed for %s.",
+ [JOB_ASSERT] = "Assertion failed for %s.",
+ [JOB_UNSUPPORTED] = "Starting of %s not supported.",
+ };
+ static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = "Stopped %s.",
+ [JOB_FAILED] = "Stopped (with error) %s.",
+ [JOB_TIMEOUT] = "Timed out stoppping %s.",
+ };
+ static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = "Reloaded %s.",
+ [JOB_FAILED] = "Reload failed for %s.",
+ [JOB_TIMEOUT] = "Timed out reloading %s.",
+ };
+ /* When verify-active detects the unit is inactive, report it.
+ * Most likely a DEPEND warning from a requisiting unit will
+ * occur next and it's nice to see what was requisited. */
+ static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = {
+ [JOB_SKIPPED] = "%s is not active.",
+ };
assert(u);
assert(t >= 0);
assert(t < _JOB_TYPE_MAX);
- format_table = &UNIT_VTABLE(u)->status_message_formats;
- if (!format_table)
- return NULL;
+ if (t == JOB_START || t == JOB_STOP || t == JOB_RESTART) {
+ format_table = &UNIT_VTABLE(u)->status_message_formats;
+ if (format_table) {
+ format = t == JOB_START ? format_table->finished_start_job[result] :
+ format_table->finished_stop_job[result];
+ if (format)
+ return format;
+ }
+ }
+ /* Return generic strings */
if (t == JOB_START)
- return format_table->finished_start_job[result];
+ return generic_finished_start_job[result];
else if (t == JOB_STOP || t == JOB_RESTART)
- return format_table->finished_stop_job[result];
+ return generic_finished_stop_job[result];
+ else if (t == JOB_RELOAD)
+ return generic_finished_reload_job[result];
+ else if (t == JOB_VERIFY_ACTIVE)
+ return generic_finished_verify_active_job[result];
return NULL;
}
-_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
+static void job_print_status_message(Unit *u, JobType t, JobResult result) {
const char *format;
+ static const char* const job_result_status_table[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF,
+ [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF,
+ [JOB_FAILED] = ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF,
+ [JOB_DEPENDENCY] = ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF,
+ [JOB_SKIPPED] = ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF,
+ [JOB_ASSERT] = ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF,
+ [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW_ON "UNSUPP" ANSI_HIGHLIGHT_OFF,
+ };
assert(u);
assert(t >= 0);
assert(t < _JOB_TYPE_MAX);
format = job_get_status_message_format(u, t, result);
- if (format)
- return format;
-
- /* Return generic strings */
- if (t == JOB_START) {
- if (result == JOB_DONE)
- return "Started %s.";
- else if (result == JOB_TIMEOUT)
- return "Timed out starting %s.";
- else if (result == JOB_FAILED)
- return "Failed to start %s.";
- else if (result == JOB_DEPENDENCY)
- return "Dependency failed for %s.";
- else if (result == JOB_ASSERT)
- return "Assertion failed for %s.";
- else if (result == JOB_UNSUPPORTED)
- return "Starting of %s not supported.";
- } else if (t == JOB_STOP || t == JOB_RESTART) {
- if (result == JOB_DONE)
- return "Stopped %s.";
- else if (result == JOB_FAILED)
- return "Stopped (with error) %s.";
- else if (result == JOB_TIMEOUT)
- return "Timed out stoppping %s.";
- } else if (t == JOB_RELOAD) {
- if (result == JOB_DONE)
- return "Reloaded %s.";
- else if (result == JOB_FAILED)
- return "Reload failed for %s.";
- else if (result == JOB_TIMEOUT)
- return "Timed out reloading %s.";
- }
-
- return NULL;
-}
+ if (!format)
+ return;
-static void job_print_status_message(Unit *u, JobType t, JobResult result) {
- const char *format;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
+ if (result != JOB_DONE)
+ manager_flip_auto_status(u->manager, true);
DISABLE_WARNING_FORMAT_NONLITERAL;
+ unit_status_printf(u, job_result_status_table[result], format);
+ REENABLE_WARNING;
- if (t == JOB_START) {
- format = job_get_status_message_format(u, t, result);
- if (!format)
- return;
-
- switch (result) {
-
- case JOB_DONE:
- if (u->condition_result)
- unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
- break;
-
- case JOB_TIMEOUT:
- manager_flip_auto_status(u->manager, true);
- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
- break;
-
- case JOB_FAILED: {
- _cleanup_free_ char *quoted = NULL;
-
- quoted = shell_maybe_quote(u->id);
-
- manager_flip_auto_status(u->manager, true);
- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
- manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
- break;
- }
-
- case JOB_DEPENDENCY:
- manager_flip_auto_status(u->manager, true);
- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
- break;
-
- case JOB_ASSERT:
- manager_flip_auto_status(u->manager, true);
- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF, format);
- break;
-
- case JOB_UNSUPPORTED:
- manager_flip_auto_status(u->manager, true);
- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "UNSUPP" ANSI_HIGHLIGHT_OFF, format);
- break;
-
- default:
- ;
- }
-
- } else if (t == JOB_STOP || t == JOB_RESTART) {
-
- format = job_get_status_message_format(u, t, result);
- if (!format)
- return;
-
- switch (result) {
-
- case JOB_TIMEOUT:
- manager_flip_auto_status(u->manager, true);
- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
- break;
-
- case JOB_DONE:
- case JOB_FAILED:
- unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
- break;
-
- default:
- ;
- }
-
- } else if (t == JOB_VERIFY_ACTIVE) {
+ if (t == JOB_START && result == JOB_FAILED) {
+ _cleanup_free_ char *quoted = shell_maybe_quote(u->id);
- /* When verify-active detects the unit is inactive, report it.
- * Most likely a DEPEND warning from a requisiting unit will
- * occur next and it's nice to see what was requisited. */
- if (result == JOB_SKIPPED)
- unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
+ manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL,
+ "See 'systemctl status %s' for details.", strna(quoted));
}
-
- REENABLE_WARNING;
}
static void job_log_status_message(Unit *u, JobType t, JobResult result) {
const char *format;
char buf[LINE_MAX];
+ sd_id128_t mid;
+ static const int job_result_log_level[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = LOG_INFO,
+ [JOB_CANCELED] = LOG_INFO,
+ [JOB_TIMEOUT] = LOG_ERR,
+ [JOB_FAILED] = LOG_ERR,
+ [JOB_DEPENDENCY] = LOG_WARNING,
+ [JOB_SKIPPED] = LOG_NOTICE,
+ [JOB_INVALID] = LOG_INFO,
+ [JOB_ASSERT] = LOG_WARNING,
+ [JOB_UNSUPPORTED] = LOG_WARNING,
+ };
assert(u);
assert(t >= 0);
@@ -754,7 +728,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
if (log_on_console())
return;
- format = job_get_status_message_format_try_harder(u, t, result);
+ format = job_get_status_message_format(u, t, result);
if (!format)
return;
@@ -762,32 +736,40 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
snprintf(buf, sizeof(buf), format, unit_description(u));
REENABLE_WARNING;
- if (t == JOB_START) {
- sd_id128_t mid;
-
+ if (t == JOB_START)
mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
- LOG_MESSAGE_ID(mid),
+ else if (t == JOB_STOP || t == JOB_RESTART)
+ mid = SD_MESSAGE_UNIT_STOPPED;
+ else if (t == JOB_RELOAD)
+ mid = SD_MESSAGE_UNIT_RELOADED;
+ else {
+ log_struct(job_result_log_level[result],
LOG_UNIT_ID(u),
LOG_MESSAGE("%s", buf),
"RESULT=%s", job_result_to_string(result),
NULL);
+ return;
+ }
- } else if (t == JOB_STOP)
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
- LOG_MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
- LOG_UNIT_ID(u),
- LOG_MESSAGE("%s", buf),
- "RESULT=%s", job_result_to_string(result),
- NULL);
+ log_struct(job_result_log_level[result],
+ LOG_MESSAGE_ID(mid),
+ LOG_UNIT_ID(u),
+ LOG_MESSAGE("%s", buf),
+ "RESULT=%s", job_result_to_string(result),
+ NULL);
+}
- else if (t == JOB_RELOAD)
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
- LOG_MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
- LOG_UNIT_ID(u),
- LOG_MESSAGE("%s", buf),
- "RESULT=%s", job_result_to_string(result),
- NULL);
+static void job_emit_status_message(Unit *u, JobType t, JobResult result) {
+
+ /* No message if the job did not actually do anything due to failed condition. */
+ if (t == JOB_START && result == JOB_DONE && !u->condition_result)
+ return;
+
+ job_log_status_message(u, t, result);
+
+ /* Reload status messages have traditionally not been printed to console. */
+ if (t != JOB_RELOAD)
+ job_print_status_message(u, t, result);
}
static void job_fail_dependencies(Unit *u, UnitDependency d) {
@@ -825,8 +807,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
log_unit_debug(u, "Job %s/%s finished, result=%s", u->id, job_type_to_string(t), job_result_to_string(result));
- job_print_status_message(u, t, result);
- job_log_status_message(u, t, result);
+ job_emit_status_message(u, t, result);
job_add_to_dbus_queue(j);
diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
index e7a6bdc8c4..fc6d2f4acb 100644
--- a/src/core/kmod-setup.c
+++ b/src/core/kmod-setup.c
@@ -116,7 +116,7 @@ int kmod_setup(void) {
else if (r == KMOD_PROBE_APPLY_BLACKLIST)
log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
else {
- bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOSYS);
+ bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT);
log_full_errno(print_warning ? LOG_WARNING : LOG_DEBUG, r,
"Failed to insert module '%s': %m", kmod_module_get_name(mod));
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index b3d22840cf..8e26362546 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -260,7 +260,7 @@ int machine_id_setup(const char *root) {
* /run/machine-id as a replacement */
RUN_WITH_UMASK(0022) {
- r = write_string_file(run_machine_id, id);
+ r = write_string_file(run_machine_id, id, WRITE_STRING_FILE_CREATE);
}
if (r < 0) {
(void) unlink(run_machine_id);
diff --git a/src/core/main.c b/src/core/main.c
index 332453a0ea..6ae8b51544 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -685,6 +685,26 @@ static int parse_config_file(void) {
return 0;
}
+static void manager_set_defaults(Manager *m) {
+
+ assert(m);
+
+ m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
+ m->default_std_output = arg_default_std_output;
+ m->default_std_error = arg_default_std_error;
+ m->default_timeout_start_usec = arg_default_timeout_start_usec;
+ m->default_timeout_stop_usec = arg_default_timeout_stop_usec;
+ m->default_restart_usec = arg_default_restart_usec;
+ m->default_start_limit_interval = arg_default_start_limit_interval;
+ m->default_start_limit_burst = arg_default_start_limit_burst;
+ m->default_cpu_accounting = arg_default_cpu_accounting;
+ m->default_blockio_accounting = arg_default_blockio_accounting;
+ m->default_memory_accounting = arg_default_memory_accounting;
+
+ manager_set_default_rlimits(m, arg_default_rlimit);
+ manager_environment_add(m, NULL, arg_default_environment);
+}
+
static int parse_argv(int argc, char *argv[]) {
enum {
@@ -1203,7 +1223,7 @@ static int write_container_id(void) {
if (isempty(c))
return 0;
- return write_string_file("/run/systemd/container", c);
+ return write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE);
}
int main(int argc, char *argv[]) {
@@ -1630,28 +1650,15 @@ int main(int argc, char *argv[]) {
}
m->confirm_spawn = arg_confirm_spawn;
- m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec;
- m->default_std_output = arg_default_std_output;
- m->default_std_error = arg_default_std_error;
- m->default_restart_usec = arg_default_restart_usec;
- m->default_timeout_start_usec = arg_default_timeout_start_usec;
- m->default_timeout_stop_usec = arg_default_timeout_stop_usec;
- m->default_start_limit_interval = arg_default_start_limit_interval;
- m->default_start_limit_burst = arg_default_start_limit_burst;
- m->default_cpu_accounting = arg_default_cpu_accounting;
- m->default_blockio_accounting = arg_default_blockio_accounting;
- m->default_memory_accounting = arg_default_memory_accounting;
m->runtime_watchdog = arg_runtime_watchdog;
m->shutdown_watchdog = arg_shutdown_watchdog;
-
m->userspace_timestamp = userspace_timestamp;
m->kernel_timestamp = kernel_timestamp;
m->initrd_timestamp = initrd_timestamp;
m->security_start_timestamp = security_start_timestamp;
m->security_finish_timestamp = security_finish_timestamp;
- manager_set_default_rlimits(m, arg_default_rlimit);
- manager_environment_add(m, NULL, arg_default_environment);
+ manager_set_defaults(m);
manager_set_show_status(m, arg_show_status);
manager_set_first_boot(m, empty_etc);
@@ -1763,6 +1770,13 @@ int main(int argc, char *argv[]) {
case MANAGER_RELOAD:
log_info("Reloading.");
+
+ r = parse_config_file();
+ if (r < 0)
+ log_error("Failed to parse config file.");
+
+ manager_set_defaults(m);
+
r = manager_reload(m);
if (r < 0)
log_error_errno(r, "Failed to reload: %m");
@@ -1995,6 +2009,10 @@ finish:
command_line[pos++] = "kmsg";
break;
+ case LOG_TARGET_NULL:
+ command_line[pos++] = "null";
+ break;
+
case LOG_TARGET_CONSOLE:
default:
command_line[pos++] = "console";
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 42a6b952b9..1782d40720 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -27,6 +27,7 @@
#include "mount-setup.h"
#include "dev-setup.h"
+#include "bus-util.h"
#include "log.h"
#include "macro.h"
#include "util.h"
@@ -105,7 +106,7 @@ static const MountPoint mount_table[] = {
is_efi_boot, MNT_NONE },
#endif
{ "kdbusfs", "/sys/fs/kdbus", "kdbusfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
- NULL, MNT_IN_CONTAINER },
+ is_kdbus_wanted, MNT_IN_CONTAINER },
};
/* These are API file systems that might be mounted by other software,
diff --git a/src/core/mount.c b/src/core/mount.c
index 851b41351e..bf8e52bf0e 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1025,7 +1025,7 @@ static int mount_reload(Unit *u) {
assert(m->state == MOUNT_MOUNTED);
mount_enter_remounting(m);
- return 0;
+ return 1;
}
static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
@@ -1897,7 +1897,6 @@ const UnitVTable mount_vtable = {
.finished_start_job = {
[JOB_DONE] = "Mounted %s.",
[JOB_FAILED] = "Failed to mount %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
[JOB_TIMEOUT] = "Timed out mounting %s.",
},
.finished_stop_job = {
diff --git a/src/core/path.c b/src/core/path.c
index 6d26d89e82..20995d920c 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -426,7 +426,7 @@ static void path_set_state(Path *p, PathState state) {
path_unwatch(p);
if (state != old_state)
- log_debug("Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state));
+ log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state));
unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], true);
}
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index e9a9a020de..50a90b0bac 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -302,12 +302,12 @@ int mac_selinux_unit_access_check_strv(
int r;
STRV_FOREACH(i, units) {
- u = manager_get_unit(m, *i);
- if (u) {
- r = mac_selinux_unit_access_check(u, message, permission, error);
- if (r < 0)
- return r;
- }
+ r = manager_load_unit(m, *i, NULL, error, &u);
+ if (r < 0)
+ return r;
+ r = mac_selinux_unit_access_check(u, message, permission, error);
+ if (r < 0)
+ return r;
}
#endif
return 0;
diff --git a/src/core/service.c b/src/core/service.c
index fa1e80b710..b790ec98be 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -401,7 +401,6 @@ static int service_add_fd_store_set(Service *s, FDSet *fds) {
r = service_add_fd_store(s, fd);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m");
-
if (r > 0) {
log_unit_debug(UNIT(s), "Added fd to fd store.");
fd = -1;
@@ -576,8 +575,10 @@ static int service_add_extras(Service *s) {
return r;
r = unit_watch_bus_name(UNIT(s), s->bus_name);
+ if (r == -EEXIST)
+ return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name);
if (r < 0)
- return r;
+ return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name);
}
if (UNIT(s)->default_dependencies) {
@@ -1235,7 +1236,7 @@ static int main_pid_good(Service *s) {
/* Returns 0 if the pid is dead, 1 if it is good, -1 if we
* don't know */
- /* If we know the pid file, then lets just check if it is
+ /* If we know the pid file, then let's just check if it is
* still valid */
if (s->main_pid_known) {
@@ -1974,7 +1975,7 @@ static int service_reload(Unit *u) {
assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED);
service_enter_reload(s);
- return 0;
+ return 1;
}
_pure_ static bool service_can_reload(Unit *u) {
@@ -3229,13 +3230,10 @@ const UnitVTable service_vtable = {
.finished_start_job = {
[JOB_DONE] = "Started %s.",
[JOB_FAILED] = "Failed to start %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
- [JOB_TIMEOUT] = "Timed out starting %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Stopped %s.",
[JOB_FAILED] = "Stopped (with error) %s.",
- [JOB_TIMEOUT] = "Timed out stopping %s.",
},
},
};
diff --git a/src/core/slice.c b/src/core/slice.c
index e52bf71515..064eb5d933 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -297,7 +297,6 @@ const UnitVTable slice_vtable = {
.status_message_formats = {
.finished_start_job = {
[JOB_DONE] = "Created slice %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Removed slice %s.",
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index ddb02a1580..cbe7d0b4a9 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -221,7 +221,7 @@ int mac_smack_setup(bool *loaded_policy) {
}
#ifdef SMACK_RUN_LABEL
- r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL);
+ r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0);
if (r)
log_warning("Failed to set SMACK label \"%s\" on self: %s",
SMACK_RUN_LABEL, strerror(-r));
diff --git a/src/core/socket.c b/src/core/socket.c
index d3178e642b..87631f8753 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -922,12 +922,6 @@ static void socket_apply_socket_options(Socket *s, int fd) {
if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m");
- if (s->reuse_port) {
- int b = s->reuse_port;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)) < 0)
- log_unit_warning_errno(UNIT(s), errno, "SO_REUSEPORT failed: %m");
- }
-
if (s->smack_ip_in) {
r = mac_smack_apply_ip_in_fd(fd, s->smack_ip_in);
if (r < 0)
@@ -1183,6 +1177,7 @@ static int socket_open_fds(Socket *s) {
s->backlog,
s->bind_ipv6_only,
s->bind_to_device,
+ s->reuse_port,
s->free_bind,
s->transparent,
s->directory_mode,
@@ -2727,7 +2722,6 @@ const UnitVTable socket_vtable = {
.finished_start_job = {
[JOB_DONE] = "Listening on %s.",
[JOB_FAILED] = "Failed to listen on %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
[JOB_TIMEOUT] = "Timed out starting %s.",
},
.finished_stop_job = {
diff --git a/src/core/swap.c b/src/core/swap.c
index 193c8c3767..0bc3827ff0 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -1505,7 +1505,6 @@ const UnitVTable swap_vtable = {
.finished_start_job = {
[JOB_DONE] = "Activated swap %s.",
[JOB_FAILED] = "Failed to activate swap %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
[JOB_TIMEOUT] = "Timed out activating swap %s.",
},
.finished_stop_job = {
diff --git a/src/core/target.c b/src/core/target.c
index 8817ef21c4..b492a7c4c7 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -227,7 +227,6 @@ const UnitVTable target_vtable = {
.status_message_formats = {
.finished_start_job = {
[JOB_DONE] = "Reached target %s.",
- [JOB_DEPENDENCY] = "Dependency failed for %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Stopped target %s.",
diff --git a/src/core/unit.c b/src/core/unit.c
index fac017c57d..dd5e801285 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1318,42 +1318,28 @@ static bool unit_assert_test(Unit *u) {
}
_pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) {
- const UnitStatusMessageFormats *format_table;
-
- assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
-
- if (t != JOB_START && t != JOB_STOP)
- return NULL;
-
- format_table = &UNIT_VTABLE(u)->status_message_formats;
- if (!format_table)
- return NULL;
-
- return format_table->starting_stopping[t == JOB_STOP];
-}
-
-_pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) {
const char *format;
+ const UnitStatusMessageFormats *format_table;
assert(u);
- assert(t >= 0);
- assert(t < _JOB_TYPE_MAX);
+ assert(t == JOB_START || t == JOB_STOP || t == JOB_RELOAD);
- format = unit_get_status_message_format(u, t);
- if (format)
- return format;
+ if (t != JOB_RELOAD) {
+ format_table = &UNIT_VTABLE(u)->status_message_formats;
+ if (format_table) {
+ format = format_table->starting_stopping[t == JOB_STOP];
+ if (format)
+ return format;
+ }
+ }
/* Return generic strings */
if (t == JOB_START)
return "Starting %s.";
else if (t == JOB_STOP)
return "Stopping %s.";
- else if (t == JOB_RELOAD)
+ else
return "Reloading %s.";
-
- return NULL;
}
static void unit_status_print_starting_stopping(Unit *u, JobType t) {
@@ -1361,12 +1347,7 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) {
assert(u);
- /* We only print status messages for selected units on
- * selected operations. */
-
format = unit_get_status_message_format(u, t);
- if (!format)
- return;
DISABLE_WARNING_FORMAT_NONLITERAL;
unit_status_printf(u, "", format);
@@ -1388,9 +1369,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
/* We log status messages for all units and all operations. */
- format = unit_get_status_message_format_try_harder(u, t);
- if (!format)
- return;
+ format = unit_get_status_message_format(u, t);
DISABLE_WARNING_FORMAT_NONLITERAL;
snprintf(buf, sizeof(buf), format, unit_description(u));
@@ -1413,6 +1392,15 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
NULL);
}
+void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
+
+ unit_status_log_starting_stopping_reloading(u, t);
+
+ /* Reload status messages have traditionally not been printed to console. */
+ if (t != JOB_RELOAD)
+ unit_status_print_starting_stopping(u, t);
+}
+
/* Errors:
* -EBADR: This unit type does not support starting.
* -EALREADY: Unit is already started.
@@ -1423,7 +1411,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
int unit_start(Unit *u) {
UnitActiveState state;
Unit *following;
- int r;
assert(u);
@@ -1477,14 +1464,7 @@ int unit_start(Unit *u) {
unit_add_to_dbus_queue(u);
- r = UNIT_VTABLE(u)->start(u);
- if (r <= 0)
- return r;
-
- /* Log if the start function actually did something */
- unit_status_log_starting_stopping_reloading(u, JOB_START);
- unit_status_print_starting_stopping(u, JOB_START);
- return r;
+ return UNIT_VTABLE(u)->start(u);
}
bool unit_can_start(Unit *u) {
@@ -1508,7 +1488,6 @@ bool unit_can_isolate(Unit *u) {
int unit_stop(Unit *u) {
UnitActiveState state;
Unit *following;
- int r;
assert(u);
@@ -1527,13 +1506,7 @@ int unit_stop(Unit *u) {
unit_add_to_dbus_queue(u);
- r = UNIT_VTABLE(u)->stop(u);
- if (r <= 0)
- return r;
-
- unit_status_log_starting_stopping_reloading(u, JOB_STOP);
- unit_status_print_starting_stopping(u, JOB_STOP);
- return r;
+ return UNIT_VTABLE(u)->stop(u);
}
/* Errors:
@@ -1544,7 +1517,6 @@ int unit_stop(Unit *u) {
int unit_reload(Unit *u) {
UnitActiveState state;
Unit *following;
- int r;
assert(u);
@@ -1571,12 +1543,7 @@ int unit_reload(Unit *u) {
unit_add_to_dbus_queue(u);
- r = UNIT_VTABLE(u)->reload(u);
- if (r <= 0)
- return r;
-
- unit_status_log_starting_stopping_reloading(u, JOB_RELOAD);
- return r;
+ return UNIT_VTABLE(u)->reload(u);
}
bool unit_can_reload(Unit *u) {
diff --git a/src/core/unit.h b/src/core/unit.h
index 9491ef64f9..e60168267f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -544,6 +544,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants);
int unit_coldplug(Unit *u);
void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0);
+void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t);
bool unit_need_daemon_reload(Unit *u);
diff --git a/src/escape/escape.c b/src/escape/escape.c
index 9ccb015538..341453398d 100644
--- a/src/escape/escape.c
+++ b/src/escape/escape.c
@@ -236,5 +236,5 @@ int main(int argc, char *argv[]) {
fputc('\n', stdout);
finish:
- return r <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index cda96d484a..3805b29437 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -415,7 +415,7 @@ static int process_hostname(void) {
return 0;
mkdir_parents(etc_hostname, 0755);
- r = write_string_file(etc_hostname, arg_hostname);
+ r = write_string_file(etc_hostname, arg_hostname, WRITE_STRING_FILE_CREATE);
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_hostname);
@@ -436,7 +436,7 @@ static int process_machine_id(void) {
return 0;
mkdir_parents(etc_machine_id, 0755);
- r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id));
+ r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id), WRITE_STRING_FILE_CREATE);
if (r < 0)
return log_error_errno(r, "Failed to write machine id: %m");
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 30254b6680..bd3051f30d 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -62,7 +62,7 @@ static const char *arg_repair = "-a";
static void start_target(const char *target) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
assert(target);
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index b46e160888..da5f3b647a 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -183,7 +183,8 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, char **devi
r = write_string_file(p,
"# Automatically generated by systemd-gpt-auto-generator\n\n"
"[Unit]\n"
- "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
+ "JobTimeoutSec=0\n",
+ WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
if (r < 0)
return log_error_errno(r, "Failed to write device drop-in: %m");
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 43aac616b6..1f3b169905 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -65,7 +65,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- r = write_string_file("/sys/power/resume", major_minor);
+ r = write_string_file("/sys/power/resume", major_minor, WRITE_STRING_FILE_CREATE);
if (r < 0) {
log_error_errno(r, "Failed to write '%s' to /sys/power/resume: %m", major_minor);
return EXIT_FAILURE;
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index 69ecd61f60..c996fc04a0 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -509,7 +509,7 @@ static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 7ff3a4e224..e52b872a8c 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -663,7 +663,7 @@ static const sd_bus_vtable hostname_vtable[] = {
};
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
assert(c);
@@ -695,7 +695,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
int main(int argc, char *argv[]) {
Context context = {};
_cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
log_set_target(LOG_TARGET_AUTO);
diff --git a/src/import/importd.c b/src/import/importd.c
index 03aede6016..dd314f5b00 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -551,8 +551,7 @@ static Manager *manager_unref(Manager *m) {
bus_verify_polkit_async_registry_free(m->polkit_registry);
- sd_bus_close(m->bus);
- sd_bus_unref(m->bus);
+ m->bus = sd_bus_flush_close_unref(m->bus);
sd_event_unref(m->event);
free(m);
diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c
index 78e3184c42..67ca1ce8e4 100644
--- a/src/import/pull-dkr.c
+++ b/src/import/pull-dkr.c
@@ -793,7 +793,7 @@ static void dkr_pull_job_on_finished_v2(PullJob *j) {
} else if (i->tags_job == j) {
const char *url;
- _cleanup_free_ const char *buf;
+ _cleanup_free_ char *buf;
_cleanup_json_variant_unref_ JsonVariant *doc = NULL;
JsonVariant *e = NULL;
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index d9450ae8cd..9a09f401e0 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -132,7 +132,7 @@ static int request_meta_ensure_tmp(RequestMeta *m) {
if (fd < 0)
return fd;
- m->tmp = fdopen(fd, "rw");
+ m->tmp = fdopen(fd, "w+");
if (!m->tmp) {
safe_close(fd);
return -errno;
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index be6a5522fa..f7815b2796 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -656,13 +656,16 @@ static int journal_file_setup_field_hash_table(JournalFile *f) {
return 0;
}
-static int journal_file_map_data_hash_table(JournalFile *f) {
+int journal_file_map_data_hash_table(JournalFile *f) {
uint64_t s, p;
void *t;
int r;
assert(f);
+ if (f->data_hash_table)
+ return 0;
+
p = le64toh(f->header->data_hash_table_offset);
s = le64toh(f->header->data_hash_table_size);
@@ -678,13 +681,16 @@ static int journal_file_map_data_hash_table(JournalFile *f) {
return 0;
}
-static int journal_file_map_field_hash_table(JournalFile *f) {
+int journal_file_map_field_hash_table(JournalFile *f) {
uint64_t s, p;
void *t;
int r;
assert(f);
+ if (f->field_hash_table)
+ return 0;
+
p = le64toh(f->header->field_hash_table_offset);
s = le64toh(f->header->field_hash_table_size);
@@ -803,10 +809,18 @@ int journal_file_find_field_object_with_hash(
assert(f);
assert(field && size > 0);
+ /* If the field hash table is empty, we can't find anything */
+ if (le64toh(f->header->field_hash_table_size) <= 0)
+ return 0;
+
+ /* Map the field hash table, if it isn't mapped yet. */
+ r = journal_file_map_field_hash_table(f);
+ if (r < 0)
+ return r;
+
osize = offsetof(Object, field.payload) + size;
m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
-
if (m <= 0)
return -EBADMSG;
@@ -866,6 +880,15 @@ int journal_file_find_data_object_with_hash(
assert(f);
assert(data || size == 0);
+ /* If there's no data hash table, then there's no entry. */
+ if (le64toh(f->header->data_hash_table_size) <= 0)
+ return 0;
+
+ /* Map the data hash table, if it isn't mapped yet. */
+ r = journal_file_map_data_hash_table(f);
+ if (r < 0)
+ return r;
+
osize = offsetof(Object, data.payload) + size;
m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
@@ -2731,14 +2754,6 @@ int journal_file_open(
#endif
}
- r = journal_file_map_field_hash_table(f);
- if (r < 0)
- goto fail;
-
- r = journal_file_map_data_hash_table(f);
- if (r < 0)
- goto fail;
-
if (mmap_cache_got_sigbus(f->mmap, f->fd)) {
r = -EIO;
goto fail;
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 403c8f760c..e92b75eabe 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -229,3 +229,6 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec);
+
+int journal_file_map_data_hash_table(JournalFile *f);
+int journal_file_map_field_hash_table(JournalFile *f);
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index 81a577ea27..17499bbc30 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -72,7 +72,7 @@ static void patch_realtime(
const struct stat *st,
unsigned long long *realtime) {
- _cleanup_free_ const char *path = NULL;
+ _cleanup_free_ char *path = NULL;
usec_t x, crtime = 0;
/* The timestamp was determined by the file name, but let's
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index ce734d8df7..eaf006db7a 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -69,6 +69,16 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
fflush(stdout);
}
+static uint64_t scale_progress(uint64_t scale, uint64_t p, uint64_t m) {
+
+ /* Calculates scale * p / m, but handles m == 0 safely, and saturates */
+
+ if (p >= m || m == 0)
+ return scale;
+
+ return scale * p / m;
+}
+
static void flush_progress(void) {
unsigned n, i;
@@ -113,8 +123,10 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
* other objects. */
if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
- o->object.type != OBJECT_DATA)
+ o->object.type != OBJECT_DATA) {
+ error(offset, "Found compressed object that isn't of type DATA, which is not allowed.");
return -EBADMSG;
+ }
switch (o->object.type) {
@@ -123,15 +135,15 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
int compression, r;
if (le64toh(o->data.entry_offset) == 0)
- warning(offset, "unused data (entry_offset==0)");
+ warning(offset, "Unused data (entry_offset==0)");
if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) {
- error(offset, "bad n_entries: %"PRIu64, o->data.n_entries);
+ error(offset, "Bad n_entries: %"PRIu64, o->data.n_entries);
return -EBADMSG;
}
if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) {
- error(offset, "bad object size (<= %zu): %"PRIu64,
+ error(offset, "Bad object size (<= %zu): %"PRIu64,
offsetof(DataObject, payload),
le64toh(o->object.size));
return -EBADMSG;
@@ -159,7 +171,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
if (h1 != h2) {
- error(offset, "invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2);
+ error(offset, "Invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2);
return -EBADMSG;
}
@@ -167,7 +179,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
!VALID64(o->data.next_field_offset) ||
!VALID64(o->data.entry_offset) ||
!VALID64(o->data.entry_array_offset)) {
- error(offset, "invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
+ error(offset, "Invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt,
o->data.next_hash_offset,
o->data.next_field_offset,
o->data.entry_offset,
@@ -181,7 +193,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
case OBJECT_FIELD:
if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) {
error(offset,
- "bad field size (<= %zu): %"PRIu64,
+ "Bad field size (<= %zu): %"PRIu64,
offsetof(FieldObject, payload),
le64toh(o->object.size));
return -EBADMSG;
@@ -190,7 +202,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if (!VALID64(o->field.next_hash_offset) ||
!VALID64(o->field.head_data_offset)) {
error(offset,
- "invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
+ "Invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt,
o->field.next_hash_offset,
o->field.head_data_offset);
return -EBADMSG;
@@ -200,7 +212,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
case OBJECT_ENTRY:
if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) {
error(offset,
- "bad entry size (<= %zu): %"PRIu64,
+ "Bad entry size (<= %zu): %"PRIu64,
offsetof(EntryObject, items),
le64toh(o->object.size));
return -EBADMSG;
@@ -208,28 +220,28 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) {
error(offset,
- "invalid number items in entry: %"PRIu64,
+ "Invalid number items in entry: %"PRIu64,
(le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem));
return -EBADMSG;
}
if (le64toh(o->entry.seqnum) <= 0) {
error(offset,
- "invalid entry seqnum: %"PRIx64,
+ "Invalid entry seqnum: %"PRIx64,
le64toh(o->entry.seqnum));
return -EBADMSG;
}
if (!VALID_REALTIME(le64toh(o->entry.realtime))) {
error(offset,
- "invalid entry realtime timestamp: %"PRIu64,
+ "Invalid entry realtime timestamp: %"PRIu64,
le64toh(o->entry.realtime));
return -EBADMSG;
}
if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) {
error(offset,
- "invalid entry monotonic timestamp: %"PRIu64,
+ "Invalid entry monotonic timestamp: %"PRIu64,
le64toh(o->entry.monotonic));
return -EBADMSG;
}
@@ -238,7 +250,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if (o->entry.items[i].object_offset == 0 ||
!VALID64(o->entry.items[i].object_offset)) {
error(offset,
- "invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
+ "Invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt,
i, journal_file_entry_n_items(o),
o->entry.items[i].object_offset);
return -EBADMSG;
@@ -252,7 +264,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 ||
(le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) {
error(offset,
- "invalid %s hash table size: %"PRIu64,
+ "Invalid %s hash table size: %"PRIu64,
o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
le64toh(o->object.size));
return -EBADMSG;
@@ -262,7 +274,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if (o->hash_table.items[i].head_hash_offset != 0 &&
!VALID64(le64toh(o->hash_table.items[i].head_hash_offset))) {
error(offset,
- "invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt,
+ "Invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt,
o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
i, journal_file_hash_table_n_items(o),
le64toh(o->hash_table.items[i].head_hash_offset));
@@ -271,7 +283,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if (o->hash_table.items[i].tail_hash_offset != 0 &&
!VALID64(le64toh(o->hash_table.items[i].tail_hash_offset))) {
error(offset,
- "invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt,
+ "Invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt,
o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
i, journal_file_hash_table_n_items(o),
le64toh(o->hash_table.items[i].tail_hash_offset));
@@ -281,7 +293,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if ((o->hash_table.items[i].head_hash_offset != 0) !=
(o->hash_table.items[i].tail_hash_offset != 0)) {
error(offset,
- "invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt,
+ "Invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt,
o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field",
i, journal_file_hash_table_n_items(o),
le64toh(o->hash_table.items[i].head_hash_offset),
@@ -296,14 +308,14 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 ||
(le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) {
error(offset,
- "invalid object entry array size: %"PRIu64,
+ "Invalid object entry array size: %"PRIu64,
le64toh(o->object.size));
return -EBADMSG;
}
if (!VALID64(o->entry_array.next_entry_array_offset)) {
error(offset,
- "invalid object entry array next_entry_array_offset: "OFSfmt,
+ "Invalid object entry array next_entry_array_offset: "OFSfmt,
o->entry_array.next_entry_array_offset);
return -EBADMSG;
}
@@ -312,7 +324,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
if (le64toh(o->entry_array.items[i]) != 0 &&
!VALID64(le64toh(o->entry_array.items[i]))) {
error(offset,
- "invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
+ "Invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
i, journal_file_entry_array_n_items(o),
le64toh(o->entry_array.items[i]));
return -EBADMSG;
@@ -323,14 +335,14 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
case OBJECT_TAG:
if (le64toh(o->object.size) != sizeof(TagObject)) {
error(offset,
- "invalid object tag size: %"PRIu64,
+ "Invalid object tag size: %"PRIu64,
le64toh(o->object.size));
return -EBADMSG;
}
if (!VALID_EPOCH(o->tag.epoch)) {
error(offset,
- "invalid object tag epoch: %"PRIu64,
+ "Invalid object tag epoch: %"PRIu64,
o->tag.epoch);
return -EBADMSG;
}
@@ -403,8 +415,7 @@ static int entry_points_to_data(
assert(entry_fd >= 0);
if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
- error(data_p,
- "data object references invalid entry at "OFSfmt, entry_p);
+ error(data_p, "Data object references invalid entry at "OFSfmt, entry_p);
return -EBADMSG;
}
@@ -420,8 +431,7 @@ static int entry_points_to_data(
}
if (!found) {
- error(entry_p,
- "data object at "OFSfmt" not referenced by linked entry", data_p);
+ error(entry_p, "Data object at "OFSfmt" not referenced by linked entry", data_p);
return -EBADMSG;
}
@@ -464,7 +474,7 @@ static int entry_points_to_data(
x = z;
}
- error(entry_p, "entry object doesn't exist in main entry array");
+ error(entry_p, "Entry object doesn't exist in main entry array");
return -EBADMSG;
}
@@ -494,9 +504,7 @@ static int verify_data(
/* Entry array means at least two objects */
if (a && n < 2) {
- error(p,
- "entry array present (entry_array_offset="OFSfmt", but n_entries=%"PRIu64")",
- a, n);
+ error(p, "Entry array present (entry_array_offset="OFSfmt", but n_entries=%"PRIu64")", a, n);
return -EBADMSG;
}
@@ -516,12 +524,12 @@ static int verify_data(
uint64_t next, m, j;
if (a == 0) {
- error(p, "array chain too short");
+ error(p, "Array chain too short");
return -EBADMSG;
}
if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
- error(p, "invalid array offset "OFSfmt, a);
+ error(p, "Invalid array offset "OFSfmt, a);
return -EBADMSG;
}
@@ -531,8 +539,7 @@ static int verify_data(
next = le64toh(o->entry_array.next_entry_array_offset);
if (next != 0 && next <= a) {
- error(p, "array chain has cycle (jumps back from "OFSfmt" to "OFSfmt")",
- a, next);
+ error(p, "Array chain has cycle (jumps back from "OFSfmt" to "OFSfmt")", a, next);
return -EBADMSG;
}
@@ -541,7 +548,7 @@ static int verify_data(
q = le64toh(o->entry_array.items[j]);
if (q <= last) {
- error(p, "data object's entry array not sorted");
+ error(p, "Data object's entry array not sorted");
return -EBADMSG;
}
last = q;
@@ -580,11 +587,18 @@ static int verify_hash_table(
assert(last_usec);
n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
+ if (n <= 0)
+ return 0;
+
+ r = journal_file_map_data_hash_table(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to map data hash table: %m");
+
for (i = 0; i < n; i++) {
uint64_t last = 0, p;
if (show_progress)
- draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
+ draw_progress(0xC000 + scale_progress(0x3FFF, i, n), last_usec);
p = le64toh(f->data_hash_table[i].head_hash_offset);
while (p != 0) {
@@ -592,8 +606,7 @@ static int verify_hash_table(
uint64_t next;
if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
- error(p, "invalid data object at hash entry %"PRIu64" of %"PRIu64,
- i, n);
+ error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
@@ -603,14 +616,12 @@ static int verify_hash_table(
next = le64toh(o->data.next_hash_offset);
if (next != 0 && next <= p) {
- error(p, "hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64,
- i, n);
+ error(p, "Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
if (le64toh(o->data.hash) % n != i) {
- error(p, "hash value mismatch in hash entry %"PRIu64" of %"PRIu64,
- i, n);
+ error(p, "Hash value mismatch in hash entry %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
@@ -623,7 +634,7 @@ static int verify_hash_table(
}
if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
- error(p, "tail hash pointer mismatch in hash table");
+ error(p, "Tail hash pointer mismatch in hash table");
return -EBADMSG;
}
}
@@ -637,6 +648,13 @@ static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p)
assert(f);
n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
+ if (n <= 0)
+ return 0;
+
+ r = journal_file_map_data_hash_table(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to map data hash table: %m");
+
h = hash % n;
q = le64toh(f->data_hash_table[h].head_hash_offset);
@@ -677,16 +695,16 @@ static int verify_entry(
h = le64toh(o->entry.items[i].hash);
if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
- error(p, "invalid data object of entry");
- return -EBADMSG;
- }
+ error(p, "Invalid data object of entry");
+ return -EBADMSG;
+ }
r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
if (r < 0)
return r;
if (le64toh(u->data.hash) != h) {
- error(p, "hash mismatch for data object of entry");
+ error(p, "Hash mismatch for data object of entry");
return -EBADMSG;
}
@@ -694,7 +712,7 @@ static int verify_entry(
if (r < 0)
return r;
if (r == 0) {
- error(p, "data object missing from hash table");
+ error(p, "Data object missing from hash table");
return -EBADMSG;
}
}
@@ -726,15 +744,15 @@ static int verify_entry_array(
Object *o;
if (show_progress)
- draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
+ draw_progress(0x8000 + scale_progress(0x3FFF, i, n), last_usec);
if (a == 0) {
- error(a, "array chain too short at %"PRIu64" of %"PRIu64, i, n);
+ error(a, "Array chain too short at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
- error(a, "invalid array %"PRIu64" of %"PRIu64, i, n);
+ error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
@@ -744,9 +762,7 @@ static int verify_entry_array(
next = le64toh(o->entry_array.next_entry_array_offset);
if (next != 0 && next <= a) {
- error(a,
- "array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")",
- i, n, next);
+ error(a, "Array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")", i, n, next);
return -EBADMSG;
}
@@ -756,15 +772,13 @@ static int verify_entry_array(
p = le64toh(o->entry_array.items[j]);
if (p <= last) {
- error(a, "entry array not sorted at %"PRIu64" of %"PRIu64,
- i, n);
+ error(a, "Entry array not sorted at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
last = p;
if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
- error(a, "invalid array entry at %"PRIu64" of %"PRIu64,
- i, n);
+ error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n);
return -EBADMSG;
}
@@ -852,7 +866,7 @@ int journal_file_verify(
for (i = 0; i < sizeof(f->header->reserved); i++)
if (f->header->reserved[i] != 0) {
- error(offsetof(Header, reserved[i]), "reserved field is non-zero");
+ error(offsetof(Header, reserved[i]), "Reserved field is non-zero");
r = -EBADMSG;
goto fail;
}
@@ -861,36 +875,37 @@ int journal_file_verify(
* superficial structure, headers, hashes. */
p = le64toh(f->header->header_size);
- while (p != 0) {
+ for (;;) {
+ /* Early exit if there are no objects in the file, at all */
+ if (le64toh(f->header->tail_object_offset) == 0)
+ break;
+
if (show_progress)
- draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
+ draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec);
r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
if (r < 0) {
- error(p, "invalid object");
+ error(p, "Invalid object");
goto fail;
}
if (p > le64toh(f->header->tail_object_offset)) {
- error(offsetof(Header, tail_object_offset), "invalid tail object pointer");
+ error(offsetof(Header, tail_object_offset), "Invalid tail object pointer");
r = -EBADMSG;
goto fail;
}
- if (p == le64toh(f->header->tail_object_offset))
- found_last = true;
-
n_objects ++;
r = journal_file_object_verify(f, p, o);
if (r < 0) {
- error(p, "invalid object contents: %s", strerror(-r));
+ error(p, "Envalid object contents: %s", strerror(-r));
goto fail;
}
if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
(o->object.flags & OBJECT_COMPRESSED_LZ4)) {
- error(p, "objected with double compression");
+ error(p, "Objected with double compression");
r = -EINVAL;
goto fail;
}
@@ -923,7 +938,7 @@ int journal_file_verify(
case OBJECT_ENTRY:
if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
- error(p, "first entry before first tag");
+ error(p, "First entry before first tag");
r = -EBADMSG;
goto fail;
}
@@ -933,21 +948,21 @@ int journal_file_verify(
goto fail;
if (le64toh(o->entry.realtime) < last_tag_realtime) {
- error(p, "older entry after newer tag");
+ error(p, "Older entry after newer tag");
r = -EBADMSG;
goto fail;
}
if (!entry_seqnum_set &&
le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
- error(p, "head entry sequence number incorrect");
+ error(p, "Head entry sequence number incorrect");
r = -EBADMSG;
goto fail;
}
if (entry_seqnum_set &&
entry_seqnum >= le64toh(o->entry.seqnum)) {
- error(p, "entry sequence number out of synchronization");
+ error(p, "Entry sequence number out of synchronization");
r = -EBADMSG;
goto fail;
}
@@ -958,7 +973,7 @@ int journal_file_verify(
if (entry_monotonic_set &&
sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
entry_monotonic > le64toh(o->entry.monotonic)) {
- error(p, "entry timestamp out of synchronization");
+ error(p, "Entry timestamp out of synchronization");
r = -EBADMSG;
goto fail;
}
@@ -969,7 +984,7 @@ int journal_file_verify(
if (!entry_realtime_set &&
le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
- error(p, "head entry realtime timestamp incorrect");
+ error(p, "Head entry realtime timestamp incorrect");
r = -EBADMSG;
goto fail;
}
@@ -982,7 +997,7 @@ int journal_file_verify(
case OBJECT_DATA_HASH_TABLE:
if (n_data_hash_tables > 1) {
- error(p, "more than one data hash table");
+ error(p, "More than one data hash table");
r = -EBADMSG;
goto fail;
}
@@ -999,14 +1014,14 @@ int journal_file_verify(
case OBJECT_FIELD_HASH_TABLE:
if (n_field_hash_tables > 1) {
- error(p, "more than one field hash table");
+ error(p, "More than one field hash table");
r = -EBADMSG;
goto fail;
}
if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
- error(p, "header fields for field hash table invalid");
+ error(p, "Header fields for field hash table invalid");
r = -EBADMSG;
goto fail;
}
@@ -1021,7 +1036,7 @@ int journal_file_verify(
if (p == le64toh(f->header->entry_array_offset)) {
if (found_main_entry_array) {
- error(p, "more than one main entry array");
+ error(p, "More than one main entry array");
r = -EBADMSG;
goto fail;
}
@@ -1034,19 +1049,19 @@ int journal_file_verify(
case OBJECT_TAG:
if (!JOURNAL_HEADER_SEALED(f->header)) {
- error(p, "tag object in file without sealing");
+ error(p, "Tag object in file without sealing");
r = -EBADMSG;
goto fail;
}
if (le64toh(o->tag.seqnum) != n_tags + 1) {
- error(p, "tag sequence number out of synchronization");
+ error(p, "Tag sequence number out of synchronization");
r = -EBADMSG;
goto fail;
}
if (le64toh(o->tag.epoch) < last_epoch) {
- error(p, "epoch sequence out of synchronization");
+ error(p, "Epoch sequence out of synchronization");
r = -EBADMSG;
goto fail;
}
@@ -1055,7 +1070,7 @@ int journal_file_verify(
if (f->seal) {
uint64_t q, rt;
- debug(p, "checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
+ debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
@@ -1102,7 +1117,7 @@ int journal_file_verify(
goto fail;
if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
- error(p, "tag failed verification");
+ error(p, "Tag failed verification");
r = -EBADMSG;
goto fail;
}
@@ -1124,79 +1139,69 @@ int journal_file_verify(
n_weird ++;
}
- if (p == le64toh(f->header->tail_object_offset))
- p = 0;
- else
- p = p + ALIGN64(le64toh(o->object.size));
- }
+ if (p == le64toh(f->header->tail_object_offset)) {
+ found_last = true;
+ break;
+ }
- if (!found_last) {
- error(le64toh(f->header->tail_object_offset), "tail object pointer dead");
+ p = p + ALIGN64(le64toh(o->object.size));
+ };
+
+ if (!found_last && le64toh(f->header->tail_object_offset) != 0) {
+ error(le64toh(f->header->tail_object_offset), "Tail object pointer dead");
r = -EBADMSG;
goto fail;
}
if (n_objects != le64toh(f->header->n_objects)) {
- error(offsetof(Header, n_objects), "object number mismatch");
+ error(offsetof(Header, n_objects), "Object number mismatch");
r = -EBADMSG;
goto fail;
}
if (n_entries != le64toh(f->header->n_entries)) {
- error(offsetof(Header, n_entries), "entry number mismatch");
+ error(offsetof(Header, n_entries), "Entry number mismatch");
r = -EBADMSG;
goto fail;
}
if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
n_data != le64toh(f->header->n_data)) {
- error(offsetof(Header, n_data), "data number mismatch");
+ error(offsetof(Header, n_data), "Data number mismatch");
r = -EBADMSG;
goto fail;
}
if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
n_fields != le64toh(f->header->n_fields)) {
- error(offsetof(Header, n_fields), "field number mismatch");
+ error(offsetof(Header, n_fields), "Field number mismatch");
r = -EBADMSG;
goto fail;
}
if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
n_tags != le64toh(f->header->n_tags)) {
- error(offsetof(Header, n_tags), "tag number mismatch");
+ error(offsetof(Header, n_tags), "Tag number mismatch");
r = -EBADMSG;
goto fail;
}
if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
- error(offsetof(Header, n_entry_arrays), "entry array number mismatch");
- r = -EBADMSG;
- goto fail;
- }
-
- if (n_data_hash_tables != 1) {
- error(0, "missing data hash table");
- r = -EBADMSG;
- goto fail;
- }
-
- if (n_field_hash_tables != 1) {
- error(0, "missing field hash table");
+ error(offsetof(Header, n_entry_arrays), "Entry array number mismatch");
r = -EBADMSG;
goto fail;
}
- if (!found_main_entry_array) {
- error(0, "missing entry array");
+ if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) {
+ error(0, "Missing entry array");
r = -EBADMSG;
goto fail;
}
if (entry_seqnum_set &&
entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
- error(offsetof(Header, tail_entry_seqnum), "invalid tail seqnum");
+ error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum");
r = -EBADMSG;
goto fail;
}
@@ -1204,13 +1209,13 @@ int journal_file_verify(
if (entry_monotonic_set &&
(!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
- error(0, "invalid tail monotonic timestamp");
+ error(0, "Invalid tail monotonic timestamp");
r = -EBADMSG;
goto fail;
}
if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
- error(0, "invalid tail realtime timestamp");
+ error(0, "Invalid tail realtime timestamp");
r = -EBADMSG;
goto fail;
}
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 76ec0827e7..073cc77711 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -1719,7 +1719,7 @@ static int access_check(sd_journal *j) {
static int flush_to_var(void) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_close_ int watch_fd = -1;
int r;
@@ -2066,6 +2066,10 @@ int main(int argc, char *argv[]) {
log_error_errno(r, "Failed to iterate through journal: %m");
goto finish;
}
+ if (r == 0) {
+ printf("-- No entries --\n");
+ goto finish;
+ }
if (!arg_follow)
pager_open_if_enabled();
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index f7402984af..28b1472ac8 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -175,9 +175,11 @@ static uint64_t available_space(Server *s, bool verbose) {
fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX];
server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
- "%s journal is using %s (max allowed %s, "
- "trying to leave %s free of %s available → current limit %s).",
- s->system_journal ? "Permanent" : "Runtime",
+ "%s is currently using %s.\n"
+ "Maximum allowed usage is set to %s.\n"
+ "Leaving at least %s free (of currently available %s of space).\n"
+ "Enforced usage limit is thus %s.",
+ s->system_journal ? "Permanent journal (/var/log/journal/)" : "Runtime journal (/run/log/journal/)",
format_bytes(fb1, sizeof(fb1), sum),
format_bytes(fb2, sizeof(fb2), m->max_use),
format_bytes(fb3, sizeof(fb3), m->keep_free),
@@ -943,7 +945,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
* the machine path */
if (s->storage == STORAGE_PERSISTENT)
- (void) mkdir("/var/log/journal/", 0755);
+ (void) mkdir_p("/var/log/journal/", 0755);
fn = strjoina("/var/log/journal/", ids);
(void) mkdir(fn, 0755);
diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h
index 9e184ac4b5..6e00b1ad30 100644
--- a/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/libsystemd-network/dhcp-lease-internal.h
@@ -72,6 +72,8 @@ struct sd_dhcp_lease {
char *root_path;
uint8_t *client_id;
size_t client_id_len;
+ uint8_t *vendor_specific;
+ size_t vendor_specific_len;
};
int dhcp_lease_new(sd_dhcp_lease **ret);
diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index abca9422c5..aa37e9b0b5 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -125,6 +125,7 @@ enum {
DHCP_OPTION_BROADCAST = 28,
DHCP_OPTION_STATIC_ROUTE = 33,
DHCP_OPTION_NTP_SERVER = 42,
+ DHCP_OPTION_VENDOR_SPECIFIC = 43,
DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
DHCP_OPTION_OVERLOAD = 52,
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index d8bc76edda..54417b3af3 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -179,6 +179,21 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes
return 0;
}
+int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data,
+ size_t *data_len) {
+ assert_return(lease, -EINVAL);
+ assert_return(data, -EINVAL);
+ assert_return(data_len, -EINVAL);
+
+ if (!lease->vendor_specific)
+ return -ENOENT;
+
+ *data = lease->vendor_specific;
+ *data_len = lease->vendor_specific_len;
+
+ return 0;
+}
+
sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
if (lease)
assert_se(REFCNT_INC(lease->n_ref) >= 2);
@@ -194,6 +209,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
free(lease->ntp);
free(lease->static_route);
free(lease->client_id);
+ free(lease->vendor_specific);
free(lease);
}
@@ -435,7 +451,8 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
break;
case DHCP_OPTION_ROUTER:
- lease_parse_be32(option, len, &lease->router);
+ if(len >= 4)
+ lease_parse_be32(option, 4, &lease->router);
break;
@@ -579,6 +596,17 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
return r;
break;
+
+ case DHCP_OPTION_VENDOR_SPECIFIC:
+ if (len >= 1) {
+ free(lease->vendor_specific);
+ lease->vendor_specific = memdup(option, len);
+ if (!lease->vendor_specific)
+ return -ENOMEM;
+ lease->vendor_specific_len = len;
+ }
+
+ break;
}
return 0;
@@ -603,8 +631,8 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
_cleanup_fclose_ FILE *f = NULL;
struct in_addr address;
const struct in_addr *addresses;
- const uint8_t *client_id;
- size_t client_id_len;
+ const uint8_t *client_id, *data;
+ size_t client_id_len, data_len;
const char *string;
uint16_t mtu;
struct sd_dhcp_route *routes;
@@ -690,6 +718,18 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
fprintf(f, "CLIENTID=%s\n", client_id_hex);
}
+ r = sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len);
+ if (r >= 0) {
+ _cleanup_free_ char *option_hex = NULL;
+
+ option_hex = hexmem(data, data_len);
+ if (!option_hex) {
+ r = -ENOMEM;
+ goto finish;
+ }
+ fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex);
+ }
+
r = 0;
fflush(f);
@@ -712,7 +752,8 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
_cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL,
*server_address = NULL, *next_server = NULL,
*dns = NULL, *ntp = NULL, *mtu = NULL,
- *routes = NULL, *client_id_hex = NULL;
+ *routes = NULL, *client_id_hex = NULL,
+ *vendor_specific_hex = NULL;
struct in_addr addr;
int r;
@@ -737,6 +778,7 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"ROOT_PATH", &lease->root_path,
"ROUTES", &routes,
"CLIENTID", &client_id_hex,
+ "VENDOR_SPECIFIC", &vendor_specific_hex,
NULL);
if (r < 0) {
if (r == -ENOENT)
@@ -811,13 +853,21 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
}
if (client_id_hex) {
- if (strlen (client_id_hex) % 2)
+ if (strlen(client_id_hex) % 2)
return -EINVAL;
- lease->client_id = unhexmem (client_id_hex, strlen (client_id_hex));
- if (!lease->client_id)
- return -ENOMEM;
- lease->client_id_len = strlen (client_id_hex) / 2;
+ r = unhexmem(client_id_hex, strlen(client_id_hex), (void**) &lease->client_id, &lease->client_id_len);
+ if (r < 0)
+ return r;
+ }
+
+ if (vendor_specific_hex) {
+ if (strlen(vendor_specific_hex) % 2)
+ return -EINVAL;
+
+ r = unhexmem(vendor_specific_hex, strlen(vendor_specific_hex), (void**) &lease->vendor_specific, &lease->vendor_specific_len);
+ if (r < 0)
+ return r;
}
*ret = lease;
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index fddda97f52..6a2c05185d 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -133,8 +133,6 @@ static int lldp_receive_frame(sd_lldp *lldp, tlv_packet *tlv) {
lldp->statistics.stats_frames_in_total ++;
- return 0;
-
out:
if (r < 0)
log_lldp("Receive frame failed: %s", strerror(-r));
diff --git a/src/libsystemd-terminal/grdev-drm.c b/src/libsystemd-terminal/grdev-drm.c
index 30c1a726eb..10c13e348a 100644
--- a/src/libsystemd-terminal/grdev-drm.c
+++ b/src/libsystemd-terminal/grdev-drm.c
@@ -2584,7 +2584,7 @@ static int unmanaged_card_new(grdev_card **out, grdev_session *session, struct u
} else {
/* We might get DRM-Master implicitly on open(); drop it immediately
* so we acquire it only once we're actually enabled. We don't
- * really care whether this call fails or not, but lets log any
+ * really care whether this call fails or not, but let's log any
* weird errors, anyway. */
r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
if (r < 0 && errno != EACCES && errno != EINVAL)
@@ -2777,7 +2777,7 @@ static int managed_card_resume_device_fn(sd_bus_message *signal,
if (cm->card.fd < 0) {
/* This shouldn't happen. We should already own an FD from
- * TakeDevice(). However, lets be safe and use this FD in case
+ * TakeDevice(). However, let's be safe and use this FD in case
* we really don't have one. There is no harm in doing this
* and our code works fine this way. */
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 97005dbac3..7bf1d66dde 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -465,4 +465,5 @@ global:
/* sd-bus */
sd_bus_emit_object_added;
sd_bus_emit_object_removed;
+ sd_bus_flush_close_unref;
} LIBSYSTEMD_221;
diff --git a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
index 859e2715f9..6aeb11364a 100644
--- a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
+++ b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
@@ -25,8 +25,8 @@ The header consists of the following:
= 12 bytes
-This header is then followed by the the fields array, whose first
-value is a 32bit array size.
+This header is then followed by the fields array, whose first value is
+a 32bit array size.
When using GVariant we keep the basic structure in place, only
slightly alter the header, and define protocol version '2'. The new
diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h
index b17b62ac93..f2092795f4 100644
--- a/src/libsystemd/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/sd-bus/bus-common-errors.h
@@ -46,6 +46,8 @@
#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
+#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
+#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
@@ -58,6 +60,7 @@
#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
+#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index 7a59702cb2..c53666ddd0 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1131,7 +1131,7 @@ static int add_name_change_match(sd_bus *bus,
/* If the old name is unset or empty, then
* this can match against added names */
- if (!old_owner || old_owner[0] == 0) {
+ if (isempty(old_owner)) {
item->type = KDBUS_ITEM_NAME_ADD;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1141,7 +1141,7 @@ static int add_name_change_match(sd_bus *bus,
/* If the new name is unset or empty, then
* this can match against removed names */
- if (!new_owner || new_owner[0] == 0) {
+ if (isempty(new_owner)) {
item->type = KDBUS_ITEM_NAME_REMOVE;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1185,8 +1185,10 @@ static int add_name_change_match(sd_bus *bus,
/* If the old name is unset or empty, then this can
* match against added ids */
- if (!old_owner || old_owner[0] == 0) {
+ if (isempty(old_owner)) {
item->type = KDBUS_ITEM_ID_ADD;
+ if (!isempty(new_owner))
+ item->id_change.id = new_owner_id;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
@@ -1195,8 +1197,10 @@ static int add_name_change_match(sd_bus *bus,
/* If thew new name is unset or empty, then this can
* match against removed ids */
- if (!new_owner || new_owner[0] == 0) {
+ if (isempty(new_owner)) {
item->type = KDBUS_ITEM_ID_REMOVE;
+ if (!isempty(old_owner))
+ item->id_change.id = old_owner_id;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
@@ -1219,7 +1223,7 @@ int bus_add_match_internal_kernel(
size_t sz;
const char *sender = NULL;
size_t sender_length = 0;
- uint64_t src_id = KDBUS_MATCH_ID_ANY;
+ uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
bool using_bloom = false;
unsigned i;
bool matches_name_change = true;
@@ -1332,13 +1336,25 @@ int bus_add_match_internal_kernel(
break;
}
- case BUS_MATCH_DESTINATION:
- /* The bloom filter does not include
- the destination, since it is only
- available for broadcast messages
- which do not carry a destination
- since they are undirected. */
+ case BUS_MATCH_DESTINATION: {
+ /*
+ * Kernel only supports matching on destination IDs, but
+ * not on destination names. So just skip the
+ * destination name restriction and verify it in
+ * user-space on retrieval.
+ */
+ r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
+
+ /* if not a broadcast, it cannot be a name-change */
+ if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
+ matches_name_change = false;
+
break;
+ }
case BUS_MATCH_ROOT:
case BUS_MATCH_VALUE:
@@ -1365,6 +1381,13 @@ int bus_add_match_internal_kernel(
item = KDBUS_ITEM_NEXT(item);
}
+ if (dst_id != KDBUS_MATCH_ID_ANY) {
+ item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
+ item->type = KDBUS_ITEM_DST_ID;
+ item->id = dst_id;
+ item = KDBUS_ITEM_NEXT(item);
+ }
+
if (using_bloom) {
item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
item->type = KDBUS_ITEM_BLOOM_MASK;
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index f08db2da89..6ac5ebc3da 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1332,8 +1332,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
KDBUS_ITEM_FOREACH(d, k, items) {
if (d->type == KDBUS_ITEM_TIMESTAMP)
ts = &d->timestamp;
-
- if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
+ else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
if (found)
return -EBADMSG;
found = d;
@@ -1385,15 +1384,16 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
r = 0;
}
- } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
+ if (r <= 0)
+ close_kdbus_msg(bus, k);
+ } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
r = bus_kernel_translate_message(bus, k);
- else {
+ close_kdbus_msg(bus, k);
+ } else {
log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
r = 0;
- }
-
- if (r <= 0)
close_kdbus_msg(bus, k);
+ }
return r < 0 ? r : 1;
}
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 983e2f62cd..18685be8ff 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -2161,6 +2161,7 @@ static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c)
}
static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
+ bool fixed_size = true;
size_t n_variable = 0;
unsigned i = 0;
const char *p;
@@ -2196,6 +2197,8 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c,
/* We need to add an offset for each item that has a
* variable size and that is not the last one in the
* list */
+ if (r == 0)
+ fixed_size = false;
if (r == 0 && p[n] != 0)
n_variable++;
@@ -2207,7 +2210,19 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c,
assert(c->need_offsets || n_variable == 0);
if (n_variable <= 0) {
- a = message_extend_body(m, 1, 0, add_offset, false);
+ int alignment = 1;
+
+ /* Structures with fixed-size members only have to be
+ * fixed-size themselves. But gvariant requires all fixed-size
+ * elements to be sized a multiple of their alignment. Hence,
+ * we must *always* add final padding after the last member so
+ * the overall size of the structure is properly aligned. */
+ if (fixed_size)
+ alignment = bus_gvariant_get_alignment(strempty(c->signature));
+
+ assert(alignment > 0);
+
+ a = message_extend_body(m, alignment, 0, add_offset, false);
if (!a)
return -ENOMEM;
} else {
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 2eaa7de306..c25293e5e9 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -68,6 +68,12 @@ static int node_vtable_get_userdata(
return 1;
}
+static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
+ assert(p);
+
+ return (uint8_t*) u + p->x.method.offset;
+}
+
static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
assert(p);
@@ -167,6 +173,7 @@ static int add_subtree_to_set(
sd_bus *bus,
const char *prefix,
struct node *n,
+ bool skip_subhierarchies,
Set *s,
sd_bus_error *error) {
@@ -198,11 +205,13 @@ static int add_subtree_to_set(
if (r < 0 && r != -EEXIST)
return r;
- r = add_subtree_to_set(bus, prefix, i, s, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
+ if (!skip_subhierarchies || !i->object_managers) {
+ r = add_subtree_to_set(bus, prefix, i, skip_subhierarchies, s, error);
+ if (r < 0)
+ return r;
+ if (bus->nodes_modified)
+ return 0;
+ }
}
return 0;
@@ -212,6 +221,7 @@ static int get_child_nodes(
sd_bus *bus,
const char *prefix,
struct node *n,
+ bool skip_subhierarchies,
Set **_s,
sd_bus_error *error) {
@@ -227,7 +237,7 @@ static int get_child_nodes(
if (!s)
return -ENOMEM;
- r = add_subtree_to_set(bus, prefix, n, s, error);
+ r = add_subtree_to_set(bus, prefix, n, skip_subhierarchies, s, error);
if (r < 0) {
set_free_free(s);
return r;
@@ -360,6 +370,8 @@ static int method_callbacks_run(
if (bus->nodes_modified)
return 0;
+ u = vtable_method_convert_userdata(c->vtable, u);
+
*found_object = true;
if (c->last_iteration == bus->iteration_counter)
@@ -892,7 +904,7 @@ static int process_introspect(
assert(n);
assert(found_object);
- r = get_child_nodes(bus, m->path, n, &s, &error);
+ r = get_child_nodes(bus, m->path, n, false, &s, &error);
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
if (bus->nodes_modified)
@@ -1158,12 +1170,16 @@ static int process_get_managed_objects(
if (require_fallback || !n->object_managers)
return 0;
- r = get_child_nodes(bus, m->path, n, &s, &error);
+ r = get_child_nodes(bus, m->path, n, true, &s, &error);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
+ r = set_put_strdup(s, m->path);
+ if (r < 0)
+ return r;
+
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return r;
@@ -1412,7 +1428,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
e = strrchr(path, '/');
assert(e);
- p = strndupa(path, MAX(1, path - e));
+ p = strndupa(path, MAX(1, e - path));
parent = bus_node_allocate(bus, p);
if (!parent)
@@ -1463,6 +1479,32 @@ void bus_node_gc(sd_bus *b, struct node *n) {
free(n);
}
+static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) {
+ struct node *n;
+
+ assert(bus);
+ assert(path);
+
+ n = hashmap_get(bus->nodes, path);
+ if (!n) {
+ char *prefix;
+
+ prefix = alloca(strlen(path) + 1);
+ OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
+ n = hashmap_get(bus->nodes, prefix);
+ if (n)
+ break;
+ }
+ }
+
+ while (n && !n->object_managers)
+ n = n->parent;
+
+ if (out)
+ *out = n;
+ return !!n;
+}
+
static int bus_add_object(
sd_bus *bus,
sd_bus_slot **slot,
@@ -2265,6 +2307,7 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
BUS_DONT_DESTROY(bus);
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ struct node *object_manager;
int r;
/*
@@ -2285,11 +2328,17 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
if (r < 0)
return r;
@@ -2428,6 +2477,7 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
BUS_DONT_DESTROY(bus);
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ struct node *object_manager;
int r;
/*
@@ -2448,11 +2498,17 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
if (r < 0)
return r;
@@ -2584,6 +2640,7 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch
BUS_DONT_DESTROY(bus);
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ struct node *object_manager;
char **i;
int r;
@@ -2597,11 +2654,17 @@ _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, ch
if (strv_isempty(interfaces))
return 0;
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
do {
bus->nodes_modified = false;
m = sd_bus_message_unref(m);
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
if (r < 0)
return r;
@@ -2661,6 +2724,7 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c
_public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ struct node *object_manager;
int r;
assert_return(bus, -EINVAL);
@@ -2673,7 +2737,13 @@ _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path,
if (strv_isempty(interfaces))
return 0;
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
+ r = bus_find_parent_object_manager(bus, &object_manager, path);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ESRCH;
+
+ r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
if (r < 0)
return r;
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index c452477566..b149ea16da 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -273,7 +273,7 @@ _public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *descript
return free_and_strdup(&slot->description, description);
}
-_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, char **description) {
+_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
assert_return(slot, -EINVAL);
assert_return(description, -EINVAL);
assert_return(slot->description, -ENXIO);
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 322d57ddbb..735a775cb4 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -264,6 +264,8 @@ static bool line_begins(const char *s, size_t m, const char *word) {
static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
_cleanup_free_ char *token = NULL;
+ size_t len;
+ int r;
if (!b->anonymous_auth)
return 0;
@@ -276,11 +278,12 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
if (l % 2 != 0)
return 0;
- token = unhexmem(p, l);
- if (!token)
- return -ENOMEM;
- if (memchr(token, 0, l/2))
+ r = unhexmem(p, l, (void **) &token, &len);
+ if (r < 0)
+ return 0;
+
+ if (memchr(token, 0, len))
return 0;
return !!utf8_is_valid(token);
@@ -288,6 +291,7 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
static int verify_external_token(sd_bus *b, const char *p, size_t l) {
_cleanup_free_ char *token = NULL;
+ size_t len;
uid_t u;
int r;
@@ -307,11 +311,11 @@ static int verify_external_token(sd_bus *b, const char *p, size_t l) {
if (l % 2 != 0)
return 0;
- token = unhexmem(p, l);
- if (!token)
- return -ENOMEM;
+ r = unhexmem(p, l, (void**) &token, &len);
+ if (r < 0)
+ return 0;
- if (memchr(token, 0, l/2))
+ if (memchr(token, 0, len))
return 0;
r = parse_uid(token, &u);
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index 39caa4e7d6..6aaaf0e5ec 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -1137,6 +1137,7 @@ static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FIL
if (m) {
dump(m, stdout);
+ fflush(stdout);
if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) {
log_info("Connection terminated, exiting.");
@@ -1973,7 +1974,7 @@ static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
log_parse_environment();
diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h
index 00a6e142c9..ecffc6b13c 100644
--- a/src/libsystemd/sd-bus/kdbus.h
+++ b/src/libsystemd/sd-bus/kdbus.h
@@ -374,6 +374,7 @@ enum kdbus_item_type {
KDBUS_ITEM_ATTACH_FLAGS_RECV,
KDBUS_ITEM_ID,
KDBUS_ITEM_NAME,
+ KDBUS_ITEM_DST_ID,
/* keep these item types in sync with KDBUS_ATTACH_* flags */
_KDBUS_ITEM_ATTACH_BASE = 0x1000,
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 5dd6468707..0ca225c617 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1428,6 +1428,17 @@ _public_ void sd_bus_close(sd_bus *bus) {
* ioctl on the fd when they are freed. */
}
+_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
+
+ if (!bus)
+ return NULL;
+
+ sd_bus_flush(bus);
+ sd_bus_close(bus);
+
+ return sd_bus_unref(bus);
+}
+
static void bus_enter_closing(sd_bus *bus) {
assert(bus);
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index 046e999008..754335b5e7 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -262,7 +262,7 @@ fail:
static void* client1(void*p) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
const char *hello;
int r;
@@ -361,7 +361,7 @@ static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_er
static void* client2(void*p) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
bool quit = false;
const char *mid;
diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c
index 22ea00c2fb..9b7dd2e499 100644
--- a/src/libsystemd/sd-bus/test-bus-gvariant.c
+++ b/src/libsystemd/sd-bus/test-bus-gvariant.c
@@ -132,7 +132,7 @@ static void test_bus_gvariant_get_alignment(void) {
static void test_marshal(void) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *n = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_free_ void *blob;
size_t sz;
int r;
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
index a866a56179..59deaea89f 100644
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ b/src/libsystemd/sd-bus/test-bus-marshal.c
@@ -131,6 +131,9 @@ int main(int argc, char *argv[]) {
r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
assert_se(r >= 0);
+ r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
+ assert_se(r >= 0);
+
r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
assert_se(r >= 0);
@@ -252,6 +255,22 @@ int main(int argc, char *argv[]) {
assert_se(v == 5);
assert_se(streq(y, "waldo"));
+ r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
+ assert_se(r > 0);
+ assert_se(v == 8);
+ assert_se(u64 == 777);
+ assert_se(u == 7);
+
+ r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
+ assert_se(r > 0);
+ assert_se(v == 9);
+ assert_se(u == 77);
+ assert_se(u64 == 7777);
+
+ r = sd_bus_message_read(m, "y", &v);
+ assert_se(r > 0);
+ assert_se(v == 10);
+
r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
assert_se(r > 0);
assert_se(boolean);
@@ -331,7 +350,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
- r = sd_bus_message_skip(m, "a{yv}");
+ r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y");
assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c
index a1687b1c7b..83cb5c62c2 100644
--- a/src/libsystemd/sd-bus/test-bus-match.c
+++ b/src/libsystemd/sd-bus/test-bus-match.c
@@ -92,7 +92,7 @@ int main(int argc, char *argv[]) {
};
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
enum bus_match_node_type i;
sd_bus_slot slots[19];
int r;
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
index 52952603e4..359984c7f3 100644
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ b/src/libsystemd/sd-bus/test-bus-objects.c
@@ -115,14 +115,13 @@ static int set_handler(sd_bus *bus, const char *path, const char *interface, con
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *s = NULL;
- const char *x;
int r;
assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
r = sd_bus_message_append(reply, "s", s);
assert_se(r >= 0);
- assert_se(x = startswith(path, "/value/"));
+ assert_se(startswith(path, "/value/") != NULL || strcmp(path, "/value") == 0);
assert_se(PTR_TO_UINT(userdata) == 30);
@@ -154,7 +153,7 @@ static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error)
static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0);
+ assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -165,7 +164,7 @@ static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error
static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.test", NULL) >= 0);
+ assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -176,7 +175,7 @@ static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_err
static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), m->path) >= 0);
+ assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -187,7 +186,7 @@ static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *er
static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
int r;
- assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), m->path) >= 0);
+ assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
r = sd_bus_reply_method_return(m, NULL);
assert_se(r >= 0);
@@ -229,6 +228,14 @@ static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, ch
return 1;
}
+static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+
+ if (object_path_startswith("/value/a", path))
+ assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z", NULL));
+
+ return 1;
+}
+
static void *server(void *p) {
struct context *c = p;
sd_bus *bus = NULL;
@@ -247,7 +254,9 @@ static void *server(void *p) {
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
+ assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0);
assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
+ assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0);
assert_se(sd_bus_start(bus) >= 0);
diff --git a/src/libsystemd/sd-bus/test-bus-proxy.c b/src/libsystemd/sd-bus/test-bus-proxy.c
new file mode 100644
index 0000000000..369c2f331c
--- /dev/null
+++ b/src/libsystemd/sd-bus/test-bus-proxy.c
@@ -0,0 +1,109 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "log.h"
+
+#include "sd-bus.h"
+#include "bus-kernel.h"
+#include "bus-util.h"
+#include "bus-dump.h"
+
+typedef struct {
+ const char *sender;
+ int matched_acquired;
+} TestProxyMatch;
+
+static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ TestProxyMatch *match = userdata;
+ const char *name;
+ int r;
+
+ r = sd_bus_message_read(m, "s", &name);
+ assert_se(r >= 0);
+
+ if (!streq_ptr(match->sender, name))
+ return 0;
+
+ ++match->matched_acquired;
+ return 1;
+}
+
+static void test_proxy_matched(void) {
+ _cleanup_bus_flush_close_unref_ sd_bus *a = NULL;
+ TestProxyMatch match = {};
+ int r;
+
+ /* open bus 'a' */
+
+ r = sd_bus_new(&a);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(a, "unix:path=/var/run/dbus/system_bus_socket");
+ assert_se(r >= 0);
+
+ r = sd_bus_set_bus_client(a, true);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(a);
+ assert_se(r >= 0);
+
+ r = sd_bus_add_match(a, NULL,
+ "type='signal',"
+ "member='NameAcquired'",
+ test_proxy_acquired, &match);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(a, &match.sender);
+ assert_se(r >= 0);
+
+ /* barrier to guarantee proxy/dbus-daemon handled the previous data */
+ r = sd_bus_call_method(a,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "GetId",
+ NULL, NULL, NULL);
+ assert_se(r >= 0);
+
+ /* now we can be sure the Name* signals were sent */
+ do {
+ r = sd_bus_process(a, NULL);
+ } while (r > 0);
+ assert_se(r == 0);
+
+ assert_se(match.matched_acquired == 1);
+}
+
+int main(int argc, char **argv) {
+ if (access("/var/run/dbus/system_bus_socket", F_OK) < 0)
+ return EXIT_TEST_SKIP;
+
+ log_parse_environment();
+
+ test_proxy_matched();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index b274f71093..7cea5a0746 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -791,6 +791,9 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
device->subsystem_set = true;
}
+ if (!device->subsystem)
+ return -ENOENT;
+
*ret = device->subsystem;
return 0;
@@ -908,6 +911,9 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
}
+ if (!device->driver)
+ return -ENOENT;
+
*ret = device->driver;
return 0;
@@ -1002,6 +1008,8 @@ _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
return r;
}
+ assert_return(device->sysname, -ENOENT);
+
*ret = device->sysname;
return 0;
diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h
index 7290f4e875..4026e2c341 100644
--- a/src/libsystemd/sd-netlink/netlink-internal.h
+++ b/src/libsystemd/sd-netlink/netlink-internal.h
@@ -92,18 +92,27 @@ struct sd_netlink {
sd_event *event;
};
+struct netlink_attribute {
+ size_t offset; /* offset from hdr to attribute */
+ bool nested:1;
+ bool net_byteorder:1;
+};
+
+struct netlink_container {
+ const struct NLTypeSystem *type_system; /* the type system of the container */
+ size_t offset; /* offset from hdr to the start of the container */
+ struct netlink_attribute *attributes;
+ unsigned short n_attributes; /* number of attributes in container */
+};
+
struct sd_netlink_message {
RefCount n_ref;
sd_netlink *rtnl;
struct nlmsghdr *hdr;
- const struct NLTypeSystem *(container_type_system[RTNL_CONTAINER_DEPTH]); /* the type of the container and all its parents */
- size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */
+ struct netlink_container containers[RTNL_CONTAINER_DEPTH];
unsigned n_containers; /* number of containers */
- size_t next_rta_offset; /* offset from hdr to next rta */
- size_t *rta_offset_tb[RTNL_CONTAINER_DEPTH];
- unsigned short rta_tb_size[RTNL_CONTAINER_DEPTH];
bool sealed:1;
bool broadcast:1;
@@ -122,14 +131,6 @@ int socket_read_message(sd_netlink *nl);
int rtnl_rqueue_make_room(sd_netlink *rtnl);
int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
-int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data);
-int rtnl_message_parse(sd_netlink_message *m,
- size_t **rta_offset_tb,
- unsigned short *rta_tb_size,
- int max,
- struct rtattr *rta,
- unsigned int rt_len);
-
/* Make sure callbacks don't destroy the rtnl connection */
#define RTNL_DONT_DESTROY(rtnl) \
_cleanup_netlink_unref_ _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index a935b821f6..b0ed2f2882 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -34,10 +34,11 @@
#include "netlink-internal.h"
#include "netlink-types.h"
-#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
+#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
+#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
sd_netlink_message *m;
@@ -88,7 +89,7 @@ int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- type_get_type_system(nl_type, &m->container_type_system[0]);
+ type_get_type_system(nl_type, &m->containers[0].type_system);
m->hdr->nlmsg_len = size;
m->hdr->nlmsg_type = type;
@@ -129,7 +130,7 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
free(m->hdr);
for (i = 0; i <= m->n_containers; i++)
- free(m->rta_offset_tb[i]);
+ free(m->containers[i].attributes);
sd_netlink_message_unref(m->next);
@@ -223,7 +224,7 @@ static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, u
assert(m);
- r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
+ r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type);
if (r < 0)
return r;
@@ -406,18 +407,18 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
if (r < 0)
return r;
- r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
+ r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
if (r < 0)
return r;
r = type_system_union_protocol_get_type_system(type_system_union,
- &m->container_type_system[m->n_containers + 1],
+ &m->containers[m->n_containers + 1].type_system,
family);
if (r < 0)
return r;
} else {
- r = type_system_get_type_system(m->container_type_system[m->n_containers],
- &m->container_type_system[m->n_containers + 1],
+ r = type_system_get_type_system(m->containers[m->n_containers].type_system,
+ &m->containers[m->n_containers + 1].type_system,
type);
if (r < 0)
return r;
@@ -427,7 +428,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
if (r < 0)
return r;
- m->container_offsets[m->n_containers ++] = r;
+ m->containers[m->n_containers ++].offset = r;
return 0;
}
@@ -439,12 +440,12 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
+ r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
if (r < 0)
return r;
r = type_system_union_get_type_system(type_system_union,
- &m->container_type_system[m->n_containers + 1],
+ &m->containers[m->n_containers + 1].type_system,
key);
if (r < 0)
return r;
@@ -454,11 +455,11 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
return r;
/* do we evere need non-null size */
- r = add_rtattr(m, type, NULL, 0);
+ r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
if (r < 0)
return r;
- m->container_offsets[m->n_containers ++] = r;
+ m->containers[m->n_containers ++].offset = r;
return 0;
}
@@ -469,29 +470,35 @@ int sd_netlink_message_close_container(sd_netlink_message *m) {
assert_return(!m->sealed, -EPERM);
assert_return(m->n_containers > 0, -EINVAL);
- m->container_type_system[m->n_containers] = NULL;
+ m->containers[m->n_containers].type_system = NULL;
m->n_containers --;
return 0;
}
-int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) {
+static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) {
+ struct netlink_attribute *attribute;
struct rtattr *rta;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
assert_return(data, -EINVAL);
assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
- assert(m->rta_offset_tb[m->n_containers]);
- assert(type < m->rta_tb_size[m->n_containers]);
+ assert(m->containers[m->n_containers].attributes);
+ assert(type < m->containers[m->n_containers].n_attributes);
- if(!m->rta_offset_tb[m->n_containers][type])
+ attribute = &m->containers[m->n_containers].attributes[type];
+
+ if(!attribute->offset)
return -ENODATA;
- rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
+ rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
*data = RTA_DATA(rta);
+ if (net_byteorder)
+ *net_byteorder = attribute->net_byteorder;
+
return RTA_PAYLOAD(rta);
}
@@ -505,7 +512,7 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if (strnlen(attr_data, r) >= (size_t) r)
@@ -527,7 +534,7 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint8_t))
@@ -540,8 +547,9 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8
}
int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) {
- int r;
void *attr_data;
+ bool net_byteorder;
+ int r;
assert_return(m, -EINVAL);
@@ -549,21 +557,26 @@ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint16_t))
return -EIO;
- if (data)
- *data = *(uint16_t *) attr_data;
+ if (data) {
+ if (net_byteorder)
+ *data = be16toh(*(uint16_t *) attr_data);
+ else
+ *data = *(uint16_t *) attr_data;
+ }
return 0;
}
int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) {
- int r;
void *attr_data;
+ bool net_byteorder;
+ int r;
assert_return(m, -EINVAL);
@@ -571,14 +584,18 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
if (r < 0)
return r;
else if ((size_t)r < sizeof(uint32_t))
return -EIO;
- if (data)
- *data = *(uint32_t *) attr_data;
+ if (data) {
+ if (net_byteorder)
+ *data = be32toh(*(uint32_t *) attr_data);
+ else
+ *data = *(uint32_t *) attr_data;
+ }
return 0;
}
@@ -593,7 +610,7 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct ether_addr))
@@ -615,7 +632,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct ifa_cacheinfo))
@@ -637,7 +654,7 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type,
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct in_addr))
@@ -659,7 +676,7 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
if (r < 0)
return r;
- r = rtnl_message_read_internal(m, type, &attr_data);
+ r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct in6_addr))
@@ -671,6 +688,42 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
return 0;
}
+static int netlink_container_parse(sd_netlink_message *m,
+ struct netlink_container *container,
+ int count,
+ struct rtattr *rta,
+ unsigned int rt_len) {
+ _cleanup_free_ struct netlink_attribute *attributes = NULL;
+
+ attributes = new0(struct netlink_attribute, count);
+ if(!attributes)
+ return -ENOMEM;
+
+ for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
+ unsigned short type;
+
+ type = RTA_TYPE(rta);
+
+ /* if the kernel is newer than the headers we used
+ when building, we ignore out-of-range attributes */
+ if (type >= count)
+ continue;
+
+ if (attributes[type].offset)
+ log_debug("rtnl: message parse - overwriting repeated attribute");
+
+ attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
+ attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
+ attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER;
+ }
+
+ container->attributes = attributes;
+ attributes = NULL;
+ container->n_attributes = count;
+
+ return 0;
+}
+
int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) {
const NLType *nl_type;
const NLTypeSystem *type_system;
@@ -682,7 +735,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
assert_return(m, -EINVAL);
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
- r = type_system_get_type(m->container_type_system[m->n_containers],
+ r = type_system_get_type(m->containers[m->n_containers].type_system,
&nl_type,
type_id);
if (r < 0)
@@ -691,7 +744,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
type = type_get_type(nl_type);
if (type == NETLINK_TYPE_NESTED) {
- r = type_system_get_type_system(m->container_type_system[m->n_containers],
+ r = type_system_get_type_system(m->containers[m->n_containers].type_system,
&type_system,
type_id);
if (r < 0)
@@ -699,7 +752,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
} else if (type == NETLINK_TYPE_UNION) {
const NLTypeSystemUnion *type_system_union;
- r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
+ r = type_system_get_type_system_union(m->containers[m->n_containers].type_system,
&type_system_union,
type_id);
if (r < 0)
@@ -744,7 +797,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
} else
return -EINVAL;
- r = rtnl_message_read_internal(m, type_id, &container);
+ r = netlink_message_read_internal(m, type_id, &container, NULL);
if (r < 0)
return r;
else
@@ -752,18 +805,17 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
m->n_containers ++;
- r = rtnl_message_parse(m,
- &m->rta_offset_tb[m->n_containers],
- &m->rta_tb_size[m->n_containers],
- type_system_get_count(type_system),
- container,
- size);
+ r = netlink_container_parse(m,
+ &m->containers[m->n_containers],
+ type_system_get_count(type_system),
+ container,
+ size);
if (r < 0) {
m->n_containers --;
return r;
}
- m->container_type_system[m->n_containers] = type_system;
+ m->containers[m->n_containers].type_system = type_system;
return 0;
}
@@ -773,9 +825,9 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
assert_return(m->sealed, -EINVAL);
assert_return(m->n_containers > 0, -EINVAL);
- free(m->rta_offset_tb[m->n_containers]);
- m->rta_offset_tb[m->n_containers] = NULL;
- m->container_type_system[m->n_containers] = NULL;
+ free(m->containers[m->n_containers].attributes);
+ m->containers[m->n_containers].attributes = NULL;
+ m->containers[m->n_containers].type_system = NULL;
m->n_containers --;
@@ -810,41 +862,6 @@ int sd_netlink_message_get_errno(sd_netlink_message *m) {
return err->error;
}
-int rtnl_message_parse(sd_netlink_message *m,
- size_t **rta_offset_tb,
- unsigned short *rta_tb_size,
- int count,
- struct rtattr *rta,
- unsigned int rt_len) {
- unsigned short type;
- size_t *tb;
-
- tb = new0(size_t, count);
- if(!tb)
- return -ENOMEM;
-
- *rta_tb_size = count;
-
- for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
- type = RTA_TYPE(rta);
-
- /* if the kernel is newer than the headers we used
- when building, we ignore out-of-range attributes
- */
- if (type >= count)
- continue;
-
- if (tb[type])
- log_debug("rtnl: message parse - overwriting repeated attribute");
-
- tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
- }
-
- *rta_offset_tb = tb;
-
- return 0;
-}
-
int sd_netlink_message_rewind(sd_netlink_message *m) {
const NLType *nl_type;
uint16_t type;
@@ -859,15 +876,13 @@ int sd_netlink_message_rewind(sd_netlink_message *m) {
rtnl_message_seal(m);
for (i = 1; i <= m->n_containers; i++) {
- free(m->rta_offset_tb[i]);
- m->rta_offset_tb[i] = NULL;
- m->rta_tb_size[i] = 0;
- m->container_type_system[i] = NULL;
+ free(m->containers[i].attributes);
+ m->containers[i].attributes = NULL;
}
m->n_containers = 0;
- if (m->rta_offset_tb[0]) {
+ if (m->containers[0].attributes) {
/* top-level attributes have already been parsed */
return 0;
}
@@ -886,14 +901,13 @@ int sd_netlink_message_rewind(sd_netlink_message *m) {
type_get_type_system(nl_type, &type_system);
- m->container_type_system[0] = type_system;
+ m->containers[0].type_system = type_system;
- r = rtnl_message_parse(m,
- &m->rta_offset_tb[m->n_containers],
- &m->rta_tb_size[m->n_containers],
- type_system_get_count(type_system),
- (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
- NLMSG_PAYLOAD(m->hdr, size));
+ r = netlink_container_parse(m,
+ &m->containers[m->n_containers],
+ type_system_get_count(type_system),
+ (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
+ NLMSG_PAYLOAD(m->hdr, size));
if (r < 0)
return r;
}
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 74ac2ab344..9b68935245 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -196,27 +196,37 @@ static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 },
[IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
[IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
};
static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
- [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
- [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
- [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
- [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 },
- [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 },
- [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
- [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
- [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 },
- [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 },
- [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
+ [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
+ [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
+ [IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
};
static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
[IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 },
[IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 },
[IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 },
- [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
- [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
+ [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
+ [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
};
static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
@@ -227,7 +237,7 @@ static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 },
[IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
[IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 },
- [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32},
+ [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
};
/* these strings must match the .kind entries in the kernel */
@@ -319,8 +329,11 @@ static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1]
[IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 },
[IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 },
[IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 },
[IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 },
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
+ [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
};
static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
@@ -362,9 +375,9 @@ static const NLTypeSystem rtnl_af_spec_type_system = {
};
static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
- [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR, },
- [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR, },
- [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1, },
+ [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
+ [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
+ [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
[IFLA_MTU] = { .type = NETLINK_TYPE_U32 },
[IFLA_LINK] = { .type = NETLINK_TYPE_U32 },
/*
diff --git a/src/locale/localectl.c b/src/locale/localectl.c
index 601839d5dc..3616f4af1f 100644
--- a/src/locale/localectl.c
+++ b/src/locale/localectl.c
@@ -667,7 +667,7 @@ static int localectl_main(sd_bus *bus, int argc, char *argv[]) {
}
int main(int argc, char*argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 0e59350e98..88756542fd 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -1240,7 +1240,7 @@ static const sd_bus_vtable locale_vtable[] = {
};
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
assert(c);
@@ -1272,7 +1272,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
int main(int argc, char *argv[]) {
_cleanup_(context_free) Context context = {};
_cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
log_set_target(LOG_TARGET_AUTO);
diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in
index ab7b66f651..de55c9a4ec 100644
--- a/src/login/71-seat.rules.in
+++ b/src/login/71-seat.rules.in
@@ -17,6 +17,11 @@ SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
# 'Plugable' USB hub, sound, network, graphics adapter
SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="000[13]", ENV{ID_AUTOSEAT}="1"
+# qemu (version 2.4+) has a PCI-PCI bridge (-device pci-bridge-seat) to group
+# devices belonging to one seat. See:
+# http://git.qemu.org/?p=qemu.git;a=blob;f=docs/multiseat.txt
+SUBSYSTEM=="pci", ATTR{vendor}=="0x1b36", ATTR{device}=="0x000a", TAG+="seat", ENV{ID_AUTOSEAT}="1"
+
# Mimo 720, with integrated USB hub, displaylink graphics, and e2i
# touchscreen. This device carries no proper VID/PID in the USB hub,
# but it does carry good ID data in the graphics component, hence we
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index 0e5dce5925..c53ea8add7 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -223,7 +223,7 @@ static int parse_argv(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
log_parse_environment();
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 06208bc4b3..9709eca9bd 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -1389,7 +1389,7 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
}
int main(int argc, char *argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index a6c01f7d85..96a20e27b9 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -317,7 +317,6 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
int r;
assert(m);
- assert(session);
if (pid < 1)
return -EINVAL;
@@ -330,7 +329,8 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
if (!s)
return 0;
- *session = s;
+ if (session)
+ *session = s;
return 1;
}
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 8ebcd3f5ca..e6371ff04d 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -689,45 +689,26 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
return r;
}
- manager_get_session_by_pid(m, leader, &session);
- if (session) {
- _cleanup_free_ char *path = NULL;
- _cleanup_close_ int fifo_fd = -1;
-
- /* Session already exists, client is probably
- * something like "su" which changes uid but is still
- * the same session */
-
- fifo_fd = session_create_fifo(session);
- if (fifo_fd < 0)
- return fifo_fd;
-
- path = session_bus_path(session);
- if (!path)
- return -ENOMEM;
-
- log_debug("Sending reply about an existing session: "
- "id=%s object_path=%s uid=%u runtime_path=%s "
- "session_fd=%d seat=%s vtnr=%u",
- session->id,
- path,
- (uint32_t) session->user->uid,
- session->user->runtime_path,
- fifo_fd,
- session->seat ? session->seat->id : "",
- (uint32_t) session->vtnr);
-
- return sd_bus_reply_method_return(
- message, "soshusub",
- session->id,
- path,
- session->user->runtime_path,
- fifo_fd,
- (uint32_t) session->user->uid,
- session->seat ? session->seat->id : "",
- (uint32_t) session->vtnr,
- true);
- }
+ r = manager_get_session_by_pid(m, leader, NULL);
+ if (r > 0)
+ return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
+
+ /*
+ * Old gdm and lightdm start the user-session on the same VT as
+ * the greeter session. But they destroy the greeter session
+ * after the user-session and want the user-session to take
+ * over the VT. We need to support this for
+ * backwards-compatibility, so make sure we allow new sessions
+ * on a VT that a greeter is running on. Furthermore, to allow
+ * re-logins, we have to allow a greeter to take over a used VT for
+ * the exact same reasons.
+ */
+ if (c != SESSION_GREETER &&
+ vtnr > 0 &&
+ vtnr < m->seat0->position_count &&
+ m->seat0->positions[vtnr] &&
+ m->seat0->positions[vtnr]->class != SESSION_GREETER)
+ return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
audit_session_from_pid(leader, &audit_id);
if (audit_id > 0) {
@@ -1194,7 +1175,7 @@ static int trigger_device(Manager *m, struct udev_device *d) {
if (!t)
return -ENOMEM;
- write_string_file(t, "change");
+ write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
}
return 0;
@@ -1486,18 +1467,13 @@ static int execute_shutdown_or_sleep(
return 0;
}
-static int manager_inhibit_timeout_handler(
- sd_event_source *s,
- uint64_t usec,
- void *userdata) {
+int manager_dispatch_delayed(Manager *manager, bool timeout) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Inhibitor *offending = NULL;
- Manager *manager = userdata;
int r;
assert(manager);
- assert(manager->inhibit_timeout_source == s);
if (manager->action_what == 0 || manager->action_job)
return 0;
@@ -1505,6 +1481,9 @@ static int manager_inhibit_timeout_handler(
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
_cleanup_free_ char *comm = NULL, *u = NULL;
+ if (!timeout)
+ return 0;
+
(void) get_process_comm(offending->pid, &comm);
u = uid_to_name(offending->uid);
@@ -1520,9 +1499,25 @@ static int manager_inhibit_timeout_handler(
manager->action_unit = NULL;
manager->action_what = 0;
+ return r;
}
- return 0;
+ return 1;
+}
+
+static int manager_inhibit_timeout_handler(
+ sd_event_source *s,
+ uint64_t usec,
+ void *userdata) {
+
+ Manager *manager = userdata;
+ int r;
+
+ assert(manager);
+ assert(manager->inhibit_timeout_source == s);
+
+ r = manager_dispatch_delayed(manager, true);
+ return (r < 0) ? r : 0;
}
static int delay_shutdown_or_sleep(
@@ -1779,7 +1774,7 @@ static int nologin_timeout_handler(
log_info("Creating /run/nologin, blocking further logins...");
- r = write_string_file_atomic("/run/nologin", "System is going down.");
+ r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
if (r < 0)
log_error_errno(r, "Failed to create /run/nologin: %m");
else
@@ -2454,8 +2449,6 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2463,6 +2456,8 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 3c30eeaa95..495ec50be0 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -269,7 +269,7 @@ int seat_set_active(Seat *s, Session *session) {
int seat_switch_to(Seat *s, unsigned int num) {
/* Public session positions skip 0 (there is only F1-F12). Maybe it
* will get reassigned in the future, so return error for now. */
- if (!num)
+ if (num == 0)
return -EINVAL;
if (num >= s->position_count || !s->positions[num]) {
@@ -286,12 +286,12 @@ int seat_switch_to(Seat *s, unsigned int num) {
int seat_switch_to_next(Seat *s) {
unsigned int start, i;
- if (!s->position_count)
+ if (s->position_count == 0)
return -EINVAL;
start = 1;
- if (s->active && s->active->pos > 0)
- start = s->active->pos;
+ if (s->active && s->active->position > 0)
+ start = s->active->position;
for (i = start + 1; i < s->position_count; ++i)
if (s->positions[i])
@@ -307,12 +307,12 @@ int seat_switch_to_next(Seat *s) {
int seat_switch_to_previous(Seat *s) {
unsigned int start, i;
- if (!s->position_count)
+ if (s->position_count == 0)
return -EINVAL;
start = 1;
- if (s->active && s->active->pos > 0)
- start = s->active->pos;
+ if (s->active && s->active->position > 0)
+ start = s->active->position;
for (i = start - 1; i > 0; --i)
if (s->positions[i])
@@ -472,21 +472,21 @@ int seat_stop_sessions(Seat *s, bool force) {
void seat_evict_position(Seat *s, Session *session) {
Session *iter;
- unsigned int pos = session->pos;
+ unsigned int pos = session->position;
- session->pos = 0;
+ session->position = 0;
- if (!pos)
+ if (pos == 0)
return;
if (pos < s->position_count && s->positions[pos] == session) {
s->positions[pos] = NULL;
/* There might be another session claiming the same
- * position (eg., during gdm->session transition), so lets look
+ * position (eg., during gdm->session transition), so let's look
* for it and set it on the free slot. */
LIST_FOREACH(sessions_by_seat, iter, s->sessions) {
- if (iter->pos == pos) {
+ if (iter->position == pos && session_get_state(iter) != SESSION_CLOSING) {
s->positions[pos] = iter;
break;
}
@@ -504,15 +504,15 @@ void seat_claim_position(Seat *s, Session *session, unsigned int pos) {
seat_evict_position(s, session);
- session->pos = pos;
- if (pos > 0 && !s->positions[pos])
+ session->position = pos;
+ if (pos > 0)
s->positions[pos] = session;
}
static void seat_assign_position(Seat *s, Session *session) {
unsigned int pos;
- if (session->pos > 0)
+ if (session->position > 0)
return;
for (pos = 1; pos < s->position_count; ++pos)
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 6a450b02a0..45f4c09d3d 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -264,7 +264,7 @@ int session_save(Session *s) {
fprintf(f, "VTNR=%u\n", s->vtnr);
if (!s->vtnr)
- fprintf(f, "POS=%u\n", s->pos);
+ fprintf(f, "POSITION=%u\n", s->position);
if (s->leader > 0)
fprintf(f, "LEADER="PID_FMT"\n", s->leader);
@@ -302,7 +302,7 @@ int session_load(Session *s) {
*seat = NULL,
*vtnr = NULL,
*state = NULL,
- *pos = NULL,
+ *position = NULL,
*leader = NULL,
*type = NULL,
*class = NULL,
@@ -329,7 +329,7 @@ int session_load(Session *s) {
"DESKTOP", &s->desktop,
"VTNR", &vtnr,
"STATE", &state,
- "POS", &pos,
+ "POSITION", &position,
"LEADER", &leader,
"TYPE", &type,
"CLASS", &class,
@@ -388,10 +388,10 @@ int session_load(Session *s) {
if (!s->seat || !seat_has_vts(s->seat))
s->vtnr = 0;
- if (pos && s->seat) {
+ if (position && s->seat) {
unsigned int npos;
- safe_atou(pos, &npos);
+ safe_atou(position, &npos);
seat_claim_position(s->seat, s, npos);
}
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 4bf739a44d..b8565ebf51 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -70,7 +70,7 @@ struct Session {
Manager *manager;
const char *id;
- unsigned int pos;
+ unsigned int position;
SessionType type;
SessionClass class;
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 0f72d70b10..36c0e8626d 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -103,11 +103,7 @@ static int property_get_sessions(
}
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- return 1;
+ return sd_bus_message_close_container(reply);
}
static int property_get_idle_hint(
diff --git a/src/login/logind.c b/src/login/logind.c
index 01f7cd9ee0..e2fb496289 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1109,6 +1109,12 @@ static int manager_run(Manager *m) {
manager_gc(m, true);
+ r = manager_dispatch_delayed(m, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ continue;
+
r = sd_event_run(m->event, (uint64_t) -1);
if (r < 0)
return r;
diff --git a/src/login/logind.h b/src/login/logind.h
index feb381d0b1..ad437b72cb 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -194,3 +194,5 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char
int manager_setup_wall_message_timer(Manager *m);
bool logind_wall_tty_filter(const char *tty, void *userdata);
+
+int manager_dispatch_delayed(Manager *manager, bool timeout);
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 0ad78802dd..d8deb7bc8b 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -90,6 +90,42 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="LockSession"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="UnlockSession"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="LockSessions"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="UnlockSessions"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="KillSession"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="KillUser"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="TerminateSession"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="TerminateUser"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="TerminateSeat"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="PowerOff"/>
<allow send_destination="org.freedesktop.login1"
@@ -130,6 +166,14 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="ScheduleShutdown"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="CancelScheduledShutdown"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="CanRebootToFirmwareSetup"/>
<allow send_destination="org.freedesktop.login1"
@@ -146,6 +190,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Seat"
+ send_member="Terminate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Seat"
send_member="ActivateSession"/>
<allow send_destination="org.freedesktop.login1"
@@ -162,14 +210,30 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Session"
+ send_member="Terminate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Session"
send_member="Activate"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Session"
+ send_member="Lock"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Session"
+ send_member="Unlock"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Session"
send_member="SetIdleHint"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Session"
+ send_member="Kill"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Session"
send_member="TakeControl"/>
<allow send_destination="org.freedesktop.login1"
@@ -188,6 +252,14 @@
send_interface="org.freedesktop.login1.Session"
send_member="PauseDeviceComplete"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.User"
+ send_member="Terminate"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.User"
+ send_member="Kill"/>
+
<allow receive_sender="org.freedesktop.login1"/>
</policy>
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index dd192b90ce..f83d18b035 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -31,6 +31,7 @@
#include <security/pam_ext.h>
#include <security/pam_misc.h>
+#include "bus-common-errors.h"
#include "util.h"
#include "audit.h"
#include "macro.h"
@@ -213,7 +214,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
*seat = NULL,
*type = NULL, *class = NULL,
*class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int session_fd = -1, existing, r;
bool debug = false, remote;
struct passwd *pw;
@@ -399,8 +400,13 @@ _public_ PAM_EXTERN int pam_sm_open_session(
remote_host,
0);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r));
- return PAM_SYSTEM_ERR;
+ if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) {
+ pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r));
+ return PAM_SUCCESS;
+ } else {
+ pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r));
+ return PAM_SYSTEM_ERR;
+ }
}
r = sd_bus_message_read(reply,
@@ -496,7 +502,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
int argc, const char **argv) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
const void *existing = NULL;
const char *id;
int r;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 7813a0bcc7..dc42ffdc52 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -55,17 +55,12 @@ static int property_get_id(
sd_bus_error *error) {
Machine *m = userdata;
- int r;
assert(bus);
assert(reply);
assert(m);
- r = sd_bus_message_append_array(reply, 'y', &m->id, 16);
- if (r < 0)
- return r;
-
- return 1;
+ return sd_bus_message_append_array(reply, 'y', &m->id, 16);
}
static int property_get_state(
@@ -104,7 +99,6 @@ static int property_get_netif(
sd_bus_error *error) {
Machine *m = userdata;
- int r;
assert(bus);
assert(reply);
@@ -112,11 +106,7 @@ static int property_get_netif(
assert_cc(sizeof(int) == sizeof(int32_t));
- r = sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
- if (r < 0)
- return r;
-
- return 1;
+ return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
}
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 7938aa4dbe..7cb6ce77ac 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -2572,7 +2572,7 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
}
int main(int argc, char*argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 0e971a6789..3637815fc9 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -31,12 +31,13 @@
#include "bus-common-errors.h"
#include "cgroup-util.h"
#include "btrfs-util.h"
+#include "formats-util.h"
+#include "process-util.h"
#include "machine-image.h"
#include "machine-pool.h"
#include "image-dbus.h"
#include "machined.h"
#include "machine-dbus.h"
-#include "formats-util.h"
static int property_get_pool_path(
sd_bus *bus,
@@ -840,6 +841,230 @@ static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bu
return bus_image_method_set_limit(message, i, error);
}
+static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_fclose_ FILE *f = NULL;
+ Manager *m = userdata;
+ const char *name, *p;
+ Machine *machine;
+ uint32_t uid;
+ int r;
+
+ r = sd_bus_message_read(message, "su", &name, &uid);
+ if (r < 0)
+ return r;
+
+ if (UID_IS_INVALID(uid))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
+
+ machine = hashmap_get(m->machines, name);
+ if (!machine)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
+
+ p = procfs_file_alloca(machine->leader, "uid_map");
+ f = fopen(p, "re");
+ if (!f)
+ return -errno;
+
+ for (;;) {
+ uid_t uid_base, uid_shift, uid_range, converted;
+ int k;
+
+ errno = 0;
+ k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
+ if (k < 0 && feof(f))
+ break;
+ if (k != 3) {
+ if (ferror(f) && errno != 0)
+ return -errno;
+
+ return -EIO;
+ }
+
+ if (uid < uid_base || uid >= uid_base + uid_range)
+ continue;
+
+ converted = uid - uid_base + uid_shift;
+ if (UID_IS_INVALID(converted))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
+
+ return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
+ }
+
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name);
+}
+
+static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ Machine *machine;
+ uid_t uid;
+ Iterator i;
+ int r;
+
+ r = sd_bus_message_read(message, "u", &uid);
+ if (r < 0)
+ return r;
+ if (UID_IS_INVALID(uid))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
+ if (uid < 0x10000)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
+
+ HASHMAP_FOREACH(machine, m->machines, i) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char p[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
+
+ xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader);
+ f = fopen(p, "re");
+ if (!f) {
+ log_warning_errno(errno, "Failed top open %s, ignoring,", p);
+ continue;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *o = NULL;
+ uid_t uid_base, uid_shift, uid_range, converted;
+ int k;
+
+ errno = 0;
+ k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
+ if (k < 0 && feof(f))
+ break;
+ if (k != 3) {
+ if (ferror(f) && errno != 0)
+ return -errno;
+
+ return -EIO;
+ }
+
+ if (uid < uid_shift || uid >= uid_shift + uid_range)
+ continue;
+
+ converted = (uid - uid_shift + uid_base);
+ if (UID_IS_INVALID(converted))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
+
+ o = machine_bus_path(machine);
+ if (!o)
+ return -ENOMEM;
+
+ return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
+ }
+ }
+
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
+}
+
+static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
+ _cleanup_fclose_ FILE *f = NULL;
+ Manager *m = groupdata;
+ const char *name, *p;
+ Machine *machine;
+ uint32_t gid;
+ int r;
+
+ r = sd_bus_message_read(message, "su", &name, &gid);
+ if (r < 0)
+ return r;
+
+ if (GID_IS_INVALID(gid))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
+
+ machine = hashmap_get(m->machines, name);
+ if (!machine)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
+
+ p = procfs_file_alloca(machine->leader, "gid_map");
+ f = fopen(p, "re");
+ if (!f)
+ return -errno;
+
+ for (;;) {
+ gid_t gid_base, gid_shift, gid_range, converted;
+ int k;
+
+ errno = 0;
+ k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
+ if (k < 0 && feof(f))
+ break;
+ if (k != 3) {
+ if (ferror(f) && errno != 0)
+ return -errno;
+
+ return -EIO;
+ }
+
+ if (gid < gid_base || gid >= gid_base + gid_range)
+ continue;
+
+ converted = gid - gid_base + gid_shift;
+ if (GID_IS_INVALID(converted))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
+
+ return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
+ }
+
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name);
+}
+
+static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
+ Manager *m = groupdata;
+ Machine *machine;
+ gid_t gid;
+ Iterator i;
+ int r;
+
+ r = sd_bus_message_read(message, "u", &gid);
+ if (r < 0)
+ return r;
+ if (GID_IS_INVALID(gid))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
+ if (gid < 0x10000)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
+
+ HASHMAP_FOREACH(machine, m->machines, i) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char p[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1];
+
+ xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader);
+ f = fopen(p, "re");
+ if (!f) {
+ log_warning_errno(errno, "Failed top open %s, ignoring,", p);
+ continue;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *o = NULL;
+ gid_t gid_base, gid_shift, gid_range, converted;
+ int k;
+
+ errno = 0;
+ k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
+ if (k < 0 && feof(f))
+ break;
+ if (k != 3) {
+ if (ferror(f) && errno != 0)
+ return -errno;
+
+ return -EIO;
+ }
+
+ if (gid < gid_shift || gid >= gid_shift + gid_range)
+ continue;
+
+ converted = (gid - gid_shift + gid_base);
+ if (GID_IS_INVALID(converted))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
+
+ o = machine_bus_path(machine);
+ if (!o)
+ return -ENOMEM;
+
+ return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
+ }
+ }
+
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
+}
+
const sd_bus_vtable manager_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
@@ -869,6 +1094,10 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("MachineNew", "so", 0),
SD_BUS_SIGNAL("MachineRemoved", "so", 0),
SD_BUS_VTABLE_END
diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf
index 93aaf6a377..d58f01507b 100644
--- a/src/machine/org.freedesktop.machine1.conf
+++ b/src/machine/org.freedesktop.machine1.conf
@@ -113,6 +113,22 @@
send_member="SetImageLimit"/>
<allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.machine1.Manager"
+ send_member="MapFromMachineUser"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.machine1.Manager"
+ send_member="MapToMachineUser"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.machine1.Manager"
+ send_member="MapFromMachineGroup"/>
+
+ <allow send_destination="org.freedesktop.machine1"
+ send_interface="org.freedesktop.machine1.Manager"
+ send_member="MapToMachineGroup"/>
+
+ <allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Machine"
send_member="GetAddresses"/>
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index d446bfa8b3..4aa301b112 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -270,12 +270,18 @@ static int dhcp_lease_lost(Link *link) {
if (link->network->dhcp_hostname) {
const char *hostname = NULL;
- r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
- if (r >= 0 && hostname) {
- r = link_set_hostname(link, "");
+ if (!link->network->hostname)
+ r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
+ else
+ hostname = link->network->hostname;
+
+ if (r >= 0 || hostname) {
+ r = link_set_hostname(link, hostname);
if (r < 0)
- log_link_error(link,
- "Failed to reset transient hostname");
+ log_link_error_errno(link, r,
+ "Failed to set transient hostname to '%s': %m",
+ hostname);
+
}
}
@@ -464,8 +470,12 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
if (link->network->dhcp_hostname) {
const char *hostname;
- r = sd_dhcp_lease_get_hostname(lease, &hostname);
- if (r >= 0) {
+ if (!link->network->hostname)
+ r = sd_dhcp_lease_get_hostname(lease, &hostname);
+ else
+ hostname = link->network->hostname;
+
+ if (r >= 0 || hostname) {
r = link_set_hostname(link, hostname);
if (r < 0)
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
@@ -616,14 +626,19 @@ int dhcp4_configure(Link *link) {
if (link->network->dhcp_sendhost) {
_cleanup_free_ char *hostname = NULL;
+ const char *hn = NULL;
+
+ if (!link->network->hostname) {
+ hostname = gethostname_malloc();
+ if (!hostname)
+ return -ENOMEM;
- hostname = gethostname_malloc();
- if (!hostname)
- return -ENOMEM;
+ hn = hostname;
+ } else
+ hn = link->network->hostname;
- if (!is_localhost(hostname)) {
- r = sd_dhcp_client_set_hostname(link->dhcp_client,
- hostname);
+ if (!is_localhost(hn)) {
+ r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
if (r < 0)
return r;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 16243a5352..f20f68b482 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -116,6 +116,16 @@ static bool link_ipv6_forward_enabled(Link *link) {
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
}
+static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
+ if (link->flags & IFF_LOOPBACK)
+ return _IPV6_PRIVACY_EXTENSIONS_INVALID;
+
+ if (!link->network)
+ return _IPV6_PRIVACY_EXTENSIONS_INVALID;
+
+ return link->network->ipv6_privacy_extensions;
+}
+
#define FLAG_STRING(string, flag, old, new) \
(((old ^ new) & flag) \
? ((old & flag) ? (" -" string) : (" +" string)) \
@@ -836,9 +846,6 @@ static int link_set_bridge(Link *link) {
assert(link);
assert(link->network);
- if(link->network->cost == 0)
- return 0;
-
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");
@@ -851,6 +858,26 @@ static int link_set_bridge(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+ 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");
+
+ 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");
+
+ 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");
+
+ 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");
+
+ 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->cost != 0) {
r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
if (r < 0)
@@ -1360,8 +1387,7 @@ static int link_joined(Link *link) {
return link_enter_set_addresses(link);
}
-static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m,
- void *userdata) {
+static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@@ -1474,35 +1500,84 @@ static int link_enter_join_netdev(Link *link) {
}
static int link_set_ipv4_forward(Link *link) {
- const char *p = NULL;
+ const char *p = NULL, *v;
int r;
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
return 0;
p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
- r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link)));
- if (r < 0)
+ v = one_zero(link_ipv4_forward_enabled(link));
+
+ r = write_string_file(p, v, 0);
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, v) > 0)
+ return 0;
+
log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
+ }
return 0;
}
static int link_set_ipv6_forward(Link *link) {
- const char *p = NULL;
+ const char *p = NULL, *v = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
if (!socket_ipv6_is_supported())
return 0;
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
- r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link)));
- if (r < 0)
+ v = one_zero(link_ipv6_forward_enabled(link));
+
+ r = write_string_file(p, v, 0);
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, v) > 0)
+ return 0;
+
log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
+ }
+
+ return 0;
+}
+
+static int link_set_ipv6_privacy_extensions(Link *link) {
+ char buf[DECIMAL_STR_MAX(unsigned) + 1];
+ IPv6PrivacyExtensions s;
+ const char *p = NULL;
+ int r;
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ s = link_ipv6_privacy_extensions(link);
+ if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
+ return 0;
+
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
+ xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
+
+ r = write_string_file(p, buf, 0);
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, buf) > 0)
+ return 0;
+
+ log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
+ }
return 0;
}
@@ -1526,6 +1601,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = link_set_ipv6_privacy_extensions(link);
+ if (r < 0)
+ return r;
+
if (link_ipv4ll_enabled(link)) {
r = ipv4ll_configure(link);
if (r < 0)
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index 66ed2e013c..fa3ba38a3b 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -36,6 +36,8 @@ Tunnel.TOS, config_parse_unsigned, 0,
Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl)
Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc)
Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode)
+Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel)
+Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp)
Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer)
Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer)
VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id)
@@ -59,6 +61,7 @@ Tun.Group, config_parse_string, 0,
Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue)
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)
Tap.User, config_parse_string, 0, offsetof(TunTap, user_name)
Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name)
Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode)
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 5533fb5c7b..7fd9ef584b 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -33,6 +33,7 @@
#include "conf-parser.h"
#define DEFAULT_TNL_HOP_LIMIT 64
+#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF)
static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
[NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -184,6 +185,16 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
+ if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+ r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
+ }
+
+ r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
+
return r;
}
@@ -264,6 +275,19 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
+ if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+ r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
+ }
+
+ if (t->copy_dscp)
+ t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
+
+ r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
+
switch (t->ip6tnl_mode) {
case NETDEV_IP6_TNL_MODE_IP6IP6:
proto = IPPROTO_IPV6;
@@ -380,6 +404,52 @@ int config_parse_tunnel_address(const char *unit,
return 0;
}
+static const char* const ipv6_flowlabel_table[_NETDEV_IPV6_FLOWLABEL_MAX] = {
+ [NETDEV_IPV6_FLOWLABEL_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ipv6_flowlabel, IPv6FlowLabel);
+
+int config_parse_ipv6_flowlabel(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) {
+ IPv6FlowLabel *ipv6_flowlabel = data;
+ Tunnel *t = userdata;
+ IPv6FlowLabel s;
+ int k = 0;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(ipv6_flowlabel);
+
+ s = ipv6_flowlabel_from_string(rvalue);
+ if (s != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+ *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
+ t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
+ } else {
+ r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
+ if (r >= 0) {
+ if (k > 0xFFFFF)
+ log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
+ else {
+ *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL;
+ t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
+ }
+ }
+ }
+
+ return 0;
+}
+
static void ipip_init(NetDev *n) {
Tunnel *t = IPIP(n);
@@ -452,6 +522,7 @@ static void ip6tnl_init(NetDev *n) {
t->ttl = DEFAULT_TNL_HOP_LIMIT;
t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
+ t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
}
const NetDevVTable ipip_vtable = {
diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h
index 88f57ac105..1fd2b94ae1 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -33,6 +33,12 @@ typedef enum Ip6TnlMode {
_NETDEV_IP6_TNL_MODE_INVALID = -1,
} Ip6TnlMode;
+typedef enum IPv6FlowLabel {
+ NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1,
+ _NETDEV_IPV6_FLOWLABEL_MAX,
+ _NETDEV_IPV6_FLOWLABEL_INVALID = -1,
+} IPv6FlowLabel;
+
struct Tunnel {
NetDev meta;
@@ -48,8 +54,10 @@ struct Tunnel {
union in_addr_union remote;
Ip6TnlMode ip6tnl_mode;
+ IPv6FlowLabel ipv6_flowlabel;
bool pmtudisc;
+ bool copy_dscp;
};
extern const NetDevVTable ipip_vtable;
@@ -70,3 +78,23 @@ int config_parse_ip6tnl_mode(const char *unit, const char *filename,
unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data,
void *userdata);
+
+int config_parse_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);
+
+const char *ipv6_flowlabel_to_string(IPv6FlowLabel d) _const_;
+IPv6FlowLabel ipv6_flowlabel_from_string(const char *d) _pure_;
+
+int config_parse_ipv6_flowlabel(const char *unit, const char *filename,
+ unsigned line, const char *section,
+ unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data,
+ void *userdata);
diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c
index 378312f091..ba84e802fc 100644
--- a/src/network/networkd-netdev-tuntap.c
+++ b/src/network/networkd-netdev-tuntap.c
@@ -51,6 +51,9 @@ static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
if (t->multi_queue)
ifr->ifr_flags |= IFF_MULTI_QUEUE;
+ if (t->vnet_hdr)
+ ifr->ifr_flags |= IFF_VNET_HDR;
+
strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
return 0;
diff --git a/src/network/networkd-netdev-tuntap.h b/src/network/networkd-netdev-tuntap.h
index b804875bbb..29f8bb0ea5 100644
--- a/src/network/networkd-netdev-tuntap.h
+++ b/src/network/networkd-netdev-tuntap.h
@@ -33,6 +33,7 @@ struct TunTap {
bool one_queue;
bool multi_queue;
bool packet_info;
+ bool vnet_hdr;
};
extern const NetDevVTable tun_vtable;
diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h
index fe5254e91f..e7d1306f13 100644
--- a/src/network/networkd-netdev-vxlan.h
+++ b/src/network/networkd-netdev-vxlan.h
@@ -53,3 +53,14 @@ struct VxLan {
};
extern const NetDevVTable vxlan_vtable;
+
+int config_parse_vxlan_group_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);
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index ece9ecc251..6949b403c8 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -92,10 +92,11 @@ static void netdev_cancel_callbacks(NetDev *netdev) {
assert(netdev->manager);
assert(netdev->manager->rtnl);
- callback->callback(netdev->manager->rtnl, m, link);
+ callback->callback(netdev->manager->rtnl, m, callback->link);
}
LIST_REMOVE(callbacks, netdev->callbacks, callback);
+ link_unref(callback->link);
free(callback);
}
}
@@ -177,6 +178,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
static int netdev_enter_failed(NetDev *netdev) {
netdev->state = NETDEV_STATE_FAILED;
+ netdev_cancel_callbacks(netdev);
+
return 0;
}
@@ -266,12 +269,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
int r;
assert(netdev);
+ assert(netdev->manager);
+ assert(netdev->manager->rtnl);
assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
if (netdev->state == NETDEV_STATE_READY) {
r = netdev_enslave_ready(netdev, link, callback);
if (r < 0)
return r;
+ } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) {
+ _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+
+ r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
+ if (r >= 0)
+ callback(netdev->manager->rtnl, m, link);
} else {
/* the netdev is not yet read, save this request for when it is */
netdev_join_callback *cb;
diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c
index b5f8f5cfb2..5717a15327 100644
--- a/src/network/networkd-network-bus.c
+++ b/src/network/networkd-network-bus.c
@@ -53,11 +53,7 @@ static int property_get_ether_addrs(
return r;
}
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- return 1;
+ return sd_bus_message_close_container(reply);
}
const sd_bus_vtable network_vtable[] = {
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index b05bc949f2..83224d7109 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -15,69 +15,76 @@ struct ConfigPerfItem;
%struct-type
%includes
%%
-Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac)
-Match.Path, config_parse_strv, 0, offsetof(Network, match_path)
-Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver)
-Match.Type, config_parse_strv, 0, offsetof(Network, match_type)
-Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name)
-Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host)
-Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt)
-Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel)
-Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
-Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
-Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
-Network.Description, config_parse_string, 0, offsetof(Network, description)
-Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
-Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
-Network.VLAN, config_parse_netdev, 0, 0
-Network.MACVLAN, config_parse_netdev, 0, 0
-Network.IPVLAN, config_parse_netdev, 0, 0
-Network.VXLAN, config_parse_netdev, 0, 0
-Network.Tunnel, config_parse_tunnel, 0, 0
-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.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
-Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token)
-Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
-Network.Address, config_parse_address, 0, 0
-Network.Gateway, config_parse_gateway, 0, 0
-Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
-Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
-Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr)
-Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
-Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
-Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
-Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
-Address.Address, config_parse_address, 0, 0
-Address.Peer, config_parse_address, 0, 0
-Address.Broadcast, config_parse_broadcast, 0, 0
-Address.Label, config_parse_label, 0, 0
-Route.Gateway, config_parse_gateway, 0, 0
-Route.Destination, config_parse_destination, 0, 0
-Route.Source, config_parse_destination, 0, 0
-Route.Metric, config_parse_route_priority, 0, 0
-Route.Scope, config_parse_route_scope, 0, 0
-DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
-DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
-DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
-DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
-DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
-DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
-DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
-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.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
-Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost)
-BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
-BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
+Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac)
+Match.Path, config_parse_strv, 0, offsetof(Network, match_path)
+Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver)
+Match.Type, config_parse_strv, 0, offsetof(Network, match_type)
+Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name)
+Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host)
+Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt)
+Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel)
+Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
+Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
+Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
+Network.Description, config_parse_string, 0, offsetof(Network, description)
+Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
+Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
+Network.VLAN, config_parse_netdev, 0, 0
+Network.MACVLAN, config_parse_netdev, 0, 0
+Network.IPVLAN, config_parse_netdev, 0, 0
+Network.VXLAN, config_parse_netdev, 0, 0
+Network.Tunnel, config_parse_tunnel, 0, 0
+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.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
+Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token)
+Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
+Network.Address, config_parse_address, 0, 0
+Network.Gateway, config_parse_gateway, 0, 0
+Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
+Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
+Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr)
+Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
+Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
+Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
+Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
+Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
+Address.Address, config_parse_address, 0, 0
+Address.Peer, config_parse_address, 0, 0
+Address.Broadcast, config_parse_broadcast, 0, 0
+Address.Label, config_parse_label, 0, 0
+Route.Gateway, config_parse_gateway, 0, 0
+Route.Destination, config_parse_destination, 0, 0
+Route.Source, config_parse_destination, 0, 0
+Route.Metric, config_parse_route_priority, 0, 0
+Route.Scope, config_parse_route_scope, 0, 0
+DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
+DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
+DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
+DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
+DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
+DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
+DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
+DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
+DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, 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.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
+Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost)
+Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu)
+Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin)
+Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave)
+Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root)
+Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood)
+BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
+BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
/* backwards compatibility: do not add new entries to this section */
-Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
-DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
-DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
-DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
-DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
+Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
+DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
+DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
+DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
+DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
+DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
+DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index ec95c8661e..d8f42621af 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -107,10 +107,16 @@ static int network_load_one(Manager *manager, const char *filename) {
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
+ network->use_bpdu = true;
+ network->allow_port_to_be_root = true;
+ network->unicast_flood = true;
+
network->llmnr = LLMNR_SUPPORT_YES;
network->link_local = ADDRESS_FAMILY_IPV6;
+ network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
+
r = config_parse(NULL, filename, file,
"Match\0"
"Link\0"
@@ -205,6 +211,7 @@ void network_free(Network *network) {
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ free(network->hostname);
free(network->mac);
@@ -751,3 +758,94 @@ int config_parse_address_family_boolean_with_kernel(
return 0;
}
+
+static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
+ [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
+ [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
+ [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
+
+int config_parse_ipv6_privacy_extensions(
+ 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) {
+
+ IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
+ int k;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(ipv6_privacy_extensions);
+
+ /* Our enum shall be a superset of booleans, hence first try
+ * to parse as boolean, and then as enum */
+
+ k = parse_boolean(rvalue);
+ if (k > 0)
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
+ else if (k == 0)
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
+ else {
+ IPv6PrivacyExtensions s;
+
+ s = ipv6_privacy_extensions_from_string(rvalue);
+ if (s < 0) {
+
+ if (streq(rvalue, "kernel"))
+ s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
+ return 0;
+ }
+ }
+
+ *ipv6_privacy_extensions = s;
+ }
+
+ return 0;
+}
+
+int config_parse_hostname(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) {
+ char **hostname = data;
+ char *hn = NULL;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = config_parse_string(unit, filename, line, section, section_line,
+ lvalue, ltype, rvalue, &hn, userdata);
+ if (r < 0)
+ return r;
+
+ if (!hostname_is_valid(hn)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "hostname is not valid, ignoring assignment: %s", rvalue);
+
+ free(hn);
+ return 0;
+ }
+
+ *hostname = hn;
+
+ return 0;
+}
diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c
index 32c31fdf3d..d958b48771 100644
--- a/src/network/networkd-wait-online.c
+++ b/src/network/networkd-wait-online.c
@@ -66,7 +66,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hiq", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0)
switch (c) {
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 9fe8a5fa15..e6259043fa 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -103,7 +103,7 @@ int main(int argc, char *argv[]) {
r = manager_rtnl_enumerate_addresses(m);
if (r < 0) {
- log_error_errno(r, "Could not enumerate links: %m");
+ log_error_errno(r, "Could not enumerate addresses: %m");
goto out;
}
diff --git a/src/network/networkd.h b/src/network/networkd.h
index ac6e2c8a8e..a285a4b08f 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -90,6 +90,15 @@ typedef enum DCHPClientIdentifier {
_DHCP_CLIENT_ID_INVALID = -1,
} DCHPClientIdentifier;
+typedef enum IPv6PrivacyExtensions {
+ /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
+ IPV6_PRIVACY_EXTENSIONS_NO,
+ IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC,
+ IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */
+ _IPV6_PRIVACY_EXTENSIONS_MAX,
+ _IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
+} IPv6PrivacyExtensions;
+
struct FdbEntry {
Network *network;
unsigned section;
@@ -124,6 +133,7 @@ struct Network {
AddressFamilyBoolean dhcp;
DCHPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
+ char *hostname;
bool dhcp_dns;
bool dhcp_ntp;
bool dhcp_mtu;
@@ -140,11 +150,18 @@ struct Network {
bool dhcp_server;
+ bool use_bpdu;
+ bool hairpin;
+ bool fast_leave;
+ bool allow_port_to_be_root;
+ bool unicast_flood;
unsigned cost;
AddressFamilyBoolean ip_forward;
bool ip_masquerade;
+ IPv6PrivacyExtensions ipv6_privacy_extensions;
+
struct ether_addr *mac;
unsigned mtu;
@@ -308,28 +325,6 @@ int config_parse_tunnel(const char *unit,
void *data,
void *userdata);
-int config_parse_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);
-
-int config_parse_vxlan_group_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);
-
extern const sd_bus_vtable network_vtable[];
int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
@@ -455,3 +450,14 @@ int config_parse_address_family_boolean_with_kernel(const char *unit, const char
const char* link_operstate_to_string(LinkOperationalState s) _const_;
LinkOperationalState link_operstate_from_string(const char *s) _pure_;
+
+/* IPv6 privacy extensions support */
+
+const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
+IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
+
+int config_parse_ipv6_privacy_extensions(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);
+
+
+/* Hostname */
+int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 4cf2d14ae2..65b9a5071b 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -341,6 +341,11 @@ static int custom_mounts_prepare(void) {
for (i = 0; i < arg_n_custom_mounts; i++) {
CustomMount *m = &arg_custom_mounts[i];
+ if (arg_userns && arg_uid_shift == UID_INVALID && path_equal(m->destination, "/")) {
+ log_error("--private-users with automatic UID shift may not be combined with custom root mounts.");
+ return -EINVAL;
+ }
+
if (m->type != CUSTOM_MOUNT_OVERLAY)
continue;
@@ -751,9 +756,8 @@ static int parse_argv(int argc, char *argv[]) {
/* If two parameters are specified,
* the first one is the lower, the
* second one the upper directory. And
- * we'll also define the the
- * destination mount point the same as
- * the upper. */
+ * we'll also define the destination
+ * mount point the same as the upper. */
upper = lower[1];
lower[1] = NULL;
@@ -1028,6 +1032,7 @@ static int tmpfs_patch_options(const char *options, char **ret) {
char *buf = NULL;
if (arg_userns && arg_uid_shift != 0) {
+ assert(arg_uid_shift != UID_INVALID);
if (options)
(void) asprintf(&buf, "%s,uid=" UID_FMT ",gid=" UID_FMT, options, arg_uid_shift, arg_uid_shift);
@@ -1074,18 +1079,18 @@ static int mount_all(const char *dest, bool userns) {
} MountPoint;
static const MountPoint mount_table[] = {
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true },
- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */
- { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, true, true }, /* Then, make it r/o */
- { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false },
- { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, true, false },
- { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false },
+ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true },
+ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */
+ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true }, /* Then, make it r/o */
+ { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false },
+ { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, true, false },
+ { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false },
+ { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
+ { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false },
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false },
#ifdef HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false, false }, /* Then, make it r/o */
+ { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false }, /* Bind mount first */
+ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false }, /* Then, make it r/o */
#endif
};
@@ -1697,7 +1702,7 @@ static int setup_boot_id(const char *dest) {
id128_format_as_uuid(rnd, as_uuid);
- r = write_string_file(from, as_uuid);
+ r = write_string_file(from, as_uuid, WRITE_STRING_FILE_CREATE);
if (r < 0)
return log_error_errno(r, "Failed to write boot id: %m");
@@ -1780,15 +1785,13 @@ static int setup_pts(const char *dest) {
#ifdef HAVE_SELINUX
if (arg_selinux_apifs_context)
(void) asprintf(&options,
- "newinstance,ptmxmode=0666,mode=620,uid=" UID_FMT ",gid=" GID_FMT ",context=\"%s\"",
- arg_uid_shift,
+ "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT ",context=\"%s\"",
arg_uid_shift + TTY_GID,
arg_selinux_apifs_context);
else
#endif
(void) asprintf(&options,
- "newinstance,ptmxmode=0666,mode=620,uid=" UID_FMT ",gid=" GID_FMT,
- arg_uid_shift,
+ "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT,
arg_uid_shift + TTY_GID);
if (!options)
@@ -2273,7 +2276,7 @@ static int drop_capabilities(void) {
static int register_machine(pid_t pid, int local_ifindex) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
if (!arg_register)
@@ -2430,7 +2433,7 @@ static int register_machine(pid_t pid, int local_ifindex) {
static int terminate_machine(pid_t pid) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
const char *path;
int r;
@@ -2502,7 +2505,7 @@ static int reset_audit_loginuid(void) {
if (streq(p, "4294967295"))
return 0;
- r = write_string_file("/proc/self/loginuid", "4294967295");
+ r = write_string_file("/proc/self/loginuid", "4294967295", 0);
if (r < 0) {
log_error_errno(r,
"Failed to reset audit login UID. This probably means that your kernel is too\n"
@@ -4259,6 +4262,7 @@ static int outer_child(
int pid_socket,
int kmsg_socket,
int rtnl_socket,
+ int uid_shift_socket,
FDSet *fds,
int argc,
char *argv[]) {
@@ -4317,6 +4321,16 @@ static int outer_child(
if (r < 0)
return r;
+ if (arg_userns) {
+ l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL);
+ if (l < 0)
+ return log_error_errno(errno, "Failed to send UID shift: %m");
+ if (l != sizeof(arg_uid_shift)) {
+ log_error("Short write while sending UID shift.");
+ return -EIO;
+ }
+ }
+
/* Turn directory into bind mount */
if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0)
return log_error_errno(errno, "Failed to make bind mount: %m");
@@ -4397,6 +4411,7 @@ static int outer_child(
if (pid == 0) {
pid_socket = safe_close(pid_socket);
+ uid_shift_socket = safe_close(uid_shift_socket);
/* The inner child has all namespaces that are
* requested, so that we all are owned by the user if
@@ -4430,13 +4445,13 @@ static int setup_uid_map(pid_t pid) {
xsprintf(uid_map, "/proc/" PID_FMT "/uid_map", pid);
xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, arg_uid_shift, arg_uid_range);
- r = write_string_file(uid_map, line);
+ r = write_string_file(uid_map, line, 0);
if (r < 0)
return log_error_errno(r, "Failed to write UID map: %m");
/* We always assign the same UID and GID ranges */
xsprintf(uid_map, "/proc/" PID_FMT "/gid_map", pid);
- r = write_string_file(uid_map, line);
+ r = write_string_file(uid_map, line, 0);
if (r < 0)
return log_error_errno(r, "Failed to write GID map: %m");
@@ -4687,7 +4702,8 @@ int main(int argc, char *argv[]) {
}
for (;;) {
- _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 };
+ _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 },
+ uid_shift_socket_pair[2] = { -1, -1 };
ContainerStatus container_status;
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
static const struct sigaction sa = {
@@ -4696,10 +4712,10 @@ int main(int argc, char *argv[]) {
};
int ifi = 0;
ssize_t l;
- _cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- char last_char = 0;
+ _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
+ _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ char last_char = 0;
r = barrier_create(&barrier);
if (r < 0) {
@@ -4722,6 +4738,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ if (arg_userns)
+ if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) {
+ r = log_error_errno(errno, "Failed to create uid shift socket pair: %m");
+ goto finish;
+ }
+
/* Child can be killed before execv(), so handle SIGCHLD
* in order to interrupt parent's blocking calls and
* give it a chance to call wait() and terminate. */
@@ -4756,6 +4778,7 @@ int main(int argc, char *argv[]) {
kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]);
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
pid_socket_pair[0] = safe_close(pid_socket_pair[0]);
+ uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]);
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
@@ -4771,6 +4794,7 @@ int main(int argc, char *argv[]) {
pid_socket_pair[1],
kmsg_socket_pair[1],
rtnl_socket_pair[1],
+ uid_shift_socket_pair[1],
fds,
argc, argv);
if (r < 0)
@@ -4819,6 +4843,17 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof(arg_uid_shift), 0);
+ if (l < 0) {
+ r = log_error_errno(errno, "Failed to read UID shift: %m");
+ goto finish;
+ }
+ if (l != sizeof(arg_uid_shift)) {
+ log_error("Short read while reading UID shift: %m");
+ r = EIO;
+ goto finish;
+ }
+
r = setup_uid_map(pid);
if (r < 0)
goto finish;
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index 9476ad1694..cdec83d074 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -28,9 +28,12 @@
#include "util.h"
#include "nss-util.h"
#include "bus-util.h"
+#include "bus-common-errors.h"
#include "in-addr-util.h"
NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
+NSS_GETPW_PROTOTYPES(mymachines);
+NSS_GETGR_PROTOTYPES(mymachines);
static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
unsigned c = 0;
@@ -79,7 +82,7 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
_cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_free_ int *ifindices = NULL;
_cleanup_free_ char *class = NULL;
size_t l, ms, idx;
@@ -228,7 +231,7 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
char **canonp) {
_cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_free_ char *class = NULL;
unsigned c = 0, i = 0;
char *r_name, *r_aliases, *r_addr, *r_addr_list;
@@ -380,4 +383,319 @@ fail:
return NSS_STATUS_UNAVAIL;
}
-NSS_GETHOSTBYNAME_FALLBACKS(mymachines)
+NSS_GETHOSTBYNAME_FALLBACKS(mymachines);
+
+enum nss_status _nss_mymachines_getpwnam_r(
+ const char *name,
+ struct passwd *pwd,
+ char *buffer, size_t buflen,
+ int *errnop) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ const char *p, *e, *machine;
+ uint32_t mapped;
+ uid_t uid;
+ size_t l;
+ int r;
+
+ assert(name);
+ assert(pwd);
+
+ p = startswith(name, "vu-");
+ if (!p)
+ goto not_found;
+
+ e = strrchr(p, '-');
+ if (!e || e == p)
+ goto not_found;
+
+ r = parse_uid(e + 1, &uid);
+ if (r < 0)
+ goto not_found;
+
+ machine = strndupa(p, e - p);
+ if (!machine_name_is_valid(machine))
+ goto not_found;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "MapFromMachineUser",
+ &error,
+ &reply,
+ "su",
+ machine, (uint32_t) uid);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
+ goto not_found;
+
+ goto fail;
+ }
+
+ r = sd_bus_message_read(reply, "u", &mapped);
+ if (r < 0)
+ goto fail;
+
+ l = strlen(name);
+ if (buflen < l+1) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ memcpy(buffer, name, l+1);
+
+ pwd->pw_name = buffer;
+ pwd->pw_uid = mapped;
+ pwd->pw_gid = 65534; /* nobody */
+ pwd->pw_gecos = buffer;
+ pwd->pw_passwd = (char*) "*"; /* locked */
+ pwd->pw_dir = (char*) "/";
+ pwd->pw_shell = (char*) "/sbin/nologin";
+
+ *errnop = 0;
+ return NSS_STATUS_SUCCESS;
+
+not_found:
+ *errnop = 0;
+ return NSS_STATUS_NOTFOUND;
+
+fail:
+ *errnop = -r;
+ return NSS_STATUS_UNAVAIL;
+}
+
+enum nss_status _nss_mymachines_getpwuid_r(
+ uid_t uid,
+ struct passwd *pwd,
+ char *buffer, size_t buflen,
+ int *errnop) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ const char *machine, *object;
+ uint32_t mapped;
+ int r;
+
+ if (UID_IS_INVALID(uid)) {
+ r = -EINVAL;
+ goto fail;
+ }
+
+ /* We consider all uids < 65536 host uids */
+ if (uid < 0x10000)
+ goto not_found;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "MapToMachineUser",
+ &error,
+ &reply,
+ "u",
+ (uint32_t) uid);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
+ goto not_found;
+
+ goto fail;
+ }
+
+ r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped);
+ if (r < 0)
+ goto fail;
+
+ if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ pwd->pw_name = buffer;
+ pwd->pw_uid = uid;
+ pwd->pw_gid = 65534; /* nobody */
+ pwd->pw_gecos = buffer;
+ pwd->pw_passwd = (char*) "*"; /* locked */
+ pwd->pw_dir = (char*) "/";
+ pwd->pw_shell = (char*) "/sbin/nologin";
+
+ *errnop = 0;
+ return NSS_STATUS_SUCCESS;
+
+not_found:
+ *errnop = 0;
+ return NSS_STATUS_NOTFOUND;
+
+fail:
+ *errnop = -r;
+ return NSS_STATUS_UNAVAIL;
+}
+
+enum nss_status _nss_mymachines_getgrnam_r(
+ const char *name,
+ struct group *gr,
+ char *buffer, size_t buflen,
+ int *errnop) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ const char *p, *e, *machine;
+ uint32_t mapped;
+ uid_t gid;
+ size_t l;
+ int r;
+
+ assert(name);
+ assert(gr);
+
+ p = startswith(name, "vg-");
+ if (!p)
+ goto not_found;
+
+ e = strrchr(p, '-');
+ if (!e || e == p)
+ goto not_found;
+
+ r = parse_gid(e + 1, &gid);
+ if (r < 0)
+ goto not_found;
+
+ machine = strndupa(p, e - p);
+ if (!machine_name_is_valid(machine))
+ goto not_found;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "MapFromMachineGroup",
+ &error,
+ &reply,
+ "su",
+ machine, (uint32_t) gid);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
+ goto not_found;
+
+ goto fail;
+ }
+
+ r = sd_bus_message_read(reply, "u", &mapped);
+ if (r < 0)
+ goto fail;
+
+ l = sizeof(char*) + strlen(name) + 1;
+ if (buflen < l) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ memzero(buffer, sizeof(char*));
+ strcpy(buffer + sizeof(char*), name);
+
+ gr->gr_name = buffer + sizeof(char*);
+ gr->gr_gid = gid;
+ gr->gr_passwd = (char*) "*"; /* locked */
+ gr->gr_mem = (char**) buffer;
+
+ *errnop = 0;
+ return NSS_STATUS_SUCCESS;
+
+not_found:
+ *errnop = 0;
+ return NSS_STATUS_NOTFOUND;
+
+fail:
+ *errnop = -r;
+ return NSS_STATUS_UNAVAIL;
+}
+
+enum nss_status _nss_mymachines_getgrgid_r(
+ gid_t gid,
+ struct group *gr,
+ char *buffer, size_t buflen,
+ int *errnop) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
+ const char *machine, *object;
+ uint32_t mapped;
+ int r;
+
+ if (GID_IS_INVALID(gid)) {
+ r = -EINVAL;
+ goto fail;
+ }
+
+ /* We consider all gids < 65536 host gids */
+ if (gid < 0x10000)
+ goto not_found;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ goto fail;
+
+ r = sd_bus_call_method(bus,
+ "org.freedesktop.machine1",
+ "/org/freedesktop/machine1",
+ "org.freedesktop.machine1.Manager",
+ "MapToMachineGroup",
+ &error,
+ &reply,
+ "u",
+ (uint32_t) gid);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
+ goto not_found;
+
+ goto fail;
+ }
+
+ r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped);
+ if (r < 0)
+ goto fail;
+
+ if (buflen < sizeof(char*) + 1) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ memzero(buffer, sizeof(char*));
+ if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) {
+ *errnop = ENOMEM;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ gr->gr_name = buffer + sizeof(char*);
+ gr->gr_gid = gid;
+ gr->gr_passwd = (char*) "*"; /* locked */
+ gr->gr_mem = (char**) buffer;
+
+ *errnop = 0;
+ return NSS_STATUS_SUCCESS;
+
+not_found:
+ *errnop = 0;
+ return NSS_STATUS_NOTFOUND;
+
+fail:
+ *errnop = -r;
+ return NSS_STATUS_UNAVAIL;
+}
diff --git a/src/nss-mymachines/nss-mymachines.sym b/src/nss-mymachines/nss-mymachines.sym
index f80b51c1aa..0728ac3ba7 100644
--- a/src/nss-mymachines/nss-mymachines.sym
+++ b/src/nss-mymachines/nss-mymachines.sym
@@ -13,5 +13,9 @@ global:
_nss_mymachines_gethostbyname2_r;
_nss_mymachines_gethostbyname3_r;
_nss_mymachines_gethostbyname4_r;
+ _nss_mymachines_getpwnam_r;
+ _nss_mymachines_getpwuid_r;
+ _nss_mymachines_getgrnam_r;
+ _nss_mymachines_getgrgid_r;
local: *;
};
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c
index 8f181a6c72..da22f98eba 100644
--- a/src/nss-resolve/nss-resolve.c
+++ b/src/nss-resolve/nss-resolve.c
@@ -122,7 +122,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
_cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
const char *canonical = NULL;
size_t l, ms, idx;
char *r_name;
@@ -305,7 +305,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
_cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char *r_name, *r_aliases, *r_addr, *r_addr_list;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
size_t l, idx, ms, alen;
const char *canonical;
int c, r, i = 0, ifindex;
@@ -513,7 +513,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
_cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char *r_name, *r_aliases, *r_addr, *r_addr_list;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
unsigned c = 0, i = 0;
size_t ms = 0, idx;
const char *n;
diff --git a/src/python-systemd/.gitignore b/src/python-systemd/.gitignore
deleted file mode 100644
index 4124b7affd..0000000000
--- a/src/python-systemd/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/id128-constants.h
-*.py[oc]
diff --git a/src/python-systemd/Makefile b/src/python-systemd/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/python-systemd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/python-systemd/__init__.py b/src/python-systemd/__init__.py
deleted file mode 100644
index 0d56b992f4..0000000000
--- a/src/python-systemd/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012 David Strauss
-#
-# 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.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/python-systemd/_daemon.c b/src/python-systemd/_daemon.c
deleted file mode 100644
index 7c5f1b2bb6..0000000000
--- a/src/python-systemd/_daemon.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#define PY_SSIZE_T_CLEAN
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wredundant-decls"
-#include <Python.h>
-#pragma GCC diagnostic pop
-
-#include <stdbool.h>
-#include <assert.h>
-#include <sys/socket.h>
-
-#include "systemd/sd-daemon.h"
-#include "pyutil.h"
-#include "macro.h"
-
-PyDoc_STRVAR(module__doc__,
- "Python interface to the libsystemd-daemon library.\n\n"
- "Provides _listen_fds, notify, booted, and is_* functions\n"
- "which wrap sd_listen_fds, sd_notify, sd_booted, sd_is_* and\n"
- "useful for socket activation and checking if the system is\n"
- "running under systemd."
-);
-
-PyDoc_STRVAR(booted__doc__,
- "booted() -> bool\n\n"
- "Return True iff this system is running under systemd.\n"
- "Wraps sd_daemon_booted(3)."
-);
-
-static PyObject* booted(PyObject *self, PyObject *args) {
- int r;
- assert(args == NULL);
-
- r = sd_booted();
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-PyDoc_STRVAR(notify__doc__,
- "notify(status, unset_environment=False) -> bool\n\n"
- "Send a message to the init system about a status change.\n"
- "Wraps sd_notify(3).");
-
-static PyObject* notify(PyObject *self, PyObject *args, PyObject *keywds) {
- int r;
- const char* msg;
- int unset = false;
-
- static const char* const kwlist[] = {
- "status",
- "unset_environment",
- NULL,
- };
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|p:notify",
- (char**) kwlist, &msg, &unset))
- return NULL;
-#else
- PyObject *obj = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|O:notify",
- (char**) kwlist, &msg, &obj))
- return NULL;
- if (obj != NULL)
- unset = PyObject_IsTrue(obj);
- if (unset < 0)
- return NULL;
-#endif
-
- r = sd_notify(unset, msg);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-
-PyDoc_STRVAR(listen_fds__doc__,
- "_listen_fds(unset_environment=True) -> int\n\n"
- "Return the number of descriptors passed to this process by the init system\n"
- "as part of the socket-based activation logic.\n"
- "Wraps sd_listen_fds(3)."
-);
-
-static PyObject* listen_fds(PyObject *self, PyObject *args, PyObject *keywds) {
- int r;
- int unset = true;
-
- static const char* const kwlist[] = {"unset_environment", NULL};
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "|p:_listen_fds",
- (char**) kwlist, &unset))
- return NULL;
-#else
- PyObject *obj = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "|O:_listen_fds",
- (char**) kwlist, &obj))
- return NULL;
- if (obj != NULL)
- unset = PyObject_IsTrue(obj);
- if (unset < 0)
- return NULL;
-#endif
-
- r = sd_listen_fds(unset);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return long_FromLong(r);
-}
-
-PyDoc_STRVAR(is_fifo__doc__,
- "_is_fifo(fd, path) -> bool\n\n"
- "Returns True iff the descriptor refers to a FIFO or a pipe.\n"
- "Wraps sd_is_fifo(3)."
-);
-
-
-static PyObject* is_fifo(PyObject *self, PyObject *args) {
- int r;
- int fd;
- const char *path = NULL;
-
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
- if (!PyArg_ParseTuple(args, "i|O&:_is_fifo",
- &fd, Unicode_FSConverter, &path))
- return NULL;
-#else
- if (!PyArg_ParseTuple(args, "i|z:_is_fifo", &fd, &path))
- return NULL;
-#endif
-
- r = sd_is_fifo(fd, path);
- if (set_error(r, path, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-
-PyDoc_STRVAR(is_mq__doc__,
- "_is_mq(fd, path) -> bool\n\n"
- "Returns True iff the descriptor refers to a POSIX message queue.\n"
- "Wraps sd_is_mq(3)."
-);
-
-static PyObject* is_mq(PyObject *self, PyObject *args) {
- int r;
- int fd;
- const char *path = NULL;
-
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
- if (!PyArg_ParseTuple(args, "i|O&:_is_mq",
- &fd, Unicode_FSConverter, &path))
- return NULL;
-#else
- if (!PyArg_ParseTuple(args, "i|z:_is_mq", &fd, &path))
- return NULL;
-#endif
-
- r = sd_is_mq(fd, path);
- if (set_error(r, path, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-
-
-PyDoc_STRVAR(is_socket__doc__,
- "_is_socket(fd, family=AF_UNSPEC, type=0, listening=-1) -> bool\n\n"
- "Returns True iff the descriptor refers to a socket.\n"
- "Wraps sd_is_socket(3).\n\n"
- "Constants for `family` are defined in the socket module."
-);
-
-static PyObject* is_socket(PyObject *self, PyObject *args) {
- int r;
- int fd, family = AF_UNSPEC, type = 0, listening = -1;
-
- if (!PyArg_ParseTuple(args, "i|iii:_is_socket",
- &fd, &family, &type, &listening))
- return NULL;
-
- r = sd_is_socket(fd, family, type, listening);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-
-PyDoc_STRVAR(is_socket_inet__doc__,
- "_is_socket_inet(fd, family=AF_UNSPEC, type=0, listening=-1, port=0) -> bool\n\n"
- "Wraps sd_is_socket_inet(3).\n\n"
- "Constants for `family` are defined in the socket module."
-);
-
-static PyObject* is_socket_inet(PyObject *self, PyObject *args) {
- int r;
- int fd, family = AF_UNSPEC, type = 0, listening = -1, port = 0;
-
- if (!PyArg_ParseTuple(args, "i|iiii:_is_socket_inet",
- &fd, &family, &type, &listening, &port))
- return NULL;
-
- if (port < 0 || port > UINT16_MAX) {
- set_error(-EINVAL, NULL, "port must fit into uint16_t");
- return NULL;
- }
-
- r = sd_is_socket_inet(fd, family, type, listening, (uint16_t) port);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-
-PyDoc_STRVAR(is_socket_unix__doc__,
- "_is_socket_unix(fd, type, listening, path) -> bool\n\n"
- "Wraps sd_is_socket_unix(3)."
-);
-
-static PyObject* is_socket_unix(PyObject *self, PyObject *args) {
- int r;
- int fd, type = 0, listening = -1;
- char* path = NULL;
- Py_ssize_t length = 0;
-
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
- _cleanup_Py_DECREF_ PyObject *_path = NULL;
- if (!PyArg_ParseTuple(args, "i|iiO&:_is_socket_unix",
- &fd, &type, &listening, Unicode_FSConverter, &_path))
- return NULL;
- if (_path) {
- assert(PyBytes_Check(_path));
- if (PyBytes_AsStringAndSize(_path, &path, &length))
- return NULL;
- }
-#else
- if (!PyArg_ParseTuple(args, "i|iiz#:_is_socket_unix",
- &fd, &type, &listening, &path, &length))
- return NULL;
-#endif
-
- r = sd_is_socket_unix(fd, type, listening, path, length);
- if (set_error(r, path, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-
-static PyMethodDef methods[] = {
- { "booted", booted, METH_NOARGS, booted__doc__},
- { "notify", (PyCFunction) notify, METH_VARARGS | METH_KEYWORDS, notify__doc__},
- { "_listen_fds", (PyCFunction) listen_fds, METH_VARARGS | METH_KEYWORDS, listen_fds__doc__},
- { "_is_fifo", is_fifo, METH_VARARGS, is_fifo__doc__},
- { "_is_mq", is_mq, METH_VARARGS, is_mq__doc__},
- { "_is_socket", is_socket, METH_VARARGS, is_socket__doc__},
- { "_is_socket_inet", is_socket_inet, METH_VARARGS, is_socket_inet__doc__},
- { "_is_socket_unix", is_socket_unix, METH_VARARGS, is_socket_unix__doc__},
- { NULL, NULL, 0, NULL } /* Sentinel */
-};
-
-#if PY_MAJOR_VERSION < 3
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC init_daemon(void) {
- PyObject *m;
-
- m = Py_InitModule3("_daemon", methods, module__doc__);
- if (m == NULL)
- return;
-
- PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START);
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
-}
-REENABLE_WARNING;
-
-#else
-
-static struct PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "_daemon", /* name of module */
- module__doc__, /* module documentation, may be NULL */
- 0, /* size of per-interpreter state of the module */
- methods
-};
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC PyInit__daemon(void) {
- PyObject *m;
-
- m = PyModule_Create(&module);
- if (m == NULL)
- return NULL;
-
- if (PyModule_AddIntConstant(m, "LISTEN_FDS_START", SD_LISTEN_FDS_START) ||
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
-REENABLE_WARNING;
-
-#endif
diff --git a/src/python-systemd/_journal.c b/src/python-systemd/_journal.c
deleted file mode 100644
index 456e4a2796..0000000000
--- a/src/python-systemd/_journal.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 David Strauss <david@davidstrauss.net>
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <Python.h>
-
-#include <alloca.h>
-#include "util.h"
-
-#define SD_JOURNAL_SUPPRESS_LOCATION
-#include "systemd/sd-journal.h"
-
-PyDoc_STRVAR(journal_sendv__doc__,
- "sendv('FIELD=value', 'FIELD=value', ...) -> None\n\n"
- "Send an entry to the journal."
-);
-
-static PyObject *journal_sendv(PyObject *self, PyObject *args) {
- struct iovec *iov = NULL;
- int argc;
- int i, r;
- PyObject *ret = NULL;
- PyObject **encoded;
-
- /* Allocate an array for the argument strings */
- argc = PyTuple_Size(args);
- encoded = alloca0(argc * sizeof(PyObject*));
-
- /* Allocate sufficient iovector space for the arguments. */
- iov = alloca(argc * sizeof(struct iovec));
-
- /* Iterate through the Python arguments and fill the iovector. */
- for (i = 0; i < argc; ++i) {
- PyObject *item = PyTuple_GetItem(args, i);
- char *stritem;
- Py_ssize_t length;
-
- if (PyUnicode_Check(item)) {
- encoded[i] = PyUnicode_AsEncodedString(item, "utf-8", "strict");
- if (encoded[i] == NULL)
- goto out;
- item = encoded[i];
- }
- if (PyBytes_AsStringAndSize(item, &stritem, &length))
- goto out;
-
- iov[i].iov_base = stritem;
- iov[i].iov_len = length;
- }
-
- /* Send the iovector to the journal. */
- r = sd_journal_sendv(iov, argc);
- if (r < 0) {
- errno = -r;
- PyErr_SetFromErrno(PyExc_IOError);
- goto out;
- }
-
- /* End with success. */
- Py_INCREF(Py_None);
- ret = Py_None;
-
-out:
- for (i = 0; i < argc; ++i)
- Py_XDECREF(encoded[i]);
-
- return ret;
-}
-
-PyDoc_STRVAR(journal_stream_fd__doc__,
- "stream_fd(identifier, priority, level_prefix) -> fd\n\n"
- "Open a stream to journal by calling sd_journal_stream_fd(3)."
-);
-
-static PyObject* journal_stream_fd(PyObject *self, PyObject *args) {
- const char* identifier;
- int priority, level_prefix;
- int fd;
-
- if (!PyArg_ParseTuple(args, "sii:stream_fd",
- &identifier, &priority, &level_prefix))
- return NULL;
-
- fd = sd_journal_stream_fd(identifier, priority, level_prefix);
- if (fd < 0) {
- errno = -fd;
- return PyErr_SetFromErrno(PyExc_IOError);
- }
-
- return PyLong_FromLong(fd);
-}
-
-static PyMethodDef methods[] = {
- { "sendv", journal_sendv, METH_VARARGS, journal_sendv__doc__ },
- { "stream_fd", journal_stream_fd, METH_VARARGS, journal_stream_fd__doc__ },
- { NULL, NULL, 0, NULL } /* Sentinel */
-};
-
-#if PY_MAJOR_VERSION < 3
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC init_journal(void) {
- PyObject *m;
-
- m = Py_InitModule("_journal", methods);
- if (m == NULL)
- return;
-
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
-}
-REENABLE_WARNING;
-
-#else
-
-static struct PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "_journal", /* name of module */
- NULL, /* module documentation, may be NULL */
- -1, /* size of per-interpreter state of the module */
- methods
-};
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC PyInit__journal(void) {
- PyObject *m;
-
- m = PyModule_Create(&module);
- if (m == NULL)
- return NULL;
-
- if (PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
-REENABLE_WARNING;
-
-#endif
diff --git a/src/python-systemd/_reader.c b/src/python-systemd/_reader.c
deleted file mode 100644
index 3a561269a7..0000000000
--- a/src/python-systemd/_reader.c
+++ /dev/null
@@ -1,1106 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Steven Hiscocks, Zbigniew Jędrzejewski-Szmek
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <Python.h>
-#include <structmember.h>
-#include <datetime.h>
-#include <time.h>
-#include <stdio.h>
-
-#include "systemd/sd-journal.h"
-
-#include "pyutil.h"
-#include "macro.h"
-#include "util.h"
-#include "strv.h"
-#include "build.h"
-
-typedef struct {
- PyObject_HEAD
- sd_journal *j;
-} Reader;
-static PyTypeObject ReaderType;
-
-PyDoc_STRVAR(module__doc__,
- "Class to reads the systemd journal similar to journalctl.");
-
-
-#if PY_MAJOR_VERSION >= 3
-static PyTypeObject MonotonicType;
-
-PyDoc_STRVAR(MonotonicType__doc__,
- "A tuple of (timestamp, bootid) for holding monotonic timestamps");
-
-static PyStructSequence_Field MonotonicType_fields[] = {
- {(char*) "timestamp", (char*) "Time"},
- {(char*) "bootid", (char*) "Unique identifier of the boot"},
- {} /* Sentinel */
-};
-
-static PyStructSequence_Desc Monotonic_desc = {
- (char*) "journal.Monotonic",
- MonotonicType__doc__,
- MonotonicType_fields,
- 2,
-};
-#endif
-
-/**
- * Convert a Python sequence object into a strv (char**), and
- * None into a NULL pointer.
- */
-static int strv_converter(PyObject* obj, void *_result) {
- char ***result = _result;
- Py_ssize_t i, len;
-
- assert(result);
-
- if (!obj)
- return 0;
-
- if (obj == Py_None) {
- *result = NULL;
- return 1;
- }
-
- if (!PySequence_Check(obj))
- return 0;
-
- len = PySequence_Length(obj);
- *result = new0(char*, len + 1);
- if (!*result) {
- set_error(-ENOMEM, NULL, NULL);
- return 0;
- }
-
- for (i = 0; i < len; i++) {
- PyObject *item;
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
- int r;
- PyObject *bytes;
-#endif
- char *s, *s2;
-
- item = PySequence_ITEM(obj, i);
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
- r = PyUnicode_FSConverter(item, &bytes);
- if (r == 0)
- goto cleanup;
-
- s = PyBytes_AsString(bytes);
-#else
- s = PyString_AsString(item);
-#endif
- if (!s)
- goto cleanup;
-
- s2 = strdup(s);
- if (!s2)
- log_oom();
-
- (*result)[i] = s2;
- }
-
- return 1;
-
-cleanup:
- strv_free(*result);
- *result = NULL;
-
- return 0;
-}
-
-static void Reader_dealloc(Reader* self) {
- sd_journal_close(self->j);
- Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
-PyDoc_STRVAR(Reader__doc__,
- "_Reader([flags | path | files]) -> ...\n\n"
- "_Reader allows filtering and retrieval of Journal entries.\n"
- "Note: this is a low-level interface, and probably not what you\n"
- "want, use systemd.journal.Reader instead.\n\n"
- "Argument `flags` sets open flags of the journal, which can be one\n"
- "of, or ORed combination of constants: LOCAL_ONLY (default) opens\n"
- "journal on local machine only; RUNTIME_ONLY opens only\n"
- "volatile journal files; and SYSTEM opens journal files of\n"
- "system services and the kernel, and CURRENT_USER opens files\n"
- "of the current user.\n\n"
- "Argument `path` is the directory of journal files.\n"
- "Argument `files` is a list of files. Note that\n"
- "`flags`, `path`, and `files` are exclusive.\n\n"
- "_Reader implements the context manager protocol: the journal\n"
- "will be closed when exiting the block.");
-static int Reader_init(Reader *self, PyObject *args, PyObject *keywds) {
- int flags = 0, r;
- char *path = NULL;
- char **files = NULL;
-
- static const char* const kwlist[] = {"flags", "path", "files", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "|izO&:__init__", (char**) kwlist,
- &flags, &path, strv_converter, &files))
- return -1;
-
- if (!!flags + !!path + !!files > 1) {
- PyErr_SetString(PyExc_ValueError, "cannot use more than one of flags, path, and files");
- return -1;
- }
-
- if (!flags)
- flags = SD_JOURNAL_LOCAL_ONLY;
-
- Py_BEGIN_ALLOW_THREADS
- if (path)
- r = sd_journal_open_directory(&self->j, path, 0);
- else if (files)
- r = sd_journal_open_files(&self->j, (const char**) files, 0);
- else
- r = sd_journal_open(&self->j, flags);
- Py_END_ALLOW_THREADS
-
- return set_error(r, path, "Invalid flags or path");
-}
-
-PyDoc_STRVAR(Reader_fileno__doc__,
- "fileno() -> int\n\n"
- "Get a file descriptor to poll for changes in the journal.\n"
- "This method invokes sd_journal_get_fd().\n"
- "See man:sd_journal_get_fd(3).");
-static PyObject* Reader_fileno(Reader *self, PyObject *args) {
- int fd;
-
- fd = sd_journal_get_fd(self->j);
- set_error(fd, NULL, NULL);
- if (fd < 0)
- return NULL;
- return long_FromLong(fd);
-}
-
-PyDoc_STRVAR(Reader_reliable_fd__doc__,
- "reliable_fd() -> bool\n\n"
- "Returns True iff the journal can be polled reliably.\n"
- "This method invokes sd_journal_reliable_fd().\n"
- "See man:sd_journal_reliable_fd(3).");
-static PyObject* Reader_reliable_fd(Reader *self, PyObject *args) {
- int r;
-
- r = sd_journal_reliable_fd(self->j);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- return PyBool_FromLong(r);
-}
-
-PyDoc_STRVAR(Reader_get_events__doc__,
- "get_events() -> int\n\n"
- "Returns a mask of poll() events to wait for on the file\n"
- "descriptor returned by .fileno().\n\n"
- "See man:sd_journal_get_events(3) for further discussion.");
-static PyObject* Reader_get_events(Reader *self, PyObject *args) {
- int r;
-
- r = sd_journal_get_events(self->j);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- return long_FromLong(r);
-}
-
-PyDoc_STRVAR(Reader_get_timeout__doc__,
- "get_timeout() -> int or None\n\n"
- "Returns a timeout value for usage in poll(), the time since the\n"
- "epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
- "is necessary.\n\n"
- "The return value must be converted to a relative timeout in\n"
- "milliseconds if it is to be used as an argument for poll().\n"
- "See man:sd_journal_get_timeout(3) for further discussion.");
-static PyObject* Reader_get_timeout(Reader *self, PyObject *args) {
- int r;
- uint64_t t;
-
- r = sd_journal_get_timeout(self->j, &t);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- if (t == (uint64_t) -1)
- Py_RETURN_NONE;
-
- assert_cc(sizeof(unsigned long long) == sizeof(t));
- return PyLong_FromUnsignedLongLong(t);
-}
-
-PyDoc_STRVAR(Reader_get_timeout_ms__doc__,
- "get_timeout_ms() -> int\n\n"
- "Returns a timeout value suitable for usage in poll(), the value\n"
- "returned by .get_timeout() converted to relative ms, or -1 if\n"
- "no timeout is necessary.");
-static PyObject* Reader_get_timeout_ms(Reader *self, PyObject *args) {
- int r;
- uint64_t t;
-
- r = sd_journal_get_timeout(self->j, &t);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return absolute_timeout(t);
-}
-
-PyDoc_STRVAR(Reader_close__doc__,
- "close() -> None\n\n"
- "Free resources allocated by this Reader object.\n"
- "This method invokes sd_journal_close().\n"
- "See man:sd_journal_close(3).");
-static PyObject* Reader_close(Reader *self, PyObject *args) {
- assert(self);
- assert(!args);
-
- sd_journal_close(self->j);
- self->j = NULL;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_get_usage__doc__,
- "get_usage() -> int\n\n"
- "Returns the total disk space currently used by journal\n"
- "files (in bytes). If `SD_JOURNAL_LOCAL_ONLY` was\n"
- "passed when opening the journal this value will only reflect\n"
- "the size of journal files of the local host, otherwise\n"
- "of all hosts.\n\n"
- "This method invokes sd_journal_get_usage().\n"
- "See man:sd_journal_get_usage(3).");
-static PyObject* Reader_get_usage(Reader *self, PyObject *args) {
- int r;
- uint64_t bytes;
-
- r = sd_journal_get_usage(self->j, &bytes);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- assert_cc(sizeof(unsigned long long) == sizeof(bytes));
- return PyLong_FromUnsignedLongLong(bytes);
-}
-
-PyDoc_STRVAR(Reader___enter____doc__,
- "__enter__() -> self\n\n"
- "Part of the context manager protocol.\n"
- "Returns self.\n");
-static PyObject* Reader___enter__(PyObject *self, PyObject *args) {
- assert(self);
- assert(!args);
-
- Py_INCREF(self);
- return self;
-}
-
-PyDoc_STRVAR(Reader___exit____doc__,
- "__exit__(type, value, traceback) -> None\n\n"
- "Part of the context manager protocol.\n"
- "Closes the journal.\n");
-static PyObject* Reader___exit__(Reader *self, PyObject *args) {
- return Reader_close(self, NULL);
-}
-
-PyDoc_STRVAR(Reader_next__doc__,
- "next([skip]) -> bool\n\n"
- "Go to the next log entry. Optional skip value means to go to\n"
- "the `skip`\\-th log entry.\n"
- "Returns False if at end of file, True otherwise.");
-static PyObject* Reader_next(Reader *self, PyObject *args) {
- int64_t skip = 1LL;
- int r;
-
- if (!PyArg_ParseTuple(args, "|L:next", &skip))
- return NULL;
-
- if (skip == 0LL) {
- PyErr_SetString(PyExc_ValueError, "skip must be nonzero");
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- if (skip == 1LL)
- r = sd_journal_next(self->j);
- else if (skip == -1LL)
- r = sd_journal_previous(self->j);
- else if (skip > 1LL)
- r = sd_journal_next_skip(self->j, skip);
- else if (skip < -1LL)
- r = sd_journal_previous_skip(self->j, -skip);
- else
- assert_not_reached("should not be here");
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- return PyBool_FromLong(r);
-}
-
-PyDoc_STRVAR(Reader_previous__doc__,
- "previous([skip]) -> bool\n\n"
- "Go to the previous log entry. Optional skip value means to \n"
- "go to the `skip`\\-th previous log entry.\n"
- "Returns False if at start of file, True otherwise.");
-static PyObject* Reader_previous(Reader *self, PyObject *args) {
- int64_t skip = 1LL;
- if (!PyArg_ParseTuple(args, "|L:previous", &skip))
- return NULL;
-
- return PyObject_CallMethod((PyObject *)self, (char*) "_next",
- (char*) "L", -skip);
-}
-
-static int extract(const char* msg, size_t msg_len,
- PyObject **key, PyObject **value) {
- PyObject *k = NULL, *v;
- const char *delim_ptr;
-
- delim_ptr = memchr(msg, '=', msg_len);
- if (!delim_ptr) {
- PyErr_SetString(PyExc_OSError,
- "journal gave us a field without '='");
- return -1;
- }
-
- if (key) {
- k = unicode_FromStringAndSize(msg, delim_ptr - (const char*) msg);
- if (!k)
- return -1;
- }
-
- if (value) {
- v = PyBytes_FromStringAndSize(delim_ptr + 1,
- (const char*) msg + msg_len - (delim_ptr + 1));
- if (!v) {
- Py_XDECREF(k);
- return -1;
- }
-
- *value = v;
- }
-
- if (key)
- *key = k;
-
- return 0;
-}
-
-PyDoc_STRVAR(Reader_get__doc__,
- "get(str) -> str\n\n"
- "Return data associated with this key in current log entry.\n"
- "Throws KeyError is the data is not available.");
-static PyObject* Reader_get(Reader *self, PyObject *args) {
- const char* field;
- const void* msg;
- size_t msg_len;
- PyObject *value;
- int r;
-
- assert(self);
- assert(args);
-
- if (!PyArg_ParseTuple(args, "s:get", &field))
- return NULL;
-
- r = sd_journal_get_data(self->j, field, &msg, &msg_len);
- if (r == -ENOENT) {
- PyErr_SetString(PyExc_KeyError, field);
- return NULL;
- }
- if (set_error(r, NULL, "field name is not valid") < 0)
- return NULL;
-
- r = extract(msg, msg_len, NULL, &value);
- if (r < 0)
- return NULL;
- return value;
-}
-
-PyDoc_STRVAR(Reader_get_all__doc__,
- "_get_all() -> dict\n\n"
- "Return dictionary of the current log entry.");
-static PyObject* Reader_get_all(Reader *self, PyObject *args) {
- PyObject *dict;
- const void *msg;
- size_t msg_len;
- int r;
-
- dict = PyDict_New();
- if (!dict)
- return NULL;
-
- SD_JOURNAL_FOREACH_DATA(self->j, msg, msg_len) {
- _cleanup_Py_DECREF_ PyObject *key = NULL, *value = NULL;
-
- r = extract(msg, msg_len, &key, &value);
- if (r < 0)
- goto error;
-
- if (PyDict_Contains(dict, key)) {
- PyObject *cur_value = PyDict_GetItem(dict, key);
-
- if (PyList_CheckExact(cur_value)) {
- r = PyList_Append(cur_value, value);
- if (r < 0)
- goto error;
- } else {
- _cleanup_Py_DECREF_ PyObject *tmp_list = PyList_New(0);
- if (!tmp_list)
- goto error;
-
- r = PyList_Append(tmp_list, cur_value);
- if (r < 0)
- goto error;
-
- r = PyList_Append(tmp_list, value);
- if (r < 0)
- goto error;
-
- r = PyDict_SetItem(dict, key, tmp_list);
- if (r < 0)
- goto error;
- }
- } else {
- r = PyDict_SetItem(dict, key, value);
- if (r < 0)
- goto error;
- }
- }
-
- return dict;
-
-error:
- Py_DECREF(dict);
- return NULL;
-}
-
-PyDoc_STRVAR(Reader_get_realtime__doc__,
- "get_realtime() -> int\n\n"
- "Return the realtime timestamp for the current journal entry\n"
- "in microseconds.\n\n"
- "Wraps sd_journal_get_realtime_usec().\n"
- "See man:sd_journal_get_realtime_usec(3).");
-static PyObject* Reader_get_realtime(Reader *self, PyObject *args) {
- uint64_t timestamp;
- int r;
-
- assert(self);
- assert(!args);
-
- r = sd_journal_get_realtime_usec(self->j, &timestamp);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
- return PyLong_FromUnsignedLongLong(timestamp);
-}
-
-PyDoc_STRVAR(Reader_get_monotonic__doc__,
- "get_monotonic() -> (timestamp, bootid)\n\n"
- "Return the monotonic timestamp for the current journal entry\n"
- "as a tuple of time in microseconds and bootid.\n\n"
- "Wraps sd_journal_get_monotonic_usec().\n"
- "See man:sd_journal_get_monotonic_usec(3).");
-static PyObject* Reader_get_monotonic(Reader *self, PyObject *args) {
- uint64_t timestamp;
- sd_id128_t id;
- PyObject *monotonic, *bootid, *tuple;
- int r;
-
- assert(self);
- assert(!args);
-
- r = sd_journal_get_monotonic_usec(self->j, &timestamp, &id);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
- monotonic = PyLong_FromUnsignedLongLong(timestamp);
- bootid = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
-#if PY_MAJOR_VERSION >= 3
- tuple = PyStructSequence_New(&MonotonicType);
-#else
- tuple = PyTuple_New(2);
-#endif
- if (!monotonic || !bootid || !tuple) {
- Py_XDECREF(monotonic);
- Py_XDECREF(bootid);
- Py_XDECREF(tuple);
- return NULL;
- }
-
-#if PY_MAJOR_VERSION >= 3
- PyStructSequence_SET_ITEM(tuple, 0, monotonic);
- PyStructSequence_SET_ITEM(tuple, 1, bootid);
-#else
- PyTuple_SET_ITEM(tuple, 0, monotonic);
- PyTuple_SET_ITEM(tuple, 1, bootid);
-#endif
-
- return tuple;
-}
-
-PyDoc_STRVAR(Reader_add_match__doc__,
- "add_match(match) -> None\n\n"
- "Add a match to filter journal log entries. All matches of different\n"
- "fields are combined with logical AND, and matches of the same field\n"
- "are automatically combined with logical OR.\n"
- "Match is a string of the form \"FIELD=value\".");
-static PyObject* Reader_add_match(Reader *self, PyObject *args, PyObject *keywds) {
- char *match;
- int match_len, r;
- if (!PyArg_ParseTuple(args, "s#:add_match", &match, &match_len))
- return NULL;
-
- r = sd_journal_add_match(self->j, match, match_len);
- if (set_error(r, NULL, "Invalid match") < 0)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_add_disjunction__doc__,
- "add_disjunction() -> None\n\n"
- "Inserts a logical OR between matches added since previous\n"
- "add_disjunction() or add_conjunction() and the next\n"
- "add_disjunction() or add_conjunction().\n\n"
- "See man:sd_journal_add_disjunction(3) for explanation.");
-static PyObject* Reader_add_disjunction(Reader *self, PyObject *args) {
- int r;
- r = sd_journal_add_disjunction(self->j);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_add_conjunction__doc__,
- "add_conjunction() -> None\n\n"
- "Inserts a logical AND between matches added since previous\n"
- "add_disjunction() or add_conjunction() and the next\n"
- "add_disjunction() or add_conjunction().\n\n"
- "See man:sd_journal_add_disjunction(3) for explanation.");
-static PyObject* Reader_add_conjunction(Reader *self, PyObject *args) {
- int r;
- r = sd_journal_add_conjunction(self->j);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_flush_matches__doc__,
- "flush_matches() -> None\n\n"
- "Clear all current match filters.");
-static PyObject* Reader_flush_matches(Reader *self, PyObject *args) {
- sd_journal_flush_matches(self->j);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_seek_head__doc__,
- "seek_head() -> None\n\n"
- "Jump to the beginning of the journal.\n"
- "This method invokes sd_journal_seek_head().\n"
- "See man:sd_journal_seek_head(3).");
-static PyObject* Reader_seek_head(Reader *self, PyObject *args) {
- int r;
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_seek_head(self->j);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_seek_tail__doc__,
- "seek_tail() -> None\n\n"
- "Jump to the end of the journal.\n"
- "This method invokes sd_journal_seek_tail().\n"
- "See man:sd_journal_seek_tail(3).");
-static PyObject* Reader_seek_tail(Reader *self, PyObject *args) {
- int r;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_seek_tail(self->j);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_seek_realtime__doc__,
- "seek_realtime(realtime) -> None\n\n"
- "Seek to nearest matching journal entry to `realtime`. Argument\n"
- "`realtime` in specified in seconds.");
-static PyObject* Reader_seek_realtime(Reader *self, PyObject *args) {
- uint64_t timestamp;
- int r;
-
- if (!PyArg_ParseTuple(args, "K:seek_realtime", &timestamp))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_seek_realtime_usec(self->j, timestamp);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_seek_monotonic__doc__,
- "seek_monotonic(monotonic[, bootid]) -> None\n\n"
- "Seek to nearest matching journal entry to `monotonic`. Argument\n"
- "`monotonic` is an timestamp from boot in microseconds.\n"
- "Argument `bootid` is a string representing which boot the\n"
- "monotonic time is reference to. Defaults to current bootid.");
-static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args) {
- char *bootid = NULL;
- uint64_t timestamp;
- sd_id128_t id;
- int r;
-
- if (!PyArg_ParseTuple(args, "K|z:seek_monotonic", &timestamp, &bootid))
- return NULL;
-
- if (bootid) {
- r = sd_id128_from_string(bootid, &id);
- if (set_error(r, NULL, "Invalid bootid") < 0)
- return NULL;
- } else {
- Py_BEGIN_ALLOW_THREADS
- r = sd_id128_get_boot(&id);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_seek_monotonic_usec(self->j, id, timestamp);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-
-PyDoc_STRVAR(Reader_process__doc__,
- "process() -> state change (integer)\n\n"
- "Process events and reset the readable state of the file\n"
- "descriptor returned by .fileno().\n\n"
- "Will return constants: NOP if no change; APPEND if new\n"
- "entries have been added to the end of the journal; and\n"
- "INVALIDATE if journal files have been added or removed.\n\n"
- "See man:sd_journal_process(3) for further discussion.");
-static PyObject* Reader_process(Reader *self, PyObject *args) {
- int r;
-
- assert(!args);
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_process(self->j);
- Py_END_ALLOW_THREADS
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return long_FromLong(r);
-}
-
-PyDoc_STRVAR(Reader_wait__doc__,
- "wait([timeout]) -> state change (integer)\n\n"
- "Wait for a change in the journal. Argument `timeout` specifies\n"
- "the maximum number of microseconds to wait before returning\n"
- "regardless of wheter the journal has changed. If `timeout` is -1,\n"
- "then block forever.\n\n"
- "Will return constants: NOP if no change; APPEND if new\n"
- "entries have been added to the end of the journal; and\n"
- "INVALIDATE if journal files have been added or removed.\n\n"
- "See man:sd_journal_wait(3) for further discussion.");
-static PyObject* Reader_wait(Reader *self, PyObject *args) {
- int r;
- int64_t timeout;
-
- if (!PyArg_ParseTuple(args, "|L:wait", &timeout))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_wait(self->j, timeout);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return long_FromLong(r);
-}
-
-PyDoc_STRVAR(Reader_seek_cursor__doc__,
- "seek_cursor(cursor) -> None\n\n"
- "Seek to journal entry by given unique reference `cursor`.");
-static PyObject* Reader_seek_cursor(Reader *self, PyObject *args) {
- const char *cursor;
- int r;
-
- if (!PyArg_ParseTuple(args, "s:seek_cursor", &cursor))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_seek_cursor(self->j, cursor);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, "Invalid cursor") < 0)
- return NULL;
-
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(Reader_get_cursor__doc__,
- "get_cursor() -> str\n\n"
- "Return a cursor string for the current journal entry.\n\n"
- "Wraps sd_journal_get_cursor(). See man:sd_journal_get_cursor(3).");
-static PyObject* Reader_get_cursor(Reader *self, PyObject *args) {
- _cleanup_free_ char *cursor = NULL;
- int r;
-
- assert(self);
- assert(!args);
-
- r = sd_journal_get_cursor(self->j, &cursor);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return unicode_FromString(cursor);
-}
-
-PyDoc_STRVAR(Reader_test_cursor__doc__,
- "test_cursor(str) -> bool\n\n"
- "Test whether the cursor string matches current journal entry.\n\n"
- "Wraps sd_journal_test_cursor(). See man:sd_journal_test_cursor(3).");
-static PyObject* Reader_test_cursor(Reader *self, PyObject *args) {
- const char *cursor;
- int r;
-
- assert(self);
- assert(args);
-
- if (!PyArg_ParseTuple(args, "s:test_cursor", &cursor))
- return NULL;
-
- r = sd_journal_test_cursor(self->j, cursor);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return PyBool_FromLong(r);
-}
-
-PyDoc_STRVAR(Reader_query_unique__doc__,
- "query_unique(field) -> a set of values\n\n"
- "Return a set of unique values appearing in journal for the\n"
- "given `field`. Note this does not respect any journal matches.");
-static PyObject* Reader_query_unique(Reader *self, PyObject *args) {
- char *query;
- int r;
- const void *uniq;
- size_t uniq_len;
- PyObject *value_set, *key, *value;
-
- if (!PyArg_ParseTuple(args, "s:query_unique", &query))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_query_unique(self->j, query);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, "Invalid field name") < 0)
- return NULL;
-
- value_set = PySet_New(0);
- key = unicode_FromString(query);
-
- SD_JOURNAL_FOREACH_UNIQUE(self->j, uniq, uniq_len) {
- const char *delim_ptr;
-
- delim_ptr = memchr(uniq, '=', uniq_len);
- value = PyBytes_FromStringAndSize(
- delim_ptr + 1,
- (const char*) uniq + uniq_len - (delim_ptr + 1));
- PySet_Add(value_set, value);
- Py_DECREF(value);
- }
-
- Py_DECREF(key);
- return value_set;
-}
-
-PyDoc_STRVAR(Reader_get_catalog__doc__,
- "get_catalog() -> str\n\n"
- "Retrieve a message catalog entry for the current journal entry.\n"
- "Will throw IndexError if the entry has no MESSAGE_ID\n"
- "and KeyError is the id is specified, but hasn't been found\n"
- "in the catalog.\n\n"
- "Wraps man:sd_journal_get_catalog(3).");
-static PyObject* Reader_get_catalog(Reader *self, PyObject *args) {
- int r;
- _cleanup_free_ char *msg = NULL;
-
- assert(self);
- assert(!args);
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_get_catalog(self->j, &msg);
- Py_END_ALLOW_THREADS
-
- if (r == -ENOENT) {
- const void* mid;
- size_t mid_len;
-
- r = sd_journal_get_data(self->j, "MESSAGE_ID", &mid, &mid_len);
- if (r == 0) {
- const size_t l = sizeof("MESSAGE_ID");
- assert(mid_len > l);
- PyErr_Format(PyExc_KeyError, "%.*s", (int) (mid_len - l),
- (const char*) mid + l);
- } else if (r == -ENOENT)
- PyErr_SetString(PyExc_IndexError, "no MESSAGE_ID field");
- else
- set_error(r, NULL, NULL);
- return NULL;
- }
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return unicode_FromString(msg);
-}
-
-PyDoc_STRVAR(get_catalog__doc__,
- "get_catalog(id128) -> str\n\n"
- "Retrieve a message catalog entry for the given id.\n"
- "Wraps man:sd_journal_get_catalog_for_message_id(3).");
-static PyObject* get_catalog(PyObject *self, PyObject *args) {
- int r;
- char *id_ = NULL;
- sd_id128_t id;
- _cleanup_free_ char *msg = NULL;
-
- assert(args);
-
- if (!PyArg_ParseTuple(args, "z:get_catalog", &id_))
- return NULL;
-
- r = sd_id128_from_string(id_, &id);
- if (set_error(r, NULL, "Invalid id128") < 0)
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_journal_get_catalog_for_message_id(id, &msg);
- Py_END_ALLOW_THREADS
-
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return unicode_FromString(msg);
-}
-
-PyDoc_STRVAR(data_threshold__doc__,
- "Threshold for field size truncation in bytes.\n\n"
- "Fields longer than this will be truncated to the threshold size.\n"
- "Defaults to 64Kb.");
-
-static PyObject* Reader_get_data_threshold(Reader *self, void *closure) {
- size_t cvalue;
- int r;
-
- r = sd_journal_get_data_threshold(self->j, &cvalue);
- if (set_error(r, NULL, NULL) < 0)
- return NULL;
-
- return long_FromSize_t(cvalue);
-}
-
-static int Reader_set_data_threshold(Reader *self, PyObject *value, void *closure) {
- int r;
-
- if (value == NULL) {
- PyErr_SetString(PyExc_AttributeError, "Cannot delete data threshold");
- return -1;
- }
-
- if (!long_Check(value)){
- PyErr_SetString(PyExc_TypeError, "Data threshold must be an int");
- return -1;
- }
-
- r = sd_journal_set_data_threshold(self->j, (size_t) long_AsLong(value));
- return set_error(r, NULL, NULL);
-}
-
-PyDoc_STRVAR(closed__doc__,
- "True iff journal is closed");
-static PyObject* Reader_get_closed(Reader *self, void *closure) {
- return PyBool_FromLong(self->j == NULL);
-}
-
-static PyGetSetDef Reader_getsetters[] = {
- { (char*) "data_threshold",
- (getter) Reader_get_data_threshold,
- (setter) Reader_set_data_threshold,
- (char*) data_threshold__doc__,
- NULL },
- { (char*) "closed",
- (getter) Reader_get_closed,
- NULL,
- (char*) closed__doc__,
- NULL },
- {} /* Sentinel */
-};
-
-static PyMethodDef Reader_methods[] = {
- {"fileno", (PyCFunction) Reader_fileno, METH_NOARGS, Reader_fileno__doc__},
- {"reliable_fd", (PyCFunction) Reader_reliable_fd, METH_NOARGS, Reader_reliable_fd__doc__},
- {"get_events", (PyCFunction) Reader_get_events, METH_NOARGS, Reader_get_events__doc__},
- {"get_timeout", (PyCFunction) Reader_get_timeout, METH_NOARGS, Reader_get_timeout__doc__},
- {"get_timeout_ms", (PyCFunction) Reader_get_timeout_ms, METH_NOARGS, Reader_get_timeout_ms__doc__},
- {"close", (PyCFunction) Reader_close, METH_NOARGS, Reader_close__doc__},
- {"get_usage", (PyCFunction) Reader_get_usage, METH_NOARGS, Reader_get_usage__doc__},
- {"__enter__", (PyCFunction) Reader___enter__, METH_NOARGS, Reader___enter____doc__},
- {"__exit__", (PyCFunction) Reader___exit__, METH_VARARGS, Reader___exit____doc__},
- {"_next", (PyCFunction) Reader_next, METH_VARARGS, Reader_next__doc__},
- {"_previous", (PyCFunction) Reader_previous, METH_VARARGS, Reader_previous__doc__},
- {"_get", (PyCFunction) Reader_get, METH_VARARGS, Reader_get__doc__},
- {"_get_all", (PyCFunction) Reader_get_all, METH_NOARGS, Reader_get_all__doc__},
- {"_get_realtime", (PyCFunction) Reader_get_realtime, METH_NOARGS, Reader_get_realtime__doc__},
- {"_get_monotonic", (PyCFunction) Reader_get_monotonic, METH_NOARGS, Reader_get_monotonic__doc__},
- {"add_match", (PyCFunction) Reader_add_match, METH_VARARGS|METH_KEYWORDS, Reader_add_match__doc__},
- {"add_disjunction", (PyCFunction) Reader_add_disjunction, METH_NOARGS, Reader_add_disjunction__doc__},
- {"add_conjunction", (PyCFunction) Reader_add_conjunction, METH_NOARGS, Reader_add_conjunction__doc__},
- {"flush_matches", (PyCFunction) Reader_flush_matches, METH_NOARGS, Reader_flush_matches__doc__},
- {"seek_head", (PyCFunction) Reader_seek_head, METH_NOARGS, Reader_seek_head__doc__},
- {"seek_tail", (PyCFunction) Reader_seek_tail, METH_NOARGS, Reader_seek_tail__doc__},
- {"seek_realtime", (PyCFunction) Reader_seek_realtime, METH_VARARGS, Reader_seek_realtime__doc__},
- {"seek_monotonic", (PyCFunction) Reader_seek_monotonic, METH_VARARGS, Reader_seek_monotonic__doc__},
- {"process", (PyCFunction) Reader_process, METH_NOARGS, Reader_process__doc__},
- {"wait", (PyCFunction) Reader_wait, METH_VARARGS, Reader_wait__doc__},
- {"seek_cursor", (PyCFunction) Reader_seek_cursor, METH_VARARGS, Reader_seek_cursor__doc__},
- {"_get_cursor", (PyCFunction) Reader_get_cursor, METH_NOARGS, Reader_get_cursor__doc__},
- {"test_cursor", (PyCFunction) Reader_test_cursor, METH_VARARGS, Reader_test_cursor__doc__},
- {"query_unique", (PyCFunction) Reader_query_unique, METH_VARARGS, Reader_query_unique__doc__},
- {"get_catalog", (PyCFunction) Reader_get_catalog, METH_NOARGS, Reader_get_catalog__doc__},
- {} /* Sentinel */
-};
-
-static PyTypeObject ReaderType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "_reader._Reader",
- .tp_basicsize = sizeof(Reader),
- .tp_dealloc = (destructor) Reader_dealloc,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = Reader__doc__,
- .tp_methods = Reader_methods,
- .tp_getset = Reader_getsetters,
- .tp_init = (initproc) Reader_init,
- .tp_new = PyType_GenericNew,
-};
-
-static PyMethodDef methods[] = {
- { "_get_catalog", get_catalog, METH_VARARGS, get_catalog__doc__},
- {} /* Sentinel */
-};
-
-#if PY_MAJOR_VERSION >= 3
-static PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "_reader",
- module__doc__,
- -1,
- methods,
-};
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-static bool initialized = false;
-#endif
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-
-PyMODINIT_FUNC
-#if PY_MAJOR_VERSION >= 3
-PyInit__reader(void)
-#else
-init_reader(void)
-#endif
-{
- PyObject* m;
-
- PyDateTime_IMPORT;
-
- if (PyType_Ready(&ReaderType) < 0)
-#if PY_MAJOR_VERSION >= 3
- return NULL;
-#else
- return;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
- m = PyModule_Create(&module);
- if (m == NULL)
- return NULL;
-
- if (!initialized) {
- PyStructSequence_InitType(&MonotonicType, &Monotonic_desc);
- initialized = true;
- }
-#else
- m = Py_InitModule3("_reader", methods, module__doc__);
- if (m == NULL)
- return;
-#endif
-
- Py_INCREF(&ReaderType);
-#if PY_MAJOR_VERSION >= 3
- Py_INCREF(&MonotonicType);
-#endif
- if (PyModule_AddObject(m, "_Reader", (PyObject *) &ReaderType) ||
-#if PY_MAJOR_VERSION >= 3
- PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) ||
-#endif
- PyModule_AddIntConstant(m, "NOP", SD_JOURNAL_NOP) ||
- PyModule_AddIntConstant(m, "APPEND", SD_JOURNAL_APPEND) ||
- PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) ||
- PyModule_AddIntConstant(m, "LOCAL_ONLY", SD_JOURNAL_LOCAL_ONLY) ||
- PyModule_AddIntConstant(m, "RUNTIME_ONLY", SD_JOURNAL_RUNTIME_ONLY) ||
- PyModule_AddIntConstant(m, "SYSTEM", SD_JOURNAL_SYSTEM) ||
- PyModule_AddIntConstant(m, "SYSTEM_ONLY", SD_JOURNAL_SYSTEM_ONLY) ||
- PyModule_AddIntConstant(m, "CURRENT_USER", SD_JOURNAL_CURRENT_USER) ||
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
-#if PY_MAJOR_VERSION >= 3
- Py_DECREF(m);
- return NULL;
-#endif
- }
-
-#if PY_MAJOR_VERSION >= 3
- return m;
-#endif
-}
-
-REENABLE_WARNING;
diff --git a/src/python-systemd/daemon.py b/src/python-systemd/daemon.py
deleted file mode 100644
index 82011ca606..0000000000
--- a/src/python-systemd/daemon.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from ._daemon import (__version__,
- booted,
- notify,
- _listen_fds,
- _is_fifo,
- _is_socket,
- _is_socket_inet,
- _is_socket_unix,
- _is_mq,
- LISTEN_FDS_START)
-from socket import AF_UNSPEC as _AF_UNSPEC
-
-def _convert_fileobj(fileobj):
- try:
- return fileobj.fileno()
- except AttributeError:
- return fileobj
-
-def is_fifo(fileobj, path=None):
- fd = _convert_fileobj(fileobj)
- return _is_fifo(fd, path)
-
-def is_socket(fileobj, family=_AF_UNSPEC, type=0, listening=-1):
- fd = _convert_fileobj(fileobj)
- return _is_socket(fd, family, type, listening)
-
-def is_socket_inet(fileobj, family=_AF_UNSPEC, type=0, listening=-1, port=0):
- fd = _convert_fileobj(fileobj)
- return _is_socket_inet(fd, family, type, listening, port)
-
-def is_socket_unix(fileobj, type=0, listening=-1, path=None):
- fd = _convert_fileobj(fileobj)
- return _is_socket_unix(fd, type, listening, path)
-
-def is_mq(fileobj, path=None):
- fd = _convert_fileobj(fileobj)
- return _is_mq(fd, path)
-
-def listen_fds(unset_environment=True):
- """Return a list of socket activated descriptors
-
- Example::
-
- (in primary window)
- $ systemd-activate -l 2000 python3 -c \\
- 'from systemd.daemon import listen_fds; print(listen_fds())'
- (in another window)
- $ telnet localhost 2000
- (in primary window)
- ...
- Execing python3 (...)
- [3]
- """
- num = _listen_fds(unset_environment)
- return list(range(LISTEN_FDS_START, LISTEN_FDS_START + num))
diff --git a/src/python-systemd/docs/.gitignore b/src/python-systemd/docs/.gitignore
deleted file mode 100644
index b06a965e6a..0000000000
--- a/src/python-systemd/docs/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-!layout.html
diff --git a/src/python-systemd/docs/conf.py b/src/python-systemd/docs/conf.py
deleted file mode 100644
index 1919170bb1..0000000000
--- a/src/python-systemd/docs/conf.py
+++ /dev/null
@@ -1,279 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# python-systemd documentation build configuration file, created by
-# sphinx-quickstart on Sat Feb 9 13:49:42 2013.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.coverage', 'sphinx.ext.viewcode']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['.']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'python-systemd'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = []
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'default'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['.']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-html_show_sourcelink = False
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'python-systemddoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
- ('index', 'python-systemd.tex', u'python-systemd Documentation',
- None, 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'python-systemd', u'python-systemd Documentation',
- [], 1)
-]
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output ------------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- ('index', 'python-systemd', u'python-systemd Documentation',
- u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks', 'python-systemd', 'One line description of project.',
- 'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-
-# -- Options for Epub output ---------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = u'python-systemd'
-epub_author = u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks'
-epub_publisher = u'David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks'
-epub_copyright = u'2013, David Strauss, Zbigniew Jędrzejewski-Szmek, Marti Raudsepp, Steven Hiscocks'
-
-# The language of the text. It defaults to the language option
-# or en if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
-
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#epub_tocdup = True
-
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'http://docs.python.org/': None}
diff --git a/src/python-systemd/docs/daemon.rst b/src/python-systemd/docs/daemon.rst
deleted file mode 100644
index 0ad11edaf3..0000000000
--- a/src/python-systemd/docs/daemon.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-`systemd.daemon` module
-=======================
-
-.. automodule:: systemd.daemon
- :members:
- :undoc-members:
- :inherited-members:
-
- .. autoattribute:: systemd.daemon.LISTEN_FDS_START
-
- .. autofunction:: _listen_fds
- .. autofunction:: _is_fifo
- .. autofunction:: _is_socket
- .. autofunction:: _is_socket_unix
- .. autofunction:: _is_socket_inet
- .. autofunction:: _is_mq
- .. autofunction:: notify
- .. autofunction:: booted
diff --git a/src/python-systemd/docs/default.css b/src/python-systemd/docs/default.css
deleted file mode 100644
index 7c097d64a2..0000000000
--- a/src/python-systemd/docs/default.css
+++ /dev/null
@@ -1,196 +0,0 @@
-@import url("basic.css");
-
-/* -- page layout ----------------------------------------------------------- */
-
-div.documentwrapper {
- float: left;
- width: 100%;
-}
-
-div.bodywrapper {
- margin: 0 0 0 230px;
-}
-
-div.body {
- background-color: #ffffff;
- color: #000000;
- padding: 0 20px 30px 20px;
-}
-
-div.footer {
- color: #ffffff;
- width: 100%;
- padding: 9px 0 9px 0;
- text-align: center;
- font-size: 75%;
-}
-
-div.footer a {
- color: #ffffff;
- text-decoration: underline;
-}
-
-div.related {
- background-color: #133f52;
- line-height: 30px;
- color: #ffffff;
-}
-
-div.related a {
- color: #ffffff;
-}
-
-div.sphinxsidebar {
- background-color: #dddddd;
-}
-
-div.sphinxsidebar p.topless {
- margin: 5px 10px 10px 10px;
-}
-
-div.sphinxsidebar ul {
- margin: 10px;
- padding: 0;
-}
-
-div.sphinxsidebar input {
- border: 1px solid #000000;
- font-family: sans-serif;
- font-size: 1em;
-}
-
-
-
-/* -- hyperlink styles ------------------------------------------------------ */
-
-a {
- text-decoration: none;
-}
-
-a:hover {
- text-decoration: underline;
-}
-
-
-
-/* -- body styles ----------------------------------------------------------- */
-
-div.body h1,
-div.body h2,
-div.body h3,
-div.body h4,
-div.body h5,
-div.body h6 {
- font-family: 'Trebuchet MS', sans-serif;
- background-color: #f2f2f2;
- font-weight: normal;
- color: #20435c;
- border-bottom: 1px solid #ccc;
- margin: 20px -20px 10px -20px;
- padding: 3px 0 3px 10px;
-}
-
-div.body h1 { margin-top: 0; font-size: 200%; }
-div.body h2 { font-size: 160%; }
-div.body h3 { font-size: 140%; }
-div.body h4 { font-size: 120%; }
-div.body h5 { font-size: 110%; }
-div.body h6 { font-size: 100%; }
-
-a.headerlink {
- color: #c60f0f;
- font-size: 0.8em;
- padding: 0 4px 0 4px;
- text-decoration: none;
-}
-
-a.headerlink:hover {
- background-color: #c60f0f;
- color: white;
-}
-
-div.body p, div.body dd, div.body li {
- text-align: justify;
- line-height: 130%;
-}
-
-div.admonition p.admonition-title + p {
- display: inline;
-}
-
-div.admonition p {
- margin-bottom: 5px;
-}
-
-div.admonition pre {
- margin-bottom: 5px;
-}
-
-div.admonition ul, div.admonition ol {
- margin-bottom: 5px;
-}
-
-div.note {
- background-color: #eee;
- border: 1px solid #ccc;
-}
-
-div.seealso {
- background-color: #ffc;
- border: 1px solid #ff6;
-}
-
-div.topic {
- background-color: #eee;
-}
-
-div.warning {
- background-color: #ffe4e4;
- border: 1px solid #f66;
-}
-
-p.admonition-title {
- display: inline;
-}
-
-p.admonition-title:after {
- content: ":";
-}
-
-pre {
- padding: 5px;
- background-color: #eeffcc;
- color: #333333;
- line-height: 120%;
- border: 1px solid #ac9;
- border-left: none;
- border-right: none;
-}
-
-tt {
- background-color: #ecf0f3;
- padding: 0 1px 0 1px;
- font-size: 0.95em;
-}
-
-th {
- background-color: #ede;
-}
-
-.warning tt {
- background: #efc2c2;
-}
-
-.note tt {
- background: #d6d6d6;
-}
-
-.viewcode-back {
- font-family: sans-serif;
-}
-
-div.viewcode-block:target {
- background-color: #f4debf;
- border-top: 1px solid #ac9;
- border-bottom: 1px solid #ac9;
-}
diff --git a/src/python-systemd/docs/id128.rst b/src/python-systemd/docs/id128.rst
deleted file mode 100644
index 89c37f3470..0000000000
--- a/src/python-systemd/docs/id128.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-`systemd.id128` module
-======================
-
-.. automodule:: systemd.id128
- :members:
- :undoc-members:
- :inherited-members:
-
- .. autoattribute:: systemd.id128.SD_MESSAGE_COREDUMP
- .. autoattribute:: systemd.id128.SD_MESSAGE_FORWARD_SYSLOG_MISSED
- .. autoattribute:: systemd.id128.SD_MESSAGE_HIBERNATE_KEY
- .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_DROPPED
- .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_MISSED
- .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_START
- .. autoattribute:: systemd.id128.SD_MESSAGE_JOURNAL_STOP
- .. autoattribute:: systemd.id128.SD_MESSAGE_LID_CLOSED
- .. autoattribute:: systemd.id128.SD_MESSAGE_LID_OPENED
- .. autoattribute:: systemd.id128.SD_MESSAGE_OVERMOUNTING
- .. autoattribute:: systemd.id128.SD_MESSAGE_POWER_KEY
- .. autoattribute:: systemd.id128.SD_MESSAGE_SEAT_START
- .. autoattribute:: systemd.id128.SD_MESSAGE_SEAT_STOP
- .. autoattribute:: systemd.id128.SD_MESSAGE_SESSION_START
- .. autoattribute:: systemd.id128.SD_MESSAGE_SESSION_STOP
- .. autoattribute:: systemd.id128.SD_MESSAGE_SHUTDOWN
- .. autoattribute:: systemd.id128.SD_MESSAGE_SLEEP_START
- .. autoattribute:: systemd.id128.SD_MESSAGE_SLEEP_STOP
- .. autoattribute:: systemd.id128.SD_MESSAGE_SPAWN_FAILED
- .. autoattribute:: systemd.id128.SD_MESSAGE_STARTUP_FINISHED
- .. autoattribute:: systemd.id128.SD_MESSAGE_SUSPEND_KEY
- .. autoattribute:: systemd.id128.SD_MESSAGE_TIMEZONE_CHANGE
- .. autoattribute:: systemd.id128.SD_MESSAGE_TIME_CHANGE
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_FAILED
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_RELOADED
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_RELOADING
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STARTED
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STARTING
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STOPPED
- .. autoattribute:: systemd.id128.SD_MESSAGE_UNIT_STOPPING
- .. autoattribute:: systemd.id128.SD_MESSAGE_CONFIG_ERROR
- .. autoattribute:: systemd.id128.SD_MESSAGE_BOOTCHART
diff --git a/src/python-systemd/docs/index.rst b/src/python-systemd/docs/index.rst
deleted file mode 100644
index e78d966274..0000000000
--- a/src/python-systemd/docs/index.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-.. python-systemd documentation master file, created by
- sphinx-quickstart on Sat Feb 9 13:49:42 2013.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-Welcome to python-systemd's documentation!
-==========================================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- journal
- id128
- daemon
- login
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
diff --git a/src/python-systemd/docs/journal.rst b/src/python-systemd/docs/journal.rst
deleted file mode 100644
index ea74cf85c4..0000000000
--- a/src/python-systemd/docs/journal.rst
+++ /dev/null
@@ -1,64 +0,0 @@
-`systemd.journal` module
-========================
-
-.. automodule:: systemd.journal
- :members: send, sendv, stream, stream_fd
- :undoc-members:
-
-`JournalHandler` class
-----------------------
-
-.. autoclass:: JournalHandler
-
-Accessing the Journal
----------------------
-
-.. autoclass:: _Reader
- :undoc-members:
- :inherited-members:
-
-.. autoclass:: Reader
- :undoc-members:
- :inherited-members:
-
- .. automethod:: __init__
-
-.. autofunction:: _get_catalog
-.. autofunction:: get_catalog
-
-.. autoclass:: Monotonic
-
-.. autoattribute:: systemd.journal.DEFAULT_CONVERTERS
-
-Example: polling for journal events
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This example shows that journal events can be waited for (using
-e.g. `poll`). This makes it easy to integrate Reader in an external
-event loop:
-
- >>> import select
- >>> from systemd import journal
- >>> j = journal.Reader()
- >>> j.seek_tail()
- >>> p = select.poll()
- >>> p.register(j, j.get_events())
- >>> p.poll()
- [(3, 1)]
- >>> j.get_next()
-
-
-Journal access types
-~~~~~~~~~~~~~~~~~~~~
-
-.. autoattribute:: systemd.journal.LOCAL_ONLY
-.. autoattribute:: systemd.journal.RUNTIME_ONLY
-.. autoattribute:: systemd.journal.SYSTEM
-.. autoattribute:: systemd.journal.CURRENT_USER
-
-Journal event types
-~~~~~~~~~~~~~~~~~~~
-
-.. autoattribute:: systemd.journal.NOP
-.. autoattribute:: systemd.journal.APPEND
-.. autoattribute:: systemd.journal.INVALIDATE
diff --git a/src/python-systemd/docs/layout.html b/src/python-systemd/docs/layout.html
deleted file mode 100644
index 930a6a7afe..0000000000
--- a/src/python-systemd/docs/layout.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% extends "!layout.html" %}
-
-{% block relbar1 %}
- <a href="../man/systemd.index.html">Index </a>·
- <a href="../man/systemd.directives.html">Directives </a>·
- <a href="index.html">Python </a>·
- <span style="float:right">systemd {{release}}</span>
- <hr />
-{% endblock %}
-
-{# remove the lower relbar #}
-{% block relbar2 %} {% endblock %}
-
-{# remove the footer #}
-{% block footer %} {% endblock %}
diff --git a/src/python-systemd/docs/login.rst b/src/python-systemd/docs/login.rst
deleted file mode 100644
index 6b4de64c55..0000000000
--- a/src/python-systemd/docs/login.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-`systemd.login` module
-=======================
-
-.. automodule:: systemd.login
- :members:
-
-.. autoclass:: Monitor
- :undoc-members:
- :inherited-members:
-
-Example: polling for events
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This example shows that session/uid/seat/machine events can be waited
-for (using e.g. `poll`). This makes it easy to integrate Monitor in an
-external event loop:
-
- >>> import select
- >>> from systemd import login
- >>> m = login.Monitor("machine")
- >>> p = select.poll()
- >>> p.register(m, m.get_events())
- >>> login.machine_names()
- []
- >>> p.poll()
- [(3, 1)]
- >>> login.machine_names()
- ['fedora-19.nspawn']
diff --git a/src/python-systemd/id128.c b/src/python-systemd/id128.c
deleted file mode 100644
index 5ec7309a54..0000000000
--- a/src/python-systemd/id128.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <Python.h>
-
-#include "systemd/sd-messages.h"
-
-#include "pyutil.h"
-#include "log.h"
-#include "util.h"
-#include "macro.h"
-
-PyDoc_STRVAR(module__doc__,
- "Python interface to the libsystemd-id128 library.\n\n"
- "Provides SD_MESSAGE_* constants and functions to query and generate\n"
- "128-bit unique identifiers."
-);
-
-PyDoc_STRVAR(randomize__doc__,
- "randomize() -> UUID\n\n"
- "Return a new random 128-bit unique identifier.\n"
- "Wraps sd_id128_randomize(3)."
-);
-
-PyDoc_STRVAR(get_machine__doc__,
- "get_machine() -> UUID\n\n"
- "Return a 128-bit unique identifier for this machine.\n"
- "Wraps sd_id128_get_machine(3)."
-);
-
-PyDoc_STRVAR(get_boot__doc__,
- "get_boot() -> UUID\n\n"
- "Return a 128-bit unique identifier for this boot.\n"
- "Wraps sd_id128_get_boot(3)."
-);
-
-static PyObject* make_uuid(sd_id128_t id) {
- _cleanup_Py_DECREF_ PyObject
- *uuid = NULL, *UUID = NULL, *bytes = NULL,
- *args = NULL, *kwargs = NULL;
-
- uuid = PyImport_ImportModule("uuid");
- if (!uuid)
- return NULL;
-
- UUID = PyObject_GetAttrString(uuid, "UUID");
- bytes = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
- args = Py_BuildValue("()");
- kwargs = PyDict_New();
- if (!UUID || !bytes || !args || !kwargs)
- return NULL;
-
- if (PyDict_SetItemString(kwargs, "bytes", bytes) < 0)
- return NULL;
-
- return PyObject_Call(UUID, args, kwargs);
-}
-
-#define helper(name) \
- static PyObject *name(PyObject *self, PyObject *args) { \
- sd_id128_t id; \
- int r; \
- \
- assert(args == NULL); \
- \
- r = sd_id128_##name(&id); \
- if (r < 0) { \
- errno = -r; \
- return PyErr_SetFromErrno(PyExc_IOError); \
- } \
- \
- return make_uuid(id); \
- }
-
-helper(randomize)
-helper(get_machine)
-helper(get_boot)
-
-static PyMethodDef methods[] = {
- { "randomize", randomize, METH_NOARGS, randomize__doc__},
- { "get_machine", get_machine, METH_NOARGS, get_machine__doc__},
- { "get_boot", get_boot, METH_NOARGS, get_boot__doc__},
- { NULL, NULL, 0, NULL } /* Sentinel */
-};
-
-static int add_id(PyObject *module, const char* name, sd_id128_t id) {
- PyObject *obj;
-
- obj = make_uuid(id);
- if (!obj)
- return -1;
-
- return PyModule_AddObject(module, name, obj);
-}
-
-#if PY_MAJOR_VERSION < 3
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC initid128(void) {
- PyObject *m;
-
- m = Py_InitModule3("id128", methods, module__doc__);
- if (m == NULL)
- return;
-
- /* a series of lines like 'add_id() ;' follow */
-#define JOINER ;
-#include "id128-constants.h"
-#undef JOINER
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
-}
-REENABLE_WARNING;
-
-#else
-
-static struct PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "id128", /* name of module */
- module__doc__, /* module documentation, may be NULL */
- -1, /* size of per-interpreter state of the module */
- methods
-};
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC PyInit_id128(void) {
- PyObject *m;
-
- m = PyModule_Create(&module);
- if (m == NULL)
- return NULL;
-
- if ( /* a series of lines like 'add_id() ||' follow */
-#define JOINER ||
-#include "id128-constants.h"
-#undef JOINER
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
-REENABLE_WARNING;
-
-#endif
diff --git a/src/python-systemd/journal.py b/src/python-systemd/journal.py
deleted file mode 100644
index dd1f229973..0000000000
--- a/src/python-systemd/journal.py
+++ /dev/null
@@ -1,548 +0,0 @@
-# -*- Mode: python; coding:utf-8; indent-tabs-mode: nil -*- */
-#
-# This file is part of systemd.
-#
-# Copyright 2012 David Strauss <david@davidstrauss.net>
-# Copyright 2012 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
-# Copyright 2012 Marti Raudsepp <marti@juffo.org>
-#
-# 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.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import division
-
-import sys as _sys
-import datetime as _datetime
-import uuid as _uuid
-import traceback as _traceback
-import os as _os
-import logging as _logging
-if _sys.version_info >= (3,3):
- from collections import ChainMap as _ChainMap
-from syslog import (LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
- LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG)
-from ._journal import __version__, sendv, stream_fd
-from ._reader import (_Reader, NOP, APPEND, INVALIDATE,
- LOCAL_ONLY, RUNTIME_ONLY,
- SYSTEM, SYSTEM_ONLY, CURRENT_USER,
- _get_catalog)
-from . import id128 as _id128
-
-if _sys.version_info >= (3,):
- from ._reader import Monotonic
-else:
- Monotonic = tuple
-
-def _convert_monotonic(m):
- return Monotonic((_datetime.timedelta(microseconds=m[0]),
- _uuid.UUID(bytes=m[1])))
-
-def _convert_source_monotonic(s):
- return _datetime.timedelta(microseconds=int(s))
-
-def _convert_realtime(t):
- return _datetime.datetime.fromtimestamp(t / 1000000)
-
-def _convert_timestamp(s):
- return _datetime.datetime.fromtimestamp(int(s) / 1000000)
-
-def _convert_trivial(x):
- return x
-
-if _sys.version_info >= (3,):
- def _convert_uuid(s):
- return _uuid.UUID(s.decode())
-else:
- _convert_uuid = _uuid.UUID
-
-DEFAULT_CONVERTERS = {
- 'MESSAGE_ID': _convert_uuid,
- '_MACHINE_ID': _convert_uuid,
- '_BOOT_ID': _convert_uuid,
- 'PRIORITY': int,
- 'LEADER': int,
- 'SESSION_ID': int,
- 'USERSPACE_USEC': int,
- 'INITRD_USEC': int,
- 'KERNEL_USEC': int,
- '_UID': int,
- '_GID': int,
- '_PID': int,
- 'SYSLOG_FACILITY': int,
- 'SYSLOG_PID': int,
- '_AUDIT_SESSION': int,
- '_AUDIT_LOGINUID': int,
- '_SYSTEMD_SESSION': int,
- '_SYSTEMD_OWNER_UID': int,
- 'CODE_LINE': int,
- 'ERRNO': int,
- 'EXIT_STATUS': int,
- '_SOURCE_REALTIME_TIMESTAMP': _convert_timestamp,
- '__REALTIME_TIMESTAMP': _convert_realtime,
- '_SOURCE_MONOTONIC_TIMESTAMP': _convert_source_monotonic,
- '__MONOTONIC_TIMESTAMP': _convert_monotonic,
- '__CURSOR': _convert_trivial,
- 'COREDUMP': bytes,
- 'COREDUMP_PID': int,
- 'COREDUMP_UID': int,
- 'COREDUMP_GID': int,
- 'COREDUMP_SESSION': int,
- 'COREDUMP_SIGNAL': int,
- 'COREDUMP_TIMESTAMP': _convert_timestamp,
-}
-
-_IDENT_LETTER = set('ABCDEFGHIJKLMNOPQRTSUVWXYZ_')
-
-def _valid_field_name(s):
- return not (set(s) - _IDENT_LETTER)
-
-class Reader(_Reader):
- """Reader allows the access and filtering of systemd journal
- entries. Note that in order to access the system journal, a
- non-root user must be in the `systemd-journal` group.
-
- Example usage to print out all informational or higher level
- messages for systemd-udevd for this boot:
-
- >>> j = journal.Reader()
- >>> j.this_boot()
- >>> j.log_level(journal.LOG_INFO)
- >>> j.add_match(_SYSTEMD_UNIT="systemd-udevd.service")
- >>> for entry in j:
- ... print(entry['MESSAGE'])
-
- See systemd.journal-fields(7) for more info on typical fields
- found in the journal.
- """
- def __init__(self, flags=0, path=None, files=None, converters=None):
- """Create an instance of Reader, which allows filtering and
- return of journal entries.
-
- Argument `flags` sets open flags of the journal, which can be one
- of, or ORed combination of constants: LOCAL_ONLY (default) opens
- journal on local machine only; RUNTIME_ONLY opens only
- volatile journal files; and SYSTEM_ONLY opens only
- journal files of system services and the kernel.
-
- Argument `path` is the directory of journal files. Note that
- `flags` and `path` are exclusive.
-
- Argument `converters` is a dictionary which updates the
- DEFAULT_CONVERTERS to convert journal field values. Field
- names are used as keys into this dictionary. The values must
- be single argument functions, which take a `bytes` object and
- return a converted value. When there's no entry for a field
- name, then the default UTF-8 decoding will be attempted. If
- the conversion fails with a ValueError, unconverted bytes
- object will be returned. (Note that ValueEror is a superclass
- of UnicodeDecodeError).
-
- Reader implements the context manager protocol: the journal
- will be closed when exiting the block.
- """
- super(Reader, self).__init__(flags, path, files)
- if _sys.version_info >= (3,3):
- self.converters = _ChainMap()
- if converters is not None:
- self.converters.maps.append(converters)
- self.converters.maps.append(DEFAULT_CONVERTERS)
- else:
- self.converters = DEFAULT_CONVERTERS.copy()
- if converters is not None:
- self.converters.update(converters)
-
- def _convert_field(self, key, value):
- """Convert value using self.converters[key]
-
- If `key` is not present in self.converters, a standard unicode
- decoding will be attempted. If the conversion (either
- key-specific or the default one) fails with a ValueError, the
- original bytes object will be returned.
- """
- convert = self.converters.get(key, bytes.decode)
- try:
- return convert(value)
- except ValueError:
- # Leave in default bytes
- return value
-
- def _convert_entry(self, entry):
- """Convert entire journal entry utilising _covert_field"""
- result = {}
- for key, value in entry.items():
- if isinstance(value, list):
- result[key] = [self._convert_field(key, val) for val in value]
- else:
- result[key] = self._convert_field(key, value)
- return result
-
- def __iter__(self):
- """Part of iterator protocol.
- Returns self.
- """
- return self
-
- def __next__(self):
- """Part of iterator protocol.
- Returns self.get_next() or raises StopIteration.
- """
- ans = self.get_next()
- if ans:
- return ans
- else:
- raise StopIteration()
-
- if _sys.version_info < (3,):
- next = __next__
-
- def add_match(self, *args, **kwargs):
- """Add one or more matches to the filter journal log entries.
- All matches of different field are combined in a logical AND,
- and matches of the same field are automatically combined in a
- logical OR.
- Matches can be passed as strings of form "FIELD=value", or
- keyword arguments FIELD="value".
- """
- args = list(args)
- args.extend(_make_line(key, val) for key, val in kwargs.items())
- for arg in args:
- super(Reader, self).add_match(arg)
-
- def get_next(self, skip=1):
- """Return the next log entry as a mapping type, currently
- a standard dictionary of fields.
-
- Optional skip value will return the `skip`\-th log entry.
-
- Entries will be processed with converters specified during
- Reader creation.
- """
- if super(Reader, self)._next(skip):
- entry = super(Reader, self)._get_all()
- if entry:
- entry['__REALTIME_TIMESTAMP'] = self._get_realtime()
- entry['__MONOTONIC_TIMESTAMP'] = self._get_monotonic()
- entry['__CURSOR'] = self._get_cursor()
- return self._convert_entry(entry)
- return dict()
-
- def get_previous(self, skip=1):
- """Return the previous log entry as a mapping type,
- currently a standard dictionary of fields.
-
- Optional skip value will return the -`skip`\-th log entry.
-
- Entries will be processed with converters specified during
- Reader creation.
-
- Equivalent to get_next(-skip).
- """
- return self.get_next(-skip)
-
- def query_unique(self, field):
- """Return unique values appearing in the journal for given `field`.
-
- Note this does not respect any journal matches.
-
- Entries will be processed with converters specified during
- Reader creation.
- """
- return set(self._convert_field(field, value)
- for value in super(Reader, self).query_unique(field))
-
- def wait(self, timeout=None):
- """Wait for a change in the journal. `timeout` is the maximum
- time in seconds to wait, or None, to wait forever.
-
- Returns one of NOP (no change), APPEND (new entries have been
- added to the end of the journal), or INVALIDATE (journal files
- have been added or removed).
- """
- us = -1 if timeout is None else int(timeout * 1000000)
- return super(Reader, self).wait(us)
-
- def seek_realtime(self, realtime):
- """Seek to a matching journal entry nearest to `realtime` time.
-
- Argument `realtime` must be either an integer unix timestamp
- or datetime.datetime instance.
- """
- if isinstance(realtime, _datetime.datetime):
- realtime = float(realtime.strftime("%s.%f")) * 1000000
- return super(Reader, self).seek_realtime(int(realtime))
-
- def seek_monotonic(self, monotonic, bootid=None):
- """Seek to a matching journal entry nearest to `monotonic` time.
-
- Argument `monotonic` is a timestamp from boot in either
- seconds or a datetime.timedelta instance. Argument `bootid`
- is a string or UUID representing which boot the monotonic time
- is reference to. Defaults to current bootid.
- """
- if isinstance(monotonic, _datetime.timedelta):
- monotonic = monotonic.totalseconds()
- monotonic = int(monotonic * 1000000)
- if isinstance(bootid, _uuid.UUID):
- bootid = bootid.hex
- return super(Reader, self).seek_monotonic(monotonic, bootid)
-
- def log_level(self, level):
- """Set maximum log `level` by setting matches for PRIORITY.
- """
- if 0 <= level <= 7:
- for i in range(level+1):
- self.add_match(PRIORITY="%d" % i)
- else:
- raise ValueError("Log level must be 0 <= level <= 7")
-
- def messageid_match(self, messageid):
- """Add match for log entries with specified `messageid`.
-
- `messageid` can be string of hexadicimal digits or a UUID
- instance. Standard message IDs can be found in systemd.id128.
-
- Equivalent to add_match(MESSAGE_ID=`messageid`).
- """
- if isinstance(messageid, _uuid.UUID):
- messageid = messageid.hex
- self.add_match(MESSAGE_ID=messageid)
-
- def this_boot(self, bootid=None):
- """Add match for _BOOT_ID equal to current boot ID or the specified boot ID.
-
- If specified, bootid should be either a UUID or a 32 digit hex number.
-
- Equivalent to add_match(_BOOT_ID='bootid').
- """
- if bootid is None:
- bootid = _id128.get_boot().hex
- else:
- bootid = getattr(bootid, 'hex', bootid)
- self.add_match(_BOOT_ID=bootid)
-
- def this_machine(self, machineid=None):
- """Add match for _MACHINE_ID equal to the ID of this machine.
-
- If specified, machineid should be either a UUID or a 32 digit hex number.
-
- Equivalent to add_match(_MACHINE_ID='machineid').
- """
- if machineid is None:
- machineid = _id128.get_machine().hex
- else:
- machineid = getattr(machineid, 'hex', machineid)
- self.add_match(_MACHINE_ID=machineid)
-
-
-def get_catalog(mid):
- if isinstance(mid, _uuid.UUID):
- mid = mid.hex
- return _get_catalog(mid)
-
-def _make_line(field, value):
- if isinstance(value, bytes):
- return field.encode('utf-8') + b'=' + value
- elif isinstance(value, int):
- return field + '=' + str(value)
- else:
- return field + '=' + value
-
-def send(MESSAGE, MESSAGE_ID=None,
- CODE_FILE=None, CODE_LINE=None, CODE_FUNC=None,
- **kwargs):
- r"""Send a message to the journal.
-
- >>> journal.send('Hello world')
- >>> journal.send('Hello, again, world', FIELD2='Greetings!')
- >>> journal.send('Binary message', BINARY=b'\xde\xad\xbe\xef')
-
- Value of the MESSAGE argument will be used for the MESSAGE=
- field. MESSAGE must be a string and will be sent as UTF-8 to
- the journal.
-
- MESSAGE_ID can be given to uniquely identify the type of
- message. It must be a string or a uuid.UUID object.
-
- CODE_LINE, CODE_FILE, and CODE_FUNC can be specified to
- identify the caller. Unless at least on of the three is given,
- values are extracted from the stack frame of the caller of
- send(). CODE_FILE and CODE_FUNC must be strings, CODE_LINE
- must be an integer.
-
- Additional fields for the journal entry can only be specified
- as keyword arguments. The payload can be either a string or
- bytes. A string will be sent as UTF-8, and bytes will be sent
- as-is to the journal.
-
- Other useful fields include PRIORITY, SYSLOG_FACILITY,
- SYSLOG_IDENTIFIER, SYSLOG_PID.
- """
-
- args = ['MESSAGE=' + MESSAGE]
-
- if MESSAGE_ID is not None:
- id = getattr(MESSAGE_ID, 'hex', MESSAGE_ID)
- args.append('MESSAGE_ID=' + id)
-
- if CODE_LINE == CODE_FILE == CODE_FUNC == None:
- CODE_FILE, CODE_LINE, CODE_FUNC = \
- _traceback.extract_stack(limit=2)[0][:3]
- if CODE_FILE is not None:
- args.append('CODE_FILE=' + CODE_FILE)
- if CODE_LINE is not None:
- args.append('CODE_LINE={:d}'.format(CODE_LINE))
- if CODE_FUNC is not None:
- args.append('CODE_FUNC=' + CODE_FUNC)
-
- args.extend(_make_line(key, val) for key, val in kwargs.items())
- return sendv(*args)
-
-def stream(identifier, priority=LOG_DEBUG, level_prefix=False):
- r"""Return a file object wrapping a stream to journal.
-
- Log messages written to this file as simple newline sepearted
- text strings are written to the journal.
-
- The file will be line buffered, so messages are actually sent
- after a newline character is written.
-
- >>> stream = journal.stream('myapp')
- >>> stream
- <open file '<fdopen>', mode 'w' at 0x...>
- >>> stream.write('message...\n')
-
- will produce the following message in the journal::
-
- PRIORITY=7
- SYSLOG_IDENTIFIER=myapp
- MESSAGE=message...
-
- Using the interface with print might be more convinient:
-
- >>> from __future__ import print_function
- >>> print('message...', file=stream)
-
- priority is the syslog priority, one of `LOG_EMERG`,
- `LOG_ALERT`, `LOG_CRIT`, `LOG_ERR`, `LOG_WARNING`,
- `LOG_NOTICE`, `LOG_INFO`, `LOG_DEBUG`.
-
- level_prefix is a boolean. If true, kernel-style log priority
- level prefixes (such as '<1>') are interpreted. See
- sd-daemon(3) for more information.
- """
-
- fd = stream_fd(identifier, priority, level_prefix)
- return _os.fdopen(fd, 'w', 1)
-
-class JournalHandler(_logging.Handler):
- """Journal handler class for the Python logging framework.
-
- Please see the Python logging module documentation for an
- overview: http://docs.python.org/library/logging.html.
-
- To create a custom logger whose messages go only to journal:
-
- >>> log = logging.getLogger('custom_logger_name')
- >>> log.propagate = False
- >>> log.addHandler(journal.JournalHandler())
- >>> log.warn("Some message: %s", detail)
-
- Note that by default, message levels `INFO` and `DEBUG` are
- ignored by the logging framework. To enable those log levels:
-
- >>> log.setLevel(logging.DEBUG)
-
- To redirect all logging messages to journal regardless of where
- they come from, attach it to the root logger:
-
- >>> logging.root.addHandler(journal.JournalHandler())
-
- For more complex configurations when using `dictConfig` or
- `fileConfig`, specify `systemd.journal.JournalHandler` as the
- handler class. Only standard handler configuration options
- are supported: `level`, `formatter`, `filters`.
-
- To attach journal MESSAGE_ID, an extra field is supported:
-
- >>> import uuid
- >>> mid = uuid.UUID('0123456789ABCDEF0123456789ABCDEF')
- >>> log.warn("Message with ID", extra={'MESSAGE_ID': mid})
-
- Fields to be attached to all messages sent through this
- handler can be specified as keyword arguments. This probably
- makes sense only for SYSLOG_IDENTIFIER and similar fields
- which are constant for the whole program:
-
- >>> journal.JournalHandler(SYSLOG_IDENTIFIER='my-cool-app')
-
- The following journal fields will be sent:
- `MESSAGE`, `PRIORITY`, `THREAD_NAME`, `CODE_FILE`, `CODE_LINE`,
- `CODE_FUNC`, `LOGGER` (name as supplied to getLogger call),
- `MESSAGE_ID` (optional, see above), `SYSLOG_IDENTIFIER` (defaults
- to sys.argv[0]).
- """
-
- def __init__(self, level=_logging.NOTSET, **kwargs):
- super(JournalHandler, self).__init__(level)
-
- for name in kwargs:
- if not _valid_field_name(name):
- raise ValueError('Invalid field name: ' + name)
- if 'SYSLOG_IDENTIFIER' not in kwargs:
- kwargs['SYSLOG_IDENTIFIER'] = _sys.argv[0]
- self._extra = kwargs
-
- def emit(self, record):
- """Write record as journal event.
-
- MESSAGE is taken from the message provided by the
- user, and PRIORITY, LOGGER, THREAD_NAME,
- CODE_{FILE,LINE,FUNC} fields are appended
- automatically. In addition, record.MESSAGE_ID will be
- used if present.
- """
- try:
- msg = self.format(record)
- pri = self.mapPriority(record.levelno)
- mid = getattr(record, 'MESSAGE_ID', None)
- send(msg,
- MESSAGE_ID=mid,
- PRIORITY=format(pri),
- LOGGER=record.name,
- THREAD_NAME=record.threadName,
- CODE_FILE=record.pathname,
- CODE_LINE=record.lineno,
- CODE_FUNC=record.funcName,
- **self._extra)
- except Exception:
- self.handleError(record)
-
- @staticmethod
- def mapPriority(levelno):
- """Map logging levels to journald priorities.
-
- Since Python log level numbers are "sparse", we have
- to map numbers in between the standard levels too.
- """
- if levelno <= _logging.DEBUG:
- return LOG_DEBUG
- elif levelno <= _logging.INFO:
- return LOG_INFO
- elif levelno <= _logging.WARNING:
- return LOG_WARNING
- elif levelno <= _logging.ERROR:
- return LOG_ERR
- elif levelno <= _logging.CRITICAL:
- return LOG_CRIT
- else:
- return LOG_ALERT
diff --git a/src/python-systemd/login.c b/src/python-systemd/login.c
deleted file mode 100644
index e844f5fc69..0000000000
--- a/src/python-systemd/login.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#define PY_SSIZE_T_CLEAN
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wredundant-decls"
-#include <Python.h>
-#pragma GCC diagnostic pop
-
-#include "systemd/sd-login.h"
-#include "pyutil.h"
-#include "util.h"
-#include "strv.h"
-
-PyDoc_STRVAR(module__doc__,
- "Python interface to the libsystemd-login library."
-);
-
-#define helper(name) \
-static PyObject* name(PyObject *self, PyObject *args) { \
- _cleanup_strv_free_ char **list = NULL; \
- int r; \
- PyObject *ans; \
- \
- assert(args == NULL); \
- \
- r = sd_get_##name(&list); \
- if (r < 0) { \
- errno = -r; \
- return PyErr_SetFromErrno(PyExc_IOError); \
- } \
- \
- ans = PyList_New(r); \
- if (!ans) \
- return NULL; \
- \
- for (r--; r >= 0; r--) { \
- PyObject *s = unicode_FromString(list[r]); \
- if (!s) { \
- Py_DECREF(ans); \
- return NULL; \
- } \
- \
- PyList_SetItem(ans, r, s); \
- } \
- \
- return ans; \
-}
-
-helper(seats)
-helper(sessions)
-helper(machine_names)
-#undef helper
-
-static PyObject* uids(PyObject *self, PyObject *args) {
- _cleanup_free_ uid_t *list = NULL;
- int r;
- PyObject *ans;
-
- assert(args == NULL);
-
- r = sd_get_uids(&list);
- if (r < 0) {
- errno = -r;
- return PyErr_SetFromErrno(PyExc_IOError);
- }
-
- ans = PyList_New(r);
- if (!ans)
- return NULL;
-
- for (r--; r >= 0; r--) {
- PyObject *s = long_FromLong(list[r]);
- if (!s) {
- Py_DECREF(ans);
- return NULL;
- }
-
- PyList_SetItem(ans, r, s);
- }
-
- return ans;
-}
-
-PyDoc_STRVAR(seats__doc__,
- "seats() -> list\n\n"
- "Returns a list of currently available local seats.\n"
- "Wraps sd_get_seats(3)."
-);
-
-PyDoc_STRVAR(sessions__doc__,
- "sessions() -> list\n\n"
- "Returns a list of current login sessions.\n"
- "Wraps sd_get_sessions(3)."
-);
-
-PyDoc_STRVAR(machine_names__doc__,
- "machine_names() -> list\n\n"
- "Returns a list of currently running virtual machines\n"
- "and containers on the system.\n"
- "Wraps sd_get_machine_names(3)."
-);
-
-PyDoc_STRVAR(uids__doc__,
- "uids() -> list\n\n"
- "Returns a list of uids of users who currently have login sessions.\n"
- "Wraps sd_get_uids(3)."
-);
-
-static PyMethodDef methods[] = {
- { "seats", seats, METH_NOARGS, seats__doc__},
- { "sessions", sessions, METH_NOARGS, sessions__doc__},
- { "machine_names", machine_names, METH_NOARGS, machine_names__doc__},
- { "uids", uids, METH_NOARGS, uids__doc__},
- {} /* Sentinel */
-};
-
-
-typedef struct {
- PyObject_HEAD
- sd_login_monitor *monitor;
-} Monitor;
-static PyTypeObject MonitorType;
-
-static void Monitor_dealloc(Monitor* self) {
- sd_login_monitor_unref(self->monitor);
- Py_TYPE(self)->tp_free((PyObject*)self);
-}
-
-PyDoc_STRVAR(Monitor__doc__,
- "Monitor([category]) -> ...\n\n"
- "Monitor may be used to monitor login sessions, users, seats,\n"
- "and virtual machines/containers. Monitor provides a file\n"
- "descriptor which can be integrated in an external event loop.\n"
- "See man:sd_login_monitor_new(3) for the details about what\n"
- "can be monitored.");
-static int Monitor_init(Monitor *self, PyObject *args, PyObject *keywds) {
- const char *category = NULL;
- int r;
-
- static const char* const kwlist[] = {"category", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "|z:__init__", (char**) kwlist,
- &category))
- return -1;
-
- Py_BEGIN_ALLOW_THREADS
- r = sd_login_monitor_new(category, &self->monitor);
- Py_END_ALLOW_THREADS
-
- return set_error(r, NULL, "Invalid category");
-}
-
-
-PyDoc_STRVAR(Monitor_fileno__doc__,
- "fileno() -> int\n\n"
- "Get a file descriptor to poll for events.\n"
- "This method wraps sd_login_monitor_get_fd(3).");
-static PyObject* Monitor_fileno(Monitor *self, PyObject *args) {
- int fd = sd_login_monitor_get_fd(self->monitor);
- set_error(fd, NULL, NULL);
- if (fd < 0)
- return NULL;
- return long_FromLong(fd);
-}
-
-
-PyDoc_STRVAR(Monitor_get_events__doc__,
- "get_events() -> int\n\n"
- "Returns a mask of poll() events to wait for on the file\n"
- "descriptor returned by .fileno().\n\n"
- "See man:sd_login_monitor_get_events(3) for further discussion.");
-static PyObject* Monitor_get_events(Monitor *self, PyObject *args) {
- int r = sd_login_monitor_get_events(self->monitor);
- set_error(r, NULL, NULL);
- if (r < 0)
- return NULL;
- return long_FromLong(r);
-}
-
-
-PyDoc_STRVAR(Monitor_get_timeout__doc__,
- "get_timeout() -> int or None\n\n"
- "Returns a timeout value for usage in poll(), the time since the\n"
- "epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
- "is necessary.\n\n"
- "The return value must be converted to a relative timeout in\n"
- "milliseconds if it is to be used as an argument for poll().\n"
- "See man:sd_login_monitor_get_timeout(3) for further discussion.");
-static PyObject* Monitor_get_timeout(Monitor *self, PyObject *args) {
- int r;
- uint64_t t;
-
- r = sd_login_monitor_get_timeout(self->monitor, &t);
- set_error(r, NULL, NULL);
- if (r < 0)
- return NULL;
-
- if (t == (uint64_t) -1)
- Py_RETURN_NONE;
-
- assert_cc(sizeof(unsigned long long) == sizeof(t));
- return PyLong_FromUnsignedLongLong(t);
-}
-
-
-PyDoc_STRVAR(Monitor_get_timeout_ms__doc__,
- "get_timeout_ms() -> int\n\n"
- "Returns a timeout value suitable for usage in poll(), the value\n"
- "returned by .get_timeout() converted to relative ms, or -1 if\n"
- "no timeout is necessary.");
-static PyObject* Monitor_get_timeout_ms(Monitor *self, PyObject *args) {
- int r;
- uint64_t t;
-
- r = sd_login_monitor_get_timeout(self->monitor, &t);
- set_error(r, NULL, NULL);
- if (r < 0)
- return NULL;
-
- return absolute_timeout(t);
-}
-
-
-PyDoc_STRVAR(Monitor_close__doc__,
- "close() -> None\n\n"
- "Free resources allocated by this Monitor object.\n"
- "This method invokes sd_login_monitor_unref().\n"
- "See man:sd_login_monitor_unref(3).");
-static PyObject* Monitor_close(Monitor *self, PyObject *args) {
- assert(self);
- assert(!args);
-
- sd_login_monitor_unref(self->monitor);
- self->monitor = NULL;
- Py_RETURN_NONE;
-}
-
-
-PyDoc_STRVAR(Monitor_flush__doc__,
- "flush() -> None\n\n"
- "Reset the wakeup state of the monitor object.\n"
- "This method invokes sd_login_monitor_flush().\n"
- "See man:sd_login_monitor_flush(3).");
-static PyObject* Monitor_flush(Monitor *self, PyObject *args) {
- assert(self);
- assert(!args);
-
- Py_BEGIN_ALLOW_THREADS
- sd_login_monitor_flush(self->monitor);
- Py_END_ALLOW_THREADS
- Py_RETURN_NONE;
-}
-
-
-PyDoc_STRVAR(Monitor___enter____doc__,
- "__enter__() -> self\n\n"
- "Part of the context manager protocol.\n"
- "Returns self.\n");
-static PyObject* Monitor___enter__(PyObject *self, PyObject *args) {
- assert(self);
- assert(!args);
-
- Py_INCREF(self);
- return self;
-}
-
-
-PyDoc_STRVAR(Monitor___exit____doc__,
- "__exit__(type, value, traceback) -> None\n\n"
- "Part of the context manager protocol.\n"
- "Closes the monitor..\n");
-static PyObject* Monitor___exit__(Monitor *self, PyObject *args) {
- return Monitor_close(self, args);
-}
-
-
-static PyMethodDef Monitor_methods[] = {
- {"fileno", (PyCFunction) Monitor_fileno, METH_NOARGS, Monitor_fileno__doc__},
- {"get_events", (PyCFunction) Monitor_get_events, METH_NOARGS, Monitor_get_events__doc__},
- {"get_timeout", (PyCFunction) Monitor_get_timeout, METH_NOARGS, Monitor_get_timeout__doc__},
- {"get_timeout_ms", (PyCFunction) Monitor_get_timeout_ms, METH_NOARGS, Monitor_get_timeout_ms__doc__},
- {"close", (PyCFunction) Monitor_close, METH_NOARGS, Monitor_close__doc__},
- {"flush", (PyCFunction) Monitor_flush, METH_NOARGS, Monitor_flush__doc__},
- {"__enter__", (PyCFunction) Monitor___enter__, METH_NOARGS, Monitor___enter____doc__},
- {"__exit__", (PyCFunction) Monitor___exit__, METH_VARARGS, Monitor___exit____doc__},
- {} /* Sentinel */
-};
-
-static PyTypeObject MonitorType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "login.Monitor",
- .tp_basicsize = sizeof(Monitor),
- .tp_dealloc = (destructor) Monitor_dealloc,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_doc = Monitor__doc__,
- .tp_methods = Monitor_methods,
- .tp_init = (initproc) Monitor_init,
- .tp_new = PyType_GenericNew,
-};
-
-#if PY_MAJOR_VERSION < 3
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC initlogin(void) {
- PyObject *m;
-
- if (PyType_Ready(&MonitorType) < 0)
- return;
-
- m = Py_InitModule3("login", methods, module__doc__);
- if (m == NULL)
- return;
-
- PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
-
- Py_INCREF(&MonitorType);
- PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType);
-}
-REENABLE_WARNING;
-
-#else
-
-static struct PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "login", /* name of module */
- module__doc__, /* module documentation, may be NULL */
- -1, /* size of per-interpreter state of the module */
- methods
-};
-
-DISABLE_WARNING_MISSING_PROTOTYPES;
-PyMODINIT_FUNC PyInit_login(void) {
- PyObject *m;
-
- if (PyType_Ready(&MonitorType) < 0)
- return NULL;
-
- m = PyModule_Create(&module);
- if (m == NULL)
- return NULL;
-
- if (PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
- Py_DECREF(m);
- return NULL;
- }
-
- Py_INCREF(&MonitorType);
- if (PyModule_AddObject(m, "Monitor", (PyObject *) &MonitorType)) {
- Py_DECREF(&MonitorType);
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
-REENABLE_WARNING;
-
-#endif
diff --git a/src/python-systemd/pyutil.c b/src/python-systemd/pyutil.c
deleted file mode 100644
index 722c4f5b5f..0000000000
--- a/src/python-systemd/pyutil.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <Python.h>
-#include "pyutil.h"
-
-void cleanup_Py_DECREFp(PyObject **p) {
- if (!*p)
- return;
-
- Py_DECREF(*p);
-}
-
-PyObject* absolute_timeout(uint64_t t) {
- if (t == (uint64_t) -1)
- return PyLong_FromLong(-1);
- else {
- struct timespec ts;
- uint64_t n;
- int msec;
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
- msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
-
- return PyLong_FromLong(msec);
- }
-}
-
-int set_error(int r, const char* path, const char* invalid_message) {
- if (r >= 0)
- return r;
- if (r == -EINVAL && invalid_message)
- PyErr_SetString(PyExc_ValueError, invalid_message);
- else if (r == -ENOMEM)
- PyErr_SetString(PyExc_MemoryError, "Not enough memory");
- else {
- errno = -r;
- PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
- }
- return -1;
-}
-
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
-int Unicode_FSConverter(PyObject* obj, void *_result) {
- PyObject **result = _result;
-
- assert(result);
-
- if (!obj)
- /* cleanup: we don't return Py_CLEANUP_SUPPORTED, so
- * we can assume that it was PyUnicode_FSConverter. */
- return PyUnicode_FSConverter(obj, result);
-
- if (obj == Py_None) {
- *result = NULL;
- return 1;
- }
-
- return PyUnicode_FSConverter(obj, result);
-}
-#endif
diff --git a/src/python-systemd/pyutil.h b/src/python-systemd/pyutil.h
deleted file mode 100644
index 1477e7bf9c..0000000000
--- a/src/python-systemd/pyutil.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
-
- 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.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#ifndef Py_TYPE
-/* avoid duplication warnings from errors in Python 2.7 headers */
-# include <Python.h>
-#endif
-
-void cleanup_Py_DECREFp(PyObject **p);
-PyObject* absolute_timeout(uint64_t t);
-int set_error(int r, const char* path, const char* invalid_message);
-
-#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 1
-int Unicode_FSConverter(PyObject* obj, void *_result);
-#endif
-
-#define _cleanup_Py_DECREF_ __attribute__((cleanup(cleanup_Py_DECREFp)))
-
-#if PY_MAJOR_VERSION >=3
-# define unicode_FromStringAndSize PyUnicode_FromStringAndSize
-# define unicode_FromString PyUnicode_FromString
-# define long_FromLong PyLong_FromLong
-# define long_FromSize_t PyLong_FromSize_t
-# define long_Check PyLong_Check
-# define long_AsLong PyLong_AsLong
-#else
-/* Python 3 type naming convention is used */
-# define unicode_FromStringAndSize PyString_FromStringAndSize
-# define unicode_FromString PyString_FromString
-# define long_FromLong PyInt_FromLong
-# define long_FromSize_t PyInt_FromSize_t
-# define long_Check PyInt_Check
-# define long_AsLong PyInt_AsLong
-#endif
diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c
index 068756cab1..0edba415b6 100644
--- a/src/resolve-host/resolve-host.c
+++ b/src/resolve-host/resolve-host.c
@@ -89,10 +89,6 @@ static int resolve_host(sd_bus *bus, const char *name) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_set_auto_start(req, false);
- if (r < 0)
- return bus_log_create_error(r);
-
r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
if (r < 0)
return bus_log_create_error(r);
@@ -592,7 +588,7 @@ static int parse_argv(int argc, char *argv[]) {
}
int main(int argc, char **argv) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
log_parse_environment();
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
index a3e740896f..e1087b3219 100644
--- a/src/resolve/dns-type.c
+++ b/src/resolve/dns-type.c
@@ -43,3 +43,8 @@ int dns_type_from_string(const char *s) {
return sc->id;
}
+
+/* XXX: find an authorotative list of all pseudo types? */
+bool dns_type_is_pseudo(int n) {
+ return IN_SET(n, DNS_TYPE_ANY, DNS_TYPE_AXFR, DNS_TYPE_IXFR, DNS_TYPE_OPT);
+}
diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h
index 86951d233a..950af36ee3 100644
--- a/src/resolve/dns-type.h
+++ b/src/resolve/dns-type.h
@@ -25,6 +25,7 @@
const char *dns_type_to_string(int type);
int dns_type_from_string(const char *s);
+bool dns_type_is_pseudo(int n);
/* DNS record types, taken from
* http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index bb74b1828e..649e8b74e1 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -32,10 +32,10 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
assert(ret);
- if (mtu <= 0)
+ if (mtu <= UDP_PACKET_HEADER_SIZE)
a = DNS_PACKET_SIZE_START;
else
- a = mtu;
+ a = mtu - UDP_PACKET_HEADER_SIZE;
if (a < DNS_PACKET_HEADER_SIZE)
a = DNS_PACKET_HEADER_SIZE;
@@ -166,10 +166,17 @@ int dns_packet_validate_reply(DnsPacket *p) {
if (DNS_PACKET_OPCODE(p) != 0)
return -EBADMSG;
- /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
- if (p->protocol == DNS_PROTOCOL_LLMNR &&
- DNS_PACKET_QDCOUNT(p) != 1)
- return -EBADMSG;
+ switch (p->protocol) {
+ case DNS_PROTOCOL_LLMNR:
+ /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
+ if (DNS_PACKET_QDCOUNT(p) != 1)
+ return -EBADMSG;
+
+ break;
+
+ default:
+ break;
+ }
return 1;
}
@@ -192,18 +199,25 @@ int dns_packet_validate_query(DnsPacket *p) {
if (DNS_PACKET_TC(p))
return -EBADMSG;
- /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
- if (p->protocol == DNS_PROTOCOL_LLMNR &&
- DNS_PACKET_QDCOUNT(p) != 1)
- return -EBADMSG;
+ switch (p->protocol) {
+ case DNS_PROTOCOL_LLMNR:
+ /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
+ if (DNS_PACKET_QDCOUNT(p) != 1)
+ return -EBADMSG;
- /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
- if (DNS_PACKET_ANCOUNT(p) > 0)
- return -EBADMSG;
+ /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
+ if (DNS_PACKET_ANCOUNT(p) > 0)
+ return -EBADMSG;
- /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
- if (DNS_PACKET_NSCOUNT(p) > 0)
- return -EBADMSG;
+ /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
+ if (DNS_PACKET_NSCOUNT(p) > 0)
+ return -EBADMSG;
+
+ break;
+
+ default:
+ break;
+ }
return 1;
}
@@ -261,7 +275,7 @@ static void dns_packet_truncate(DnsPacket *p, size_t sz) {
if (p->size <= sz)
return;
- HASHMAP_FOREACH_KEY(s, n, p->names, i) {
+ HASHMAP_FOREACH_KEY(n, s, p->names, i) {
if (PTR_TO_SIZE(n) < sz)
continue;
@@ -488,6 +502,90 @@ fail:
return r;
}
+static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
+ size_t saved_size;
+ int r;
+
+ assert(p);
+ assert(types);
+
+ saved_size = p->size;
+
+ if (length != 0) {
+
+ r = dns_packet_append_uint8(p, window, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, length, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_blob(p, types, length, NULL);
+ if (r < 0)
+ goto fail;
+ }
+
+ if (start)
+ *start = saved_size;
+
+ return 0;
+fail:
+ dns_packet_truncate(p, saved_size);
+ return r;
+}
+
+static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
+ Iterator i;
+ uint8_t window = 0;
+ uint8_t len = 0;
+ uint8_t bitmaps[32] = {};
+ unsigned n;
+ size_t saved_size;
+ int r;
+
+ assert(p);
+ assert(types);
+
+ saved_size = p->size;
+
+ BITMAP_FOREACH(n, types, i) {
+ uint8_t entry;
+
+ assert(n <= 0xffff);
+
+ if ((n << 8) != window) {
+ r = dns_packet_append_type_window(p, window, len, bitmaps, NULL);
+ if (r < 0)
+ goto fail;
+
+ if (len > 0) {
+ len = 0;
+ zero(bitmaps);
+ }
+ }
+
+ window = n << 8;
+ len ++;
+
+ entry = n & 255;
+
+ bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
+ }
+
+ r = dns_packet_append_type_window(p, window, len, bitmaps, NULL);
+ if (r < 0)
+ goto fail;
+
+ if (start)
+ *start = saved_size;
+
+ return 0;
+fail:
+ dns_packet_truncate(p, saved_size);
+ return r;
+}
+
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
size_t saved_size, rdlength_offset, end, rdlength;
int r;
@@ -638,6 +736,22 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
break;
+ case DNS_TYPE_DS:
+ r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
+ break;
+
case DNS_TYPE_SSHFP:
r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
if (r < 0)
@@ -647,7 +761,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
- r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
+ r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
break;
case DNS_TYPE_DNSKEY:
@@ -691,7 +805,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
if (r < 0)
goto fail;
- r = dns_packet_append_uint8(p, rr->rrsig.key_tag, NULL);
+ r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
if (r < 0)
goto fail;
@@ -702,6 +816,50 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
break;
+ case DNS_TYPE_NSEC:
+ r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_types(p, rr->nsec.types, NULL);
+ if (r < 0)
+ goto fail;
+
+ break;
+ case DNS_TYPE_NSEC3:
+ r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_append_types(p, rr->nsec3.types, NULL);
+ if (r < 0)
+ goto fail;
+
+ break;
case _DNS_TYPE_INVALID: /* unparseable */
default:
@@ -775,6 +933,42 @@ int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
return 0;
}
+static int dns_packet_read_memdup(
+ DnsPacket *p, size_t size,
+ void **ret, size_t *ret_size,
+ size_t *ret_start) {
+
+ const void *src;
+ size_t start;
+ int r;
+
+ assert(p);
+ assert(ret);
+
+ r = dns_packet_read(p, size, &src, &start);
+ if (r < 0)
+ return r;
+
+ if (size <= 0)
+ *ret = NULL;
+ else {
+ void *copy;
+
+ copy = memdup(src, size);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret = copy;
+ }
+
+ if (ret_size)
+ *ret_size = size;
+ if (ret_start)
+ *ret_start = start;
+
+ return 0;
+}
+
int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
const void *d;
int r;
@@ -966,6 +1160,114 @@ fail:
return r;
}
+static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
+ uint8_t window;
+ uint8_t length;
+ const uint8_t *bitmap;
+ unsigned i;
+ bool found = false;
+ size_t saved_rindex;
+ int r;
+
+ assert(p);
+ assert(types);
+
+ saved_rindex = p->rindex;
+
+ r = bitmap_ensure_allocated(types);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &window, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &length, NULL);
+ if (r < 0)
+ goto fail;
+
+ if (length == 0 || length > 32)
+ return -EBADMSG;
+
+ r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
+ if (r < 0)
+ goto fail;
+
+ for (i = 0; i < length; i++) {
+ uint8_t bitmask = 1 << 7;
+ uint8_t bit = 0;
+
+ if (!bitmap[i]) {
+ found = false;
+ continue;
+ }
+
+ found = true;
+
+ while (bitmask) {
+ if (bitmap[i] & bitmask) {
+ uint16_t n;
+
+ n = (uint16_t) window << 8 | (uint16_t) bit;
+
+ /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
+ if (dns_type_is_pseudo(n))
+ continue;
+
+ r = bitmap_set(*types, n);
+ if (r < 0)
+ goto fail;
+ }
+
+ bit ++;
+ bitmask >>= 1;
+ }
+ }
+
+ if (!found)
+ return -EBADMSG;
+
+ if (start)
+ *start = saved_rindex;
+
+ return 0;
+fail:
+ dns_packet_rewind(p, saved_rindex);
+ return r;
+}
+
+static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
+ size_t saved_rindex;
+ int r;
+
+ saved_rindex = p->rindex;
+
+ while (p->rindex < saved_rindex + size) {
+ r = dns_packet_read_type_window(p, types, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* don't read past end of current RR */
+ if (p->rindex > saved_rindex + size) {
+ r = -EBADMSG;
+ goto fail;
+ }
+ }
+
+ if (p->rindex != saved_rindex + size) {
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ if (start)
+ *start = saved_rindex;
+
+ return 0;
+fail:
+ dns_packet_rewind(p, saved_rindex);
+ return r;
+}
+
int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
_cleanup_free_ char *name = NULL;
uint16_t class, type;
@@ -1008,26 +1310,6 @@ fail:
return r;
}
-static int dns_packet_read_public_key(DnsPacket *p, size_t length,
- void **dp, size_t *lengthp,
- size_t *start) {
- int r;
- const void *d;
- void *d2;
-
- r = dns_packet_read(p, length, &d, NULL);
- if (r < 0)
- return r;
-
- d2 = memdup(d, length);
- if (!d2)
- return -ENOMEM;
-
- *dp = d2;
- *lengthp = length;
- return 0;
-}
-
static bool loc_size_ok(uint8_t size) {
uint8_t m = size >> 4, e = size & 0xF;
@@ -1050,7 +1332,6 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
size_t saved_rindex, offset;
uint16_t rdlength;
- const void *d;
int r;
assert(p);
@@ -1248,6 +1529,33 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
}
}
+ case DNS_TYPE_DS:
+ r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_memdup(p, rdlength - 4,
+ &rr->ds.digest, &rr->ds.digest_size,
+ NULL);
+ if (r < 0)
+ goto fail;
+
+ if (rr->ds.digest_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ break;
case DNS_TYPE_SSHFP:
r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
if (r < 0)
@@ -1257,9 +1565,17 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
- r = dns_packet_read_public_key(p, rdlength - 2,
- &rr->sshfp.key, &rr->sshfp.key_size,
- NULL);
+ r = dns_packet_read_memdup(p, rdlength - 2,
+ &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
+ NULL);
+
+ if (rr->sshfp.fingerprint_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
case DNS_TYPE_DNSKEY: {
@@ -1288,9 +1604,17 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
- r = dns_packet_read_public_key(p, rdlength - 4,
- &rr->dnskey.key, &rr->dnskey.key_size,
- NULL);
+ r = dns_packet_read_memdup(p, rdlength - 4,
+ &rr->dnskey.key, &rr->dnskey.key_size,
+ NULL);
+
+ if (rr->dnskey.key_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
}
@@ -1327,24 +1651,83 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
if (r < 0)
goto fail;
- r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
- &rr->rrsig.signature, &rr->rrsig.signature_size,
- NULL);
+ r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
+ &rr->rrsig.signature, &rr->rrsig.signature_size,
+ NULL);
+
+ if (rr->rrsig.signature_size <= 0) {
+ /* the accepted size depends on the algorithm, but for now
+ just ensure that the value is greater than zero */
+ r = -EBADMSG;
+ goto fail;
+ }
+
break;
- default:
- unparseable:
- r = dns_packet_read(p, rdlength, &d, NULL);
+ case DNS_TYPE_NSEC:
+ r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
if (r < 0)
goto fail;
- rr->generic.data = memdup(d, rdlength);
- if (!rr->generic.data) {
- r = -ENOMEM;
+ r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them
+ so we allow it */
+
+ break;
+
+ case DNS_TYPE_NSEC3: {
+ uint8_t size;
+
+ r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* this may be zero */
+ r = dns_packet_read_uint8(p, &size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint8(p, &size, NULL);
+ if (r < 0)
+ goto fail;
+
+ if (size <= 0) {
+ r = -EBADMSG;
goto fail;
}
- rr->generic.size = rdlength;
+ r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
+ if (r < 0)
+ goto fail;
+
+ /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
+
+ break;
+ }
+ default:
+ unparseable:
+ r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
+ if (r < 0)
+ goto fail;
break;
}
if (r < 0)
@@ -1466,13 +1849,15 @@ static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
- [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
- [DNSSEC_ALGORITHM_DH] = "DH",
- [DNSSEC_ALGORITHM_DSA] = "DSA",
- [DNSSEC_ALGORITHM_ECC] = "ECC",
- [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
- [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
- [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
- [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
+ [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
+ [DNSSEC_ALGORITHM_DH] = "DH",
+ [DNSSEC_ALGORITHM_DSA] = "DSA",
+ [DNSSEC_ALGORITHM_ECC] = "ECC",
+ [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
+ [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
+ [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
+ [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
+ [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
+ [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
};
DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index c5867386c6..58559c85df 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -21,6 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <netinet/udp.h>
+#include <netinet/ip.h>
#include "macro.h"
#include "sparse-endian.h"
@@ -53,6 +55,7 @@ struct DnsPacketHeader {
};
#define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader)
+#define UDP_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr))
/* The various DNS protocols deviate in how large a packet can grow,
but the TCP transport has a 16bit size field, hence that appears to
@@ -99,10 +102,18 @@ static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {
#define DNS_PACKET_ID(p) DNS_PACKET_HEADER(p)->id
#define DNS_PACKET_QR(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 15) & 1)
#define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15)
-#define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15)
+#define DNS_PACKET_AA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1)
#define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1)
-#define DNS_PACKET_C(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1)
-#define DNS_PACKET_T(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1)
+#define DNS_PACKET_RD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1)
+#define DNS_PACKET_RA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 7) & 1)
+#define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1)
+#define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1)
+#define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15)
+
+/* LLMNR defines some bits differently */
+#define DNS_PACKET_LLMNR_C(p) DNS_PACKET_AA(p)
+#define DNS_PACKET_LLMNR_T(p) DNS_PACKET_RD(p)
+
#define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount)
#define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount)
#define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount)
@@ -212,6 +223,8 @@ enum {
DNSSEC_ALGORITHM_DSA,
DNSSEC_ALGORITHM_ECC,
DNSSEC_ALGORITHM_RSASHA1,
+ DNSSEC_ALGORITHM_DSA_NSEC3_SHA1,
+ DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
DNSSEC_ALGORITHM_INDIRECT = 252,
DNSSEC_ALGORITHM_PRIVATEDNS,
DNSSEC_ALGORITHM_PRIVATEOID,
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index c1818eef9c..ad7ca26cfe 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -171,19 +171,19 @@ const struct hash_ops dns_resource_key_hash_ops = {
};
int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
- char cbuf[DECIMAL_STR_MAX(uint16_t)], tbuf[DECIMAL_STR_MAX(uint16_t)];
+ char cbuf[strlen("CLASS") + DECIMAL_STR_MAX(uint16_t)], tbuf[strlen("TYPE") + DECIMAL_STR_MAX(uint16_t)];
const char *c, *t;
char *s;
c = dns_class_to_string(key->class);
if (!c) {
- sprintf(cbuf, "%i", key->class);
+ sprintf(cbuf, "CLASS%u", key->class);
c = cbuf;
}
t = dns_type_to_string(key->type);
if (!t){
- sprintf(tbuf, "%i", key->type);
+ sprintf(tbuf, "TYPE%u", key->type);
t = tbuf;
}
@@ -271,8 +271,12 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
free(rr->mx.exchange);
break;
+ case DNS_TYPE_DS:
+ free(rr->ds.digest);
+ break;
+
case DNS_TYPE_SSHFP:
- free(rr->sshfp.key);
+ free(rr->sshfp.fingerprint);
break;
case DNS_TYPE_DNSKEY:
@@ -284,6 +288,17 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
free(rr->rrsig.signature);
break;
+ case DNS_TYPE_NSEC:
+ free(rr->nsec.next_domain_name);
+ bitmap_free(rr->nsec.types);
+ break;
+
+ case DNS_TYPE_NSEC3:
+ free(rr->nsec3.next_hashed_name);
+ free(rr->nsec3.salt);
+ bitmap_free(rr->nsec3.types);
+ break;
+
case DNS_TYPE_LOC:
case DNS_TYPE_A:
case DNS_TYPE_AAAA:
@@ -409,11 +424,18 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
a->loc.longitude == b->loc.longitude &&
a->loc.altitude == b->loc.altitude;
+ case DNS_TYPE_DS:
+ return a->ds.key_tag == b->ds.key_tag &&
+ a->ds.algorithm == b->ds.algorithm &&
+ a->ds.digest_type == b->ds.digest_type &&
+ a->ds.digest_size == b->ds.digest_size &&
+ memcmp(a->ds.digest, b->ds.digest, a->ds.digest_size) == 0;
+
case DNS_TYPE_SSHFP:
return a->sshfp.algorithm == b->sshfp.algorithm &&
a->sshfp.fptype == b->sshfp.fptype &&
- a->sshfp.key_size == b->sshfp.key_size &&
- memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
+ a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
+ memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
case DNS_TYPE_DNSKEY:
return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
@@ -437,6 +459,19 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
+ case DNS_TYPE_NSEC:
+ return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
+ bitmap_equal(a->nsec.types, b->nsec.types);
+
+ case DNS_TYPE_NSEC3:
+ return a->nsec3.algorithm == b->nsec3.algorithm &&
+ a->nsec3.flags == b->nsec3.flags &&
+ a->nsec3.iterations == b->nsec3.iterations &&
+ a->nsec3.salt_size == b->nsec3.salt_size &&
+ memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 &&
+ memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 &&
+ bitmap_equal(a->nsec3.types, b->nsec3.types);
+
default:
return a->generic.size == b->generic.size &&
memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
@@ -474,6 +509,53 @@ static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t alt
return s;
}
+static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
+ struct tm tm;
+
+ assert(buf);
+ assert(l > strlen("YYYYMMDDHHmmSS"));
+
+ if (!gmtime_r(&sec, &tm))
+ return -EINVAL;
+
+ if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static char *format_types(Bitmap *types) {
+ _cleanup_strv_free_ char **strv = NULL;
+ _cleanup_free_ char *str = NULL;
+ Iterator i;
+ unsigned type;
+ int r;
+
+ BITMAP_FOREACH(type, types, i) {
+ if (dns_type_to_string(type)) {
+ r = strv_extend(&strv, dns_type_to_string(type));
+ if (r < 0)
+ return NULL;
+ } else {
+ char *t;
+
+ r = asprintf(&t, "TYPE%u", type);
+ if (r < 0)
+ return NULL;
+
+ r = strv_consume(&strv, t);
+ if (r < 0)
+ return NULL;
+ }
+ }
+
+ str = strv_join(strv, " ");
+ if (!str)
+ return NULL;
+
+ return strjoin("( ", str, " )", NULL);
+}
+
int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
_cleanup_free_ char *k = NULL, *t = NULL;
char *s;
@@ -589,8 +671,23 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
return -ENOMEM;
break;
+ case DNS_TYPE_DS:
+ t = hexmem(rr->ds.digest, rr->ds.digest_size);
+ if (!t)
+ return -ENOMEM;
+
+ r = asprintf(&s, "%s %u %u %u %s",
+ k,
+ rr->ds.key_tag,
+ rr->ds.algorithm,
+ rr->ds.digest_type,
+ t);
+ if (r < 0)
+ return -ENOMEM;
+ break;
+
case DNS_TYPE_SSHFP:
- t = hexmem(rr->sshfp.key, rr->sshfp.key_size);
+ t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
if (!t)
return -ENOMEM;
@@ -608,7 +705,7 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
- t = hexmem(rr->dnskey.key, rr->dnskey.key_size);
+ t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
if (!t)
return -ENOMEM;
@@ -625,18 +722,27 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
case DNS_TYPE_RRSIG: {
const char *type, *alg;
+ char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
type = dns_type_to_string(rr->rrsig.type_covered);
alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
- t = hexmem(rr->rrsig.signature, rr->rrsig.signature_size);
+ t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
if (!t)
return -ENOMEM;
+ r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
+ if (r < 0)
+ return r;
+
+ r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
+ if (r < 0)
+ return r;
+
/* TYPE?? follows
* http://tools.ietf.org/html/rfc3597#section-5 */
- r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %u %u %u %s %s",
+ r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %s %s %u %s %s",
k,
type ?: "TYPE",
type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
@@ -644,8 +750,8 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
rr->rrsig.labels,
rr->rrsig.original_ttl,
- rr->rrsig.expiration,
- rr->rrsig.inception,
+ expiration,
+ inception,
rr->rrsig.key_tag,
rr->rrsig.signer,
t);
@@ -654,13 +760,57 @@ int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
break;
}
+ case DNS_TYPE_NSEC:
+ t = format_types(rr->nsec.types);
+ if (!t)
+ return -ENOMEM;
+
+ r = asprintf(&s, "%s %s %s",
+ k,
+ rr->nsec.next_domain_name,
+ t);
+ if (r < 0)
+ return -ENOMEM;
+ break;
+
+ case DNS_TYPE_NSEC3: {
+ _cleanup_free_ char *salt = NULL, *hash = NULL;
+
+ if (rr->nsec3.salt_size > 0) {
+ salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
+ if (!salt)
+ return -ENOMEM;
+ }
+
+ hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
+ if (!hash)
+ return -ENOMEM;
+
+ t = format_types(rr->nsec3.types);
+ if (!t)
+ return -ENOMEM;
+
+ r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
+ k,
+ rr->nsec3.algorithm,
+ rr->nsec3.flags,
+ rr->nsec3.iterations,
+ rr->nsec3.salt_size > 0 ? salt : "-",
+ hash,
+ t);
+ if (r < 0)
+ return -ENOMEM;
+
+ break;
+ }
+
default:
t = hexmem(rr->generic.data, rr->generic.size);
if (!t)
return -ENOMEM;
- s = strjoin(k, " ", t, NULL);
- if (!s)
+ r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
+ if (r < 0)
return -ENOMEM;
break;
}
@@ -690,7 +840,7 @@ int dns_class_from_string(const char *s, uint16_t *class) {
if (strcaseeq(s, "IN"))
*class = DNS_CLASS_IN;
else if (strcaseeq(s, "ANY"))
- *class = DNS_TYPE_ANY;
+ *class = DNS_CLASS_ANY;
else
return -EINVAL;
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 26796c842b..0f40f3ceef 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -23,6 +23,7 @@
#include <netinet/in.h>
+#include "bitmap.h"
#include "hashmap.h"
#include "in-addr-util.h"
#include "dns-type.h"
@@ -52,7 +53,7 @@ struct DnsResourceRecord {
union {
struct {
void *data;
- uint16_t size;
+ size_t size;
} generic;
struct {
@@ -109,10 +110,19 @@ struct DnsResourceRecord {
} loc;
struct {
+ uint16_t key_tag;
+ uint8_t algorithm;
+ uint8_t digest_type;
+ void *digest;
+ size_t digest_size;
+ } ds;
+
+ /* https://tools.ietf.org/html/rfc4255#section-3.1 */
+ struct {
uint8_t algorithm;
uint8_t fptype;
- void *key;
- size_t key_size;
+ void *fingerprint;
+ size_t fingerprint_size;
} sshfp;
/* http://tools.ietf.org/html/rfc4034#section-2.1 */
@@ -137,6 +147,22 @@ struct DnsResourceRecord {
void *signature;
size_t signature_size;
} rrsig;
+
+ struct {
+ char *next_domain_name;
+ Bitmap *types;
+ } nsec;
+
+ struct {
+ uint8_t algorithm;
+ uint8_t flags;
+ uint16_t iterations;
+ void *salt;
+ size_t salt_size;
+ void *next_hashed_name;
+ size_t next_hashed_name_size;
+ Bitmap *types;
+ } nsec3;
};
};
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index c25ac2216d..927a1ddc26 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -28,6 +28,7 @@
#include "random-util.h"
#include "hostname-util.h"
#include "dns-domain.h"
+#include "resolved-llmnr.h"
#include "resolved-dns-scope.h"
#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
@@ -124,17 +125,17 @@ void dns_scope_next_dns_server(DnsScope *s) {
manager_next_dns_server(s->manager);
}
-int dns_scope_emit(DnsScope *s, DnsPacket *p) {
+int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
union in_addr_union addr;
int ifindex = 0, r;
int family;
uint16_t port;
uint32_t mtu;
- int fd;
assert(s);
assert(p);
assert(p->protocol == s->protocol);
+ assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
if (s->link) {
mtu = s->link->mtu;
@@ -143,33 +144,18 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p) {
mtu = manager_find_mtu(s->manager);
if (s->protocol == DNS_PROTOCOL_DNS) {
- DnsServer *srv;
-
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
- srv = dns_scope_get_dns_server(s);
- if (!srv)
- return -ESRCH;
-
- family = srv->family;
- addr = srv->address;
- port = 53;
-
if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
return -EMSGSIZE;
- if (p->size > mtu)
+ if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
return -EMSGSIZE;
- if (family == AF_INET)
- fd = manager_dns_ipv4_fd(s->manager);
- else if (family == AF_INET6)
- fd = manager_dns_ipv6_fd(s->manager);
- else
- return -EAFNOSUPPORT;
- if (fd < 0)
- return fd;
+ r = manager_write(s->manager, fd, p);
+ if (r < 0)
+ return r;
} else if (s->protocol == DNS_PROTOCOL_LLMNR) {
@@ -180,7 +166,7 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p) {
return -EBUSY;
family = s->family;
- port = 5355;
+ port = LLMNR_PORT;
if (family == AF_INET) {
addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
@@ -192,17 +178,18 @@ int dns_scope_emit(DnsScope *s, DnsPacket *p) {
return -EAFNOSUPPORT;
if (fd < 0)
return fd;
+
+ r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
+ if (r < 0)
+ return r;
} else
return -EAFNOSUPPORT;
- r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
- if (r < 0)
- return r;
-
return 1;
}
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port) {
+static int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
+ DnsServer *srv = NULL;
_cleanup_close_ int fd = -1;
union sockaddr_union sa = {};
socklen_t salen;
@@ -213,8 +200,6 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add
assert((family == AF_UNSPEC) == !address);
if (family == AF_UNSPEC) {
- DnsServer *srv;
-
srv = dns_scope_get_dns_server(s);
if (!srv)
return -ESRCH;
@@ -247,13 +232,15 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add
return -EAFNOSUPPORT;
}
- fd = socket(sa.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return -errno;
- r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
- if (r < 0)
- return -errno;
+ if (type == SOCK_STREAM) {
+ r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
+ if (r < 0)
+ return -errno;
+ }
if (s->link) {
uint32_t ifindex = htobe32(s->link->ifindex);
@@ -287,12 +274,23 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add
if (r < 0 && errno != EINPROGRESS)
return -errno;
+ if (server)
+ *server = srv;
+
ret = fd;
fd = -1;
return ret;
}
+int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server) {
+ return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, 53, server);
+}
+
+int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
+ return dns_scope_socket(s, SOCK_STREAM, family, address, port, server);
+}
+
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
char **i;
@@ -415,19 +413,6 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) {
return 0;
}
-int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address) {
- assert(s);
- assert(address);
-
- if (s->protocol != DNS_PROTOCOL_DNS)
- return 1;
-
- if (s->link)
- return !!link_find_dns_server(s->link, family, address);
- else
- return !!manager_find_dns_server(s->manager, family, address);
-}
-
static int dns_scope_make_reply_packet(
DnsScope *s,
uint16_t id,
@@ -546,7 +531,7 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
return;
}
- if (DNS_PACKET_C(p)) {
+ if (DNS_PACKET_LLMNR_C(p)) {
/* Somebody notified us about a possible conflict */
dns_scope_verify_conflicts(s, p);
return;
@@ -695,7 +680,7 @@ static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata
return 0;
}
- r = dns_scope_emit(scope, p);
+ r = dns_scope_emit(scope, -1, p);
if (r < 0)
log_debug_errno(r, "Failed to send conflict packet: %m");
}
@@ -760,10 +745,10 @@ void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
if (DNS_PACKET_RRCOUNT(p) <= 0)
return;
- if (DNS_PACKET_C(p) != 0)
+ if (DNS_PACKET_LLMNR_C(p) != 0)
return;
- if (DNS_PACKET_T(p) != 0)
+ if (DNS_PACKET_LLMNR_T(p) != 0)
return;
if (manager_our_packet(scope->manager, p))
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index cfbde1343f..29479ad550 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -65,12 +65,12 @@ struct DnsScope {
int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family);
DnsScope* dns_scope_free(DnsScope *s);
-int dns_scope_emit(DnsScope *s, DnsPacket *p);
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port);
+int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p);
+int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server);
+int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server);
DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
-int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address);
DnsServer *dns_scope_get_dns_server(DnsScope *s);
void dns_scope_next_dns_server(DnsScope *s);
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 9a62a63258..92e48ae442 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -41,6 +41,7 @@ int dns_server_new(
if (!s)
return -ENOMEM;
+ s->n_ref = 1;
s->type = type;
s->family = family;
s->address = *in_addr;
@@ -74,33 +75,46 @@ int dns_server_new(
return 0;
}
-DnsServer* dns_server_free(DnsServer *s) {
+DnsServer* dns_server_ref(DnsServer *s) {
if (!s)
return NULL;
- if (s->link) {
- if (s->type == DNS_SERVER_LINK)
- LIST_REMOVE(servers, s->link->dns_servers, s);
+ assert(s->n_ref > 0);
- if (s->link->current_dns_server == s)
- link_set_dns_server(s->link, NULL);
- }
+ s->n_ref ++;
- if (s->manager) {
- if (s->type == DNS_SERVER_SYSTEM)
- LIST_REMOVE(servers, s->manager->dns_servers, s);
- else if (s->type == DNS_SERVER_FALLBACK)
- LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
+ return s;
+}
+
+static DnsServer* dns_server_free(DnsServer *s) {
+ if (!s)
+ return NULL;
- if (s->manager->current_dns_server == s)
- manager_set_dns_server(s->manager, NULL);
- }
+ if (s->link && s->link->current_dns_server == s)
+ link_set_dns_server(s->link, NULL);
+
+ if (s->manager && s->manager->current_dns_server == s)
+ manager_set_dns_server(s->manager, NULL);
free(s);
return NULL;
}
+DnsServer* dns_server_unref(DnsServer *s) {
+ if (!s)
+ return NULL;
+
+ assert(s->n_ref > 0);
+
+ if (s->n_ref == 1)
+ dns_server_free(s);
+ else
+ s->n_ref --;
+
+ return NULL;
+}
+
static unsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
const DnsServer *s = p;
uint64_t u;
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index 70ff35b08f..06059e8829 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -37,6 +37,8 @@ typedef enum DnsServerType {
struct DnsServer {
Manager *manager;
+ unsigned n_ref;
+
DnsServerType type;
Link *link;
@@ -57,6 +59,9 @@ int dns_server_new(
int family,
const union in_addr_union *address);
-DnsServer* dns_server_free(DnsServer *s);
+DnsServer* dns_server_ref(DnsServer *s);
+DnsServer* dns_server_unref(DnsServer *s);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
extern const struct hash_ops dns_server_hash_ops;
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 214938986d..b235fda3d2 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -21,6 +21,7 @@
#include "af-list.h"
+#include "resolved-llmnr.h"
#include "resolved-dns-transaction.h"
#include "random-util.h"
@@ -38,6 +39,10 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
dns_packet_unref(t->received);
dns_answer_unref(t->cached);
+ sd_event_source_unref(t->dns_event_source);
+ safe_close(t->dns_fd);
+
+ dns_server_unref(t->server);
dns_stream_free(t->stream);
if (t->scope) {
@@ -87,6 +92,8 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsQuestion *q) {
if (!t)
return -ENOMEM;
+ t->dns_fd = -1;
+
t->question = dns_question_ref(q);
do
@@ -236,6 +243,7 @@ static int on_stream_complete(DnsStream *s, int error) {
}
static int dns_transaction_open_tcp(DnsTransaction *t) {
+ DnsServer *server = NULL;
_cleanup_close_ int fd = -1;
int r;
@@ -245,12 +253,12 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
return 0;
if (t->scope->protocol == DNS_PROTOCOL_DNS)
- fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
+ fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
/* When we already received a query to this (but it was truncated), send to its sender address */
if (t->received)
- fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
+ fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
else {
union in_addr_union address;
int family = AF_UNSPEC;
@@ -264,7 +272,7 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
if (r == 0)
return -EINVAL;
- fd = dns_scope_tcp_socket(t->scope, family, &address, 5355);
+ fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
}
} else
return -EAFNOSUPPORT;
@@ -284,6 +292,9 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
return r;
}
+
+ dns_server_unref(t->server);
+ t->server = dns_server_ref(server);
t->received = dns_packet_unref(t->received);
t->stream->complete = on_stream_complete;
t->stream->transaction = t;
@@ -297,6 +308,16 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
return 0;
}
+static void dns_transaction_next_dns_server(DnsTransaction *t) {
+ assert(t);
+
+ t->server = dns_server_unref(t->server);
+ t->dns_event_source = sd_event_source_unref(t->dns_event_source);
+ t->dns_fd = safe_close(t->dns_fd);
+
+ dns_scope_next_dns_server(t->scope);
+}
+
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
int r;
@@ -323,25 +344,12 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
/* Tentative packets are not full responses but still
* useful for identifying uniqueness conflicts during
* probing. */
- if (DNS_PACKET_T(p)) {
+ if (DNS_PACKET_LLMNR_T(p)) {
dns_transaction_tentative(t, p);
return;
}
}
- if (t->scope->protocol == DNS_PROTOCOL_DNS) {
-
- /* For DNS we are fine with accepting packets on any
- * interface, but the source IP address must be one of
- * a valid DNS server */
-
- if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
- return;
-
- if (p->sender_port != 53)
- return;
- }
-
if (t->received != p) {
dns_packet_unref(t->received);
t->received = dns_packet_ref(p);
@@ -378,7 +386,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
}
/* On DNS, couldn't send? Try immediately again, with a new server */
- dns_scope_next_dns_server(t->scope);
+ dns_transaction_next_dns_server(t);
r = dns_transaction_go(t);
if (r < 0) {
@@ -397,6 +405,13 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
return;
}
+ /* Only consider responses with equivalent query section to the request */
+ if (!dns_question_is_superset(p->question, t->question) ||
+ !dns_question_is_superset(t->question, p->question)) {
+ dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
+ return;
+ }
+
/* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
@@ -406,6 +421,56 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
}
+static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ DnsTransaction *t = userdata;
+ int r;
+
+ assert(t);
+ assert(t->scope);
+
+ r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
+ if (r <= 0)
+ return r;
+
+ if (dns_packet_validate_reply(p) > 0 &&
+ DNS_PACKET_ID(p) == t->id) {
+ dns_transaction_process_reply(t, p);
+ } else
+ log_debug("Invalid DNS packet.");
+
+ return 0;
+}
+
+static int dns_transaction_emit(DnsTransaction *t) {
+ int r;
+
+ assert(t);
+
+ if (t->scope->protocol == DNS_PROTOCOL_DNS && !t->server) {
+ DnsServer *server = NULL;
+ _cleanup_close_ int fd = -1;
+
+ fd = dns_scope_udp_dns_socket(t->scope, &server);
+ if (fd < 0)
+ return fd;
+
+ r = sd_event_add_io(t->scope->manager->event, &t->dns_event_source, fd, EPOLLIN, on_dns_packet, t);
+ if (r < 0)
+ return r;
+
+ t->dns_fd = fd;
+ fd = -1;
+ t->server = dns_server_ref(server);
+ }
+
+ r = dns_scope_emit(t->scope, t->dns_fd, t->sent);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
DnsTransaction *t = userdata;
int r;
@@ -414,7 +479,7 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat
assert(t);
/* Timeout reached? Try again, with a new server */
- dns_scope_next_dns_server(t->scope);
+ dns_transaction_next_dns_server(t);
r = dns_transaction_go(t);
if (r < 0)
@@ -571,7 +636,7 @@ int dns_transaction_go(DnsTransaction *t) {
r = dns_transaction_open_tcp(t);
} else {
/* Try via UDP, and if that fails due to large size try via TCP */
- r = dns_scope_emit(t->scope, t->sent);
+ r = dns_transaction_emit(t);
if (r == -EMSGSIZE)
r = dns_transaction_open_tcp(t);
}
@@ -579,15 +644,14 @@ int dns_transaction_go(DnsTransaction *t) {
/* No servers to send this to? */
dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
return 0;
- }
- if (r < 0) {
+ } else if (r < 0) {
if (t->scope->protocol != DNS_PROTOCOL_DNS) {
dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
return 0;
}
/* Couldn't send? Try immediately again, with a new server */
- dns_scope_next_dns_server(t->scope);
+ dns_transaction_next_dns_server(t);
return dns_transaction_go(t);
}
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
index f6d539d315..a8f4267bc8 100644
--- a/src/resolve/resolved-dns-transaction.h
+++ b/src/resolve/resolved-dns-transaction.h
@@ -61,6 +61,12 @@ struct DnsTransaction {
sd_event_source *timeout_event_source;
unsigned n_attempts;
+ int dns_fd;
+ sd_event_source *dns_event_source;
+
+ /* the active server */
+ DnsServer *server;
+
/* TCP connection logic, if we need it */
DnsStream *stream;
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index ff8dc3a5bc..d66b3a88fc 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -58,7 +58,6 @@ int link_new(Manager *m, Link **ret, int ifindex) {
}
Link *link_free(Link *l) {
-
if (!l)
return NULL;
@@ -68,8 +67,12 @@ Link *link_free(Link *l) {
if (l->manager)
hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
- while (l->dns_servers)
- dns_server_free(l->dns_servers);
+ while (l->dns_servers) {
+ DnsServer *s = l->dns_servers;
+
+ LIST_REMOVE(servers, l->dns_servers, s);
+ dns_server_unref(s);
+ }
dns_scope_free(l->unicast_scope);
dns_scope_free(l->llmnr_ipv4_scope);
@@ -182,14 +185,20 @@ static int link_update_dns_servers(Link *l) {
}
LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
- if (s->marked)
- dns_server_free(s);
+ if (s->marked) {
+ LIST_REMOVE(servers, l->dns_servers, s);
+ dns_server_unref(s);
+ }
return 0;
clear:
- while (l->dns_servers)
- dns_server_free(l->dns_servers);
+ while (l->dns_servers) {
+ s = l->dns_servers;
+
+ LIST_REMOVE(servers, l->dns_servers, s);
+ dns_server_unref(s);
+ }
return r;
}
diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c
new file mode 100644
index 0000000000..8afaf8db6e
--- /dev/null
+++ b/src/resolve/resolved-llmnr.c
@@ -0,0 +1,473 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <resolv.h>
+#include <netinet/in.h>
+
+#include "resolved-manager.h"
+#include "resolved-llmnr.h"
+
+void manager_llmnr_stop(Manager *m) {
+ assert(m);
+
+ m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
+ m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
+
+ m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
+ m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
+
+ m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
+ m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
+
+ m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
+ m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
+}
+
+int manager_llmnr_start(Manager *m) {
+ int r;
+
+ assert(m);
+
+ if (m->llmnr_support == SUPPORT_NO)
+ return 0;
+
+ r = manager_llmnr_ipv4_udp_fd(m);
+ if (r == -EADDRINUSE)
+ goto eaddrinuse;
+ if (r < 0)
+ return r;
+
+ r = manager_llmnr_ipv4_tcp_fd(m);
+ if (r == -EADDRINUSE)
+ goto eaddrinuse;
+ if (r < 0)
+ return r;
+
+ if (socket_ipv6_is_supported()) {
+ r = manager_llmnr_ipv6_udp_fd(m);
+ if (r == -EADDRINUSE)
+ goto eaddrinuse;
+ if (r < 0)
+ return r;
+
+ r = manager_llmnr_ipv6_tcp_fd(m);
+ if (r == -EADDRINUSE)
+ goto eaddrinuse;
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+
+eaddrinuse:
+ log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
+ m->llmnr_support = SUPPORT_NO;
+ manager_llmnr_stop(m);
+
+ return 0;
+}
+
+static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+ DnsTransaction *t = NULL;
+ Manager *m = userdata;
+ DnsScope *scope;
+ int r;
+
+ r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
+ if (r <= 0)
+ return r;
+
+ scope = manager_find_scope(m, p);
+ if (!scope) {
+ log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
+ return 0;
+ }
+
+ if (dns_packet_validate_reply(p) > 0) {
+ log_debug("Got LLMNR reply packet for id %u", DNS_PACKET_ID(p));
+
+ dns_scope_check_conflicts(scope, p);
+
+ t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
+ if (t)
+ dns_transaction_process_reply(t, p);
+
+ } else if (dns_packet_validate_query(p) > 0) {
+ log_debug("Got LLMNR query packet for id %u", DNS_PACKET_ID(p));
+
+ dns_scope_process_query(scope, NULL, p);
+ } else
+ log_debug("Invalid LLMNR UDP packet.");
+
+ return 0;
+}
+
+int manager_llmnr_ipv4_udp_fd(Manager *m) {
+ union sockaddr_union sa = {
+ .in.sin_family = AF_INET,
+ .in.sin_port = htobe16(LLMNR_PORT),
+ };
+ static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
+ int r;
+
+ assert(m);
+
+ if (m->llmnr_ipv4_udp_fd >= 0)
+ return m->llmnr_ipv4_udp_fd;
+
+ m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (m->llmnr_ipv4_udp_fd < 0)
+ return -errno;
+
+ /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
+ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ /* Disable Don't-Fragment bit in the IP header */
+ r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
+ if (r < 0)
+ goto fail;
+
+ return m->llmnr_ipv4_udp_fd;
+
+fail:
+ m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
+ return r;
+}
+
+int manager_llmnr_ipv6_udp_fd(Manager *m) {
+ union sockaddr_union sa = {
+ .in6.sin6_family = AF_INET6,
+ .in6.sin6_port = htobe16(LLMNR_PORT),
+ };
+ static const int one = 1, ttl = 255;
+ int r;
+
+ assert(m);
+
+ if (m->llmnr_ipv6_udp_fd >= 0)
+ return m->llmnr_ipv6_udp_fd;
+
+ m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (m->llmnr_ipv6_udp_fd < 0)
+ return -errno;
+
+ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
+ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ return m->llmnr_ipv6_udp_fd;
+
+fail:
+ m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
+ return r;
+}
+
+static int on_llmnr_stream_packet(DnsStream *s) {
+ DnsScope *scope;
+
+ assert(s);
+
+ scope = manager_find_scope(s->manager, s->read_packet);
+ if (!scope) {
+ log_warning("Got LLMNR TCP packet on unknown scope. Ignroing.");
+ return 0;
+ }
+
+ if (dns_packet_validate_query(s->read_packet) > 0) {
+ log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet));
+
+ dns_scope_process_query(scope, s, s->read_packet);
+
+ /* If no reply packet was set, we free the stream */
+ if (s->write_packet)
+ return 0;
+ } else
+ log_debug("Invalid LLMNR TCP packet.");
+
+ dns_stream_free(s);
+ return 0;
+}
+
+static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ DnsStream *stream;
+ Manager *m = userdata;
+ int cfd, r;
+
+ cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+ if (cfd < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
+
+ return -errno;
+ }
+
+ r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
+ if (r < 0) {
+ safe_close(cfd);
+ return r;
+ }
+
+ stream->on_packet = on_llmnr_stream_packet;
+ return 0;
+}
+
+int manager_llmnr_ipv4_tcp_fd(Manager *m) {
+ union sockaddr_union sa = {
+ .in.sin_family = AF_INET,
+ .in.sin_port = htobe16(LLMNR_PORT),
+ };
+ static const int one = 1, pmtu = IP_PMTUDISC_DONT;
+ int r;
+
+ assert(m);
+
+ if (m->llmnr_ipv4_tcp_fd >= 0)
+ return m->llmnr_ipv4_tcp_fd;
+
+ m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (m->llmnr_ipv4_tcp_fd < 0)
+ return -errno;
+
+ /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
+ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ /* Disable Don't-Fragment bit in the IP header */
+ r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
+ if (r < 0)
+ goto fail;
+
+ return m->llmnr_ipv4_tcp_fd;
+
+fail:
+ m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
+ return r;
+}
+
+int manager_llmnr_ipv6_tcp_fd(Manager *m) {
+ union sockaddr_union sa = {
+ .in6.sin6_family = AF_INET6,
+ .in6.sin6_port = htobe16(LLMNR_PORT),
+ };
+ static const int one = 1;
+ int r;
+
+ assert(m);
+
+ if (m->llmnr_ipv6_tcp_fd >= 0)
+ return m->llmnr_ipv6_tcp_fd;
+
+ m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (m->llmnr_ipv6_tcp_fd < 0)
+ return -errno;
+
+ /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
+ r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ return m->llmnr_ipv6_tcp_fd;
+
+fail:
+ m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
+ return r;
+}
diff --git a/src/resolve/resolved-llmnr.h b/src/resolve/resolved-llmnr.h
new file mode 100644
index 0000000000..d489d481e8
--- /dev/null
+++ b/src/resolve/resolved-llmnr.h
@@ -0,0 +1,34 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "resolved-manager.h"
+
+#define LLMNR_PORT 5355
+
+int manager_llmnr_ipv4_udp_fd(Manager *m);
+int manager_llmnr_ipv6_udp_fd(Manager *m);
+int manager_llmnr_ipv4_tcp_fd(Manager *m);
+int manager_llmnr_ipv6_tcp_fd(Manager *m);
+
+void manager_llmnr_stop(Manager *m);
+int manager_llmnr_start(Manager *m);
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index dee5e61922..5be01d3cb8 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -38,6 +38,7 @@
#include "resolved-conf.h"
#include "resolved-bus.h"
#include "resolved-manager.h"
+#include "resolved-llmnr.h"
#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
@@ -393,66 +394,6 @@ static int manager_watch_hostname(Manager *m) {
return 0;
}
-static void manager_llmnr_stop(Manager *m) {
- assert(m);
-
- m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
- m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
-
- m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
- m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
-
- m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
- m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
-
- m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
- m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
-}
-
-static int manager_llmnr_start(Manager *m) {
- int r;
-
- assert(m);
-
- if (m->llmnr_support == SUPPORT_NO)
- return 0;
-
- r = manager_llmnr_ipv4_udp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- r = manager_llmnr_ipv4_tcp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- if (socket_ipv6_is_supported()) {
- r = manager_llmnr_ipv6_udp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- r = manager_llmnr_ipv6_tcp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
- }
-
- return 0;
-
-eaddrinuse:
- log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
- m->llmnr_support = SUPPORT_NO;
- manager_llmnr_stop(m);
-
- return 0;
-}
-
int manager_new(Manager **ret) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
@@ -463,7 +404,6 @@ int manager_new(Manager **ret) {
if (!m)
return -ENOMEM;
- m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
m->hostname_fd = -1;
@@ -545,11 +485,6 @@ Manager *manager_free(Manager *m) {
sd_event_source_unref(m->network_event_source);
sd_network_monitor_unref(m->network_monitor);
- sd_event_source_unref(m->dns_ipv4_event_source);
- sd_event_source_unref(m->dns_ipv6_event_source);
- safe_close(m->dns_ipv4_fd);
- safe_close(m->dns_ipv6_fd);
-
manager_llmnr_stop(m);
sd_bus_slot_unref(m->prepare_for_sleep_slot);
@@ -662,8 +597,10 @@ int manager_read_resolv_conf(Manager *m) {
}
LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
- if (s->marked)
- dns_server_free(s);
+ if (s->marked) {
+ LIST_REMOVE(servers, m->dns_servers, s);
+ dns_server_unref(s);
+ }
/* Whenever /etc/resolv.conf changes, start using the first
* DNS server of it. This is useful to deal with broken
@@ -678,8 +615,12 @@ int manager_read_resolv_conf(Manager *m) {
return 0;
clear:
- while (m->dns_servers)
- dns_server_free(m->dns_servers);
+ while (m->dns_servers) {
+ s = m->dns_servers;
+
+ LIST_REMOVE(servers, m->dns_servers, s);
+ dns_server_unref(s);
+ }
return r;
}
@@ -971,10 +912,12 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
if (p->ifindex == LOOPBACK_IFINDEX)
p->ifindex = 0;
- /* If we don't know the interface index still, we look for the
- * first local interface with a matching address. Yuck! */
- if (p->ifindex <= 0)
- p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
+ if (protocol != DNS_PROTOCOL_DNS) {
+ /* If we don't know the interface index still, we look for the
+ * first local interface with a matching address. Yuck! */
+ if (p->ifindex <= 0)
+ p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
+ }
*ret = p;
p = NULL;
@@ -982,97 +925,38 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
return 1;
}
-static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- DnsTransaction *t = NULL;
- Manager *m = userdata;
+static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
int r;
- r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
- if (r <= 0)
- return r;
+ assert(fd >= 0);
+ assert(mh);
- if (dns_packet_validate_reply(p) > 0) {
- t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
- if (!t)
+ for (;;) {
+ if (sendmsg(fd, mh, flags) >= 0)
return 0;
- dns_transaction_process_reply(t, p);
-
- } else
- log_debug("Invalid DNS packet.");
-
- return 0;
-}
-
-int manager_dns_ipv4_fd(Manager *m) {
- const int one = 1;
- int r;
-
- assert(m);
-
- if (m->dns_ipv4_fd >= 0)
- return m->dns_ipv4_fd;
-
- m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->dns_ipv4_fd < 0)
- return -errno;
-
- r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
- if (r < 0)
- goto fail;
-
- return m->dns_ipv4_fd;
-
-fail:
- m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
- return r;
-}
-
-int manager_dns_ipv6_fd(Manager *m) {
- const int one = 1;
- int r;
-
- assert(m);
-
- if (m->dns_ipv6_fd >= 0)
- return m->dns_ipv6_fd;
+ if (errno == EINTR)
+ continue;
- m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->dns_ipv6_fd < 0)
- return -errno;
+ if (errno != EAGAIN)
+ return -errno;
- r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
+ r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ETIMEDOUT;
}
-
- r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
- if (r < 0)
- goto fail;
-
- return m->dns_ipv6_fd;
-
-fail:
- m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
- return r;
}
-static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
+static int write_loop(int fd, void *message, size_t length) {
int r;
assert(fd >= 0);
- assert(mh);
+ assert(message);
for (;;) {
- if (sendmsg(fd, mh, flags) >= 0)
+ if (write(fd, message, length) >= 0)
return 0;
if (errno == EINTR)
@@ -1089,6 +973,18 @@ static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
}
}
+int manager_write(Manager *m, int fd, DnsPacket *p) {
+ int r;
+
+ log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
+
+ r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
union sockaddr_union sa = {
.in.sin_family = AF_INET,
@@ -1316,393 +1212,6 @@ uint32_t manager_find_mtu(Manager *m) {
return mtu;
}
-static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- DnsTransaction *t = NULL;
- Manager *m = userdata;
- DnsScope *scope;
- int r;
-
- r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
- if (r <= 0)
- return r;
-
- scope = manager_find_scope(m, p);
- if (!scope) {
- log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
- return 0;
- }
-
- if (dns_packet_validate_reply(p) > 0) {
- log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
-
- dns_scope_check_conflicts(scope, p);
-
- t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
- if (t)
- dns_transaction_process_reply(t, p);
-
- } else if (dns_packet_validate_query(p) > 0) {
- log_debug("Got query packet for id %u", DNS_PACKET_ID(p));
-
- dns_scope_process_query(scope, NULL, p);
- } else
- log_debug("Invalid LLMNR UDP packet.");
-
- return 0;
-}
-
-int manager_llmnr_ipv4_udp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in.sin_family = AF_INET,
- .in.sin_port = htobe16(5355),
- };
- static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv4_udp_fd >= 0)
- return m->llmnr_ipv4_udp_fd;
-
- m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv4_udp_fd < 0)
- return -errno;
-
- /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- /* Disable Don't-Fragment bit in the IP header */
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
- if (r < 0)
- goto fail;
-
- return m->llmnr_ipv4_udp_fd;
-
-fail:
- m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
- return r;
-}
-
-int manager_llmnr_ipv6_udp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in6.sin6_family = AF_INET6,
- .in6.sin6_port = htobe16(5355),
- };
- static const int one = 1, ttl = 255;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv6_udp_fd >= 0)
- return m->llmnr_ipv6_udp_fd;
-
- m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv6_udp_fd < 0)
- return -errno;
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- return m->llmnr_ipv6_udp_fd;
-
-fail:
- m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
- return r;
-}
-
-static int on_llmnr_stream_packet(DnsStream *s) {
- DnsScope *scope;
-
- assert(s);
-
- scope = manager_find_scope(s->manager, s->read_packet);
- if (!scope) {
- log_warning("Got LLMNR TCP packet on unknown scope. Ignroing.");
- return 0;
- }
-
- if (dns_packet_validate_query(s->read_packet) > 0) {
- log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet));
-
- dns_scope_process_query(scope, s, s->read_packet);
-
- /* If no reply packet was set, we free the stream */
- if (s->write_packet)
- return 0;
- } else
- log_debug("Invalid LLMNR TCP packet.");
-
- dns_stream_free(s);
- return 0;
-}
-
-static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- DnsStream *stream;
- Manager *m = userdata;
- int cfd, r;
-
- cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
- if (cfd < 0) {
- if (errno == EAGAIN || errno == EINTR)
- return 0;
-
- return -errno;
- }
-
- r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
- if (r < 0) {
- safe_close(cfd);
- return r;
- }
-
- stream->on_packet = on_llmnr_stream_packet;
- return 0;
-}
-
-int manager_llmnr_ipv4_tcp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in.sin_family = AF_INET,
- .in.sin_port = htobe16(5355),
- };
- static const int one = 1, pmtu = IP_PMTUDISC_DONT;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv4_tcp_fd >= 0)
- return m->llmnr_ipv4_tcp_fd;
-
- m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv4_tcp_fd < 0)
- return -errno;
-
- /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- /* Disable Don't-Fragment bit in the IP header */
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
- if (r < 0)
- goto fail;
-
- return m->llmnr_ipv4_tcp_fd;
-
-fail:
- m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
- return r;
-}
-
-int manager_llmnr_ipv6_tcp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in6.sin6_family = AF_INET6,
- .in6.sin6_port = htobe16(5355),
- };
- static const int one = 1;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv6_tcp_fd >= 0)
- return m->llmnr_ipv6_tcp_fd;
-
- m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv6_tcp_fd < 0)
- return -errno;
-
- /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- return m->llmnr_ipv6_tcp_fd;
-
-fail:
- m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
- return r;
-}
-
int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
LinkAddress *a;
@@ -1827,15 +1336,25 @@ void manager_verify_all(Manager *m) {
}
void manager_flush_dns_servers(Manager *m, DnsServerType t) {
+ DnsServer *s;
+
assert(m);
if (t == DNS_SERVER_SYSTEM)
- while (m->dns_servers)
- dns_server_free(m->dns_servers);
+ while (m->dns_servers) {
+ s = m->dns_servers;
+
+ LIST_REMOVE(servers, m->dns_servers, s);
+ dns_server_unref(s);
+ }
if (t == DNS_SERVER_FALLBACK)
- while (m->fallback_dns_servers)
- dns_server_free(m->fallback_dns_servers);
+ while (m->fallback_dns_servers) {
+ s = m->fallback_dns_servers;
+
+ LIST_REMOVE(servers, m->fallback_dns_servers, s);
+ dns_server_unref(s);
+ }
}
static const char* const support_table[_SUPPORT_MAX] = {
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 0f4ffad141..53b5acb33c 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -65,12 +65,6 @@ struct Manager {
unsigned n_dns_streams;
/* Unicast dns */
- int dns_ipv4_fd;
- int dns_ipv6_fd;
-
- sd_event_source *dns_ipv4_event_source;
- sd_event_source *dns_ipv6_event_source;
-
LIST_HEAD(DnsServer, dns_servers);
LIST_HEAD(DnsServer, fallback_dns_servers);
DnsServer *current_dns_server;
@@ -125,16 +119,10 @@ void manager_next_dns_server(Manager *m);
uint32_t manager_find_mtu(Manager *m);
+int manager_write(Manager *m, int fd, DnsPacket *p);
int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p);
int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret);
-int manager_dns_ipv4_fd(Manager *m);
-int manager_dns_ipv6_fd(Manager *m);
-int manager_llmnr_ipv4_udp_fd(Manager *m);
-int manager_llmnr_ipv6_udp_fd(Manager *m);
-int manager_llmnr_ipv4_tcp_fd(Manager *m);
-int manager_llmnr_ipv6_tcp_fd(Manager *m);
-
int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr);
LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr);
diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c
index 5a90c778fb..904dec6bfc 100644
--- a/src/rfkill/rfkill.c
+++ b/src/rfkill/rfkill.c
@@ -127,7 +127,7 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
- r = write_string_file(saved, value);
+ r = write_string_file(saved, value, WRITE_STRING_FILE_CREATE);
if (r < 0) {
log_error_errno(r, "Failed to write %s: %m", saved);
return EXIT_FAILURE;
diff --git a/src/run/run.c b/src/run/run.c
index 99d960a664..148854a9b5 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -1099,7 +1099,7 @@ static int start_transient_timer(
}
int main(int argc, char* argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
_cleanup_free_ char *description = NULL, *command = NULL;
int r;
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index d8dba584d6..4ae216b7d9 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -135,22 +135,15 @@ typedef struct UnitInfo {
int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
-static inline void sd_bus_close_unrefp(sd_bus **bus) {
- if (*bus) {
- sd_bus_flush(*bus);
- sd_bus_close(*bus);
- sd_bus_unref(*bus);
- }
-}
-
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_flush_close_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref);
#define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
-#define _cleanup_bus_close_unref_ _cleanup_(sd_bus_close_unrefp)
+#define _cleanup_bus_flush_close_unref_ _cleanup_(sd_bus_flush_close_unrefp)
#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp)
#define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp)
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 20a44ce4e1..8a0dec1540 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -114,6 +114,68 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
return r;
}
+/* @label_terminal: terminal character of a label, updated to point to the terminal character of
+ * the previous label (always skipping one dot) or to NULL if there are no more
+ * labels. */
+int dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) {
+ const char *terminal;
+ int r;
+
+ assert(name);
+ assert(label_terminal);
+ assert(dest);
+
+ /* no more labels */
+ if (!*label_terminal) {
+ if (sz >= 1)
+ *dest = 0;
+
+ return 0;
+ }
+
+ assert(**label_terminal == '.' || **label_terminal == 0);
+
+ /* skip current terminal character */
+ terminal = *label_terminal - 1;
+
+ /* point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */
+ for (;;) {
+ if (terminal < name) {
+ /* reached the first label, so indicate that there are no more */
+ terminal = NULL;
+ break;
+ }
+
+ /* find the start of the last label */
+ if (*terminal == '.') {
+ const char *y;
+ unsigned slashes = 0;
+
+ for (y = terminal - 1; y >= name && *y == '\\'; y--)
+ slashes ++;
+
+ if (slashes % 2 == 0) {
+ /* the '.' was not escaped */
+ name = terminal + 1;
+ break;
+ } else {
+ terminal = y;
+ continue;
+ }
+ }
+
+ terminal --;
+ }
+
+ r = dns_label_unescape(&name, dest, sz);
+ if (r < 0)
+ return r;
+
+ *label_terminal = terminal;
+
+ return r;
+}
+
int dns_label_escape(const char *p, size_t l, char **ret) {
_cleanup_free_ char *s = NULL;
char *q;
@@ -338,20 +400,23 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_
}
int dns_name_compare_func(const void *a, const void *b) {
- const char *x = a, *y = b;
+ const char *x, *y;
int r, q, k, w;
assert(a);
assert(b);
+ x = (const char *) a + strlen(a);
+ y = (const char *) b + strlen(b);
+
for (;;) {
char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
- if (*x == 0 && *y == 0)
+ if (x == NULL && y == NULL)
return 0;
- r = dns_label_unescape(&x, la, sizeof(la));
- q = dns_label_unescape(&y, lb, sizeof(lb));
+ r = dns_label_unescape_suffix(a, &x, la, sizeof(la));
+ q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb));
if (r < 0 || q < 0)
return r - q;
@@ -464,6 +529,28 @@ int dns_name_endswith(const char *name, const char *suffix) {
}
}
+int dns_name_between(const char *a, const char *b, const char *c) {
+ int n;
+
+ /* Determine if b is strictly greater than a and strictly smaller than c.
+ We consider the order of names to be circular, so that if a is
+ strictly greater than c, we consider b to be between them if it is
+ either greater than a or smaller than c. This is how the canonical
+ DNS name order used in NSEC records work. */
+
+ n = dns_name_compare_func(a, c);
+ if (n == 0)
+ return -EINVAL;
+ else if (n < 0)
+ /* a<---b--->c */
+ return dns_name_compare_func(a, b) < 0 &&
+ dns_name_compare_func(b, c) < 0;
+ else
+ /* <--b--c a--b--> */
+ return dns_name_compare_func(b, c) < 0 ||
+ dns_name_compare_func(a, b) < 0;
+}
+
int dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
const uint8_t *p;
int r;
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index 00caf5d700..bd50ad3e6d 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -29,6 +29,7 @@
#define DNS_NAME_MAX 255
int dns_label_unescape(const char **name, char *dest, size_t sz);
+int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz);
int dns_label_escape(const char *p, size_t l, char **ret);
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
@@ -49,6 +50,7 @@ unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_
int dns_name_compare_func(const void *a, const void *b);
extern const struct hash_ops dns_name_hash_ops;
+int dns_name_between(const char *a, const char *b, const char *c);
int dns_name_equal(const char *x, const char *y);
int dns_name_endswith(const char *name, const char *suffix);
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 0d6ecf52cf..347cd30b09 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -125,7 +125,19 @@ static int get_os_indications(uint64_t *os_indication) {
return r;
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
- if (r < 0)
+ if (r == -ENOENT) {
+ /* Some firmware implementations that do support
+ * OsIndications and report that with
+ * OsIndicationsSupported will remove the
+ * OsIndications variable when it is unset. Let's
+ * pretend it's 0 then, to hide this implementation
+ * detail. Note that this call will return -ENOENT
+ * then only if the support for OsIndications is
+ * missing entirely, as determined by
+ * efi_reboot_to_firmware_supported() above. */
+ *os_indication = 0;
+ return 0;
+ } else if (r < 0)
return r;
else if (s != sizeof(uint64_t))
return -EINVAL;
diff --git a/src/shared/nss-util.h b/src/shared/nss-util.h
index 230a986040..3657aa5d9c 100644
--- a/src/shared/nss-util.h
+++ b/src/shared/nss-util.h
@@ -24,6 +24,9 @@
#include <nss.h>
#include <netdb.h>
#include <resolv.h>
+#include <pwd.h>
+#include <grp.h>
+
#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \
enum nss_status _nss_##module##_gethostbyname4_r( \
@@ -109,7 +112,8 @@ enum nss_status _nss_##module##_gethostbyname_r( \
NULL, \
NULL); \
return ret; \
-}
+} \
+struct __useless_struct_to_allow_trailing_semicolon__
#define NSS_GETHOSTBYADDR_FALLBACKS(module) \
enum nss_status _nss_##module##_gethostbyaddr_r( \
@@ -125,4 +129,29 @@ enum nss_status _nss_##module##_gethostbyaddr_r( \
buffer, buflen, \
errnop, h_errnop, \
NULL); \
-}
+} \
+struct __useless_struct_to_allow_trailing_semicolon__
+
+#define NSS_GETPW_PROTOTYPES(module) \
+enum nss_status _nss_##module##_getpwnam_r( \
+ const char *name, \
+ struct passwd *pwd, \
+ char *buffer, size_t buflen, \
+ int *errnop) _public_; \
+enum nss_status _nss_mymachines_getpwuid_r( \
+ uid_t uid, \
+ struct passwd *pwd, \
+ char *buffer, size_t buflen, \
+ int *errnop) _public_
+
+#define NSS_GETGR_PROTOTYPES(module) \
+enum nss_status _nss_##module##_getgrnam_r( \
+ const char *name, \
+ struct group *gr, \
+ char *buffer, size_t buflen, \
+ int *errnop) _public_; \
+enum nss_status _nss_##module##_getgrgid_r( \
+ gid_t gid, \
+ struct group *gr, \
+ char *buffer, size_t buflen, \
+ int *errnop) _public_
diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c
index 55f4e48601..1de0b94fd5 100644
--- a/src/shared/sysctl-util.c
+++ b/src/shared/sysctl-util.c
@@ -66,7 +66,7 @@ int sysctl_write(const char *property, const char *value) {
log_debug("Setting '%s' to '%s'", property, value);
p = strjoina("/proc/sys/", property);
- return write_string_file(p, value);
+ return write_string_file(p, value, 0);
}
int sysctl_read(const char *property, char **content) {
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index eee6bc8982..2b2310152d 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -42,7 +42,7 @@ static int write_mode(char **modes) {
STRV_FOREACH(mode, modes) {
int k;
- k = write_string_file("/sys/power/disk", *mode);
+ k = write_string_file("/sys/power/disk", *mode, 0);
if (k == 0)
return 0;
@@ -65,7 +65,7 @@ static int write_state(FILE **f, char **states) {
STRV_FOREACH(state, states) {
int k;
- k = write_string_stream(*f, *state);
+ k = write_string_stream(*f, *state, true);
if (k == 0)
return 0;
log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 538838b7fc..6db4d6587a 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -617,7 +617,7 @@ static int get_unit_list_recursive(
return r;
STRV_FOREACH(i, machines) {
- _cleanup_bus_close_unref_ sd_bus *container = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
int k;
r = sd_bus_open_system_machine(&container, *i);
@@ -1709,7 +1709,7 @@ static int compare_machine_info(const void *a, const void *b) {
}
static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
- _cleanup_bus_close_unref_ sd_bus *container = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
int r;
assert(mi);
@@ -7340,7 +7340,7 @@ static int halt_main(sd_bus *bus) {
if (arg_when > 0) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *b = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
_cleanup_free_ char *m = NULL;
if (avoid_bus()) {
@@ -7449,7 +7449,7 @@ static int runlevel_main(void) {
}
int main(int argc, char*argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
@@ -7517,7 +7517,7 @@ int main(int argc, char*argv[]) {
case ACTION_CANCEL_SHUTDOWN: {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *b = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
_cleanup_free_ char *m = NULL;
if (avoid_bus()) {
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index a03221502a..bb4b1eb748 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -67,6 +67,7 @@ struct sd_bus_vtable {
const char *signature;
const char *result;
sd_bus_message_handler_t handler;
+ size_t offset;
} method;
struct {
const char *member;
@@ -89,7 +90,7 @@ struct sd_bus_vtable {
.x.start.element_size = sizeof(sd_bus_vtable), \
}
-#define SD_BUS_METHOD(_member, _signature, _result, _handler, _flags) \
+#define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags) \
{ \
.type = _SD_BUS_VTABLE_METHOD, \
.flags = _flags, \
@@ -97,7 +98,10 @@ struct sd_bus_vtable {
.x.method.signature = _signature, \
.x.method.result = _result, \
.x.method.handler = _handler, \
+ .x.method.offset = _offset, \
}
+#define SD_BUS_METHOD(_member, _signature, _result, _handler, _flags) \
+ SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, 0, _flags)
#define SD_BUS_SIGNAL(_member, _signature, _flags) \
{ \
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 57e46ced8e..5439a1903b 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -156,6 +156,7 @@ void sd_bus_close(sd_bus *bus);
sd_bus *sd_bus_ref(sd_bus *bus);
sd_bus *sd_bus_unref(sd_bus *bus);
+sd_bus *sd_bus_flush_close_unref(sd_bus *bus);
int sd_bus_is_open(sd_bus *bus);
@@ -204,7 +205,7 @@ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot);
void *sd_bus_slot_get_userdata(sd_bus_slot *slot);
void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description);
-int sd_bus_slot_get_description(sd_bus_slot *slot, char **description);
+int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description);
sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot);
sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *bus);
diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h
index 4296b91d8a..5afa50a9d0 100644
--- a/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/sd-dhcp-lease.h
@@ -45,6 +45,8 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);
int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn);
+int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data,
+ size_t *data_len);
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
size_t *client_id_len);
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 9ae518ac4a..45b119362c 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -240,20 +240,21 @@ static bool usage_contains_reload(const char *line) {
}
static char *sysv_translate_name(const char *name) {
- char *r;
+ _cleanup_free_ char *c = NULL;
+ char *res;
- r = new(char, strlen(name) + strlen(".service") + 1);
- if (!r)
+ c = strdup(name);
+ if (!c)
return NULL;
- if (endswith(name, ".sh"))
- /* Drop .sh suffix */
- strcpy(stpcpy(r, name) - 3, ".service");
- else
- /* Normal init script name */
- strcpy(stpcpy(r, name), ".service");
+ res = endswith(c, ".sh");
+ if (res)
+ *res = 0;
- return r;
+ if (unit_name_mangle(c, UNIT_NAME_NOGLOB, &res) < 0)
+ return NULL;
+
+ return res;
}
static int sysv_translate_facility(const char *name, const char *filename, char **_r) {
@@ -340,6 +341,7 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
FOREACH_WORD_QUOTED(word, z, text, state_) {
_cleanup_free_ char *n = NULL, *m = NULL;
+ UnitType t;
n = strndup(word, z);
if (!n)
@@ -351,12 +353,13 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
if (r == 0)
continue;
- if (unit_name_to_type(m) == UNIT_SERVICE) {
+ t = unit_name_to_type(m);
+ if (t == UNIT_SERVICE) {
log_debug("Adding Provides: alias '%s' for '%s'", m, s->name);
r = add_alias(s->name, m);
if (r < 0)
log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m);
- } else {
+ } else if (t == UNIT_TARGET) {
/* NB: SysV targets which are provided by a
* service are pulled in by the services, as
* an indication that the generic service is
@@ -373,7 +376,10 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
if (r < 0)
return log_oom();
}
- }
+ } else if (t == _UNIT_TYPE_INVALID)
+ log_warning("Unit name '%s' is invalid", m);
+ else
+ log_warning("Unknown unit type for unit '%s'", m);
}
if (!isempty(state_))
log_error("[%s:%u] Trailing garbage in Provides, ignoring.", s->path, line);
diff --git a/src/test/test-bitmap.c b/src/test/test-bitmap.c
new file mode 100644
index 0000000000..96deeded7e
--- /dev/null
+++ b/src/test/test-bitmap.c
@@ -0,0 +1,105 @@
+/***
+ This file is part of systemd
+
+ Copyright 2015 Tom Gundersen
+
+ 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.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "bitmap.h"
+
+int main(int argc, const char *argv[]) {
+ _cleanup_bitmap_free_ Bitmap *b = NULL;
+ Iterator it;
+ unsigned n = (unsigned) -1, i = 0;
+
+ b = bitmap_new();
+ assert_se(b);
+
+ assert_se(bitmap_ensure_allocated(&b) == 0);
+ bitmap_free(b);
+ b = NULL;
+ assert_se(bitmap_ensure_allocated(&b) == 0);
+
+ assert_se(bitmap_isset(b, 0) == false);
+ assert_se(bitmap_isset(b, 1) == false);
+ assert_se(bitmap_isset(b, 256) == false);
+ assert_se(bitmap_isclear(b) == true);
+
+ assert_se(bitmap_set(b, 0) == 0);
+ assert_se(bitmap_isset(b, 0) == true);
+ assert_se(bitmap_isclear(b) == false);
+ bitmap_unset(b, 0);
+ assert_se(bitmap_isset(b, 0) == false);
+ assert_se(bitmap_isclear(b) == true);
+
+ assert_se(bitmap_set(b, 1) == 0);
+ assert_se(bitmap_isset(b, 1) == true);
+ assert_se(bitmap_isclear(b) == false);
+ bitmap_unset(b, 1);
+ assert_se(bitmap_isset(b, 1) == false);
+ assert_se(bitmap_isclear(b) == true);
+
+ assert_se(bitmap_set(b, 256) == 0);
+ assert_se(bitmap_isset(b, 256) == true);
+ assert_se(bitmap_isclear(b) == false);
+ bitmap_unset(b, 256);
+ assert_se(bitmap_isset(b, 256) == false);
+ assert_se(bitmap_isclear(b) == true);
+
+ assert_se(bitmap_set(b, 32) == 0);
+ bitmap_unset(b, 0);
+ assert_se(bitmap_isset(b, 32) == true);
+ bitmap_unset(b, 32);
+
+ BITMAP_FOREACH(n, NULL, it)
+ assert_not_reached("NULL bitmap");
+
+ assert_se(bitmap_set(b, 0) == 0);
+ assert_se(bitmap_set(b, 1) == 0);
+ assert_se(bitmap_set(b, 256) == 0);
+
+ BITMAP_FOREACH(n, b, it) {
+ assert_se(n == i);
+ if (i == 0)
+ i = 1;
+ else if (i == 1)
+ i = 256;
+ else if (i == 256)
+ i = (unsigned) -1;
+ }
+
+ assert_se(i == (unsigned) -1);
+
+ i = 0;
+
+ BITMAP_FOREACH(n, b, it) {
+ assert_se(n == i);
+ if (i == 0)
+ i = 1;
+ else if (i == 1)
+ i = 256;
+ else if (i == 256)
+ i = (unsigned) -1;
+ }
+
+ assert_se(i == (unsigned) -1);
+
+ bitmap_clear(b);
+ assert_se(bitmap_isclear(b) == true);
+
+ assert_se(bitmap_set(b, (unsigned) -1) == -ERANGE);
+
+ return 0;
+}
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index 838ffcba3d..e4771c9dd7 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to make subvolume: %m");
- r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha");
+ r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE);
if (r < 0)
log_error_errno(r, "Failed to write file: %m");
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index b1385b8b87..b73c958ec5 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -43,7 +43,7 @@ static void test_copy_file(void) {
assert_se(fd >= 0);
close(fd);
- assert_se(write_string_file(fn, "foo bar bar bar foo") == 0);
+ assert_se(write_string_file(fn, "foo bar bar bar foo", WRITE_STRING_FILE_CREATE) == 0);
assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
@@ -67,7 +67,7 @@ static void test_copy_file_fd(void) {
out_fd = mkostemp_safe(out_fn, O_RDWR);
assert_se(out_fd >= 0);
- assert_se(write_string_file(in_fn, text) == 0);
+ assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0);
assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, true) < 0);
assert_se(copy_file_fd(in_fn, out_fd, true) >= 0);
assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
@@ -94,7 +94,7 @@ static void test_copy_tree(void) {
char *f = strjoina(original_dir, *p);
assert_se(mkdir_parents(f, 0755) >= 0);
- assert_se(write_string_file(f, "file") == 0);
+ assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
}
STRV_FOREACH_PAIR(link, p, links) {
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index 527cdd3b54..31e110cf0d 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -50,6 +50,46 @@ static void test_dns_label_unescape(void) {
test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
}
+static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {
+ char buffer[buffer_sz];
+ const char *label;
+ int r;
+
+ label = what + strlen(what);
+
+ r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
+ assert_se(r == ret1);
+ if (r >= 0)
+ assert_se(streq(buffer, expect1));
+
+ r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz);
+ assert_se(r == ret2);
+ if (r >= 0)
+ assert_se(streq(buffer, expect2));
+}
+
+static void test_dns_label_unescape_suffix(void) {
+ test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0);
+ test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOSPC, -ENOSPC);
+ test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0);
+ test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0);
+ test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5);
+ test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL);
+ test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0);
+ test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0);
+ test_dns_label_unescape_suffix_one("..", "", "", 20, 0, 0);
+ test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL);
+ test_dns_label_unescape_suffix_one("foobar.", "", "foobar", 20, 0, 6);
+ test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0);
+ test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3);
+ test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL);
+ test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL);
+ test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0);
+ test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4);
+ test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0);
+}
+
static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) {
_cleanup_free_ char *t = NULL;
int r;
@@ -120,6 +160,38 @@ static void test_dns_name_equal(void) {
test_dns_name_equal_one("..", "..", -EINVAL);
}
+static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) {
+ int r;
+
+ r = dns_name_between(a, b, c);
+ assert_se(r == ret);
+
+ r = dns_name_between(c, b, a);
+ if (ret >= 0)
+ assert_se(r == 0);
+ else
+ assert_se(r == ret);
+}
+
+static void test_dns_name_between(void) {
+ /* see https://tools.ietf.org/html/rfc4034#section-6.1
+ Note that we use "\033.z.example" in stead of "\001.z.example" as we
+ consider the latter invalid */
+ test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true);
+ test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true);
+ test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true);
+ test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true);
+ test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true);
+ test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true);
+ test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true);
+ test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true);
+ test_dns_name_between_one("\\200.z.example", "example", "a.example", true);
+
+ test_dns_name_between_one("example", "a.example", "example", -EINVAL);
+ test_dns_name_between_one("example", "example", "yljkjljk.a.example", false);
+ test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false);
+}
+
static void test_dns_name_endswith_one(const char *a, const char *b, int ret) {
assert_se(dns_name_endswith(a, b) == ret);
}
@@ -180,10 +252,12 @@ static void test_dns_name_reverse(void) {
int main(int argc, char *argv[]) {
test_dns_label_unescape();
+ test_dns_label_unescape_suffix();
test_dns_label_escape();
test_dns_name_normalize();
test_dns_name_equal();
test_dns_name_endswith();
+ test_dns_name_between();
test_dns_name_root();
test_dns_name_single_label();
test_dns_name_reverse();
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 4c31b776bd..be3a87958f 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -302,17 +302,27 @@ static void test_write_string_stream(void) {
f = fdopen(fd, "r");
assert_se(f);
- assert_se(write_string_stream(f, "boohoo") < 0);
+ assert_se(write_string_stream(f, "boohoo", true) < 0);
f = freopen(fn, "r+", f);
assert_se(f);
- assert_se(write_string_stream(f, "boohoo") == 0);
+ assert_se(write_string_stream(f, "boohoo", true) == 0);
rewind(f);
assert_se(fgets(buf, sizeof(buf), f));
assert_se(streq(buf, "boohoo\n"));
+ f = freopen(fn, "w+", f);
+ assert_se(f);
+
+ assert_se(write_string_stream(f, "boohoo", false) == 0);
+ rewind(f);
+
+ assert_se(fgets(buf, sizeof(buf), f));
+ printf(">%s<", buf);
+ assert_se(streq(buf, "boohoo"));
+
unlink(fn);
}
@@ -324,7 +334,7 @@ static void test_write_string_file(void) {
fd = mkostemp_safe(fn, O_RDWR);
assert_se(fd >= 0);
- assert_se(write_string_file(fn, "boohoo") == 0);
+ assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
assert_se(read(fd, buf, sizeof(buf)) == 7);
assert_se(streq(buf, "boohoo\n"));
@@ -340,8 +350,8 @@ static void test_write_string_file_no_create(void) {
fd = mkostemp_safe(fn, O_RDWR);
assert_se(fd >= 0);
- assert_se(write_string_file_no_create("/a/file/which/does/not/exists/i/guess", "boohoo") < 0);
- assert_se(write_string_file_no_create(fn, "boohoo") == 0);
+ assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
+ assert_se(write_string_file(fn, "boohoo", 0) == 0);
assert_se(read(fd, buf, sizeof(buf)) == strlen("boohoo\n"));
assert_se(streq(buf, "boohoo\n"));
@@ -367,8 +377,8 @@ static void test_load_env_file_pairs(void) {
"ANSI_COLOR=\"0;36\"\n"
"HOME_URL=\"https://www.archlinux.org/\"\n"
"SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
- "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n"
- );
+ "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n",
+ WRITE_STRING_FILE_CREATE);
assert_se(r == 0);
f = fdopen(fd, "r");
diff --git a/src/test/test-pty.c b/src/test/test-pty.c
index 3f97a64ccd..fbab3d4ebe 100644
--- a/src/test/test-pty.c
+++ b/src/test/test-pty.c
@@ -133,7 +133,7 @@ int main(int argc, char *argv[]) {
/* Oh, there're ugly races in the TTY layer regarding HUP vs IN. Turns
* out they appear only 10% of the time. I fixed all of them and
- * don't see them, anymore. But lets be safe and run this 1000 times
+ * don't see them, anymore. But let's be safe and run this 1000 times
* so we catch any new ones, in case they appear again. */
for (i = 0; i < 1000; ++i)
test_pty();
diff --git a/src/test/test-util.c b/src/test/test-util.c
index ad9ea3bcce..f43433baa1 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -390,6 +390,39 @@ static void test_unhexchar(void) {
assert_se(unhexchar('0') == 0x0);
}
+static void test_base32hexchar(void) {
+ assert_se(base32hexchar(0) == '0');
+ assert_se(base32hexchar(9) == '9');
+ assert_se(base32hexchar(10) == 'A');
+ assert_se(base32hexchar(31) == 'V');
+}
+
+static void test_unbase32hexchar(void) {
+ assert_se(unbase32hexchar('0') == 0);
+ assert_se(unbase32hexchar('9') == 9);
+ assert_se(unbase32hexchar('A') == 10);
+ assert_se(unbase32hexchar('V') == 31);
+ assert_se(unbase32hexchar('=') == -EINVAL);
+}
+
+static void test_base64char(void) {
+ assert_se(base64char(0) == 'A');
+ assert_se(base64char(26) == 'a');
+ assert_se(base64char(63) == '/');
+}
+
+static void test_unbase64char(void) {
+ assert_se(unbase64char('A') == 0);
+ assert_se(unbase64char('Z') == 25);
+ assert_se(unbase64char('a') == 26);
+ assert_se(unbase64char('z') == 51);
+ assert_se(unbase64char('0') == 52);
+ assert_se(unbase64char('9') == 61);
+ assert_se(unbase64char('+') == 62);
+ assert_se(unbase64char('/') == 63);
+ assert_se(unbase64char('=') == -EINVAL);
+}
+
static void test_octchar(void) {
assert_se(octchar(00) == '0');
assert_se(octchar(07) == '7');
@@ -410,6 +443,264 @@ static void test_undecchar(void) {
assert_se(undecchar('9') == 9);
}
+static void test_unhexmem(void) {
+ const char *hex = "efa214921";
+ const char *hex_invalid = "efa214921o";
+ _cleanup_free_ char *hex2 = NULL;
+ _cleanup_free_ void *mem = NULL;
+ size_t len;
+
+ assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
+ assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
+
+ assert_se((hex2 = hexmem(mem, len)));
+
+ free(mem);
+
+ assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
+
+ free(hex2);
+
+ assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
+ assert_se((hex2 = hexmem(mem, len)));
+ assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base32hexmem(void) {
+ char *b32;
+
+ b32 = base32hexmem("", strlen(""), true);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CO======"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG===="));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU==="));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG="));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8======"));
+ free(b32);
+
+ b32 = base32hexmem("", strlen(""), false);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CO"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG"));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU"));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG"));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8"));
+ free(b32);
+}
+
+static void test_unbase32hexmem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base64mem(void) {
+ char *b64;
+
+ b64 = base64mem("", strlen(""));
+ assert_se(b64);
+ assert_se(streq(b64, ""));
+ free(b64);
+
+ b64 = base64mem("f", strlen("f"));
+ assert_se(b64);
+ assert_se(streq(b64, "Zg=="));
+ free(b64);
+
+ b64 = base64mem("fo", strlen("fo"));
+ assert_se(b64);
+ assert_se(streq(b64, "Zm8="));
+ free(b64);
+
+ b64 = base64mem("foo", strlen("foo"));
+ assert_se(b64);
+ assert_se(streq(b64, "Zm9v"));
+ free(b64);
+
+ b64 = base64mem("foob", strlen("foob"));
+ assert_se(b64);
+ assert_se(streq(b64, "Zm9vYg=="));
+ free(b64);
+
+ b64 = base64mem("fooba", strlen("fooba"));
+ assert_se(b64);
+ assert_se(streq(b64, "Zm9vYmE="));
+ free(b64);
+
+ b64 = base64mem("foobar", strlen("foobar"));
+ assert_se(b64);
+ assert_se(streq(b64, "Zm9vYmFy"));
+ free(b64);
+}
+
+static void test_unbase64mem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
+}
+
static void test_cescape(void) {
_cleanup_free_ char *escaped;
@@ -565,14 +856,14 @@ static void test_read_hostname_config(void) {
close(fd);
/* simple hostname */
- write_string_file(path, "foo");
+ write_string_file(path, "foo", WRITE_STRING_FILE_CREATE);
assert_se(read_hostname_config(path, &hostname) == 0);
assert_se(streq(hostname, "foo"));
free(hostname);
hostname = NULL;
/* with comment */
- write_string_file(path, "# comment\nfoo");
+ write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE);
assert_se(read_hostname_config(path, &hostname) == 0);
assert_se(hostname);
assert_se(streq(hostname, "foo"));
@@ -580,7 +871,7 @@ static void test_read_hostname_config(void) {
hostname = NULL;
/* with comment and extra whitespace */
- write_string_file(path, "# comment\n\n foo ");
+ write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE);
assert_se(read_hostname_config(path, &hostname) == 0);
assert_se(hostname);
assert_se(streq(hostname, "foo"));
@@ -588,7 +879,7 @@ static void test_read_hostname_config(void) {
hostname = NULL;
/* cleans up name */
- write_string_file(path, "!foo/bar.com");
+ write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE);
assert_se(read_hostname_config(path, &hostname) == 0);
assert_se(hostname);
assert_se(streq(hostname, "foobar.com"));
@@ -597,7 +888,7 @@ static void test_read_hostname_config(void) {
/* no value set */
hostname = (char*) 0x1234;
- write_string_file(path, "# nothing here\n");
+ write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE);
assert_se(read_hostname_config(path, &hostname) == -ENOENT);
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
@@ -1191,11 +1482,11 @@ static void test_execute_directory(void) {
masked = strjoina(template_lo, "/masked");
mask = strjoina(template_hi, "/masked");
- assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works") == 0);
- assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2") == 0);
- assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed") == 0);
- assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0") == 0);
- assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed") == 0);
+ assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
+ assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
assert_se(symlink("/dev/null", mask) == 0);
assert_se(chmod(name, 0755) == 0);
assert_se(chmod(name2, 0755) == 0);
@@ -1398,6 +1689,17 @@ static void test_unquote_first_word(void) {
assert_se(streq(t, "\\w+\b"));
free(t);
assert_se(p == original + 5);
+
+ p = original = "-N ''";
+ assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) > 0);
+ assert_se(streq(t, "-N"));
+ free(t);
+ assert_se(p == original + 3);
+
+ assert_se(unquote_first_word(&p, &t, UNQUOTE_CUNESCAPE) > 0);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 5);
}
static void test_unquote_first_word_and_warn(void) {
@@ -1804,10 +2106,19 @@ int main(int argc, char *argv[]) {
test_in_charset();
test_hexchar();
test_unhexchar();
+ test_base32hexchar();
+ test_unbase32hexchar();
+ test_base64char();
+ test_unbase64char();
test_octchar();
test_unoctchar();
test_decchar();
test_undecchar();
+ test_unhexmem();
+ test_base32hexmem();
+ test_unbase32hexmem();
+ test_base64mem();
+ test_unbase64mem();
test_cescape();
test_cunescape();
test_foreach_word();
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 195d5f3892..240578bca0 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -154,11 +154,12 @@ static void print_status_info(const StatusInfo *i) {
if (i->rtc_local)
fputs("\n" ANSI_HIGHLIGHT_ON
- "Warning: The system is configured to read the RTC time in the local time zone. This\n"
- " mode can not be fully supported. It will create various problems with time\n"
- " zone changes and daylight saving time adjustments. The RTC time is never updated,\n"
- " it relies on external facilities to maintain it. If at all possible, use\n"
- " RTC in UTC by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
+ "Warning: The system is configured to read the RTC time in the local time zone.\n"
+ " This mode can not be fully supported. It will create various problems\n"
+ " with time zone changes and daylight saving time adjustments. The RTC\n"
+ " time is never updated, it relies on external facilities to maintain it.\n"
+ " If at all possible, use RTC in UTC by calling\n"
+ " 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
}
static int show_status(sd_bus *bus, char **args, unsigned n) {
@@ -490,7 +491,7 @@ static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 4e8ae94717..21d6ee4c0c 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -660,7 +660,7 @@ static const sd_bus_vtable timedate_vtable[] = {
};
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
assert(c);
@@ -692,7 +692,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
int main(int argc, char *argv[]) {
Context context = {};
_cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
log_set_target(LOG_TARGET_AUTO);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 42f757c4b7..271984b5a8 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -955,9 +955,10 @@ static int path_set_attribute(Item *item, const char *path) {
r = chattr_fd(fd, f, item->attribute_mask);
if (r < 0)
- return log_error_errno(r,
- "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m",
- path, item->attribute_value, item->attribute_mask);
+ log_full_errno(r == -ENOTTY ? LOG_DEBUG : LOG_WARNING,
+ r,
+ "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m",
+ path, item->attribute_value, item->attribute_mask);
return 0;
}
diff --git a/src/udev/accelerometer/Makefile b/src/udev/accelerometer/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/udev/accelerometer/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/udev/accelerometer/accelerometer.c b/src/udev/accelerometer/accelerometer.c
deleted file mode 100644
index 9e2c590c15..0000000000
--- a/src/udev/accelerometer/accelerometer.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * accelerometer - exports device orientation through property
- *
- * When an "change" event is received on an accelerometer,
- * open its device node, and from the value, as well as the previous
- * value of the property, calculate the device's new orientation,
- * and export it as ID_INPUT_ACCELEROMETER_ORIENTATION.
- *
- * Possible values are:
- * undefined
- * * normal
- * * bottom-up
- * * left-up
- * * right-up
- *
- * The property will be persistent across sessions, and the new
- * orientations can be deducted from the previous one (it allows
- * for a threshold for switching between opposite ends of the
- * orientation).
- *
- * Copyright (C) 2011 Red Hat, Inc.
- * Author:
- * Bastien Nocera <hadess@hadess.net>
- *
- * orientation_calc() from the sensorfw package
- * Copyright (C) 2009-2010 Nokia Corporation
- * Authors:
- * Üstün Ergenoglu <ext-ustun.ergenoglu@nokia.com>
- * Timo Rongas <ext-timo.2.rongas@nokia.com>
- * Lihan Guo <lihan.guo@digia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <limits.h>
-#include <linux/input.h>
-
-#include "libudev.h"
-#include "libudev-private.h"
-
-/* we must use this kernel-compatible implementation */
-#define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
-#define OFF(x) ((x)%BITS_PER_LONG)
-#define BIT(x) (1UL<<OFF(x))
-#define LONG(x) ((x)/BITS_PER_LONG)
-#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
-
-typedef enum {
- ORIENTATION_UNDEFINED,
- ORIENTATION_NORMAL,
- ORIENTATION_BOTTOM_UP,
- ORIENTATION_LEFT_UP,
- ORIENTATION_RIGHT_UP
-} OrientationUp;
-
-static const char *orientations[] = {
- "undefined",
- "normal",
- "bottom-up",
- "left-up",
- "right-up",
- NULL
-};
-
-#define ORIENTATION_UP_UP ORIENTATION_NORMAL
-
-#define DEFAULT_THRESHOLD 250
-#define RADIANS_TO_DEGREES 180.0/M_PI
-#define SAME_AXIS_LIMIT 5
-
-#define THRESHOLD_LANDSCAPE 25
-#define THRESHOLD_PORTRAIT 20
-
-static const char *
-orientation_to_string (OrientationUp o)
-{
- return orientations[o];
-}
-
-static OrientationUp
-string_to_orientation (const char *orientation)
-{
- int i;
-
- if (orientation == NULL)
- return ORIENTATION_UNDEFINED;
- for (i = 0; orientations[i] != NULL; i++) {
- if (streq (orientation, orientations[i]))
- return i;
- }
- return ORIENTATION_UNDEFINED;
-}
-
-static OrientationUp
-orientation_calc (OrientationUp prev,
- int x, int y, int z)
-{
- int rotation;
- OrientationUp ret = prev;
-
- /* Portrait check */
- rotation = round(atan((double) x / sqrt(y * y + z * z)) * RADIANS_TO_DEGREES);
-
- if (abs(rotation) > THRESHOLD_PORTRAIT) {
- ret = (rotation < 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP;
-
- /* Some threshold to switching between portrait modes */
- if (prev == ORIENTATION_LEFT_UP || prev == ORIENTATION_RIGHT_UP) {
- if (abs(rotation) < SAME_AXIS_LIMIT) {
- ret = prev;
- }
- }
-
- } else {
- /* Landscape check */
- rotation = round(atan((double) y / sqrt(x * x + z * z)) * RADIANS_TO_DEGREES);
-
- if (abs(rotation) > THRESHOLD_LANDSCAPE) {
- ret = (rotation < 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL;
-
- /* Some threshold to switching between landscape modes */
- if (prev == ORIENTATION_BOTTOM_UP || prev == ORIENTATION_NORMAL) {
- if (abs(rotation) < SAME_AXIS_LIMIT) {
- ret = prev;
- }
- }
- }
- }
-
- return ret;
-}
-
-static OrientationUp
-get_prev_orientation(struct udev_device *dev)
-{
- const char *value;
-
- value = udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER_ORIENTATION");
- if (value == NULL)
- return ORIENTATION_UNDEFINED;
- return string_to_orientation(value);
-}
-
-#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; }
-
-/* accelerometers */
-static void test_orientation(struct udev *udev,
- struct udev_device *dev,
- const char *devpath)
-{
- OrientationUp old, new;
- _cleanup_close_ int fd = -1;
- struct input_absinfo abs_info;
- int x = 0, y = 0, z = 0;
- int r;
- char text[64];
-
- old = get_prev_orientation(dev);
-
- fd = open(devpath, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return;
-
- READ_AXIS(ABS_X, x);
- READ_AXIS(ABS_Y, y);
- READ_AXIS(ABS_Z, z);
-
- new = orientation_calc(old, x, y, z);
- snprintf(text, sizeof(text),
- "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new));
- puts(text);
-}
-
-static void help(void) {
-
- printf("%s [options] <device path>\n\n"
- "Accelerometer device identification.\n\n"
- " -h --help Print this message\n"
- " -d --debug Debug to stderr\n"
- , program_invocation_short_name);
-}
-
-int main (int argc, char** argv)
-{
- struct udev *udev;
- struct udev_device *dev;
-
- static const struct option options[] = {
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- {}
- };
-
- char devpath[PATH_MAX];
- char *devnode;
- struct udev_enumerate *enumerate;
- struct udev_list_entry *list_entry;
-
- log_parse_environment();
- log_open();
-
- udev = udev_new();
- if (udev == NULL)
- return 1;
-
- /* CLI argument parsing */
- while (1) {
- int option;
-
- option = getopt_long(argc, argv, "dh", options, NULL);
- if (option == -1)
- break;
-
- switch (option) {
- case 'd':
- log_set_target(LOG_TARGET_CONSOLE);
- log_set_max_level(LOG_DEBUG);
- log_open();
- break;
- case 'h':
- help();
- exit(0);
- default:
- exit(1);
- }
- }
-
- if (argv[optind] == NULL) {
- help();
- exit(1);
- }
-
- /* get the device */
- snprintf(devpath, sizeof(devpath), "/sys/%s", argv[optind]);
- dev = udev_device_new_from_syspath(udev, devpath);
- if (dev == NULL) {
- fprintf(stderr, "unable to access '%s'\n", devpath);
- return 1;
- }
-
- /* Get the children devices and find the devnode */
- devnode = NULL;
- enumerate = udev_enumerate_new(udev);
- udev_enumerate_add_match_parent(enumerate, dev);
- udev_enumerate_scan_devices(enumerate);
- udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
- struct udev_device *device;
- const char *node;
-
- device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
- udev_list_entry_get_name(list_entry));
- if (device == NULL)
- continue;
- /* Already found it */
- if (devnode != NULL) {
- udev_device_unref(device);
- continue;
- }
-
- node = udev_device_get_devnode(device);
- if (node == NULL) {
- udev_device_unref(device);
- continue;
- }
- /* Use the event sub-device */
- if (strstr(node, "/event") == NULL) {
- udev_device_unref(device);
- continue;
- }
-
- devnode = strdup(node);
- udev_device_unref(device);
- }
-
- if (devnode == NULL) {
- fprintf(stderr, "unable to get device node for '%s'\n", devpath);
- return 0;
- }
-
- log_debug("opening accelerometer device %s", devnode);
- test_orientation(udev, dev, devnode);
- free(devnode);
- log_close();
- return 0;
-}
diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c
index 7ba0b7fc8f..c6a2c56e77 100644
--- a/src/udev/ata_id/ata_id.c
+++ b/src/udev/ata_id/ata_id.c
@@ -409,7 +409,6 @@ int main(int argc, char *argv[])
union {
uint8_t byte[512];
uint16_t wyde[256];
- uint64_t octa[64];
} identify;
char model[41];
char model_enc[256];
@@ -638,10 +637,20 @@ int main(int argc, char *argv[])
* All other values are reserved.
*/
word = identify.wyde[108];
- if ((word & 0xf000) == 0x5000)
+ if ((word & 0xf000) == 0x5000) {
+ uint64_t wwwn;
+
+ wwwn = identify.wyde[108];
+ wwwn <<= 16;
+ wwwn |= identify.wyde[109];
+ wwwn <<= 16;
+ wwwn |= identify.wyde[110];
+ wwwn <<= 16;
+ wwwn |= identify.wyde[111];
printf("ID_WWN=0x%1$" PRIx64 "\n"
"ID_WWN_WITH_EXTENSION=0x%1$" PRIx64 "\n",
- identify.octa[108/4]);
+ wwwn);
+ }
/* from Linux's include/linux/ata.h */
if (identify.wyde[0] == 0x848a ||
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index b656204c46..72109d93d2 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -33,7 +33,7 @@ static sd_hwdb *hwdb;
int udev_builtin_hwdb_lookup(struct udev_device *dev,
const char *prefix, const char *modalias,
const char *filter, bool test) {
- _cleanup_free_ const char *lookup = NULL;
+ _cleanup_free_ char *lookup = NULL;
const char *key, *value;
int n = 0;
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 1092071e26..4761222786 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -721,19 +721,13 @@ int udev_event_spawn(struct udev_event *event,
usec_t timeout_usec,
usec_t timeout_warn_usec,
bool accept_failure,
- const char *cmd, char **envp,
+ const char *cmd,
char *result, size_t ressize) {
int outpipe[2] = {-1, -1};
int errpipe[2] = {-1, -1};
pid_t pid;
- char arg[UTIL_PATH_SIZE];
- char *argv[128];
- char program[UTIL_PATH_SIZE];
int err = 0;
- strscpy(arg, sizeof(arg), cmd);
- udev_build_argv(event->udev, arg, NULL, argv);
-
/* pipes from child to parent */
if (result != NULL || log_get_max_level() >= LOG_INFO) {
if (pipe2(outpipe, O_NONBLOCK) != 0) {
@@ -750,15 +744,14 @@ int udev_event_spawn(struct udev_event *event,
}
}
- /* allow programs in /usr/lib/udev/ to be called without the path */
- if (argv[0][0] != '/') {
- strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL);
- argv[0] = program;
- }
-
pid = fork();
switch(pid) {
case 0:
+ {
+ char arg[UTIL_PATH_SIZE];
+ char *argv[128];
+ char program[UTIL_PATH_SIZE];
+
/* child closes parent's ends of pipes */
if (outpipe[READ_END] >= 0) {
close(outpipe[READ_END]);
@@ -769,12 +762,22 @@ int udev_event_spawn(struct udev_event *event,
errpipe[READ_END] = -1;
}
+ strscpy(arg, sizeof(arg), cmd);
+ udev_build_argv(event->udev, arg, NULL, argv);
+
+ /* allow programs in /usr/lib/udev/ to be called without the path */
+ if (argv[0][0] != '/') {
+ strscpyl(program, sizeof(program), UDEVLIBEXECDIR "/", argv[0], NULL);
+ argv[0] = program;
+ }
+
log_debug("starting '%s'", cmd);
- spawn_exec(event, cmd, argv, envp,
+ spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev),
outpipe[WRITE_END], errpipe[WRITE_END]);
- _exit(2 );
+ _exit(2);
+ }
case -1:
log_error_errno(errno, "fork of '%s' failed: %m", cmd);
err = -1;
@@ -934,26 +937,21 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
struct udev_list_entry *list_entry;
udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) {
+ char command[UTIL_PATH_SIZE];
const char *cmd = udev_list_entry_get_name(list_entry);
enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
- if (builtin_cmd < UDEV_BUILTIN_MAX) {
- char command[UTIL_PATH_SIZE];
+ udev_event_apply_format(event, cmd, command, sizeof(command));
- udev_event_apply_format(event, cmd, command, sizeof(command));
+ if (builtin_cmd < UDEV_BUILTIN_MAX)
udev_builtin_run(event->dev, builtin_cmd, command, false);
- } else {
- char program[UTIL_PATH_SIZE];
- char **envp;
-
+ else {
if (event->exec_delay > 0) {
- log_debug("delay execution of '%s'", program);
+ log_debug("delay execution of '%s'", command);
sleep(event->exec_delay);
}
- udev_event_apply_format(event, cmd, program, sizeof(program));
- envp = udev_device_get_properties_envp(event->dev);
- udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, program, envp, NULL, 0);
+ udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, command, NULL, 0);
}
}
}
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 8ebc061eb1..d00f90afa6 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -634,14 +634,11 @@ static int import_program_into_properties(struct udev_event *event,
usec_t timeout_usec,
usec_t timeout_warn_usec,
const char *program) {
- struct udev_device *dev = event->dev;
- char **envp;
char result[UTIL_LINE_SIZE];
char *line;
int err;
- envp = udev_device_get_properties_envp(dev);
- err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result));
+ err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result));
if (err < 0)
return err;
@@ -654,7 +651,7 @@ static int import_program_into_properties(struct udev_event *event,
pos[0] = '\0';
pos = &pos[1];
}
- import_property_from_string(dev, line);
+ import_property_from_string(event->dev, line);
line = pos;
}
return 0;
@@ -682,41 +679,6 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi
return 0;
}
-#define WAIT_LOOP_PER_SECOND 50
-static int wait_for_file(struct udev_device *dev, const char *file, int timeout) {
- char filepath[UTIL_PATH_SIZE];
- char devicepath[UTIL_PATH_SIZE];
- struct stat stats;
- int loop = timeout * WAIT_LOOP_PER_SECOND;
-
- /* a relative path is a device attribute */
- devicepath[0] = '\0';
- if (file[0] != '/') {
- strscpyl(devicepath, sizeof(devicepath), udev_device_get_syspath(dev), NULL);
- strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL);
- file = filepath;
- }
-
- while (--loop) {
- const struct timespec duration = { 0, 1000 * 1000 * 1000 / WAIT_LOOP_PER_SECOND };
-
- /* lookup file */
- if (stat(file, &stats) == 0) {
- log_debug("file '%s' appeared after %i loops", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
- return 0;
- }
- /* make sure, the device did not disappear in the meantime */
- if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) {
- log_debug("device disappeared while waiting for '%s'", file);
- return -2;
- }
- log_debug("wait for '%s' for %i mseconds", file, 1000 / WAIT_LOOP_PER_SECOND);
- nanosleep(&duration, NULL);
- }
- log_debug("waiting for '%s' failed", file);
- return -1;
-}
-
static int attr_subst_subdir(char *attr, size_t len) {
bool found = false;
@@ -1397,15 +1359,6 @@ static int add_rule(struct udev_rules *rules, char *line,
continue;
}
- if (streq(key, "WAIT_FOR") || streq(key, "WAIT_FOR_SYSFS")) {
- if (op == OP_REMOVE) {
- log_error("invalid WAIT_FOR/WAIT_FOR_SYSFS operation");
- goto invalid;
- }
- rule_add_key(&rule_tmp, TK_M_WAITFOR, 0, value, NULL);
- continue;
- }
-
if (streq(key, "LABEL")) {
if (op == OP_REMOVE) {
log_error("invalid LABEL operation");
@@ -1999,16 +1952,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0)
goto nomatch;
break;
- case TK_M_WAITFOR: {
- char filename[UTIL_PATH_SIZE];
- int found;
-
- udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename));
- found = (wait_for_file(event->dev, filename, 10) == 0);
- if (!found && (cur->key.op != OP_NOMATCH))
- goto nomatch;
- break;
- }
case TK_M_ATTR:
if (match_attr(rules, event->dev, event, cur) != 0)
goto nomatch;
@@ -2119,19 +2062,17 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
}
case TK_M_PROGRAM: {
char program[UTIL_PATH_SIZE];
- char **envp;
char result[UTIL_LINE_SIZE];
free(event->program_result);
event->program_result = NULL;
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program));
- envp = udev_device_get_properties_envp(event->dev);
log_debug("PROGRAM '%s' %s:%u",
program,
rules_str(rules, rule->rule.filename_off),
rule->rule.filename_line);
- if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, envp, result, sizeof(result)) < 0) {
+ if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)) < 0) {
if (cur->key.op != OP_NOMATCH)
goto nomatch;
} else {
diff --git a/src/udev/udev.h b/src/udev/udev.h
index 3dca72e499..d17fc8c1ea 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -85,8 +85,7 @@ int udev_event_spawn(struct udev_event *event,
usec_t timeout_usec,
usec_t timeout_warn_usec,
bool accept_failure,
- const char *cmd, char **envp,
- char *result, size_t ressize);
+ const char *cmd, char *result, size_t ressize);
void udev_event_execute_rules(struct udev_event *event,
usec_t timeout_usec, usec_t timeout_warn_usec,
struct udev_list *properties_list,
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index cf15ddf641..d0b8bad48e 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -398,7 +398,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
prctl(PR_SET_PDEATHSIG, SIGTERM);
/* reset OOM score, we only protect the main daemon */
- write_string_file("/proc/self/oom_score_adj", "0");
+ write_string_file("/proc/self/oom_score_adj", "0", 0);
for (;;) {
struct udev_event *udev_event;
@@ -1091,7 +1091,7 @@ static int synthesize_change(struct udev_device *dev) {
*/
log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev));
strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL);
- write_string_file(filename, "change");
+ write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
@@ -1106,7 +1106,7 @@ static int synthesize_change(struct udev_device *dev) {
log_debug("device %s closed, synthesising partition '%s' 'change'",
udev_device_get_devnode(dev), udev_device_get_devnode(d));
strscpyl(filename, sizeof(filename), udev_device_get_syspath(d), "/uevent", NULL);
- write_string_file(filename, "change");
+ write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
}
return 0;
@@ -1114,7 +1114,7 @@ static int synthesize_change(struct udev_device *dev) {
log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev));
strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL);
- write_string_file(filename, "change");
+ write_string_file(filename, "change", WRITE_STRING_FILE_CREATE);
return 0;
}
@@ -1358,6 +1358,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
* udev.event-timeout=<number of seconds> seconds to wait before terminating an event
*/
static int parse_proc_cmdline_item(const char *key, const char *value) {
+ const char *full_key = key;
int r;
assert(key);
@@ -1377,26 +1378,29 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
int prio;
prio = util_log_priority(value);
+ if (prio < 0)
+ goto invalid;
log_set_max_level(prio);
} else if (streq(key, "children-max")) {
r = safe_atou(value, &arg_children_max);
if (r < 0)
- log_warning("invalid udev.children-max ignored: %s", value);
+ goto invalid;
} else if (streq(key, "exec-delay")) {
r = safe_atoi(value, &arg_exec_delay);
if (r < 0)
- log_warning("invalid udev.exec-delay ignored: %s", value);
+ goto invalid;
} else if (streq(key, "event-timeout")) {
r = safe_atou64(value, &arg_event_timeout_usec);
if (r < 0)
- log_warning("invalid udev.event-timeout ignored: %s", value);
- else {
- arg_event_timeout_usec *= USEC_PER_SEC;
- arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1;
- }
+ goto invalid;
+ arg_event_timeout_usec *= USEC_PER_SEC;
+ arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1;
}
return 0;
+invalid:
+ log_warning("invalid %s ignored: %s", full_key, value);
+ return 0;
}
static void help(void) {
@@ -1432,7 +1436,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "c:de:DtN:hV", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) {
int r;
switch (c) {
@@ -1608,8 +1612,42 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
return 0;
}
-int main(int argc, char *argv[]) {
+static int run(int fd_ctrl, int fd_uevent, const char *cgroup) {
_cleanup_(manager_freep) Manager *manager = NULL;
+ int r;
+
+ r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
+ if (r < 0) {
+ r = log_error_errno(r, "failed to allocate manager object: %m");
+ goto exit;
+ }
+
+ r = udev_rules_apply_static_dev_perms(manager->rules);
+ if (r < 0)
+ log_error_errno(r, "failed to apply permissions on static device nodes: %m");
+
+ (void) sd_notify(false,
+ "READY=1\n"
+ "STATUS=Processing...");
+
+ r = sd_event_loop(manager->event);
+ if (r < 0) {
+ log_error_errno(r, "event loop failed: %m");
+ goto exit;
+ }
+
+ sd_event_get_exit_code(manager->event, &r);
+
+exit:
+ sd_notify(false,
+ "STOPPING=1\n"
+ "STATUS=Shutting down...");
+ if (manager)
+ udev_ctrl_cleanup(manager->ctrl);
+ return r;
+}
+
+int main(int argc, char *argv[]) {
_cleanup_free_ char *cgroup = NULL;
int r, fd_ctrl, fd_uevent;
@@ -1625,8 +1663,10 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_warning_errno(r, "failed to parse kernel command line, ignoring: %m");
- if (arg_debug)
+ if (arg_debug) {
+ log_set_target(LOG_TARGET_CONSOLE);
log_set_max_level(LOG_DEBUG);
+ }
if (getuid() != 0) {
r = log_error_errno(EPERM, "root privileges required");
@@ -1711,38 +1751,12 @@ int main(int argc, char *argv[]) {
setsid();
- write_string_file("/proc/self/oom_score_adj", "-1000");
- }
-
- r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup);
- if (r < 0) {
- r = log_error_errno(r, "failed to allocate manager object: %m");
- goto exit;
- }
-
- r = udev_rules_apply_static_dev_perms(manager->rules);
- if (r < 0)
- log_error_errno(r, "failed to apply permissions on static device nodes: %m");
-
- (void) sd_notify(false,
- "READY=1\n"
- "STATUS=Processing...");
-
- r = sd_event_loop(manager->event);
- if (r < 0) {
- log_error_errno(r, "event loop failed: %m");
- goto exit;
+ write_string_file("/proc/self/oom_score_adj", "-1000", 0);
}
- sd_event_get_exit_code(manager->event, &r);
+ r = run(fd_ctrl, fd_uevent, cgroup);
exit:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- if (manager)
- udev_ctrl_cleanup(manager->ctrl);
mac_selinux_finish();
log_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c
index 1c31769fde..e80a7771de 100644
--- a/src/user-sessions/user-sessions.c
+++ b/src/user-sessions/user-sessions.c
@@ -65,7 +65,7 @@ int main(int argc, char*argv[]) {
} else if (streq(argv[1], "stop")) {
int r;
- r = write_string_file_atomic("/run/nologin", "System is going down.");
+ r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
if (r < 0) {
log_error_errno(r, "Failed to create /run/nologin: %m");
return EXIT_FAILURE;
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index f7728dcfff..7bdc158ad7 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -56,7 +56,7 @@ static int disable_utf8(int fd) {
if (k < 0)
r = k;
- k = write_string_file("/sys/module/vt/parameters/default_utf8", "0");
+ k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0);
if (k < 0)
r = k;
@@ -89,7 +89,7 @@ static int enable_utf8(int fd) {
if (k < 0)
r = k;
- k = write_string_file("/sys/module/vt/parameters/default_utf8", "1");
+ k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0);
if (k < 0)
r = k;
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py
index 80bbe65bea..e43a3daeb3 100644
--- a/test/rule-syntax-check.py
+++ b/test/rule-syntax-check.py
@@ -35,7 +35,7 @@ else:
no_args_tests = re.compile('(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST)\s*(?:=|!)=\s*"([^"]*)"$')
args_tests = re.compile('(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$')
-no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$')
+no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$')
args_assign = re.compile('(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*"([^"]*)"$')
result = 0
diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
index af0493b9a8..721e53a4ee 100644
--- a/test/sysv-generator-test.py
+++ b/test/sysv-generator-test.py
@@ -190,6 +190,15 @@ class SysvGeneratorTest(unittest.TestCase):
self.assert_enabled('foo.service', ['multi-user', 'graphical'])
self.assertNotIn('Overwriting', err)
+ def test_simple_escaped(self):
+ '''simple service without dependencies, that requires escaping the name'''
+
+ self.add_sysv('foo+', {})
+ self.add_sysv('foo-admin', {})
+ err, results = self.run_generator()
+ self.assertEqual(set(results), {'foo-admin.service', 'foo\\x2b.service'})
+ self.assertNotIn('Overwriting', err)
+
def test_simple_enabled_some(self):
'''simple service without dependencies, enabled in some runlevels'''
@@ -276,6 +285,16 @@ class SysvGeneratorTest(unittest.TestCase):
'foo.service')
self.assertNotIn('Overwriting', err)
+ def test_provides_escaped(self):
+ '''a script that Provides: a name that requires escaping'''
+
+ self.add_sysv('foo', {'Provides': 'foo foo+'})
+ err, results = self.run_generator()
+ self.assertEqual(list(results), ['foo.service'])
+ self.assertEqual(os.readlink(os.path.join(self.out_dir, 'foo\\x2b.service')),
+ 'foo.service')
+ self.assertNotIn('Overwriting', err)
+
def test_same_provides_in_multiple_scripts(self):
'''multiple init.d scripts provide the same name'''
diff --git a/tmpfiles.d/systemd.conf.m4 b/tmpfiles.d/systemd.conf.m4
index b447b01f58..d9d51af929 100644
--- a/tmpfiles.d/systemd.conf.m4
+++ b/tmpfiles.d/systemd.conf.m4
@@ -35,7 +35,7 @@ z /var/log/journal 2755 root systemd-journal - -
z /var/log/journal/%m 2755 root systemd-journal - -
m4_ifdef(`HAVE_ACL',``
a+ /var/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x
-A+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
+a+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
'')m4_dnl
d /var/lib/systemd 0755 root root -
diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py
index e75bfffba1..5e61917d60 100644
--- a/tools/make-man-rules.py
+++ b/tools/make-man-rules.py
@@ -62,7 +62,7 @@ FOOTER = '''\
# Really, do not edit this file.
EXTRA_DIST += \\
- {files}
+ {dist_files}
'''
def man(page, number):
@@ -106,7 +106,7 @@ def create_rules(xml_files):
def mjoin(files):
return ' \\\n\t'.join(sorted(files) or '#')
-def make_makefile(rules, files):
+def make_makefile(rules, dist_files):
return HEADER + '\n'.join(
(CONDITIONAL if conditional else SECTION).format(
manpages=mjoin(set(rulegroup.values())),
@@ -119,9 +119,11 @@ def make_makefile(rules, files):
if k != v),
conditional=conditional)
for conditional,rulegroup in sorted(rules.items())
- ) + FOOTER.format(files=mjoin(sorted(files)))
+ ) + FOOTER.format(dist_files=mjoin(sorted(dist_files)))
if __name__ == '__main__':
rules = create_rules(sys.argv[1:])
- files = (xml(file) for file in sys.argv[1:])
- print(make_makefile(rules, files), end='')
+ dist_files = (xml(file) for file in sys.argv[1:]
+ if not file.endswith(".directives.xml") and
+ not file.endswith(".index.xml"))
+ print(make_makefile(rules, dist_files), end='')
diff --git a/units/emergency.service.in b/units/emergency.service.in
index 52b9b1cd03..8dc3cbdede 100644
--- a/units/emergency.service.in
+++ b/units/emergency.service.in
@@ -16,7 +16,7 @@ Before=shutdown.target
[Service]
Environment=HOME=/root
WorkingDirectory=/root
-ExecStartPre=-/bin/plymouth quit
+ExecStartPre=-/bin/plymouth --wait quit
ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\ntry again to boot into default mode.'
ExecStart=-/bin/sh -c "@SULOGIN@; @SYSTEMCTL@ --job-mode=fail --no-block default"
Type=idle
diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in
index 19c33959d6..fb1f383cdc 100644
--- a/units/systemd-machined.service.in
+++ b/units/systemd-machined.service.in
@@ -15,7 +15,7 @@ After=machine.slice
[Service]
ExecStart=@rootlibexecdir@/systemd-machined
BusName=org.freedesktop.machine1
-CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE
+CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID
WatchdogSec=1min
# Note that machined cannot be placed in a mount namespace, since it
diff --git a/units/systemd-networkd.service.m4.in b/units/systemd-networkd.service.m4.in
index 64d9130c24..35be713ade 100644
--- a/units/systemd-networkd.service.m4.in
+++ b/units/systemd-networkd.service.m4.in
@@ -12,7 +12,7 @@ ConditionCapability=CAP_NET_ADMIN
DefaultDependencies=no
# dbus.service can be dropped once on kdbus, and systemd-udevd.service can be
# dropped once tuntap is moved to netlink
-After=systemd-udevd.service dbus.service network-pre.target systemd-sysusers.service
+After=systemd-udevd.service dbus.service network-pre.target systemd-sysusers.service systemd-sysctl.service
Before=network.target multi-user.target shutdown.target
Conflicts=shutdown.target
Wants=network.target