]> git.proxmox.com Git - systemd.git/commitdiff
New upstream version 234
authorMichael Biebl <biebl@debian.org>
Wed, 12 Jul 2017 19:26:31 +0000 (21:26 +0200)
committerMichael Biebl <biebl@debian.org>
Wed, 12 Jul 2017 19:26:31 +0000 (21:26 +0200)
644 files changed:
.dir-locals.el
.github/CONTRIBUTING.md
.github/ISSUE_TEMPLATE.md
.gitignore
.mailmap
.mkosi/mkosi.arch
.mkosi/mkosi.debian
.mkosi/mkosi.fedora
HACKING
Makefile-man.am
Makefile.am
NEWS
README
README.md
TODO
catalog/meson.build [new file with mode: 0644]
configure.ac
docs/sysvinit/meson.build [new file with mode: 0644]
docs/var-log/meson.build [new file with mode: 0644]
hwdb/20-OUI.hwdb
hwdb/20-acpi-vendor.hwdb
hwdb/20-pci-vendor-model.hwdb
hwdb/20-usb-vendor-model.hwdb
hwdb/60-evdev.hwdb
hwdb/60-keyboard.hwdb
hwdb/60-sensor.hwdb
hwdb/70-joystick.hwdb [new file with mode: 0644]
hwdb/70-mouse.hwdb
hwdb/70-pointingstick.hwdb
hwdb/70-touchpad.hwdb
hwdb/acpi-update.py
hwdb/meson.build [new file with mode: 0644]
hwdb/parse_hwdb.py
man/90-rearrange-path.py
man/custom-entities.ent.in [new file with mode: 0644]
man/environment.d.xml
man/journalctl.xml
man/kernel-command-line.xml
man/less-variables.xml
man/locale.conf.xml
man/logind.conf.xml
man/machinectl.xml
man/meson.build [new file with mode: 0644]
man/networkctl.xml
man/nss-resolve.xml
man/nss-systemd.xml
man/pam_systemd.xml
man/resolved.conf.xml
man/rules/meson.build [new file with mode: 0644]
man/sd_bus_add_match.xml
man/sd_bus_error.xml
man/sd_bus_message_append.xml
man/sd_get_seats.xml
man/sd_id128_randomize.xml
man/sd_journal_get_catalog.xml
man/sd_journal_get_fd.xml
man/sd_login_monitor_new.xml
man/sd_notify.xml
man/sd_pid_get_session.xml
man/sd_seat_get_active.xml
man/sd_session_is_active.xml
man/systemctl.xml
man/systemd-ask-password.xml
man/systemd-coredump.xml
man/systemd-delta.xml
man/systemd-environment-d-generator.xml
man/systemd-fstab-generator.xml
man/systemd-hibernate-resume-generator.xml
man/systemd-hibernate-resume@.service.xml
man/systemd-mount.xml
man/systemd-nspawn.xml
man/systemd-resolve.xml
man/systemd-timesyncd.service.xml
man/systemd-vconsole-setup.service.xml
man/systemd.environment-generator.xml
man/systemd.exec.xml
man/systemd.journal-fields.xml
man/systemd.link.xml
man/systemd.mount.xml
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.service.xml
man/systemd.special.xml
man/systemd.target.xml
man/systemd.time.xml
man/systemd.timer.xml
man/systemd.unit.xml
man/sysusers.d.xml
man/udevadm.xml
man/vconsole.conf.xml
meson.build [new file with mode: 0644]
meson_options.txt [new file with mode: 0644]
mkosi.build
network/meson.build [new file with mode: 0644]
po/LINGUAS
po/cs.po
po/meson.build [new file with mode: 0644]
po/pt_BR.po
po/sk.po [new file with mode: 0644]
po/sv.po
rules/.gitignore
rules/50-udev-default.rules [deleted file]
rules/50-udev-default.rules.in [new file with mode: 0644]
rules/60-block.rules
rules/60-cdrom_id.rules
rules/60-evdev.rules
rules/60-input-id.rules [new file with mode: 0644]
rules/60-persistent-input.rules
rules/60-persistent-storage.rules
rules/60-sensor.rules
rules/70-joystick.rules [new file with mode: 0644]
rules/meson.build [new file with mode: 0644]
shell-completion/bash/meson.build [new file with mode: 0644]
shell-completion/bash/networkctl
shell-completion/bash/systemctl.in
shell-completion/zsh/_networkctl
shell-completion/zsh/_sd_outputmodes
shell-completion/zsh/_systemctl.in
shell-completion/zsh/meson.build [new file with mode: 0644]
src/analyze/analyze.c
src/analyze/meson.build [new file with mode: 0644]
src/basic/af-to-name.awk [new file with mode: 0644]
src/basic/architecture.c
src/basic/architecture.h
src/basic/arphrd-to-name.awk [new file with mode: 0644]
src/basic/blkid-util.h
src/basic/build.h
src/basic/calendarspec.c
src/basic/cap-to-name.awk [new file with mode: 0644]
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/basic/def.h
src/basic/dirent-util.c
src/basic/dirent-util.h
src/basic/env-util.c
src/basic/errno-to-name.awk [new file with mode: 0644]
src/basic/escape.c
src/basic/escape.h
src/basic/extract-word.c
src/basic/extract-word.h
src/basic/fileio-label.c
src/basic/fileio-label.h
src/basic/fileio.c
src/basic/fileio.h
src/basic/format-util.h
src/basic/generate-af-list.sh [new file with mode: 0755]
src/basic/generate-arphrd-list.sh [new file with mode: 0755]
src/basic/generate-cap-list.sh [new file with mode: 0755]
src/basic/generate-errno-list.sh [new file with mode: 0755]
src/basic/generate-gperfs.py [new file with mode: 0755]
src/basic/glob-util.c
src/basic/glob-util.h
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/journal-importer.c
src/basic/log.c
src/basic/log.h
src/basic/macro.h
src/basic/meson.build [new file with mode: 0644]
src/basic/missing.h
src/basic/missing_syscall.h
src/basic/mount-util.c
src/basic/mount-util.h
src/basic/parse-util.c
src/basic/parse-util.h
src/basic/path-util.c
src/basic/path-util.h
src/basic/process-util.c
src/basic/process-util.h
src/basic/random-util.c
src/basic/random-util.h
src/basic/rm-rf.c
src/basic/selinux-util.c
src/basic/selinux-util.h
src/basic/socket-util.c
src/basic/stat-util.c
src/basic/stat-util.h
src/basic/strv.c
src/basic/strxcpyx.c
src/basic/time-util.c
src/basic/time-util.h
src/basic/unit-name.c
src/basic/unit-name.h
src/basic/util.c
src/basic/virt.c
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/measure.c
src/boot/efi/measure.h
src/boot/efi/meson.build [new file with mode: 0644]
src/boot/efi/no-undefined-symbols.sh [new file with mode: 0755]
src/boot/efi/pe.c [new file with mode: 0644]
src/boot/efi/pe.h [new file with mode: 0644]
src/boot/efi/pefile.c [deleted file]
src/boot/efi/pefile.h [deleted file]
src/boot/efi/shim.c [new file with mode: 0644]
src/boot/efi/shim.h [new file with mode: 0644]
src/boot/efi/stub.c
src/busctl/busctl-introspect.c [new file with mode: 0644]
src/busctl/busctl-introspect.h [new file with mode: 0644]
src/busctl/busctl.c [new file with mode: 0644]
src/cgtop/cgtop.c
src/core/audit-fd.c
src/core/automount.c
src/core/busname.c
src/core/cgroup.c
src/core/dbus-cgroup.c
src/core/dbus-execute.c
src/core/dbus-service.c
src/core/dbus-timer.c
src/core/dbus-unit.c
src/core/dbus.c
src/core/device.c
src/core/execute.c
src/core/execute.h
src/core/ima-setup.c
src/core/job.c
src/core/job.h
src/core/load-dropin.c
src/core/load-fragment-gperf-nulstr.awk [new file with mode: 0644]
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/loopback-setup.c
src/core/main.c
src/core/manager.c
src/core/meson.build [new file with mode: 0644]
src/core/mount.c
src/core/namespace.c
src/core/selinux-access.c
src/core/service.c
src/core/service.h
src/core/shutdown.c
src/core/smack-setup.c
src/core/socket.c
src/core/swap.c
src/core/target.c
src/core/timer.c
src/core/timer.h
src/core/transaction.c
src/core/umount.c
src/core/unit.c
src/core/unit.h
src/coredump/coredump.c
src/coredump/meson.build [new file with mode: 0644]
src/cryptsetup/cryptsetup.c
src/delta/delta.c
src/environment-d-generator/environment-d-generator.c
src/firstboot/firstboot.c
src/fstab-generator/fstab-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/hostname/meson.build [new file with mode: 0644]
src/hwdb/hwdb.c
src/import/import-raw.c
src/import/import-tar.c
src/import/meson.build [new file with mode: 0644]
src/import/pull-common.c
src/import/pull-job.c
src/import/pull-job.h
src/import/pull-raw.c
src/import/pull-tar.c
src/journal-remote/journal-remote-parse.c
src/journal-remote/journal-remote.c
src/journal-remote/journal-upload-journal.c
src/journal-remote/journal-upload.c
src/journal-remote/log-generator.py
src/journal-remote/meson.build [new file with mode: 0644]
src/journal-remote/microhttpd-util.c
src/journal-remote/microhttpd-util.h
src/journal/audit_type-to-name.awk [new file with mode: 0644]
src/journal/fsprg.c
src/journal/generate-audit_type-list.sh [new file with mode: 0755]
src/journal/journal-file.c
src/journal/journal-file.h
src/journal/journal-qrcode.c
src/journal/journal-verify.c
src/journal/journalctl.c
src/journal/journald-console.c
src/journal/journald-native.c
src/journal/journald-server.c
src/journal/journald-server.h
src/journal/journald-stream.c
src/journal/journald-syslog.c
src/journal/meson.build [new file with mode: 0644]
src/journal/mmap-cache.c
src/journal/mmap-cache.h
src/journal/sd-journal.c
src/journal/test-compress-benchmark.c
src/journal/test-compress.c
src/journal/test-mmap-cache.c
src/kernel-install/50-depmod.install
src/kernel-install/90-loaderentry.install
src/kernel-install/kernel-install
src/kernel-install/meson.build [new file with mode: 0644]
src/libsystemd-network/dhcp-lease-internal.h
src/libsystemd-network/icmp6-util.c
src/libsystemd-network/icmp6-util.h
src/libsystemd-network/lldp-neighbor.c
src/libsystemd-network/meson.build [new file with mode: 0644]
src/libsystemd-network/ndisc-internal.h
src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
src/libsystemd-network/radv-internal.h [new file with mode: 0644]
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp-lease.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd-network/sd-ipv4ll.c
src/libsystemd-network/sd-lldp.c
src/libsystemd-network/sd-ndisc.c
src/libsystemd-network/sd-radv.c [new file with mode: 0644]
src/libsystemd-network/test-dhcp-server.c
src/libsystemd-network/test-ipv4ll.c
src/libsystemd-network/test-ndisc-ra.c [new file with mode: 0644]
src/libsystemd-network/test-ndisc-rs.c
src/libsystemd-network/test-sd-dhcp-lease.c [new file with mode: 0644]
src/libsystemd/libsystemd.sym
src/libsystemd/meson.build [new file with mode: 0644]
src/libsystemd/sd-bus/DIFFERENCES [deleted file]
src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
src/libsystemd/sd-bus/PORTING-DBUS1 [deleted file]
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-convenience.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-kernel.c
src/libsystemd/sd-bus/bus-message.c
src/libsystemd/sd-bus/bus-message.h
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-bus/busctl-introspect.c [deleted file]
src/libsystemd/sd-bus/busctl-introspect.h [deleted file]
src/libsystemd/sd-bus/busctl.c [deleted file]
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-objects.c
src/libsystemd/sd-bus/test-bus-track.c
src/libsystemd/sd-bus/test-bus-vtable-cc.cc [new symlink]
src/libsystemd/sd-bus/test-bus-vtable.c [new file with mode: 0644]
src/libsystemd/sd-device/device-enumerator.c
src/libsystemd/sd-device/device-private.c
src/libsystemd/sd-device/sd-device.c
src/libsystemd/sd-event/test-event.c
src/libsystemd/sd-id128/sd-id128.c
src/libsystemd/sd-login/sd-login.c
src/libsystemd/sd-login/test-login.c
src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h
src/libsystemd/sd-netlink/netlink-util.c
src/libsystemd/sd-netlink/netlink-util.h
src/libsystemd/sd-netlink/rtnl-message.c
src/libudev/libudev-monitor.c
src/libudev/libudev.c
src/libudev/libudev.pc.in
src/libudev/meson.build [new file with mode: 0644]
src/locale/keymap-util.c
src/locale/localed.c
src/locale/meson.build [new file with mode: 0644]
src/login/70-power-switch.rules
src/login/loginctl.c
src/login/logind-button.c
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-inhibit.c
src/login/logind-session-dbus.c
src/login/logind-session-device.c
src/login/logind-session-device.h
src/login/logind-session.c
src/login/logind-session.h
src/login/logind.c
src/login/meson.build [new file with mode: 0644]
src/machine/image-dbus.c
src/machine/machinectl.c
src/machine/meson.build [new file with mode: 0644]
src/machine/operation.c
src/mount/mount-tool.c
src/network/meson.build [new file with mode: 0644]
src/network/netdev/bridge.c
src/network/netdev/geneve.c [new file with mode: 0644]
src/network/netdev/geneve.h [new file with mode: 0644]
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/vlan.c
src/network/netdev/vlan.h
src/network/netdev/vxlan.c
src/network/netdev/vxlan.h
src/network/networkctl.c
src/network/networkd-address-label.c [new file with mode: 0644]
src/network/networkd-address-label.h [new file with mode: 0644]
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-conf.c
src/network/networkd-dhcp4.c
src/network/networkd-ipv4ll.c
src/network/networkd-ipv6-proxy-ndp.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c
src/network/networkd-ndisc.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-radv.c [new file with mode: 0644]
src/network/networkd-radv.h [new file with mode: 0644]
src/network/networkd-route.c
src/network/networkd-route.h
src/nspawn/meson.build [new file with mode: 0644]
src/nspawn/nspawn-cgroup.c
src/nspawn/nspawn-mount.c
src/nspawn/nspawn-network.c
src/nspawn/nspawn-register.c
src/nspawn/nspawn-register.h
src/nspawn/nspawn-stub-pid1.c
src/nspawn/nspawn.c
src/nss-resolve/nss-resolve.c
src/rc-local-generator/rc-local-generator.c
src/resolve/dns_type-to-name.awk [new file with mode: 0644]
src/resolve/generate-dns_type-gperf.py [new file with mode: 0755]
src/resolve/generate-dns_type-list.sed [new file with mode: 0644]
src/resolve/meson.build [new file with mode: 0644]
src/resolve/resolve-tool.c
src/resolve/resolved-bus.c
src/resolve/resolved-conf.c
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-question.c
src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-trust-anchor.c
src/resolve/resolved-gperf.gperf
src/resolve/resolved-link.c
src/resolve/resolved-llmnr.c
src/resolve/resolved-manager.c
src/resolve/resolved-mdns.c
src/resolve/resolved.conf.in
src/resolve/test-dnssec-complex.c
src/resolve/test-resolved-packet.c [new file with mode: 0644]
src/shared/base-filesystem.c
src/shared/bus-unit-util.c
src/shared/bus-util.c
src/shared/cgroup-show.c
src/shared/cgroup-show.h
src/shared/condition.c
src/shared/condition.h
src/shared/conf-parser.c
src/shared/conf-parser.h
src/shared/dissect-image.c
src/shared/dns-domain.c
src/shared/dns-domain.h
src/shared/efivars.c
src/shared/fstab-util.c
src/shared/fstab-util.h
src/shared/generator.c
src/shared/generator.h
src/shared/install.c
src/shared/linux-3.13/dm-ioctl.h [new file with mode: 0644]
src/shared/logs-show.c
src/shared/meson.build [new file with mode: 0644]
src/shared/output-mode.c
src/shared/output-mode.h
src/shared/pager.c
src/shared/seccomp-util.c
src/shared/seccomp-util.h
src/shared/sleep-config.c
src/shared/udev-util.c [new file with mode: 0644]
src/shared/udev-util.h
src/shared/vlan-util.c
src/shared/vlan-util.h
src/stdio-bridge/stdio-bridge.c
src/sulogin-shell/.gitignore [new file with mode: 0644]
src/sulogin-shell/meson.build [new file with mode: 0644]
src/sulogin-shell/systemd-sulogin-shell.in [new file with mode: 0755]
src/systemctl/systemctl.c
src/systemd/_sd-common.h
src/systemd/meson.build [new file with mode: 0644]
src/systemd/sd-bus-vtable.h
src/systemd/sd-bus.h
src/systemd/sd-dhcp-client.h
src/systemd/sd-dhcp-lease.h
src/systemd/sd-event.h
src/systemd/sd-ipv4ll.h
src/systemd/sd-netlink.h
src/systemd/sd-radv.h [new file with mode: 0644]
src/sysusers/sysusers.c
src/sysv-generator/sysv-generator.c
src/test/generate-sym-test.py [new file with mode: 0755]
src/test/meson.build [new file with mode: 0644]
src/test/test-af-list.c
src/test/test-calendarspec.c
src/test/test-condition.c
src/test/test-conf-parser.c
src/test/test-date.c
src/test/test-dlopen.c [new file with mode: 0644]
src/test/test-dns-domain.c
src/test/test-env-util.c
src/test/test-escape.c
src/test/test-exec-util.c
src/test/test-execute.c
src/test/test-fs-util.c
src/test/test-glob-util.c
src/test/test-hash.c
src/test/test-hashmap-ordered.awk [new file with mode: 0644]
src/test/test-id128.c
src/test/test-libudev.c
src/test/test-log.c
src/test/test-loopback.c
src/test/test-nss.c
src/test/test-parse-util.c
src/test/test-path-util.c
src/test/test-random-util.c [new file with mode: 0644]
src/test/test-seccomp.c
src/test/test-selinux.c
src/test/test-sigbus.c
src/test/test-sizeof.c
src/test/test-stat-util.c
src/test/test-strxcpyx.c
src/test/test-time.c
src/test/test-udev.c
src/test/test-unit-file.c
src/timedate/meson.build [new file with mode: 0644]
src/timesync/meson.build [new file with mode: 0644]
src/timesync/test-timesync.c [new file with mode: 0644]
src/timesync/timesyncd-conf.c
src/timesync/timesyncd-conf.h
src/timesync/timesyncd-manager.c
src/timesync/timesyncd-manager.h
src/timesync/timesyncd.c
src/tmpfiles/tmpfiles.c
src/udev/ata_id/ata_id.c
src/udev/cdrom_id/cdrom_id.c
src/udev/collect/collect.c
src/udev/generate-keyboard-keys-gperf.sh [new file with mode: 0755]
src/udev/generate-keyboard-keys-list.sh [new file with mode: 0755]
src/udev/meson.build [new file with mode: 0644]
src/udev/net/ethtool-util.c
src/udev/net/ethtool-util.h
src/udev/net/link-config-gperf.gperf
src/udev/net/link-config.c
src/udev/net/link-config.h
src/udev/scsi_id/scsi_id.c
src/udev/udev-builtin-blkid.c
src/udev/udev-builtin-input_id.c
src/udev/udev-builtin-keyboard.c
src/udev/udev-builtin-net_id.c
src/udev/udev-ctrl.c
src/udev/udev-event.c
src/udev/udev-rules.c
src/udev/udev.pc.in
src/udev/udevadm-hwdb.c
src/udev/udevadm-info.c
src/udev/udevadm-monitor.c
src/udev/udevadm-test.c
src/udev/udevadm.c
src/udev/udevd.c
src/update-done/update-done.c
src/vconsole/meson.build [new file with mode: 0644]
src/vconsole/vconsole-setup.c
sysctl.d/meson.build [new file with mode: 0644]
system-preset/90-systemd.preset
sysusers.d/basic.conf.in
sysusers.d/meson.build [new file with mode: 0644]
test/README.testsuite
test/TEST-12-ISSUE-3171/test.sh
test/create-sys-script.py
test/meson.build [new file with mode: 0644]
test/networkd-test.py
test/rule-syntax-check.py
test/sys-script.py
test/sysv-generator-test.py
test/test-efi-create-disk.sh
test/test-exec-deserialization.py [new file with mode: 0755]
test/test-execute/exec-inaccessiblepaths-mount-propagation.service
test/test-execute/exec-inaccessiblepaths-proc.service [new file with mode: 0644]
test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service
test/test-execute/exec-readonlypaths-mount-propagation.service
test/test-execute/exec-readwritepaths-mount-propagation.service
test/test-functions
tmpfiles.d/.gitignore
tmpfiles.d/meson.build [new file with mode: 0644]
tmpfiles.d/systemd-remote.conf [deleted file]
tmpfiles.d/systemd-remote.conf.m4 [new file with mode: 0644]
tmpfiles.d/var.conf [deleted file]
tmpfiles.d/var.conf.m4 [new file with mode: 0644]
tools/catalog-report.py [changed mode: 0644->0755]
tools/gdb-sd_dump_hashmaps.py
tools/make-directive-index.py
tools/make-man-index.py
tools/make-man-rules.py [changed mode: 0644->0755]
tools/meson-check-compilation.sh [new file with mode: 0755]
tools/meson-check-help.sh [new file with mode: 0755]
tools/meson-git-contrib.sh [new file with mode: 0755]
tools/meson-hwdb-update.sh [new file with mode: 0755]
tools/meson-link-test.c [new file with mode: 0644]
tools/meson-make-symlink.sh [new file with mode: 0755]
tools/xml_helper.py [changed mode: 0644->0755]
units/console-getty.service.m4.in
units/container-getty@.service.m4.in
units/dev-hugepages.mount
units/dev-mqueue.mount
units/emergency.service.in
units/getty@.service.m4
units/meson-add-wants.sh [new file with mode: 0755]
units/meson.build [new file with mode: 0644]
units/network-online.target
units/network-pre.target
units/network.target
units/org.freedesktop.hostname1.busname
units/org.freedesktop.locale1.busname
units/org.freedesktop.login1.busname
units/org.freedesktop.machine1.busname
units/org.freedesktop.resolve1.busname
units/org.freedesktop.systemd1.busname
units/org.freedesktop.timedate1.busname
units/proc-sys-fs-binfmt_misc.automount
units/proc-sys-fs-binfmt_misc.mount
units/quotaon.service.in
units/rescue.service.in
units/serial-getty@.service.m4
units/sys-fs-fuse-connections.mount
units/sys-kernel-config.mount
units/sys-kernel-debug.mount
units/syslog.socket
units/systemd-ask-password-console.service.in
units/systemd-ask-password-wall.service.in
units/systemd-coredump@.service.in
units/systemd-hostnamed.service.in
units/systemd-importd.service.in
units/systemd-initctl.service.in
units/systemd-journal-gatewayd.service.in
units/systemd-journal-remote.service.in
units/systemd-journal-upload.service.in
units/systemd-journald.service.in
units/systemd-localed.service.in
units/systemd-logind.service.in
units/systemd-machined.service.in
units/systemd-networkd-wait-online.service.in
units/systemd-networkd.service.m4.in
units/systemd-nspawn@.service.in
units/systemd-quotacheck.service.in
units/systemd-remount-fs.service.in
units/systemd-resolved.service.m4.in
units/systemd-timedated.service.in
units/systemd-timesyncd.service.in
units/systemd-udevd.service.in
units/tmp.mount.m4
units/user/meson.build [new file with mode: 0644]

index 3e1b2d76c070c5f36504eae6fd5d37c815ef6cdd..5ef7e11634cd942602ba45b97e7e86a9e62d070e 100644 (file)
@@ -20,4 +20,8 @@
             (eval . (c-set-offset 'arglist-intro '++))
             (eval . (c-set-offset 'arglist-close 0))))
  (nxml-mode . ((nxml-child-indent . 2)
-               (fill-column . 119))))
+               (fill-column . 119)))
+ (meson-mode . ((meson-indent-basic . 8)))
+ (sh-mode . ((sh-basic-offset . 8)
+             (sh-indentation . 8)))
+ (awk-mode . ((c-basic-offset . 8))))
index abee9cc740a96aa73bc56c866403e057df1b1e34..f2ed0d9f64f5cea7635801ca142bdf338f68f639 100644 (file)
@@ -4,13 +4,23 @@ We welcome contributions from everyone. However, please follow the following gui
 
 ## Filing Issues
 
-* We use GitHub Issues **exclusively** for tracking **bugs** and **feature** **requests** of systemd. If you are looking for help, please contact our [mailing list](http://lists.freedesktop.org/mailman/listinfo/systemd-devel) instead.
+* We use GitHub Issues **exclusively** for tracking **bugs** and **feature** **requests** of systemd. If you are looking for help, please contact our [mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) instead.
 * We only track bugs in the **two** **most** **recently** **released** **versions** of systemd in the GitHub Issue tracker. If you are using an older version of systemd, please contact your distribution's bug tracker instead.
 * When filing an issue, specify the **systemd** **version** you are experiencing the issue with. Also, indicate which **distribution** you are using.
 * Please include an explanation how to reproduce the issue you are pointing out.
 
 Following these guidelines makes it easier for us to process your issue, and ensures we won't close your issue right-away for being misfiled.
 
+### Older downstream versions
+For older versions that are still supported by your distribution please use respective downstream tracker:
+* **Fedora** - [bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=systemd)
+* **RHEL-7/CentOS-7** - [bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=Red%20Hat%20Enterprise%20Linux%207&component=systemd) or [systemd-rhel github](https://github.com/lnykryn/systemd-rhel/issues)
+* **Debian** - [bugs.debian.org](https://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=systemd)
+
+## Security vulnerability reports
+
+If you discover a security vulnerability, we'd appreciate a non-public disclosure. The issue tracker and mailing list listed above are fully public. If you need to reach systemd developers in a non-public way, report the issue in one of the "big" distributions using systemd: [Fedora](https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=systemd) (be sure to check "Security Sensitive Bug" under "Show Advanced Fields"), [Ubuntu](https://launchpad.net/ubuntu/+source/systemd/+filebug) (be sure to change "This bug contains information that is" from "Public" to "Private Security"), or [Debian](mailto:security@debian.org). Various systemd developers are active distribution maintainers and will propagate the information about the bug to other parties.
+
 ## Posting Pull Requests
 
 * Make sure to post PRs only relative to a very recent git master.
index 750f9e774d94c449e9efc27e0cb28b930863f356..687270eaae3b73536b75fda1b85ce34b00b5d2f5 100644 (file)
@@ -1,15 +1,18 @@
 ### Submission type
 
-  - [ ] Bug report
-  - [ ] Request for enhancement (RFE)
+<!-- Delete the inappropriate option below: -->
 
-*NOTE: Do not submit anything other than bug reports or RFEs via the issue tracker!*
+ - Bug report
+ - Request for enhancement (RFE)
+
+<!-- **NOTE:** Do not submit anything other than bug reports or RFEs via the issue tracker! -->
 
 ### systemd version the issue has been seen with
 
 > …
 
-*NOTE: Do not submit bug reports about anything but the two most recently released systemd versions upstream!*
+<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released systemd versions upstream! -->
+<!-- For older version please use distribution trackers (see https://github.com/systemd/systemd/blob/master/.github/CONTRIBUTING.md#filing-issues). -->
 
 ### Used distribution
 
index 01cb6e7db7ef6c0890cc558260be477d6161180b..8c4331e54f4d3e0435ea30d5644e825ae727c75a 100644 (file)
@@ -28,7 +28,7 @@
 /TAGS
 /ata_id
 /bootctl
-/build-aux
+/build*
 /busctl
 /cdrom_id
 /collect
 /test-bus-server
 /test-bus-signature
 /test-bus-track
+/test-bus-vtable
+/test-bus-vtable-cc
 /test-bus-zero-copy
 /test-calendarspec
 /test-cap-list
 /test-process-util
 /test-pty
 /test-qcow2
+/test-random-util
 /test-ratelimit
 /test-replace-var
 /test-resolve
 /test-resolve-tables
+/test-resolved-packet
 /test-ring
 /test-rlimit-util
 /test-sched-prio
+/test-sd-dhcp-lease
 /test-seccomp
 /test-selinux
 /test-set
 /test-tables
 /test-terminal-util
 /test-time
+/test-timesync
 /test-tmpfiles
 /test-udev
 /test-uid-range
index d46c166cf9192e6868db60cf73e45505d0f1cfe2..e2a390bbea7f199aea362d6c042c3376f964efe3 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -102,3 +102,24 @@ Paolo Giangrandi <paolo@luccalug.it>
 Karl Kraus <karl.kraus@tum.de> <laqueray@gmail.com>
 Tibor Nagy <xnagytibor@gmail.com>
 Stuart McLaren <stuart.mclaren@hp.com>
+John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> <glaubitz@suse.com>
+Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+Neil Brown <neil@brown.name>
+Michal Suchanek <msuchanek@suse.de> <hramrach@gmail.com>
+Michal Suchanek <msuchanek@suse.de>
+Bastien Nocera <hadess@hadess.net> <hadess@users.noreply.github.com>
+Umut Tezduyar Lindskog <umut@tezduyar.com>
+Alexander Kurtz <alexander@kurtz.be>
+Piotr Szydełko <wiertel@users.sourceforge.net>
+Łukasz Stelmach <l.stelmach@samsung.com> <stlman@poczta.fm>
+Krzysztof Jackiewicz <k.jackiewicz@samsung.com> <kjackiewicz@users.noreply.github.com>
+Marcus Cooper <marcusc@axis.com> <codekipper@gmail.com>
+Insun Pyo <insun.pyo@samsung.com> <iplayinsun@gmail.com>
+Ted Wood <ted.l.wood@gmail.com>
+Ted Wood <ted@mailchimp.com>
+Anthony Parsons <flussence@users.noreply.github.com>
+Federico Di Pierro <nierro92@gmail.com>
+Josef Andersson <josef.andersson@fripost.org>
+Josef Andersson <l10nl18nsweja@gmail.com>
+Hendrik Westerberg <hendrik@gestorf.com>
index 4c44f288aeca6c54f7f112cd9f9f5f5865d9f644..613ef4746f83f17380cba3bbadf2073ef8dcdf24 100644 (file)
@@ -32,8 +32,6 @@ RootSize=2G
 Cache=/var/cache/pacman/pkg/
 BuildPackages=
         acl
-        autoconf
-        automake
         bzip2
         cryptsetup
         curl
@@ -50,7 +48,7 @@ BuildPackages=
         kmod
         libcap
         libgcrypt
-        libidn
+        libidn2
         libmicrohttpd
         libseccomp
         libtool
@@ -58,10 +56,13 @@ BuildPackages=
         libxkbcommon
         libxslt
         lz4
-        make
+        meson
         pam
         pkgconfig
         python
         python-lxml
         qrencode
         xz
+
+Packages=
+        libidn2
index a68d9dfa116c0139434fb6f26ad6b7e9b587f718..c41fc1d4197ca1cca17feef1490c0f4b2acd5e98 100644 (file)
@@ -32,9 +32,6 @@ RootSize=2G
 [Packages]
 BuildPackages=
         acl
-        autoconf
-        automake
-        diffutils
         docbook-xml
         docbook-xsl
         gcc
@@ -55,7 +52,7 @@ BuildPackages=
         libfdisk-dev
         libgcrypt20-dev
         libgnutls28-dev
-        libidn11-dev
+        libidn2-0-dev
         libkmod-dev
         liblzma-dev
         liblz4-dev
@@ -68,7 +65,7 @@ BuildPackages=
         libsmartcols-dev
         libtool
         libxkbcommon-dev
-        make
+        meson
         pkg-config
         python3
         python3-lxml
@@ -80,3 +77,4 @@ BuildPackages=
 Packages=
         libqrencode3
         locales
+        libidn2-0
index 1b8dd47ca4fb763b7852e8b8511ad29458f51462..c38ee7e6d3131a5adaa897fff63f85ffa2ba9d65 100644 (file)
@@ -20,7 +20,7 @@
 
 [Distribution]
 Distribution=fedora
-Release=25
+Release=26
 
 [Output]
 Format=raw_btrfs
@@ -32,8 +32,6 @@ RootSize=3G
 [Packages]
 BuildPackages=
         audit-libs-devel
-        autoconf
-        automake
         bzip2-devel
         cryptsetup-devel
         dbus-devel
@@ -54,7 +52,7 @@ BuildPackages=
         libcap-devel
         libcurl-devel
         libgcrypt-devel
-        libidn-devel
+        libidn2-devel
         libmicrohttpd-devel
         libmount-devel
         libseccomp-devel
@@ -62,8 +60,9 @@ BuildPackages=
         libtool
         libxkbcommon-devel
         libxslt
+        lz4
         lz4-devel
-        make
+        meson
         pam-devel
         pkgconfig
         python3-devel
@@ -71,3 +70,6 @@ BuildPackages=
         qrencode-devel
         tree
         xz-devel
+
+Packages=
+        libidn2
diff --git a/HACKING b/HACKING
index 0d1a93e2111b4069ea5f0e96f81e7f9497337860..193cff13f720ba8791aaf3145a19943c2540c7c7 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -30,7 +30,7 @@ systemd-nspawn or in an UEFI-capable VM:
 
 or:
 
-        # qemu-kvm -m 512 -smp 2 -bios /usr/share/edk2/ovmf/OVMF_CODE.fd -hda image.raw
+        # qemu-system-x86_64 -enable-kvm -m 512 -smp 2 -bios /usr/share/edk2/ovmf/OVMF_CODE.fd -hda image.raw
 
 Every time you rerun the "mkosi" command a fresh image is built, incorporating
 all current changes you made to the project tree.
index d5626411a530a9dafb1dfb00c6159602efd8fef8..d51236ed56d42ff8d544e6ed901476200caa62c4 100644 (file)
@@ -11,7 +11,6 @@ MANPAGES += \
        man/bootup.7 \
        man/busctl.1 \
        man/daemon.7 \
-       man/environment.d.5 \
        man/file-hierarchy.7 \
        man/halt.8 \
        man/hostname.5 \
@@ -24,7 +23,6 @@ MANPAGES += \
        man/localtime.5 \
        man/machine-id.5 \
        man/machine-info.5 \
-       man/nss-systemd.8 \
        man/os-release.5 \
        man/sd-bus-errors.3 \
        man/sd-bus.3 \
@@ -111,15 +109,12 @@ MANPAGES += \
        man/systemd-debug-generator.8 \
        man/systemd-delta.1 \
        man/systemd-detect-virt.1 \
-       man/systemd-environment-d-generator.8 \
        man/systemd-escape.1 \
        man/systemd-fsck@.service.8 \
        man/systemd-fstab-generator.8 \
        man/systemd-getty-generator.8 \
        man/systemd-gpt-auto-generator.8 \
        man/systemd-halt.service.8 \
-       man/systemd-hibernate-resume-generator.8 \
-       man/systemd-hibernate-resume@.service.8 \
        man/systemd-inhibit.1 \
        man/systemd-initctl.service.8 \
        man/systemd-journald.service.8 \
@@ -130,7 +125,6 @@ MANPAGES += \
        man/systemd-nspawn.1 \
        man/systemd-path.1 \
        man/systemd-remount-fs.service.8 \
-       man/systemd-resolve.1 \
        man/systemd-run.1 \
        man/systemd-sleep.conf.5 \
        man/systemd-socket-activate.1 \
@@ -148,7 +142,6 @@ MANPAGES += \
        man/systemd.1 \
        man/systemd.automount.5 \
        man/systemd.device.5 \
-       man/systemd.environment-generator.7 \
        man/systemd.exec.5 \
        man/systemd.generator.7 \
        man/systemd.journal-fields.7 \
@@ -187,7 +180,6 @@ MANPAGES += \
        man/udev_new.3 \
        man/udevadm.8
 MANPAGES_ALIAS += \
-       man/30-systemd-environment-d-generator.8 \
        man/SD_ALERT.3 \
        man/SD_BUS_ERROR_ACCESS_DENIED.3 \
        man/SD_BUS_ERROR_ADDRESS_IN_USE.3 \
@@ -266,7 +258,6 @@ MANPAGES_ALIAS += \
        man/SD_WARNING.3 \
        man/init.1 \
        man/journald.conf.d.5 \
-       man/libnss_systemd.so.2.8 \
        man/poweroff.8 \
        man/reboot.8 \
        man/sd_bus_creds_get_audit_login_uid.3 \
@@ -326,6 +317,7 @@ MANPAGES_ALIAS += \
        man/sd_bus_message_append_array_space.3 \
        man/sd_bus_message_append_string_iovec.3 \
        man/sd_bus_message_append_string_space.3 \
+       man/sd_bus_message_appendv.3 \
        man/sd_bus_message_get_realtime_usec.3 \
        man/sd_bus_message_get_reply_cookie.3 \
        man/sd_bus_message_get_seqnum.3 \
@@ -462,7 +454,6 @@ MANPAGES_ALIAS += \
        man/systemd-ask-password-wall.service.8 \
        man/systemd-fsck-root.service.8 \
        man/systemd-fsck.8 \
-       man/systemd-hibernate-resume.8 \
        man/systemd-hibernate.service.8 \
        man/systemd-hybrid-sleep.service.8 \
        man/systemd-initctl.8 \
@@ -546,7 +537,6 @@ MANPAGES_ALIAS += \
        man/udev_ref.3 \
        man/udev_unref.3 \
        man/user.conf.d.5
-man/30-systemd-environment-d-generator.8: man/systemd-environment-d-generator.8
 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
@@ -625,7 +615,6 @@ man/SD_NOTICE.3: man/sd-daemon.3
 man/SD_WARNING.3: man/sd-daemon.3
 man/init.1: man/systemd.1
 man/journald.conf.d.5: man/journald.conf.5
-man/libnss_systemd.so.2.8: man/nss-systemd.8
 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
@@ -685,6 +674,7 @@ 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
 man/sd_bus_message_append_string_iovec.3: man/sd_bus_message_append_string_memfd.3
 man/sd_bus_message_append_string_space.3: man/sd_bus_message_append_string_memfd.3
+man/sd_bus_message_appendv.3: man/sd_bus_message_append.3
 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
@@ -821,7 +811,6 @@ man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8
 man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8
 man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8
 man/systemd-fsck.8: man/systemd-fsck@.service.8
-man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8
 man/systemd-hibernate.service.8: man/systemd-suspend.service.8
 man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8
 man/systemd-initctl.8: man/systemd-initctl.service.8
@@ -905,9 +894,6 @@ man/udev_monitor_unref.3: man/udev_monitor_new_from_netlink.3
 man/udev_ref.3: man/udev_new.3
 man/udev_unref.3: man/udev_new.3
 man/user.conf.d.5: man/systemd-system.conf.5
-man/30-systemd-environment-d-generator.html: man/systemd-environment-d-generator.html
-       $(html-alias)
-
 man/SD_ALERT.html: man/sd-daemon.html
        $(html-alias)
 
@@ -1142,9 +1128,6 @@ man/init.html: man/systemd.html
 man/journald.conf.d.html: man/journald.conf.html
        $(html-alias)
 
-man/libnss_systemd.so.2.html: man/nss-systemd.html
-       $(html-alias)
-
 man/poweroff.html: man/halt.html
        $(html-alias)
 
@@ -1322,6 +1305,9 @@ man/sd_bus_message_append_string_iovec.html: man/sd_bus_message_append_string_me
 man/sd_bus_message_append_string_space.html: man/sd_bus_message_append_string_memfd.html
        $(html-alias)
 
+man/sd_bus_message_appendv.html: man/sd_bus_message_append.html
+       $(html-alias)
+
 man/sd_bus_message_get_realtime_usec.html: man/sd_bus_message_get_monotonic_usec.html
        $(html-alias)
 
@@ -1730,9 +1716,6 @@ man/systemd-fsck-root.service.html: man/systemd-fsck@.service.html
 man/systemd-fsck.html: man/systemd-fsck@.service.html
        $(html-alias)
 
-man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html
-       $(html-alias)
-
 man/systemd-hibernate.service.html: man/systemd-suspend.service.html
        $(html-alias)
 
@@ -2038,6 +2021,19 @@ MANPAGES_ALIAS += \
 
 endif
 
+if ENABLE_ENVIRONMENT_D
+MANPAGES += \
+       man/environment.d.5 \
+       man/systemd-environment-d-generator.8 \
+       man/systemd.environment-generator.7
+MANPAGES_ALIAS += \
+       man/30-systemd-environment-d-generator.8
+man/30-systemd-environment-d-generator.8: man/systemd-environment-d-generator.8
+man/30-systemd-environment-d-generator.html: man/systemd-environment-d-generator.html
+       $(html-alias)
+
+endif
+
 if ENABLE_FIRSTBOOT
 MANPAGES += \
        man/systemd-firstboot.1
@@ -2049,6 +2045,18 @@ man/systemd-firstboot.service.html: man/systemd-firstboot.html
 
 endif
 
+if ENABLE_HIBERNATE
+MANPAGES += \
+       man/systemd-hibernate-resume-generator.8 \
+       man/systemd-hibernate-resume@.service.8
+MANPAGES_ALIAS += \
+       man/systemd-hibernate-resume.8
+man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8
+man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html
+       $(html-alias)
+
+endif
+
 if ENABLE_HOSTNAMED
 MANPAGES += \
        man/hostnamectl.1 \
@@ -2156,6 +2164,17 @@ man/systemd-networkd.html: man/systemd-networkd.service.html
 
 endif
 
+if ENABLE_NSS_SYSTEMD
+MANPAGES += \
+       man/nss-systemd.8
+MANPAGES_ALIAS += \
+       man/libnss_systemd.so.2.8
+man/libnss_systemd.so.2.8: man/nss-systemd.8
+man/libnss_systemd.so.2.html: man/nss-systemd.html
+       $(html-alias)
+
+endif
+
 if ENABLE_QUOTACHECK
 MANPAGES += \
        man/systemd-quotacheck.service.8
@@ -2183,6 +2202,7 @@ MANPAGES += \
        man/dnssec-trust-anchors.d.5 \
        man/nss-resolve.8 \
        man/resolved.conf.5 \
+       man/systemd-resolve.1 \
        man/systemd-resolved.service.8
 MANPAGES_ALIAS += \
        man/libnss_resolve.so.2.8 \
index 2a5610740ee084308fbbc57ea1e8cce03e84b0c4..c16e62280be792167b1b891fd37b79b6b5174c58 100644 (file)
@@ -42,9 +42,9 @@ LIBUDEV_CURRENT=7
 LIBUDEV_REVISION=6
 LIBUDEV_AGE=6
 
-LIBSYSTEMD_CURRENT=18
+LIBSYSTEMD_CURRENT=19
 LIBSYSTEMD_REVISION=0
-LIBSYSTEMD_AGE=18
+LIBSYSTEMD_AGE=19
 
 # Dirs of external packages
 dbuspolicydir=@dbuspolicydir@
@@ -59,7 +59,7 @@ polkitrulesdir=$(datadir)/polkit-1/rules.d
 polkitpkladir=$(localstatedir)/lib/polkit-1/localauthority/10-vendor.d
 bashcompletiondir=@bashcompletiondir@
 zshcompletiondir=@zshcompletiondir@
-rpmmacrosdir=$(prefix)/lib/rpm/macros.d
+rpmmacrosdir=@rpmmacrosdir@
 sysvinitdir=$(SYSTEM_SYSVINIT_PATH)
 sysvrcnddir=$(SYSTEM_SYSVRCND_PATH)
 varlogdir=$(localstatedir)/log
@@ -178,6 +178,7 @@ CLEANFILES = $(BUILT_SOURCES) \
        $(pkgconfiglib_DATA) \
        $(nodist_bashcompletion_data) \
        $(nodist_zshcompletion_data) \
+       $(nodist_rpmmacros_DATA) \
        $(in_files:.in=) $(in_in_files:.in.in=) \
        $(m4_files:.m4=)
 
@@ -268,8 +269,10 @@ INSTALL_DIRS =
 
 SHUTDOWN_TARGET_WANTS =
 LOCAL_FS_TARGET_WANTS =
+REMOTE_FS_TARGET_WANTS =
 MULTI_USER_TARGET_WANTS =
 GRAPHICAL_TARGET_WANTS =
+MACHINES_TARGET_WANTS =
 RESCUE_TARGET_WANTS =
 SYSINIT_TARGET_WANTS =
 SOCKETS_TARGET_WANTS =
@@ -286,6 +289,8 @@ GENERAL_ALIASES =
 install-target-wants-hook:
        what="$(SHUTDOWN_TARGET_WANTS)" && wants=shutdown.target && dir=$(systemunitdir) && $(add-wants)
        what="$(LOCAL_FS_TARGET_WANTS)" && wants=local-fs.target && dir=$(systemunitdir) && $(add-wants)
+       what="$(REMOTE_FS_TARGET_WANTS)" && wants=remote-fs.target && dir=$(systemunitdir) && $(add-wants)
+       what="$(MACHINES_TARGET_WANTS)" && wants=machines.target && dir=$(systemunitdir) && $(add-wants)
        what="$(MULTI_USER_TARGET_WANTS)" && wants=multi-user.target && dir=$(systemunitdir) && $(add-wants)
        what="$(GRAPHICAL_TARGET_WANTS)" && wants=graphical.target && dir=$(systemunitdir) && $(add-wants)
        what="$(RESCUE_TARGET_WANTS)" && wants=rescue.target && dir=$(systemunitdir) && $(add-wants)
@@ -442,6 +447,12 @@ userenvgenerator_PROGRAMS = \
        30-systemd-environment-d-generator
 endif
 
+rootlibexec_SCRIPTS = \
+       src/sulogin-shell/systemd-sulogin-shell
+
+EXTRA_DIST += \
+       src/sulogin-shell/systemd-sulogin-shell.in
+
 dist_bashcompletion_data = \
        shell-completion/bash/busctl \
        shell-completion/bash/journalctl \
@@ -532,7 +543,6 @@ dist_systemunit_DATA = \
        units/sys-kernel-debug.mount \
        units/sys-fs-fuse-connections.mount \
        units/tmp.mount \
-       units/var-lib-machines.mount \
        units/printer.target \
        units/sound.target \
        units/bluetooth.target \
@@ -650,7 +660,7 @@ EXTRA_DIST += \
        units/initrd-switch-root.service.in \
        units/systemd-nspawn@.service.in \
        units/systemd-update-done.service.in \
-    units/tmp.mount.m4
+       units/tmp.mount.m4
 
 if HAVE_SYSV_COMPAT
 nodist_systemunit_DATA += \
@@ -677,8 +687,6 @@ dist_doc_DATA = \
        LICENSE.LGPL2.1 \
        LICENSE.GPL2 \
        DISTRO_PORTING \
-       src/libsystemd/sd-bus/PORTING-DBUS1 \
-       src/libsystemd/sd-bus/DIFFERENCES \
        src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
 
 EXTRA_DIST += \
@@ -744,9 +752,11 @@ man/index.html: man/systemd.index.html
        $(AM_V_LN)$(LN_S) -f systemd.index.html $@
 
 if HAVE_PYTHON
+if ENABLE_MANPAGES
 noinst_DATA += \
        man/index.html
 endif
+endif
 
 CLEANFILES += \
        man/index.html
@@ -1005,8 +1015,7 @@ libbasic_la_CFLAGS = \
 libbasic_la_LIBADD = \
        $(SELINUX_LIBS) \
        $(CAP_LIBS) \
-       -lrt \
-       -lm
+       -lrt
 
 # -----------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
@@ -1017,7 +1026,9 @@ libshared_la_SOURCES = \
        src/shared/output-mode.c \
        src/shared/gpt.h \
        src/shared/udev-util.h \
+       src/shared/udev-util.c \
        src/shared/linux/auto_dev-ioctl.h \
+       src/shared/linux-3.13/dm-ioctl.h \
        src/shared/initreq.h \
        src/shared/dns-domain.c \
        src/shared/dns-domain.h \
@@ -1130,6 +1141,7 @@ libshared_la_CFLAGS = \
        $(AM_CFLAGS) \
        $(ACL_CFLAGS) \
        $(LIBIDN_CFLAGS) \
+       $(LIBIDN2_CFLAGS) \
        $(SECCOMP_CFLAGS) \
        $(BLKID_CFLAGS) \
        $(LIBCRYPTSETUP_CFLAGS)
@@ -1141,6 +1153,7 @@ libshared_la_LIBADD = \
        libudev-internal.la \
        $(ACL_LIBS) \
        $(LIBIDN_LIBS) \
+       $(LIBIDN2_LIBS) \
        $(SECCOMP_LIBS) \
        $(BLKID_LIBS) \
        $(LIBCRYPTSETUP_LIBS)
@@ -1164,6 +1177,7 @@ libsystemd_shared_la_CFLAGS = \
        $(libudev_internal_la_CFLAGS) \
        $(ACL_CFLAGS) \
        $(LIBIDN_CFLAGS) \
+       $(LIBIDN2_CFLAGS) \
        $(SECCOMP_CFLAGS) \
        $(BLKID_CFLAGS) \
        $(LIBCRYPTSETUP_CFLAGS) \
@@ -1178,6 +1192,7 @@ libsystemd_shared_la_LIBADD = \
        $(libudev_internal_la_LIBADD) \
        $(ACL_LIBS) \
        $(LIBIDN_LIBS) \
+       $(LIBIDN2_LIBS) \
        $(SECCOMP_LIBS) \
        $(BLKID_LIBS) \
        $(LIBCRYPTSETUP_LIBS)
@@ -1498,8 +1513,10 @@ polkitpolicy_in_in_files += \
 pkgconfigdata_DATA += \
        src/core/systemd.pc
 
+if ENABLE_RPM_MACROS
 nodist_rpmmacros_DATA = \
        src/core/macros.systemd
+endif
 
 BUILT_SOURCES += \
        src/core/triggers.systemd
@@ -1607,6 +1624,7 @@ tests += \
        test-conf-parser \
        test-capability \
        test-async \
+       test-random-util \
        test-ratelimit \
        test-condition \
        test-uid-range \
@@ -1723,6 +1741,7 @@ TEST_DATA_FILES += \
        test/test-execute/exec-readonlypaths-mount-propagation.service \
        test/test-execute/exec-readwritepaths-mount-propagation.service \
        test/test-execute/exec-inaccessiblepaths-mount-propagation.service \
+       test/test-execute/exec-inaccessiblepaths-proc.service \
        test/test-execute/exec-spec-interpolation.service \
        test/test-execute/exec-systemcallerrornumber.service \
        test/test-execute/exec-systemcallfilter-failing2.service \
@@ -1927,6 +1946,12 @@ test_fstab_util_SOURCES = \
 test_fstab_util_LDADD = \
        libsystemd-shared.la
 
+test_random_util_SOURCES = \
+       src/test/test-random-util.c
+
+test_random_util_LDADD = \
+       libsystemd-shared.la
+
 test_ratelimit_SOURCES = \
        src/test/test-ratelimit.c
 
@@ -2130,6 +2155,10 @@ test_acl_util_LDADD = \
 test_seccomp_SOURCES = \
        src/test/test-seccomp.c
 
+test_seccomp_CFLAGS = \
+       $(AM_CFLAGS) \
+       $(SECCOMP_CFLAGS)
+
 test_seccomp_LDADD = \
        libsystemd-shared.la \
        $(SECCOMP_LIBS)
@@ -2175,9 +2204,6 @@ test_selinux_LDADD = \
 test_sizeof_SOURCES = \
        src/test/test-sizeof.c
 
-test_sizeof_LDADD = \
-       libsystemd-shared.la
-
 BUILT_SOURCES += \
        src/test/test-hashmap-ordered.c
 
@@ -2429,6 +2455,7 @@ test_execute_SOURCES = \
 
 test_execute_CFLAGS = \
        $(AM_CFLAGS) \
+       $(SECCOMP_CFLAGS) \
        $(MOUNT_CFLAGS)
 
 test_execute_LDADD = \
@@ -2659,13 +2686,13 @@ nodist_systemunit_DATA += \
 
 nodist_tmpfiles_DATA = \
        tmpfiles.d/systemd.conf \
+       tmpfiles.d/var.conf \
        tmpfiles.d/etc.conf
 
 dist_tmpfiles_DATA = \
        tmpfiles.d/systemd-nologin.conf \
        tmpfiles.d/tmp.conf \
        tmpfiles.d/x11.conf \
-       tmpfiles.d/var.conf \
        tmpfiles.d/home.conf \
        tmpfiles.d/systemd-nspawn.conf \
        tmpfiles.d/journal-nocow.conf
@@ -2675,6 +2702,11 @@ dist_tmpfiles_DATA += \
        tmpfiles.d/legacy.conf
 endif
 
+if HAVE_REMOTE
+nodist_tmpfiles_DATA += \
+       tmpfiles.d/systemd-remote.conf
+endif
+
 SYSINIT_TARGET_WANTS += \
        systemd-tmpfiles-setup-dev.service \
        systemd-tmpfiles-setup.service
@@ -2692,7 +2724,9 @@ endif
 
 EXTRA_DIST += \
        tmpfiles.d/systemd.conf.m4 \
+       tmpfiles.d/systemd-remote.conf.m4 \
        tmpfiles.d/etc.conf.m4 \
+       tmpfiles.d/var.conf.m4 \
        units/systemd-tmpfiles-setup-dev.service.in \
        units/systemd-tmpfiles-setup.service.in \
        units/systemd-tmpfiles-clean.service.in
@@ -2812,9 +2846,6 @@ systemd_detect_virt_SOURCES = \
 systemd_detect_virt_LDADD = \
        libsystemd-shared.la
 
-INSTALL_EXEC_HOOKS += \
-       systemd-detect-virt-install-hook
-
 # ------------------------------------------------------------------------------
 systemd_delta_SOURCES = \
        src/delta/delta.c
@@ -2978,28 +3009,37 @@ if ARCH_AARCH64
 efi_ldflags += --defsym=EFI_SUBSYSTEM=0xa
 EFI_FORMAT = -O binary
 else
+if ARCH_ARM
+efi_ldflags += --defsym=EFI_SUBSYSTEM=0xa
+EFI_FORMAT = -O binary
+else
 EFI_FORMAT = --target=efi-app-$(EFI_ARCH)
 endif
 endif
 endif
+endif
 
 # ------------------------------------------------------------------------------
-systemd_boot_headers = \
-       src/boot/efi/util.h \
+efi_headers = \
        src/boot/efi/console.h \
+       src/boot/efi/disk.h \
        src/boot/efi/graphics.h \
-       src/boot/efi/pefile.h \
+       src/boot/efi/linux.h \
        src/boot/efi/measure.h \
-       src/boot/efi/disk.h
+       src/boot/efi/pe.h \
+       src/boot/efi/splash.h \
+       src/boot/efi/util.h \
+       src/boot/efi/shim.h
 
 systemd_boot_sources = \
-       src/boot/efi/util.c \
+       src/boot/efi/boot.c \
        src/boot/efi/console.c \
-       src/boot/efi/graphics.c \
-       src/boot/efi/pefile.c \
        src/boot/efi/disk.c \
+       src/boot/efi/graphics.c \
        src/boot/efi/measure.c \
-       src/boot/efi/boot.c
+       src/boot/efi/pe.c \
+       src/boot/efi/util.c \
+       src/boot/efi/shim.c
 
 EXTRA_DIST += $(systemd_boot_sources) $(systemd_boot_headers)
 
@@ -3011,7 +3051,7 @@ if ENABLE_EFI
 if HAVE_GNUEFI
 bootlib_DATA = $(systemd_boot)
 
-$(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(systemd_boot_headers))
+$(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(efi_headers))
        @$(MKDIR_P) $(top_builddir)/src/boot/efi/
        $(AM_V_CC)$(EFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@
 
@@ -3029,24 +3069,15 @@ endif
 CLEANFILES += $(systemd_boot_objects) $(systemd_boot_solib) $(systemd_boot)
 
 # ------------------------------------------------------------------------------
-stub_headers = \
-       src/boot/efi/util.h \
-       src/boot/efi/pefile.h \
-       src/boot/efi/disk.h \
-       src/boot/efi/graphics.h \
-       src/boot/efi/splash.h \
-       src/boot/efi/measure.h \
-       src/boot/efi/linux.h
-
 stub_sources = \
-       src/boot/efi/util.c \
-       src/boot/efi/pefile.c \
        src/boot/efi/disk.c \
        src/boot/efi/graphics.c \
-       src/boot/efi/splash.c \
        src/boot/efi/linux.c \
        src/boot/efi/measure.c \
-       src/boot/efi/stub.c
+       src/boot/efi/pe.c \
+       src/boot/efi/splash.c \
+       src/boot/efi/stub.c \
+       src/boot/efi/util.c
 
 EXTRA_DIST += \
        $(stub_sources) \
@@ -3061,10 +3092,6 @@ if ENABLE_EFI
 if HAVE_GNUEFI
 bootlib_DATA += $(stub)
 
-$(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(top_srcdir)/,$(stub_headers))
-       @$(MKDIR_P) $(top_builddir)/src/boot/efi/
-       $(AM_V_CC)$(EFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@
-
 $(stub_solib): $(stub_objects)
        $(AM_V_CCLD)$(LD) $(efi_ldflags) $(stub_objects) \
                -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \
@@ -3082,8 +3109,8 @@ CLEANFILES += $(stub_objects) $(stub_solib) $(stub)
 # ------------------------------------------------------------------------------
 CLEANFILES += test-efi-disk.img
 
-test-efi-disk.img: $(systemd_boot) $(stub) test/test-efi-create-disk.sh
-       $(AM_V_GEN)test/test-efi-create-disk.sh
+test-efi-disk.img: $(systemd_boot) $(stub) test/splash.bmp test/test-efi-create-disk.sh
+       $(AM_V_GEN)test/test-efi-create-disk.sh $@ $(systemd_boot) $(stub) test/splash.bmp
 
 test-efi: test-efi-disk.img
        $(QEMU) -machine accel=kvm -m 1024 -bios $(QEMU_BIOS) -snapshot test-efi-disk.img
@@ -3410,7 +3437,6 @@ noinst_LTLIBRARIES += \
 
 EXTRA_DIST += \
        src/libsystemd/libsystemd.pc.in \
-       src/libsystemd/sd-bus/DIFFERENCES \
        src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
 
 libsystemd_la_SOURCES =
@@ -3453,6 +3479,7 @@ tests += \
        test-bus-zero-copy \
        test-bus-introspect \
        test-bus-objects \
+       test-bus-vtable \
        test-bus-error \
        test-bus-creds \
        test-bus-gvariant \
@@ -3522,6 +3549,12 @@ test_bus_objects_SOURCES = \
 test_bus_objects_LDADD = \
        libsystemd-shared.la
 
+test_bus_vtable_SOURCES = \
+       src/libsystemd/sd-bus/test-bus-vtable.c
+
+test_bus_vtable_LDADD = \
+       libsystemd-shared.la
+
 test_bus_error_SOURCES = \
        src/libsystemd/sd-bus/test-bus-error.c
 
@@ -3607,9 +3640,9 @@ test_resolve_LDADD = \
        libsystemd-shared.la
 
 busctl_SOURCES = \
-       src/libsystemd/sd-bus/busctl.c \
-       src/libsystemd/sd-bus/busctl-introspect.c \
-       src/libsystemd/sd-bus/busctl-introspect.h
+       src/busctl/busctl.c \
+       src/busctl/busctl-introspect.c \
+       src/busctl/busctl-introspect.h
 
 busctl_LDADD = \
        libsystemd-shared.la
@@ -3629,6 +3662,7 @@ libsystemd_network_la_SOURCES = \
        src/systemd/sd-ipv4ll.h \
        src/systemd/sd-ipv4acd.h \
        src/systemd/sd-ndisc.h \
+       src/systemd/sd-radv.h \
        src/systemd/sd-dhcp6-client.h \
        src/systemd/sd-dhcp6-lease.h \
        src/systemd/sd-lldp.h \
@@ -3652,6 +3686,8 @@ libsystemd_network_la_SOURCES = \
        src/libsystemd-network/ndisc-internal.h \
        src/libsystemd-network/ndisc-router.h \
        src/libsystemd-network/ndisc-router.c \
+       src/libsystemd-network/sd-radv.c \
+       src/libsystemd-network/radv-internal.h \
        src/libsystemd-network/icmp6-util.h \
        src/libsystemd-network/icmp6-util.c \
        src/libsystemd-network/sd-dhcp6-client.c \
@@ -3682,6 +3718,14 @@ test_dhcp_option_LDADD = \
        libsystemd-network.la \
        libsystemd-shared.la
 
+test_sd_dhcp_lease_SOURCES = \
+      src/libsystemd-network/dhcp-lease-internal.h \
+      src/libsystemd-network/test-sd-dhcp-lease.c
+
+test_sd_dhcp_lease_LDADD = \
+      libsystemd-network.la \
+      libsystemd-shared.la
+
 test_dhcp_client_SOURCES = \
        src/systemd/sd-dhcp-client.h \
        src/libsystemd-network/dhcp-protocol.h \
@@ -3737,6 +3781,16 @@ test_ndisc_rs_LDADD = \
        libudev.la \
        libsystemd-shared.la
 
+test_ndisc_ra_SOURCES = \
+       src/systemd/sd-ndisc.h \
+       src/libsystemd-network/icmp6-util.h \
+       src/libsystemd-network/test-ndisc-ra.c
+
+test_ndisc_ra_LDADD = \
+       libsystemd-network.la \
+       libudev.la \
+       libsystemd-shared.la
+
 test_dhcp6_client_SOURCES = \
        src/systemd/sd-dhcp6-client.h \
        src/libsystemd-network/dhcp6-internal.h \
@@ -3760,8 +3814,10 @@ tests += \
        test-dhcp-option \
        test-dhcp-client \
        test-dhcp-server \
+       test-sd-dhcp-lease \
        test-ipv4ll \
        test-ndisc-rs \
+       test-ndisc-ra \
        test-dhcp6-client \
        test-lldp
 
@@ -3819,10 +3875,10 @@ dist_network_DATA = \
        network/80-container-vz.network
 
 dist_udevrules_DATA += \
-       rules/50-udev-default.rules \
        rules/60-block.rules \
        rules/60-drm.rules \
        rules/60-evdev.rules \
+       rules/60-input-id.rules \
        rules/60-persistent-storage-tape.rules \
        rules/60-persistent-input.rules \
        rules/60-persistent-alsa.rules \
@@ -3830,6 +3886,7 @@ dist_udevrules_DATA += \
        rules/60-sensor.rules \
        rules/60-serial.rules \
        rules/64-btrfs.rules \
+       rules/70-joystick.rules \
        rules/70-mouse.rules \
        rules/70-touchpad.rules \
        rules/75-net-description.rules \
@@ -3837,6 +3894,7 @@ dist_udevrules_DATA += \
        rules/80-net-setup-link.rules
 
 nodist_udevrules_DATA += \
+       rules/50-udev-default.rules \
        rules/99-systemd.rules
 
 udevconfdir = $(sysconfdir)/udev
@@ -3847,6 +3905,7 @@ pkgconfigdata_DATA += \
        src/udev/udev.pc
 
 EXTRA_DIST += \
+       rules/50-udev-default.rules.in \
        rules/99-systemd.rules.in \
        src/udev/udev.pc.in
 
@@ -3874,10 +3933,10 @@ noinst_LTLIBRARIES += \
 
 src/udev/keyboard-keys-list.txt:
        $(AM_V_at)$(MKDIR_P) $(dir $@)
-       $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9K]/ { if ($$2 != "KEY_MAX") { print $$2 } }' > $@
+       $(AM_V_GEN)$(top_srcdir)/src/udev/generate-keyboard-keys-list.sh "$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS)" > $@
 
 src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys-list.txt
-       $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print tolower(substr($$1 ,5)) ", " $$1 }' < $< > $@
+       $(AM_V_GEN)$(top_srcdir)/src/udev/generate-keyboard-keys-gperf.sh $< > $@
 
 src/udev/keyboard-keys-from-name.h: src/udev/keyboard-keys-from-name.gperf
        $(AM_V_GPERF)$(GPERF) -L ANSI-C -t -N keyboard_lookup_key -H hash_key_name -p -C < $< > $@
@@ -3916,7 +3975,8 @@ gperf_gperf_sources += \
 libudev_core_la_CFLAGS = \
        $(AM_CFLAGS) \
        $(BLKID_CFLAGS) \
-       $(KMOD_CFLAGS)
+       $(KMOD_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
 
 libudev_core_la_LIBADD = \
        libsystemd-network.la \
@@ -3948,6 +4008,10 @@ endif
 systemd_udevd_SOURCES = \
        src/udev/udevd.c
 
+systemd_udevd_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 systemd_udevd_LDADD = \
        libudev-core.la \
        libbasic.la
@@ -4091,6 +4155,10 @@ EXTRA_DIST += \
 ata_id_SOURCES = \
        src/udev/ata_id/ata_id.c
 
+ata_id_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 ata_id_LDADD = \
        libshared.la
 
@@ -4101,6 +4169,10 @@ udevlibexec_PROGRAMS += \
 cdrom_id_SOURCES = \
        src/udev/cdrom_id/cdrom_id.c
 
+cdrom_id_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 cdrom_id_LDADD = \
        libshared.la
 
@@ -4114,6 +4186,10 @@ dist_udevrules_DATA += \
 collect_SOURCES = \
        src/udev/collect/collect.c
 
+collect_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 collect_LDADD = \
        libshared.la
 
@@ -4127,6 +4203,10 @@ scsi_id_SOURCES =\
        src/udev/scsi_id/scsi.h \
        src/udev/scsi_id/scsi_id.h
 
+scsi_id_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 scsi_id_LDADD = \
        libshared.la
 
@@ -4140,6 +4220,10 @@ EXTRA_DIST += \
 v4l_id_SOURCES = \
        src/udev/v4l_id/v4l_id.c
 
+v4l_id_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 v4l_id_LDADD = \
        libshared.la
 
@@ -4155,6 +4239,10 @@ mtd_probe_SOURCES =  \
        src/udev/mtd_probe/mtd_probe.h \
        src/udev/mtd_probe/probe_smartmedia.c
 
+mtd_probe_CFLAGS = \
+       $(AM_CFLAGS) \
+       -DLOG_REALM=LOG_REALM_UDEV
+
 dist_udevrules_DATA += \
        rules/75-probe_mtd.rules
 
@@ -4261,11 +4349,6 @@ systemd_journal_remote_CFLAGS = \
 systemd_journal_remote_LDADD += \
        $(MICROHTTPD_LIBS)
 
-if ENABLE_TMPFILES
-dist_tmpfiles_DATA += \
-       tmpfiles.d/systemd-remote.conf
-endif
-
 if HAVE_GNUTLS
 systemd_journal_remote_LDADD += \
        $(GNUTLS_LIBS)
@@ -4561,10 +4644,8 @@ libsystemd_journal_internal_la_SOURCES += \
 libsystemd_journal_internal_la_LIBADD += \
        $(GCRYPT_LIBS)
 
-# fsprg.c is a drop-in file using void pointer arithmetic
 libsystemd_journal_internal_la_CFLAGS += \
-       $(GCRYPT_CFLAGS) \
-       -Wno-pointer-arith
+       $(GCRYPT_CFLAGS)
 endif
 
 noinst_LTLIBRARIES += \
@@ -5020,10 +5101,6 @@ systemd_localed_LDADD = \
        libsystemd-shared.la \
        -ldl
 
-systemd_localed_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(XKBCOMMON_CFLAGS)
-
 nodist_systemunit_DATA += \
        units/systemd-localed.service
 
@@ -5080,8 +5157,6 @@ dist_zshcompletion_data += \
        shell-completion/zsh/_localectl
 endif
 
-.PHONY: update-kbd-model-map
-
 polkitpolicy_in_files += \
        src/locale/org.freedesktop.locale1.policy.in
 
@@ -5161,6 +5236,25 @@ systemd_timesyncd_LDADD = \
        libsystemd-shared.la \
        -lm
 
+test_timesync_SOURCES = \
+       src/timesync/test-timesync.c \
+       src/timesync/timesyncd-manager.c \
+       src/timesync/timesyncd-manager.h \
+       src/timesync/timesyncd-conf.c \
+       src/timesync/timesyncd-conf.h \
+       src/timesync/timesyncd-server.c \
+       src/timesync/timesyncd-server.h
+
+nodist_test_timesync_SOURCES = \
+       src/timesync/timesyncd-gperf.c
+
+test_timesync_LDADD = \
+       libsystemd-shared.la \
+       -lm
+
+tests += \
+       test-timesync
+
 rootlibexec_PROGRAMS += \
        systemd-timesyncd
 
@@ -5195,6 +5289,7 @@ manual_tests += \
        test-nss
 
 # ------------------------------------------------------------------------------
+if ENABLE_NSS_SYSTEMD
 libnss_systemd_la_SOURCES = \
        src/nss-systemd/nss-systemd.sym \
        src/nss-systemd/nss-systemd.c
@@ -5214,6 +5309,7 @@ libnss_systemd_la_LIBADD = \
 
 rootlib_LTLIBRARIES += \
        libnss_systemd.la
+endif
 
 # ------------------------------------------------------------------------------
 if HAVE_MYHOSTNAME
@@ -5240,6 +5336,10 @@ endif
 
 # ------------------------------------------------------------------------------
 if ENABLE_MACHINED
+
+dist_systemunit_DATA += \
+       units/var-lib-machines.mount
+
 systemd_machined_SOURCES = \
        src/machine/machined.c \
        src/machine/machined.h
@@ -5612,6 +5712,9 @@ GENERAL_ALIASES += \
 nodist_pkgsysconf_DATA += \
        src/resolve/resolved.conf
 
+dist_rootlibexec_DATA += \
+       src/resolve/resolv.conf
+
 libnss_resolve_la_SOURCES = \
        src/nss-resolve/nss-resolve.sym \
        src/nss-resolve/nss-resolve.c
@@ -5627,8 +5730,7 @@ libnss_resolve_la_LDFLAGS = \
 
 libnss_resolve_la_LIBADD = \
        libsystemd-internal.la \
-       libbasic.la \
-        -ldl
+       libbasic.la
 
 rootlib_LTLIBRARIES += \
        libnss_resolve.la
@@ -5664,6 +5766,7 @@ dist_zshcompletion_data += \
 tests += \
        test-dns-packet \
        test-resolve-tables \
+       test-resolved-packet \
        test-dnssec
 
 manual_tests += \
@@ -5685,6 +5788,19 @@ test_resolve_tables_LDADD = \
        $(GCRYPT_LIBS) \
        -lm
 
+test_resolved_packet_SOURCES = \
+       src/resolve/test-resolved-packet.c \
+       $(basic_dns_sources)
+
+test_resolved_packet_CFLAGS = \
+       $(AM_CFLAGS) \
+       $(GCRYPT_CFLAGS)
+
+test_resolved_packet_LDADD = \
+       libsystemd-shared.la \
+       $(GCRYPT_LIBS) \
+       -lm
+
 test_dns_packet_SOURCES = \
        src/resolve/test-dns-packet.c \
        $(basic_dns_sources)
@@ -5750,9 +5866,6 @@ EXTRA_DIST += \
        units/systemd-resolved.service.m4.in \
        src/resolve/resolved.conf.in
 
-dist_rootlibexec_DATA += \
-       src/resolve/resolv.conf
-
 # ------------------------------------------------------------------------------
 if ENABLE_NETWORKD
 rootlibexec_PROGRAMS += \
@@ -5787,6 +5900,8 @@ libnetworkd_core_la_SOURCES = \
        src/network/netdev/veth.c \
        src/network/netdev/vxlan.h \
        src/network/netdev/vxlan.c \
+       src/network/netdev/geneve.h \
+       src/network/netdev/geneve.c \
        src/network/netdev/vlan.h \
        src/network/netdev/vlan.c \
        src/network/netdev/macvlan.h \
@@ -5817,12 +5932,16 @@ libnetworkd_core_la_SOURCES = \
        src/network/networkd-dhcp4.c \
        src/network/networkd-dhcp6.c \
        src/network/networkd-ndisc.h \
+       src/network/networkd-radv.c \
+       src/network/networkd-radv.h \
        src/network/networkd-ndisc.c \
        src/network/networkd-network.h \
        src/network/networkd-network.c \
        src/network/networkd-network-bus.c \
        src/network/networkd-address.h \
        src/network/networkd-address.c \
+       src/network/networkd-address-label.h \
+       src/network/networkd-address-label.c \
        src/network/networkd-route.h \
        src/network/networkd-route.c \
        src/network/networkd-fdb.h \
@@ -5933,10 +6052,8 @@ dist_dbuspolicy_DATA += \
 GENERAL_ALIASES += \
        $(systemunitdir)/systemd-networkd.socket $(pkgsysconfdir)/system/sockets.target.wants/systemd-networkd.socket \
        $(systemunitdir)/systemd-networkd.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-networkd.service \
-       $(systemunitdir)/systemd-networkd-wait-online.service $(pkgsysconfdir)/system/network-online.target.wants/systemd-networkd-wait-online.service
-
-SYSTEM_UNIT_ALIASES += \
-       systemd-networkd.service dbus-org.freedesktop.network1.service
+       $(systemunitdir)/systemd-networkd-wait-online.service $(pkgsysconfdir)/system/network-online.target.wants/systemd-networkd-wait-online.service \
+       $(systemunitdir)/systemd-networkd.service $(pkgsysconfdir)/system/dbus-org.freedesktop.network1.service
 
 BUSNAMES_TARGET_WANTS += \
        org.freedesktop.network1.busname
@@ -5959,7 +6076,8 @@ EXTRA_DIST += \
        src/network/systemd-networkd.pkla \
        units/systemd-networkd.service.m4.in \
        units/systemd-networkd-wait-online.service.in \
-       test/networkd-test.py
+       test/networkd-test.py \
+       test/test-exec-deserialization.py
 
 # ------------------------------------------------------------------------------
 if ENABLE_LOGIND
@@ -6064,10 +6182,10 @@ test_login_tables_LDADD = \
        liblogind-core.la
 
 manual_tests += \
-       test-login \
        test-inhibit
 
 tests += \
+       test-login \
        test-login-tables \
        test-login-shared
 
@@ -6271,7 +6389,6 @@ substitutions = \
        '|exec_prefix=$(exec_prefix)|' \
        '|libdir=$(libdir)|' \
        '|includedir=$(includedir)|' \
-       '|VERSION=$(VERSION)|' \
        '|rootprefix=$(rootprefix)|' \
        '|udevlibexecdir=$(udevlibexecdir)|' \
        '|SUSHELL=$(SUSHELL)|' \
@@ -6295,6 +6412,7 @@ substitutions = \
        '|KILL_USER_PROCESSES=$(KILL_USER_PROCESSES)|' \
        '|systemuidmax=$(SYSTEM_UID_MAX)|' \
        '|systemgidmax=$(SYSTEM_GID_MAX)|' \
+       '|DEV_KVM_MODE=$(DEV_KVM_MODE)|' \
        '|TTY_GID=$(TTY_GID)|' \
        '|systemsleepdir=$(systemsleepdir)|' \
        '|systemshutdowndir=$(systemshutdowndir)|' \
@@ -6328,6 +6446,10 @@ src/core/%.systemd: src/core/%.systemd.in
 src/%.policy.in: src/%.policy.in.in
        $(SED_PROCESS)
 
+src/sulogin-shell/%: src/sulogin-shell/%.in
+       $(SED_PROCESS)
+       $(AM_V_GEN)chmod +x $@
+
 shell-completion/%: shell-completion/%.in
        $(SED_PROCESS)
 
@@ -6371,8 +6493,10 @@ nodist_polkitpolicy_DATA = \
        $(polkitpolicy_files) \
        $(polkitpolicy_in_in_files:.policy.in.in=.policy)
 polkitrules_DATA = $(polkitrules_files)
+if ENABLE_POLKIT_PKLA
 polkitpkla_DATA = $(polkitpkla_files)
 endif
+endif
 
 EXTRA_DIST += \
        $(polkitpolicy_in_files) \
@@ -6395,7 +6519,7 @@ XSLTPROC_FLAGS = \
        --stringparam funcsynopsis.style ansi \
        --stringparam man.authors.section.enabled 0 \
        --stringparam man.copyright.section.enabled 0 \
-       --stringparam systemd.version $(VERSION) \
+       --stringparam systemd.version $(PACKAGE_VERSION) \
        --path '$(builddir)/man:$(srcdir)/man'
 
 XSLT = $(if $(XSLTPROC), $(XSLTPROC), xsltproc)
@@ -6476,7 +6600,9 @@ SYSINIT_TARGET_WANTS += \
 
 LOCAL_FS_TARGET_WANTS += \
        systemd-remount-fs.service \
-       tmp.mount \
+       tmp.mount
+
+REMOTE_FS_TARGET_WANTS += \
        var-lib-machines.mount
 
 MULTI_USER_TARGET_WANTS += \
@@ -6492,6 +6618,11 @@ SYSINIT_TARGET_WANTS += \
        systemd-sysctl.service \
        systemd-ask-password-console.path
 
+if ENABLE_MACHINED
+MACHINES_TARGET_WANTS += \
+       var-lib-machines.mount
+endif
+
 if HAVE_SYSV_COMPAT
 SYSTEM_UNIT_ALIASES += \
        poweroff.target runlevel0.target \
@@ -6567,6 +6698,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
        --with-zshcompletiondir=$$dc_install_base/$(zshcompletiondir) \
        --with-pamlibdir=$$dc_install_base/$(pamlibdir) \
        --with-pamconfdir=$$dc_install_base/$(pamconfdir) \
+       --with-rpmmacrosdir=$$dc_install_base/$(rpmmacrosdir) \
        --with-rootprefix=$$dc_install_base \
        --enable-compat-libs
 
@@ -6610,34 +6742,27 @@ dist-check-includes: $(public_headers)
        done; exit $$res
 
 .PHONY: hwdb-update
-hwdb-update:
-       ( cd $(top_srcdir)/hwdb && \
-       wget -O usb.ids 'http://www.linux-usb.org/usb.ids' && \
-       wget -O pci.ids 'http://pci-ids.ucw.cz/v2.2/pci.ids' && \
-       wget -O ma-large.txt 'http://standards.ieee.org/develop/regauth/oui/oui.txt' && \
-       wget -O ma-medium.txt 'http://standards.ieee.org/develop/regauth/oui28/mam.txt' && \
-       wget -O ma-small.txt 'http://standards.ieee.org/develop/regauth/oui36/oui36.txt' && \
-       wget -O pnp_id_registry.html 'http://www.uefi.org/uefi-pnp-export' && \
-       wget -O acpi_id_registry.html 'http://www.uefi.org/uefi-acpi-export' && \
-       ./ids-update.pl && \
-       ./acpi-update.py > 20-acpi-vendor.hwdb.base && \
-       patch -p0 -o- 20-acpi-vendor.hwdb.base < 20-acpi-vendor.hwdb.patch > 20-acpi-vendor.hwdb )
+hwdb-update: tools/meson-hwdb-update.sh
+       $< $(top_srcdir)/hwdb
 
 .PHONY: built-sources
 built-sources: $(BUILT_SOURCES)
 
 .PHONY: git-tag
 git-tag:
-       git tag -s "v$(VERSION)" -m "systemd $(VERSION)"
+       git tag -s "v$(PACKAGE_VERSION)" -m "systemd $(PACKAGE_VERSION)"
 
 .PHONY: git-tar
 git-tar:
-       git archive --format=tar --prefix=systemd-$(VERSION)/ HEAD | gzip > systemd-$(VERSION).tar.gz
+       git archive -o systemd-$(PACKAGE_VERSION).tar.gz --prefix=systemd-$(PACKAGE_VERSION)/ HEAD
+
+%.asc: %
+       gpg2 --detach-sign -a -o $@ $<
 
 www_target = www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd
 
 .PHONY: doc-sync
-doc-sync: all
+doc-sync: man
        rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times man/ $(www_target)/man/
 
 .PHONY: install-tree
@@ -6774,14 +6899,17 @@ cppcheck:
 print-%:
        @echo $($*)
 
+.PHONY: git-contrib
 git-contrib:
        @git shortlog -s `git describe --abbrev=0`.. | cut -c8- | sed 's/ / /g' | awk '{ print $$0 "," }' | sort -u
 
 EXTRA_DIST += \
         tools/gdb-sd_dump_hashmaps.py
 
+.PHONY: list-keys
 list-keys:
        gpg --verbose --no-options --no-default-keyring --no-auto-key-locate --batch --trust-model=always --keyring=$(srcdir)/src/import/import-pubring.gpg --list-keys
 
+.PHONY: add-key
 add-key:
        gpg --verbose --no-options --no-default-keyring --no-auto-key-locate --batch --trust-model=always --keyring=$(srcdir)/src/import/import-pubring.gpg --import -
diff --git a/NEWS b/NEWS
index da9e203832227dce1d4a026aeebc76b6f28bd8a9..d56b7a6f274a0f5388964fe4e58e36f0db719be9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,140 @@
 systemd System and Service Manager
 
+CHANGES WITH 234:
+
+        * Meson is now supported as build system in addition to Automake. It is
+          our plan to remove Automake in one of our next releases, so that
+          Meson becomes our exclusive build system. Hence, please start using
+          the Meson build system in your downstream packaging. There's plenty
+          of documentation around how to use Meson, the extremely brief
+          summary:
+
+              ./autogen.sh && ./configure && make && sudo make install
+
+          becomes:
+
+              meson build && ninja -C build && sudo ninja -C build install
+
+        * Unit files gained support for a new JobRunningTimeoutUSec= setting,
+          which permits configuring a timeout on the time a job is
+          running. This is particularly useful for setting timeouts on jobs for
+          .device units.
+
+        * Unit files gained two new options ConditionUser= and ConditionGroup=
+          for conditionalizing units based on the identity of the user/group
+          running a systemd user instance.
+
+        * systemd-networkd now understands a new FlowLabel= setting in the
+          [VXLAN] section of .network files, as well as a Priority= in
+          [Bridge], GVRP= + MVRP= + LooseBinding= + ReorderHeader= in [VLAN]
+          and GatewayOnlink= + IPv6Preference= + Protocol= in [Route]. It also
+          gained support for configuration of GENEVE links, and IPv6 address
+          labels. The [Network] section gained the new IPv6ProxyNDP= setting.
+
+        * .link files now understand a new Port= setting.
+
+        * systemd-networkd's DHCP support gained support for DHCP option 119
+          (domain search list).
+
+        * systemd-networkd gained support for serving IPv6 address ranges using
+          the Router Advertisment protocol. The new .network configuration
+          section [IPv6Prefix] may be used to configure the ranges to
+          serve. This is implemented based on a new, minimal, native server
+          implementation of RA.
+
+        * journalctl's --output= switch gained support for a new parameter
+          "short-iso-precise" for a mode where timestamps are shown as precise
+          ISO date values.
+
+        * systemd-udevd's "net_id" builtin may now generate stable network
+          interface names from IBM PowerVM VIO devices as well as ACPI platform
+          devices.
+
+        * MulticastDNS support in systemd-resolved may now be explicitly
+          enabled/disabled using the new MulticastDNS= configuration file
+          option.
+
+        * systemd-resolved may now optionally use libidn2 instead of the libidn
+          for processing internationalized domain names. Support for libidn2
+          should be considered experimental and should not be enabled by
+          default yet.
+
+        * "machinectl pull-tar" and related call may now do verification of
+          downloaded images using SUSE-style .sha256 checksum files in addition
+          to the already existing support for validating using Ubuntu-style
+          SHA256SUMS files.
+
+        * sd-bus gained support for a new sd_bus_message_appendv() call which
+          is va_list equivalent of sd_bus_message_append().
+
+        * sd-boot gained support for validating images using SHIM/MOK.
+
+        * The SMACK code learnt support for "onlycap".
+
+        * systemd-mount --umount is now much smarter in figuring out how to
+          properly unmount a device given its mount or device path.
+
+        * The code to call libnss_dns as a fallback from libnss_resolve when
+          the communication with systemd-resolved fails was removed. This
+          fallback was redundant and interfered with the [!UNAVAIL=return]
+          suffix. See nss-resolve(8) for the recommended configuration.
+
+        * systemd-logind may now be restarted without losing state. It stores
+          the file descriptors for devices it manages in the system manager
+          using the FDSTORE= mechanism. Please note that further changes in
+          other components may be required to make use of this (for example
+          Xorg has code to listen for stops of systemd-logind and terminate
+          itself when logind is stopped or restarted, in order to avoid using
+          stale file descriptors for graphical devices, which is now
+          counterproductive and must be reverted in order for restarts of
+          systemd-logind to be safe. See
+          https://cgit.freedesktop.org/xorg/xserver/commit/?id=dc48bd653c7e101.)
+
+        * All kernel install plugins are called with the environment variable
+          KERNEL_INSTALL_MACHINE_ID which is set to the machine ID given by
+          /etc/machine-id. If the file is missing or empty, the variable is
+          empty and BOOT_DIR_ABS is the path of a temporary directory which is
+          removed after all the plugins exit. So, if KERNEL_INSTALL_MACHINE_ID
+          is empty, all plugins should not put anything in BOOT_DIR_ABS.
+
+        Contributions from: Adrian Heine né Lang, Aggelos Avgerinos, Alexander
+        Kurtz, Alexandros Frantzis, Alexey Brodkin, Alex Lu, Amir Pakdel, Amir
+        Yalon, Anchor Cat, Anthony Parsons, Bastien Nocera, Benjamin Gilbert,
+        Benjamin Robin, Boucman, Charles Plessy, Chris Chiu, Chris Lamb,
+        Christian Brauner, Christian Hesse, Colin Walters, Daniel Drake,
+        Danielle Church, Daniel Molkentin, Daniel Rusek, Daniel Wang, Davide
+        Cavalca, David Herrmann, David Michael, Dax Kelson, Dimitri John
+        Ledkov, Djalal Harouni, Dušan Kazik, Elias Probst, Evgeny Vereshchagin,
+        Federico Di Pierro, Felipe Sateler, Felix Zhang, Franck Bui, Gary
+        Tierney, George McCollister, Giedrius Statkevičius, Hans de Goede,
+        hecke, Hendrik Westerberg, Hristo Venev, Ian Wienand, Insun Pyo, Ivan
+        Shapovalov, James Cowgill, James Hemsing, Janne Heß, Jan Synacek, Jason
+        Reeder, João Paulo Rechi Vita, John Paul Adrian Glaubitz, Jörg
+        Thalheim, Josef Andersson, Josef Gajdusek, Julian Mehne, Kai Krakow,
+        Krzysztof Jackiewicz, Lars Karlitski, Lennart Poettering, Lluís Gili,
+        Lucas Werkmeister, Lukáš Nykrýn, Łukasz Stelmach, Mantas Mikulėnas,
+        Marcin Bachry, Marcus Cooper, Mark Stosberg, Martin Pitt, Matija Skala,
+        Matt Clarkson, Matthew Garrett, Matthias Greiner, Matthijs van Duin,
+        Max Resch, Michael Biebl, Michal Koutný, Michal Sekletar, Michal
+        Soltys, Michal Suchanek, Mike Gilbert, Nate Clark, Nathaniel R. Lewis,
+        Neil Brown, Nikolai Kondrashov, Pascal S. de Kloe, Pat Riehecky, Patrik
+        Flykt, Paul Kocialkowski, Peter Hutterer, Philip Withnall, Piotr
+        Szydełko, Rafael Fontenelle, Ray Strode, Richard Maw, Roelf Wichertjes,
+        Ronny Chevalier, Sarang S. Dalal, Sjoerd Simons, slodki, Stefan
+        Schweter, Susant Sahani, Ted Wood, Thomas Blume, Thomas Haller, Thomas
+        H. P. Andersen, Timothée Ravier, Tobias Jungel, Tobias Stoeckmann, Tom
+        Gundersen, Tom Yan, Torstein Husebø, Umut Tezduyar Lindskog,
+        userwithuid, Vito Caputo, Waldemar Brodkorb, WaLyong Cho, Yu, Li-Yu,
+        Yusuke Nojima, Yu Watanabe, Zbigniew Jędrzejewski-Szmek, Дамјан
+        Георгиевски
+
+        — Berlin, 2017-07-12
+
 CHANGES WITH 233:
 
+        * This version requires at least gperf 3.1 for building, 3.0 is not
+          sufficient.
+
         * The "hybrid" control group mode has been modified to improve
           compatibility with "legacy" cgroups-v1 setups. Specifically, the
           "hybrid" setup of /sys/fs/cgroup is now pretty much identical to
@@ -348,7 +481,7 @@ CHANGES WITH 233:
           these NTP servers officially. We still recommend downstreams to
           properly register an NTP pool with the NTP pool project though.
 
-        * coredumpctl gained new new "--reverse" option for printing the list
+        * coredumpctl gained a new "--reverse" option for printing the list
           of coredumps in reverse order.
 
         * coredumpctl will now show additional information about truncated and
@@ -3315,7 +3448,7 @@ CHANGES WITH 216:
           like Cockpit which register web clients as PAM sessions.
 
         * timer units with at least one OnCalendar= setting will now
-          be started only after timer-sync.target has been
+          be started only after time-sync.target has been
           reached. This way they will not elapse before the system
           clock has been corrected by a local NTP client or
           similar. This is particular useful on RTC-less embedded
diff --git a/README b/README
index a4a649395933c40978038ea94c482e8aa67fead6..60388eebe624a01e5094bf87e86d55ef616ff84f 100644 (file)
--- a/README
+++ b/README
@@ -35,7 +35,7 @@ LICENSE:
         - except src/udev/* which is (currently still) GPLv2, GPLv2+
 
 REQUIREMENTS:
-        Linux kernel >= 3.12
+        Linux kernel >= 3.13
         Linux kernel >= 4.2 for unified cgroup hierarchy support
 
         Kernel Config Options:
@@ -127,7 +127,8 @@ REQUIREMENTS:
         glibc >= 2.16
         libcap
         libmount >= 2.27.1 (from util-linux)
-                (util-linux *must* be built with --enable-libmount-force-mountinfo)
+                (util-linux < 2.29 *must* be built with --enable-libmount-force-mountinfo,
+                 and later versions without --enable-libmount-support-mtab.)
         libseccomp >= 2.3.1 (optional)
         libblkid >= 2.24 (from util-linux) (optional)
         libkmod >= 15 (optional)
@@ -142,7 +143,7 @@ REQUIREMENTS:
         libqrencode (optional)
         libmicrohttpd (optional)
         libpython (optional)
-        libidn (optional)
+        libidn2 or libidn (optional)
         elfutils >= 158 (optional)
         make, gcc, and similar tools
 
@@ -156,21 +157,47 @@ REQUIREMENTS:
         dracut (optional)
         PolicyKit (optional)
 
-        When building from git, the following tools are needed:
+        Two build systems are supported: meson + ninja-build and autools + make.
+
+        The following tools are needed with both systems:
 
         pkg-config
-        docbook-xsl
-        xsltproc
+        gperf >= 3.1
+        docbook-xsl (optional, required for documentation)
+        xsltproc    (optional, required for documentation)
+        python-lxml (optional, required to build the indices)
+
+        When building with meson, python and ninja-build are required.
+
+        To build in directory build/:
+          meson build/ && ninja -C build
+
+        Any configuration options can be specfied as -Darg=value... arguments
+        to meson. After the build directory is initially configured, meson will
+        refuse to run again, and options must be changed with:
+          mesonconf -Darg=value...
+        mesonconf without any arguments will print out available options and
+        their current values.
+
+        Useful commands:
+          ninja -v some/target
+          ninja test
+          sudo ninja install
+          DESTDIR=... ninja install
+
+        When building with autotools, the following tools are needed:
+
         automake
         autoconf
         libtool
         intltool
-        gperf
         python (optional)
-        python-lxml (optional, but required to build the indices)
 
-        The build system is initialized with ./autogen.sh. A tar ball
-        can be created with:
+        The build system is initialized with ./autogen.sh and the usual
+          ./configure && make
+        should be used.
+
+        A tar ball can be created with:
           git archive --format=tar --prefix=systemd-222/ v222 | xz > systemd-222.tar.xz
 
         When systemd-hostnamed is used, it is strongly recommended to
index 82fb799b4276e8a3570000d0648ce1ee6ead0e82..c406aca8dc0cbd3ffc81f1d161c1797ff8ebce37 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 # systemd - System and Service Manager
 
+<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
+<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
 [![Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
 [![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)
 
diff --git a/TODO b/TODO
index 3cf4ce393c6d7b832f28e0820631622c7e1f8def..61efa5e9f3468bf3c0660cf3ee92a4e3ebfe986f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -24,6 +24,15 @@ Janitorial Clean-ups:
 
 Features:
 
+* Add AddUser= setting to unit files, similar to DynamicUser=1 which however
+  creates a static, persistent user rather than a dynamic, transient user. We
+  can leverage code from sysusers.d for this.
+
+* add some optional flag to ReadWritePaths= and friends, that has the effect
+  that we create the dir in question when the service is started. Example:
+
+  ReadWritePaths=:/var/lib/foobar
+
 * sort generated hwdb files alphabetically when we import them, so that git
   diffs remain minimal (in particular: the OUI databases we import are not
   sorted, and not stable)
diff --git a/catalog/meson.build b/catalog/meson.build
new file mode 100644 (file)
index 0000000..6d205b1
--- /dev/null
@@ -0,0 +1,28 @@
+in_files = '''
+        systemd.bg.catalog
+        systemd.be.catalog
+        systemd.be@latin.catalog
+        systemd.fr.catalog
+        systemd.it.catalog
+        systemd.pl.catalog
+        systemd.pt_BR.catalog
+        systemd.ru.catalog
+        systemd.zh_CN.catalog
+        systemd.zh_TW.catalog
+        systemd.catalog
+'''.split()
+
+support_url = get_option('support-url')
+support_sed = 's~%SUPPORT_URL%~@0@~'.format(support_url)
+build_catalog_dir = meson.current_build_dir()
+
+foreach file : in_files
+        custom_target(
+                file,
+                input : file + '.in',
+                output: file,
+                command : [sed, support_sed, '@INPUT@'],
+                capture : true,
+                install : true,
+                install_dir : catalogdir)
+endforeach
index 3835413ad59e4412687ee53059c89f0131a6aa1a..c7537aafc0c92e42c72e83652e9542c2974ddd87 100644 (file)
@@ -20,7 +20,7 @@
 AC_PREREQ([2.64])
 
 AC_INIT([systemd],
-        [233],
+        [234],
         [https://github.com/systemd/systemd/issues],
         [systemd],
         [https://www.freedesktop.org/wiki/Software/systemd])
@@ -57,6 +57,7 @@ AS_IF([test "x$enable_largefile" = "xno"], [AC_MSG_ERROR([--disable-largefile is
 SET_ARCH(X86_64, x86_64*)
 SET_ARCH(IA32, i*86*)
 SET_ARCH(MIPS, mips*)
+SET_ARCH(ARM, arm*)
 SET_ARCH(AARCH64, aarch64*)
 
 # i18n stuff for the PolicyKit policy files, heck whether intltool can be found, disable NLS otherwise
@@ -327,7 +328,6 @@ AC_CHECK_DECLS([
         pivot_root,
         name_to_handle_at,
         setns,
-        getrandom,
         renameat2,
         kcmp,
         keyctl,
@@ -342,6 +342,13 @@ AC_CHECK_DECLS([
 #include <sched.h>
 #include <string.h>
 #include <linux/loop.h>
+]])
+
+AC_CHECK_DECLS([getrandom],
+               [AC_DEFINE([USE_SYS_RANDOM_H], [], [sys/random.h is usable])],
+               [AC_CHECK_DECLS([getrandom], [], [], [[
+#include <sys/random.h>
+]])], [[
 #include <linux/random.h>
 ]])
 
@@ -360,7 +367,8 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
                 IFLA_PHYS_PORT_ID,
                 IFLA_BOND_AD_INFO,
                 IFLA_VLAN_PROTOCOL,
-                IFLA_VXLAN_REMCSUM_NOPARTIAL,
+                IFLA_VXLAN_GPE,
+                IFLA_GENEVE_LABEL,
                 IFLA_IPTUN_ENCAP_DPORT,
                 IFLA_GRE_ENCAP_DPORT,
                 IFLA_BRIDGE_VLAN_INFO,
@@ -397,6 +405,16 @@ AS_IF([test "x$enable_dbus" != "xno"], [
                 [AC_MSG_ERROR([*** dbus-1 support requested but libraries not found])])])
 AM_CONDITIONAL(HAVE_DBUS, [test "$have_dbus" = "yes"])
 
+# ------------------------------------------------------------------------------
+have_glib=no
+AC_ARG_ENABLE(glib, AS_HELP_STRING([--disable-glib], [disable usage of glib,gobject,gio in tests]))
+AS_IF([test "x$enable_glib" != "xno"], [
+        PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.22.0 gobject-2.0 >= 2.22.0 gio-2.0],
+                [AC_DEFINE(HAVE_GLIB, 1, [Define if glib,gobject,gio are available]) have_glib=yes],
+                [have_glib=no])
+        AS_IF([test "x$have_glib" = "xno" -a "x$enable_glib" = "xyes"],
+                [AC_MSG_ERROR([*** glib support requested but libraries not found])])])
+
 # ------------------------------------------------------------------------------
 have_utmp=yes
 AC_ARG_ENABLE([utmp], AS_HELP_STRING([--disable-utmp], [disable utmp/wtmp log handling]),
@@ -404,7 +422,11 @@ AC_ARG_ENABLE([utmp], AS_HELP_STRING([--disable-utmp], [disable utmp/wtmp log ha
                 [xyes], [have_utmp=yes],
                 [xno],  [have_utmp=no],
                 AC_MSG_ERROR(bad value ${enableval} for --enable-utmp)))
-AS_IF([test "x$have_utmp" = "xyes"], [AC_DEFINE(HAVE_UTMP, 1, [Define if utmp/wtmp support is enabled])])
+AS_IF([test "x$have_utmp" = "xyes"], [
+        AC_DEFINE(HAVE_UTMP, 1, [Define if utmp/wtmp support is enabled])
+        have_utmp=yes
+        M4_DEFINES="$M4_DEFINES -DHAVE_UTMP"],
+        [have_utmp=no])
 AM_CONDITIONAL([HAVE_UTMP], [test "x$have_utmp" = "xyes"])
 
 # ------------------------------------------------------------------------------
@@ -1011,6 +1033,40 @@ if test "x$enable_libidn" != "xno"; then
 fi
 AM_CONDITIONAL(HAVE_LIBIDN, [test "$have_libidn" = "yes"])
 
+have_libidn2=no
+AC_ARG_ENABLE(libidn2, AS_HELP_STRING([--disable-libidn2], [disable optional LIBIDN2 support]))
+if test "$have_libidn" != "yes"; then
+        if test "x$enable_libidn2" != "xno"; then
+                PKG_CHECK_MODULES(LIBIDN2, [libidn2 >= 2.0.0],
+                       [AC_DEFINE(HAVE_LIBIDN2, 1, [Define if libidn2 is available])
+                        have_libidn2=yes
+                        M4_DEFINES="$M4_DEFINES -DHAVE_LIBIDN2"],
+                       [have_libidn2=no])
+                if test "x$have_libidn2" = "xno" -a "x$enable_libidn2" = "xyes"; then
+                        AC_MSG_ERROR([*** libidn2 support requested but libraries not found])
+                fi
+        fi
+fi
+AM_CONDITIONAL(HAVE_LIBIDN2, [test "$have_libidn2" = "yes"])
+
+# ------------------------------------------------------------------------------
+have_idn=no
+AC_ARG_ENABLE(idn, AS_HELP_STRING([--disable-idn], [disable IDN when printing host names]))
+if test "x$enable_idn" != "xno"; then
+        have_idn=yes
+        AC_DEFINE(ENABLE_IDN, [1], [IDN is enabled])
+fi
+AM_CONDITIONAL(ENABLE_IDN, [test "$have_idn" = "yes"])
+
+# ------------------------------------------------------------------------------
+have_nss_systemd=no
+AC_ARG_ENABLE(nss-systemd, AS_HELP_STRING([--disable-nss-systemd], [disable nss-systemd support]))
+if test "x$enable_nss_systemd" != "xno"; then
+        have_nss_systemd=yes
+        AC_DEFINE(ENABLE_NSS_SYSTEMD, [1], [nss-systemd is enabled])
+fi
+AM_CONDITIONAL(ENABLE_NSS_SYSTEMD, [test "$have_nss_systemd" = "yes"])
+
 # ------------------------------------------------------------------------------
 have_libiptc=no
 AC_ARG_ENABLE(libiptc, AS_HELP_STRING([--disable-libiptc], [disable optional LIBIPTC support]))
@@ -1074,6 +1130,11 @@ if test "x$enable_sysusers" != "xno"; then
 fi
 AM_CONDITIONAL(ENABLE_SYSUSERS, [test "$have_sysusers" = "yes"])
 
+AC_ARG_ENABLE(gshadow, AS_HELP_STRING([--disable-gshadow], [disable shadow group support]))
+AS_IF([test "x${enable_gshadow}" != "xno"], [
+        AC_DEFINE(ENABLE_GSHADOW, 1, [shadow group support is enabled])
+])
+
 # ------------------------------------------------------------------------------
 have_firstboot=no
 AC_ARG_ENABLE(firstboot, AS_HELP_STRING([--disable-firstboot], [disable firstboot support]))
@@ -1113,7 +1174,7 @@ if test "x$enable_logind" != "xno"; then
         have_logind=yes
 fi
 AM_CONDITIONAL(ENABLE_LOGIND, [test "$have_logind" = "yes"])
-AS_IF([test "$have_logind" = "yes"], [ AC_DEFINE(HAVE_LOGIND, [1], [Logind support available]) ])
+AS_IF([test "$have_logind" = "yes"], [ AC_DEFINE(ENABLE_LOGIND, [1], [Logind support available]) ])
 
 AC_ARG_WITH([kill-user-processes],
         [AS_HELP_STRING([--without-kill-user-processes], [set logind's KillUserProcesses=no by default])])
@@ -1205,6 +1266,16 @@ AC_ARG_WITH(system-gid-max,
 AC_DEFINE_UNQUOTED(SYSTEM_GID_MAX, [$SYSTEM_GID_MAX], [Maximum System GID])
 AC_SUBST(SYSTEM_GID_MAX)
 
+# ------------------------------------------------------------------------------
+
+AC_ARG_WITH(dev-kvm-mode,
+        AS_HELP_STRING([--with-dev-kvm-mode=MODE],
+                [/dev/kvm access mode, defaults to "0660"]),
+        [DEV_KVM_MODE="$withval"],
+        [DEV_KVM_MODE="0660"])
+
+AC_SUBST(DEV_KVM_MODE, [$DEV_KVM_MODE], [/dev/kvm access mode])
+
 # ------------------------------------------------------------------------------
 have_localed=no
 AC_ARG_ENABLE(localed, AS_HELP_STRING([--disable-localed], [disable locale daemon]))
@@ -1228,8 +1299,14 @@ AC_ARG_ENABLE(polkit, AS_HELP_STRING([--disable-polkit], [disable PolicyKit supp
 if test "x$enable_polkit" != "xno"; then
         AC_DEFINE(ENABLE_POLKIT, 1, [Define if PolicyKit support is to be enabled])
         have_polkit=yes
+
+        # also enable support for *.pkla files on old polkit
+        PKG_CHECK_MODULES(POLKIT, [ polkit-gobject-1 < 0.106 ],
+                           [polkit_pkla=yes],
+                           [polkit_pkla=no])
 fi
 AM_CONDITIONAL(ENABLE_POLKIT, [test "x$have_polkit" = "xyes"])
+AM_CONDITIONAL(ENABLE_POLKIT_PKLA, [test "x$polkit_pkla" = "xyes"])
 
 # ------------------------------------------------------------------------------
 have_resolved=no
@@ -1258,6 +1335,11 @@ AC_ARG_WITH(default-dnssec,
         [DEFAULT_DNSSEC_MODE="$withval"],
         [DEFAULT_DNSSEC_MODE="allow-downgrade"])
 
+if test "x$have_gcrypt" = xno -a "x${DEFAULT_DNSSEC_MODE}" != xno ; then
+        AC_MSG_WARN(default-dnssec cannot be set to yes or allow-downgrade when gcrypt is disabled. Setting default-dnssec to no.)
+        DEFAULT_DNSSEC_MODE="no"
+fi
+
 AS_CASE("x${DEFAULT_DNSSEC_MODE}",
         [xno], [mode=DNSSEC_NO],
         [xyes], [mode=DNSSEC_YES],
@@ -1297,6 +1379,9 @@ AM_COND_IF(ARCH_IA32, [
 AM_COND_IF(ARCH_X86_64, [
         EFI_MACHINE_TYPE_NAME=x64])
 
+AM_COND_IF(ARCH_ARM, [
+        EFI_MACHINE_TYPE_NAME=arm])
+
 AM_COND_IF(ARCH_AARCH64, [
         EFI_MACHINE_TYPE_NAME=aa64])
 
@@ -1306,7 +1391,13 @@ AC_SUBST([EFI_MACHINE_TYPE_NAME])
 have_gnuefi=no
 AC_ARG_ENABLE(gnuefi, AS_HELP_STRING([--enable-gnuefi], [enable optional gnuefi support]))
 AS_IF([test "x$enable_gnuefi" != "xno"], [
-        AC_CHECK_HEADERS(efi/${EFI_ARCH}/efibind.h,
+        AC_ARG_WITH(efi-includedir,
+                AS_HELP_STRING([--with-efi-includedir=PATH], [path to EFI include directory]),
+                [EFI_INC_DIR="$withval"], [EFI_INC_DIR="/usr/include"]
+        )
+        AC_SUBST([EFI_INC_DIR])
+
+        AC_CHECK_HEADERS(${EFI_INC_DIR}/efi/${EFI_ARCH}/efibind.h,
                 [AC_DEFINE(HAVE_GNUEFI, 1, [Define if gnuefi is available])
                  have_gnuefi=yes],
                 [AS_IF([test "x$enable_gnuefi" = xyes],
@@ -1335,12 +1426,6 @@ AS_IF([test "x$enable_gnuefi" != "xno"], [
               [AS_IF([test "x$enable_gnuefi" = xyes],
                      [AC_MSG_ERROR([*** gnuefi support requested but files not found])],
                      [have_gnuefi=no])])
-
-        AC_ARG_WITH(efi-includedir,
-                AS_HELP_STRING([--with-efi-includedir=PATH], [path to EFI include directory]),
-                [EFI_INC_DIR="$withval"], [EFI_INC_DIR="/usr/include"]
-        )
-        AC_SUBST([EFI_INC_DIR])
 ])
 AM_CONDITIONAL(HAVE_GNUEFI, [test "x$have_gnuefi" = xyes])
 
@@ -1571,6 +1656,12 @@ AC_ARG_WITH([pamconfdir],
 AM_CONDITIONAL(ENABLE_PAM_CONFIG, [test "$with_pamconfdir" != "no"])
 AX_NORMALIZE_PATH([with_pamconfdir])
 
+AC_ARG_WITH([rpmmacrosdir],
+        AS_HELP_STRING([--with-rpmmacrosdir=DIR], [directory to store macros for RPM]),
+        [], [with_rpmmacrosdir=\${prefix}/lib/rpm/macros.d])
+AM_CONDITIONAL(ENABLE_RPM_MACROS, [test "$with_rpmmacrosdir" != "no"])
+AX_NORMALIZE_PATH([with_rpmmacrosdir])
+
 AC_ARG_ENABLE([split-usr],
         AS_HELP_STRING([--enable-split-usr], [assume that /bin, /sbin aren't symlinks into /usr]),
         [],
@@ -1641,6 +1732,7 @@ AC_SUBST([bashcompletiondir], [$with_bashcompletiondir])
 AC_SUBST([zshcompletiondir], [$with_zshcompletiondir])
 AC_SUBST([pamlibdir], [$with_pamlibdir])
 AC_SUBST([pamconfdir], [$with_pamconfdir])
+AC_SUBST([rpmmacrosdir], [$with_rpmmacrosdir])
 AC_SUBST([rootprefix], [$with_rootprefix])
 AC_SUBST([rootlibdir], [$with_rootlibdir])
 
@@ -1651,7 +1743,7 @@ AC_CONFIG_FILES([
 
 AC_OUTPUT
 AC_MSG_RESULT([
-        $PACKAGE_NAME $VERSION
+        $PACKAGE_NAME $PACKAGE_VERSION
 
         libcryptsetup:                     ${have_libcryptsetup}
         PAM:                               ${have_pam}
@@ -1671,7 +1763,9 @@ AC_MSG_RESULT([
         MICROHTTPD:                        ${have_microhttpd}
         GNUTLS:                            ${have_gnutls}
         libcurl:                           ${have_libcurl}
+        libidn2:                           ${have_libidn2}
         libidn:                            ${have_libidn}
+        IDN:                               ${have_idn}
         libiptc:                           ${have_libiptc}
         ELFUTILS:                          ${have_elfutils}
         binfmt:                            ${have_binfmt}
@@ -1700,7 +1794,7 @@ AC_MSG_RESULT([
         default DNS servers:               ${DNS_SERVERS}
         default DNSSEC mode:               ${DEFAULT_DNSSEC_MODE}
         coredump:                          ${have_coredump}
-        polkit:                            ${have_polkit}
+        polkit:                            ${have_polkit} (legacy pkla support: ${polkit_pkla})
         efi:                               ${have_efi}
         gnuefi:                            ${have_gnuefi}
         efi arch:                          ${EFI_ARCH}
@@ -1714,7 +1808,9 @@ AC_MSG_RESULT([
         blkid:                             ${have_blkid}
         libmount:                          ${have_libmount}
         dbus:                              ${have_dbus}
+        glib:                              ${have_glib}
         nss-myhostname:                    ${have_myhostname}
+        nss-systemd:                       ${have_nss_systemd}
         hwdb:                              ${enable_hwdb}
         tpm:                               ${have_tpm}
         Python:                            ${have_python}
@@ -1740,6 +1836,7 @@ AC_MSG_RESULT([
         build Python:                      ${PYTHON}
         PAM modules dir:                   ${with_pamlibdir}
         PAM configuration dir:             ${with_pamconfdir}
+        RPM macros dir:                    ${with_rpmmacrosdir}
         D-Bus policy dir:                  ${with_dbuspolicydir}
         D-Bus session dir:                 ${with_dbussessionservicedir}
         D-Bus system dir:                  ${with_dbussystemservicedir}
@@ -1753,6 +1850,7 @@ AC_MSG_RESULT([
         TTY GID:                           ${TTY_GID}
         maximum system UID:                ${SYSTEM_UID_MAX}
         maximum system GID:                ${SYSTEM_GID_MAX}
+        /dev/kvm access mode:              ${DEV_KVM_MODE}
         certificate root:                  ${CERTIFICATEROOT}
         support URL:                       ${SUPPORT_URL}
         nobody user name:                  ${NOBODY_USER_NAME}
diff --git a/docs/sysvinit/meson.build b/docs/sysvinit/meson.build
new file mode 100644 (file)
index 0000000..79d1bab
--- /dev/null
@@ -0,0 +1,9 @@
+file = configure_file(
+        input : 'README.in',
+        output : 'README',
+        configuration : substs)
+
+if conf.get('HAVE_SYSV_COMPAT', false)
+        install_data(file,
+                     install_dir : sysvinit_path)
+endif
diff --git a/docs/var-log/meson.build b/docs/var-log/meson.build
new file mode 100644 (file)
index 0000000..d8364e3
--- /dev/null
@@ -0,0 +1,9 @@
+file = configure_file(
+        input : 'README.in',
+        output : 'README',
+        configuration : substs)
+
+if conf.get('HAVE_SYSV_COMPAT', false)
+        install_data(file,
+                     install_dir : varlogdir)
+endif
index 2f0dbc9e749e02d767fd96b99ba811705f44ce69..5c1bb7fe207f6562ff9ee9605571dcf20023eab3 100644 (file)
@@ -101,9 +101,6 @@ OUI:70B3D55B1*
 OUI:70B3D5EAE*
  ID_OUI_FROM_DATABASE=Orlaco Products B.V.
 
-OUI:70B3D5066*
- ID_OUI_FROM_DATABASE=North Pole Engineering, Inc.
-
 OUI:70B3D557D*
  ID_OUI_FROM_DATABASE=WICOM1 GmbH
 
@@ -833,9 +830,6 @@ OUI:70B3D53A9*
 OUI:001BC5087*
  ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC
 
-OUI:70B3D5720*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:70B3D56BF*
  ID_OUI_FROM_DATABASE=Otto Bihler Maschinenfabrik GmbH & Co. KG
 
@@ -908,9 +902,6 @@ OUI:70B3D5ABA*
 OUI:70B3D565A*
  ID_OUI_FROM_DATABASE=Aplex Technology Inc.
 
-OUI:70B3D5FFE*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:70B3D5721*
  ID_OUI_FROM_DATABASE=Zoe Medical
 
@@ -1103,21 +1094,21 @@ OUI:70B3D58EC*
 OUI:70B3D5CF5*
  ID_OUI_FROM_DATABASE=Petring Energietechnik GmbH
 
+OUI:70B3D5269*
+ ID_OUI_FROM_DATABASE=Gilbarco Veeder-Root  ‎
+
 OUI:70B3D5FF7*
  ID_OUI_FROM_DATABASE=Cybercom AB
 
 OUI:70B3D5DCC*
  ID_OUI_FROM_DATABASE=Eutron SPA
 
-OUI:70B3D5269*
- ID_OUI_FROM_DATABASE=Gilbarco Veeder-Root  ‎
+OUI:70B3D515C*
+ ID_OUI_FROM_DATABASE=Woods Hole Oceanographic Institution
 
 OUI:70B3D5173*
  ID_OUI_FROM_DATABASE=National TeleConsultants LLC
 
-OUI:70B3D515C*
- ID_OUI_FROM_DATABASE=Woods Hole Oceanographic Institution
-
 OUI:70B3D5CAE*
  ID_OUI_FROM_DATABASE=THEMA
 
@@ -1133,12 +1124,12 @@ OUI:70B3D585A*
 OUI:70B3D5FAF*
  ID_OUI_FROM_DATABASE=Radig Hard & Software
 
-OUI:70B3D57A2*
- ID_OUI_FROM_DATABASE=Alpha ESS Co., Ltd.
-
 OUI:70B3D50BC*
  ID_OUI_FROM_DATABASE=Practical Software Studio LLC
 
+OUI:70B3D57A2*
+ ID_OUI_FROM_DATABASE=Alpha ESS Co., Ltd.
+
 OUI:70B3D5724*
  ID_OUI_FROM_DATABASE=Quan International Co., Ltd.
 
@@ -1169,9 +1160,6 @@ OUI:70B3D5209*
 OUI:70B3D514C*
  ID_OUI_FROM_DATABASE=CRDE
 
-OUI:70B3D5AB8*
- ID_OUI_FROM_DATABASE=HORIBA MEDICAL
-
 OUI:70B3D5F9E*
  ID_OUI_FROM_DATABASE=International Center for Elementary Particle Physics, The University of Tokyo
 
@@ -1205,6 +1193,162 @@ OUI:70B3D5585*
 OUI:70B3D5495*
  ID_OUI_FROM_DATABASE=Fiem Industries Ltd.
 
+OUI:70B3D5AD2*
+ ID_OUI_FROM_DATABASE=Wart-Elektronik
+
+OUI:70B3D52B4*
+ ID_OUI_FROM_DATABASE=Foerster-Technik GmbH
+
+OUI:70B3D5276*
+ ID_OUI_FROM_DATABASE=TELL Software Hungaria Kft.
+
+OUI:70B3D528C*
+ ID_OUI_FROM_DATABASE=Step Technica Co., Ltd.
+
+OUI:70B3D57E0*
+ ID_OUI_FROM_DATABASE=Sanko-sha,inc.
+
+OUI:70B3D5E50*
+ ID_OUI_FROM_DATABASE=Advanced Vision Technology Ltd
+
+OUI:70B3D58C1*
+ ID_OUI_FROM_DATABASE=Rievtech Electronic Co.,Ltd
+
+OUI:70B3D5F0C*
+ ID_OUI_FROM_DATABASE=ModulaTeam GmbH
+
+OUI:70B3D58AC*
+ ID_OUI_FROM_DATABASE=​ASUNG TECHNO CO.,Ltd
+
+OUI:70B3D5CE1*
+ ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG
+
+OUI:70B3D5677*
+ ID_OUI_FROM_DATABASE=Fraunhofer-Institut IIS
+
+OUI:70B3D538B*
+ ID_OUI_FROM_DATABASE=Lookman Electroplast Industries Ltd
+
+OUI:70B3D59DC*
+ ID_OUI_FROM_DATABASE=Shanghai Daorech Industry Developmnet Co.,Ltd
+
+OUI:70B3D5888*
+ ID_OUI_FROM_DATABASE=Zetechtics Ltd
+
+OUI:70B3D5168*
+ ID_OUI_FROM_DATABASE=Biwave Technologies, Inc.
+
+OUI:70B3D5F25*
+ ID_OUI_FROM_DATABASE=JSC “Scientific Industrial Enterprise Rubin
+
+OUI:70B3D5A48*
+ ID_OUI_FROM_DATABASE=Applied Satellite Engineering
+
+OUI:70B3D546C*
+ ID_OUI_FROM_DATABASE=SHANGHAI CHENZHU INSTRUMENT CO., LTD.
+
+OUI:70B3D580B*
+ ID_OUI_FROM_DATABASE=Fischer Block, Inc.
+
+OUI:70B3D5FAD*
+ ID_OUI_FROM_DATABASE=ARC Technology Solutions, LLC
+
+OUI:70B3D5AB8*
+ ID_OUI_FROM_DATABASE=HORIBA ABX SAS
+
+OUI:70B3D5E6C*
+ ID_OUI_FROM_DATABASE=Fusar Technologies inc
+
+OUI:70B3D52B0*
+ ID_OUI_FROM_DATABASE=Beijing Zhongyi Yue Tai Technology Co., Ltd
+
+OUI:70B3D52E2*
+ ID_OUI_FROM_DATABASE=Spark Lasers
+
+OUI:70B3D5446*
+ ID_OUI_FROM_DATABASE=Santa Barbara Imaging Systems
+
+OUI:70B3D556B*
+ ID_OUI_FROM_DATABASE=S.E.I. CO.,LTD.
+
+OUI:70B3D5B48*
+ ID_OUI_FROM_DATABASE=DWQ Informatikai Tanacsado es Vezerlestechnikai KFT
+
+OUI:70B3D5A7E*
+ ID_OUI_FROM_DATABASE=QUICCO SOUND Corporation
+
+OUI:70B3D5878*
+ ID_OUI_FROM_DATABASE=Package Guard, Inc
+
+OUI:70B3D5245*
+ ID_OUI_FROM_DATABASE=Newtec A/S
+
+OUI:70B3D5FFE*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D53FE*
+ ID_OUI_FROM_DATABASE=Mentor Graphics
+
+OUI:70B3D574D*
+ ID_OUI_FROM_DATABASE=SPEECH TECHNOLOGY CENTER LIMITED
+
+OUI:70B3D55BF*
+ ID_OUI_FROM_DATABASE=Aton srl
+
+OUI:70B3D5EEA*
+ ID_OUI_FROM_DATABASE=Dameca a/s
+
+OUI:70B3D59B8*
+ ID_OUI_FROM_DATABASE=Loma Systems
+
+OUI:70B3D5BEA*
+ ID_OUI_FROM_DATABASE=Virtuosys Ltd
+
+OUI:70B3D5066*
+ ID_OUI_FROM_DATABASE=North Pole Engineering, Inc.
+
+OUI:70B3D52A1*
+ ID_OUI_FROM_DATABASE=Blink Services AB
+
+OUI:70B3D5591*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D5133*
+ ID_OUI_FROM_DATABASE=Vidisys GmbH
+
+OUI:70B3D5720*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D51E6*
+ ID_OUI_FROM_DATABASE=Sanmina Israel
+
+OUI:70B3D5809*
+ ID_OUI_FROM_DATABASE=Tecnint HTE SRL
+
+OUI:70B3D52AB*
+ ID_OUI_FROM_DATABASE=NASA Johnson Space Center
+
+OUI:70B3D5254*
+ ID_OUI_FROM_DATABASE=Spectrum Brands
+
+OUI:70B3D57C9*
+ ID_OUI_FROM_DATABASE=Council Rock
+
+OUI:70B3D553A*
+ ID_OUI_FROM_DATABASE=Pano0ramic Power
+
+OUI:70B3D5E18*
+ ID_OUI_FROM_DATABASE=Plasmapp Co.,Ltd.
+
+OUI:70B3D5D44*
+ ID_OUI_FROM_DATABASE=ic-automation GmbH
+
+OUI:70B3D59D7*
+ ID_OUI_FROM_DATABASE=KM OptoElektronik GmbH
+
+OUI:70B3D561B*
+ ID_OUI_FROM_DATABASE=Nubewell Networks Pvt Ltd
+
 OUI:70B3D5D60*
  ID_OUI_FROM_DATABASE=Flintab AB
 
@@ -1337,9 +1481,6 @@ OUI:70B3D58A4*
 OUI:70B3D5166*
  ID_OUI_FROM_DATABASE=SERIAL IMAGE INC.
 
-OUI:70B3D5E59*
- ID_OUI_FROM_DATABASE=FRACARRO SPA
-
 OUI:70B3D576D*
  ID_OUI_FROM_DATABASE=Trimble
 
@@ -1775,9 +1916,6 @@ OUI:001BC5054*
 OUI:001BC5050*
  ID_OUI_FROM_DATABASE=TeliSwitch Solutions
 
-OUI:001BC5046*
- ID_OUI_FROM_DATABASE=Trans-European Research and Education Networking Association (TERENA)
-
 OUI:001BC5040*
  ID_OUI_FROM_DATABASE=OOO Actidata
 
@@ -1997,9 +2135,6 @@ OUI:70B3D5DE4*
 OUI:70B3D5712*
  ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC
 
-OUI:70B3D5580*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:70B3D5776*
  ID_OUI_FROM_DATABASE=Power Ltd.
 
@@ -2276,12 +2411,12 @@ OUI:70B3D521D*
 OUI:70B3D5E9C*
  ID_OUI_FROM_DATABASE=ATG UV Technology
 
-OUI:70B3D539E*
- ID_OUI_FROM_DATABASE=Lanmark Controls Inc.
-
 OUI:70B3D5267*
  ID_OUI_FROM_DATABASE=Zehntner Testing Instruments
 
+OUI:70B3D539E*
+ ID_OUI_FROM_DATABASE=Lanmark Controls Inc.
+
 OUI:70B3D5C2E*
  ID_OUI_FROM_DATABASE=Triax A/S
 
@@ -2324,12 +2459,12 @@ OUI:70B3D5DFD*
 OUI:70B3D5B30*
  ID_OUI_FROM_DATABASE=Systolé Hardware B.V.
 
-OUI:70B3D53BF*
- ID_OUI_FROM_DATABASE=Star Electronics GmbH & Co. KG
-
 OUI:70B3D5745*
  ID_OUI_FROM_DATABASE=TMSI LLC
 
+OUI:70B3D53BF*
+ ID_OUI_FROM_DATABASE=Star Electronics GmbH & Co. KG
+
 OUI:70B3D5D1C*
  ID_OUI_FROM_DATABASE=Specialised Imaging Limited
 
@@ -2342,12 +2477,12 @@ OUI:70B3D5ADF*
 OUI:70B3D522C*
  ID_OUI_FROM_DATABASE=Hiquel Elektronik- und Anlagenbau GmbH
 
-OUI:70B3D5DCE*
- ID_OUI_FROM_DATABASE=Stahl GmbH
-
 OUI:70B3D52A2*
  ID_OUI_FROM_DATABASE=Visualware, Inc.
 
+OUI:70B3D5DCE*
+ ID_OUI_FROM_DATABASE=Stahl GmbH
+
 OUI:70B3D5D08*
  ID_OUI_FROM_DATABASE=Veeco Instruments
 
@@ -2378,6 +2513,180 @@ OUI:70B3D542D*
 OUI:70B3D5332*
  ID_OUI_FROM_DATABASE=InnoSenT
 
+OUI:70B3D5A47*
+ ID_OUI_FROM_DATABASE=KANOA INC
+
+OUI:70B3D5F45*
+ ID_OUI_FROM_DATABASE=Norbit ODM AS
+
+OUI:70B3D5DEE*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5E59*
+ ID_OUI_FROM_DATABASE=Fracarro srl
+
+OUI:70B3D5127*
+ ID_OUI_FROM_DATABASE=VITEC
+
+OUI:001BC5046*
+ ID_OUI_FROM_DATABASE=GÉANT
+
+OUI:70B3D573A*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D59DE*
+ ID_OUI_FROM_DATABASE=System 11 Sp. z o.o.
+
+OUI:70B3D596D*
+ ID_OUI_FROM_DATABASE=MSB Elektronik und Gerätebau GmbH
+
+OUI:70B3D5C17*
+ ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC
+
+OUI:70B3D5108*
+ ID_OUI_FROM_DATABASE=TEX COMPUTER SRL
+
+OUI:70B3D54E7*
+ ID_OUI_FROM_DATABASE=Digital Domain
+
+OUI:70B3D5007*
+ ID_OUI_FROM_DATABASE=SENSONEO
+
+OUI:70B3D5D10*
+ ID_OUI_FROM_DATABASE=Contec DTx
+
+OUI:70B3D57F3*
+ ID_OUI_FROM_DATABASE=Shenzhen Virtual Clusters Information Technology Co.,Ltd.
+
+OUI:70B3D5C8C*
+ ID_OUI_FROM_DATABASE=Rollogo Limited
+
+OUI:70B3D5D4C*
+ ID_OUI_FROM_DATABASE=Elystec Technology Co., Ltd
+
+OUI:70B3D596B*
+ ID_OUI_FROM_DATABASE=FOCAL-JMLab
+
+OUI:70B3D584D*
+ ID_OUI_FROM_DATABASE=Quantum Design Inc.
+
+OUI:70B3D5E57*
+ ID_OUI_FROM_DATABASE=Iradimed
+
+OUI:70B3D5125*
+ ID_OUI_FROM_DATABASE=Securolytics, Inc.
+
+OUI:70B3D5C6E*
+ ID_OUI_FROM_DATABASE=Orion Technologies, LLC
+
+OUI:70B3D5CC8*
+ ID_OUI_FROM_DATABASE=PROFEN COMMUNICATIONS
+
+OUI:70B3D5FDB*
+ ID_OUI_FROM_DATABASE=Design SHIFT
+
+OUI:70B3D5791*
+ ID_OUI_FROM_DATABASE=Romteck Australia
+
+OUI:70B3D569F*
+ ID_OUI_FROM_DATABASE=T+A elektroakustik GmbH & Co.KG
+
+OUI:70B3D5D20*
+ ID_OUI_FROM_DATABASE=Rheonics GmbH
+
+OUI:70B3D55FB*
+ ID_OUI_FROM_DATABASE=TELEPLATFORMS
+
+OUI:70B3D5768*
+ ID_OUI_FROM_DATABASE=Kazan Networks Corporation
+
+OUI:70B3D56B2*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D57F7*
+ ID_OUI_FROM_DATABASE=JASCO Applied Sciences Canada Ltd
+
+OUI:70B3D5F42*
+ ID_OUI_FROM_DATABASE=Matsuhisa Corporation
+
+OUI:70B3D5381*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5488*
+ ID_OUI_FROM_DATABASE=Cardinal Scale Mfg Co
+
+OUI:70B3D5273*
+ ID_OUI_FROM_DATABASE=WeVo Tech
+
+OUI:70B3D5379*
+ ID_OUI_FROM_DATABASE=Vensi, Inc.
+
+OUI:70B3D50B2*
+ ID_OUI_FROM_DATABASE=ndb technologies
+
+OUI:70B3D5CB3*
+ ID_OUI_FROM_DATABASE=KST technology
+
+OUI:70B3D530D*
+ ID_OUI_FROM_DATABASE=Fiberbase
+
+OUI:70B3D5842*
+ ID_OUI_FROM_DATABASE=PLUTO Solution co.,ltd.
+
+OUI:70B3D5EB9*
+ ID_OUI_FROM_DATABASE=Thiel Audio Products Company, LLC
+
+OUI:70B3D5031*
+ ID_OUI_FROM_DATABASE=SHENZHEN GAONA ELECTRONIC CO.LTD
+
+OUI:70B3D5548*
+ ID_OUI_FROM_DATABASE=DIGIVERV INC
+
+OUI:70B3D5284*
+ ID_OUI_FROM_DATABASE=Globalcom Engineering SPA
+
+OUI:70B3D5A4E*
+ ID_OUI_FROM_DATABASE=Array Technologies Inc.
+
+OUI:70B3D5580*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D52F2*
+ ID_OUI_FROM_DATABASE=Health Care Originals, Inc.
+
+OUI:70B3D5B98*
+ ID_OUI_FROM_DATABASE=GSF Corporation Pte Ltd
+
+OUI:70B3D5BA9*
+ ID_OUI_FROM_DATABASE=Alma
+
+OUI:70B3D50DE*
+ ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG
+
+OUI:70B3D54B8*
+ ID_OUI_FROM_DATABASE=International Roll-Call Corporation
+
+OUI:70B3D5991*
+ ID_OUI_FROM_DATABASE=Javasparrow Inc.
+
+OUI:70B3D5894*
+ ID_OUI_FROM_DATABASE=UnI Systech Co.,Ltd
+
+OUI:70B3D516B*
+ ID_OUI_FROM_DATABASE=IOT Engineering
+
+OUI:70B3D53AA*
+ ID_OUI_FROM_DATABASE=RCATSONE
+
+OUI:70B3D5432*
+ ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH
+
+OUI:70B3D5086*
+ ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J.
+
+OUI:70B3D5E17*
+ ID_OUI_FROM_DATABASE=Private
+
 OUI:70B3D5494*
  ID_OUI_FROM_DATABASE=Schildknecht AG
 
@@ -3113,9 +3422,6 @@ OUI:70B3D50FA*
 OUI:70B3D531E*
  ID_OUI_FROM_DATABASE=GILLAM-FEI S.A.
 
-OUI:70B3D54D5*
- ID_OUI_FROM_DATABASE=Morgan Rekofa  GmbH
-
 OUI:70B3D58C5*
  ID_OUI_FROM_DATABASE=HMicro Inc
 
@@ -3152,9 +3458,6 @@ OUI:70B3D54FE*
 OUI:70B3D51FD*
  ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos
 
-OUI:70B3D5631*
- ID_OUI_FROM_DATABASE=SENSO2ME
-
 OUI:70B3D5396*
  ID_OUI_FROM_DATABASE=CTG sp. z o. o.
 
@@ -3173,9 +3476,6 @@ OUI:70B3D53D9*
 OUI:70B3D535F*
  ID_OUI_FROM_DATABASE=Aplex Technology Inc.
 
-OUI:70B3D5FFF*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:70B3D533E*
  ID_OUI_FROM_DATABASE=Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd.
 
@@ -3533,6 +3833,159 @@ OUI:70B3D5579*
 OUI:70B3D59B2*
  ID_OUI_FROM_DATABASE=CONTINENT, Ltd
 
+OUI:70B3D5365*
+ ID_OUI_FROM_DATABASE=CircuitMeter Inc.
+
+OUI:70B3D5805*
+ ID_OUI_FROM_DATABASE=Eurotronik Kranj d.o.o.
+
+OUI:70B3D5BF6*
+ ID_OUI_FROM_DATABASE=comtac AG
+
+OUI:70B3D50B4*
+ ID_OUI_FROM_DATABASE=AVER
+
+OUI:70B3D51B6*
+ ID_OUI_FROM_DATABASE=DACOM West GmbH
+
+OUI:70B3D59C1*
+ ID_OUI_FROM_DATABASE=Zeroplus Technology Co.,Ltd.
+
+OUI:70B3D5094*
+ ID_OUI_FROM_DATABASE=Circuitlink Pty Ltd
+
+OUI:70B3D5AA3*
+ ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD.,
+
+OUI:70B3D5AEF*
+ ID_OUI_FROM_DATABASE=Baumtec GmbH
+
+OUI:70B3D5D92*
+ ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd.
+
+OUI:70B3D5DA4*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5CC9*
+ ID_OUI_FROM_DATABASE=Rapiscan Systems
+
+OUI:70B3D52D0*
+ ID_OUI_FROM_DATABASE=ijin co.,ltd.
+
+OUI:70B3D50A0*
+ ID_OUI_FROM_DATABASE=Cominfo, Inc.
+
+OUI:70B3D520F*
+ ID_OUI_FROM_DATABASE=Tieline Research Pty Ltd
+
+OUI:70B3D5C20*
+ ID_OUI_FROM_DATABASE=Mipot S.p.a.
+
+OUI:70B3D54D5*
+ ID_OUI_FROM_DATABASE=Moog Rekofa  GmbH
+
+OUI:70B3D5D3C*
+ ID_OUI_FROM_DATABASE=HRT
+
+OUI:70B3D5DDB*
+ ID_OUI_FROM_DATABASE=Intra Corporation
+
+OUI:70B3D58EE*
+ ID_OUI_FROM_DATABASE=Network Additions
+
+OUI:70B3D5445*
+ ID_OUI_FROM_DATABASE=Advanced Devices SpA
+
+OUI:70B3D5674*
+ ID_OUI_FROM_DATABASE=Fortress Cyber Security
+
+OUI:70B3D5FFF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D5DB8*
+ ID_OUI_FROM_DATABASE=SISTEM SA
+
+OUI:70B3D5FBC*
+ ID_OUI_FROM_DATABASE=Twoway Communications, Inc.
+
+OUI:70B3D5969*
+ ID_OUI_FROM_DATABASE=Emtel System Sp. z o.o.
+
+OUI:70B3D5C33*
+ ID_OUI_FROM_DATABASE=Dandong Dongfang Measurement & Control Technology Co., Ltd.
+
+OUI:70B3D5B2E*
+ ID_OUI_FROM_DATABASE=Green Access Ltd
+
+OUI:70B3D558C*
+ ID_OUI_FROM_DATABASE=OPTSYS
+
+OUI:70B3D595B*
+ ID_OUI_FROM_DATABASE=SRS Group s.r.o.
+
+OUI:70B3D534E*
+ ID_OUI_FROM_DATABASE=Risk Expert sarl
+
+OUI:70B3D56AD*
+ ID_OUI_FROM_DATABASE=CONNIT
+
+OUI:70B3D5C14*
+ ID_OUI_FROM_DATABASE=Grupo Epelsa S.L.
+
+OUI:70B3D5631*
+ ID_OUI_FROM_DATABASE=SENSO2ME bvba
+
+OUI:70B3D5C53*
+ ID_OUI_FROM_DATABASE=S Labs sp. z o.o.
+
+OUI:70B3D5F24*
+ ID_OUI_FROM_DATABASE=Daavlin
+
+OUI:70B3D56E7*
+ ID_OUI_FROM_DATABASE=AML
+
+OUI:70B3D577B*
+ ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc.
+
+OUI:70B3D504E*
+ ID_OUI_FROM_DATABASE=HUGEL GmbH
+
+OUI:70B3D5319*
+ ID_OUI_FROM_DATABASE=ISO/TC 22/SC 31
+
+OUI:70B3D5844*
+ ID_OUI_FROM_DATABASE=SANSFIL Technologies
+
+OUI:70B3D5826*
+ ID_OUI_FROM_DATABASE=Elbit Systems of Amerixca
+
+OUI:70B3D5C42*
+ ID_OUI_FROM_DATABASE=CRDE
+
+OUI:70B3D5557*
+ ID_OUI_FROM_DATABASE=HEITEC AG
+
+OUI:70B3D568C*
+ ID_OUI_FROM_DATABASE=ND METER
+
+OUI:70B3D5727*
+ ID_OUI_FROM_DATABASE=LP Technologies Inc.
+
+OUI:70B3D549B*
+ ID_OUI_FROM_DATABASE=Algodue Elettronica Srl
+
+OUI:70B3D57F9*
+ ID_OUI_FROM_DATABASE=CSS Inc.
+
+OUI:70B3D592B*
+ ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD.
+
+OUI:70B3D5B13*
+ ID_OUI_FROM_DATABASE=Omwave
+
+OUI:70B3D5EA7*
+ ID_OUI_FROM_DATABASE=S.I.C.E.S. srl
+
 OUI:70B3D566B*
  ID_OUI_FROM_DATABASE=Innitive B.V.
 
@@ -3698,9 +4151,6 @@ OUI:70B3D5435*
 OUI:70B3D50CD*
  ID_OUI_FROM_DATABASE=AML Oceanographic
 
-OUI:70B3D56E8*
- ID_OUI_FROM_DATABASE=BluWireless Technology Ltd
-
 OUI:70B3D56B3*
  ID_OUI_FROM_DATABASE=DuraComm Corporation
 
@@ -4232,9 +4682,6 @@ OUI:70B3D5528*
 OUI:70B3D5B81*
  ID_OUI_FROM_DATABASE=Instro Precision Limited
 
-OUI:70B3D5479*
- ID_OUI_FROM_DATABASE=LINEAGE POWER PVT. LTD.
-
 OUI:70B3D5A66*
  ID_OUI_FROM_DATABASE=Trapeze Software Group Inc
 
@@ -4712,6 +5159,126 @@ OUI:70B3D5138*
 OUI:70B3D517A*
  ID_OUI_FROM_DATABASE=Gencoa Ltd
 
+OUI:70B3D5C49*
+ ID_OUI_FROM_DATABASE=BTG Instruments AB
+
+OUI:70B3D530B*
+ ID_OUI_FROM_DATABASE=Ash Technologies
+
+OUI:70B3D56A6*
+ ID_OUI_FROM_DATABASE=WOW System
+
+OUI:70B3D5FEF*
+ ID_OUI_FROM_DATABASE=HANGZHOU HUALAN MICROELECTRONIQUE CO.,LTD
+
+OUI:70B3D5211*
+ ID_OUI_FROM_DATABASE=Fracarro srl
+
+OUI:70B3D560A*
+ ID_OUI_FROM_DATABASE=TATA POWER SED
+
+OUI:70B3D5129*
+ ID_OUI_FROM_DATABASE=OOO Microlink-Svyaz
+
+OUI:70B3D5479*
+ ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD.,
+
+OUI:70B3D564C*
+ ID_OUI_FROM_DATABASE=ACEMIS FRANCE
+
+OUI:70B3D5763*
+ ID_OUI_FROM_DATABASE=A Trap, USA
+
+OUI:70B3D5175*
+ ID_OUI_FROM_DATABASE=Akribis Systems
+
+OUI:70B3D547F*
+ ID_OUI_FROM_DATABASE=ASE GmbH
+
+OUI:70B3D5DC9*
+ ID_OUI_FROM_DATABASE=Sensoterra BV
+
+OUI:70B3D5371*
+ ID_OUI_FROM_DATABASE=BEDEROV GmbH
+
+OUI:70B3D559C*
+ ID_OUI_FROM_DATABASE=DAVE SRL
+
+OUI:70B3D5C79*
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
+OUI:70B3D5B04*
+ ID_OUI_FROM_DATABASE=Herrmann Datensysteme GmbH
+
+OUI:70B3D5229*
+ ID_OUI_FROM_DATABASE=CONTROL SYSTEMS Srl
+
+OUI:70B3D555E*
+ ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos
+
+OUI:70B3D5EE3*
+ ID_OUI_FROM_DATABASE=Lithe Technology, LLC
+
+OUI:70B3D5D69*
+ ID_OUI_FROM_DATABASE=Thermo Fisher Scientific
+
+OUI:70B3D5FA0*
+ ID_OUI_FROM_DATABASE=TIAMA
+
+OUI:70B3D57DF*
+ ID_OUI_FROM_DATABASE=RDT Ltd
+
+OUI:70B3D508D*
+ ID_OUI_FROM_DATABASE=Clover Electronics Technology Co., Ltd.
+
+OUI:70B3D57D2*
+ ID_OUI_FROM_DATABASE=SDK Kristall
+
+OUI:70B3D5AF0*
+ ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY
+
+OUI:70B3D5D6C*
+ ID_OUI_FROM_DATABASE=GP Systems GmbH
+
+OUI:70B3D56AF*
+ ID_OUI_FROM_DATABASE=Sensorberg GmbH
+
+OUI:70B3D518E*
+ ID_OUI_FROM_DATABASE=NIPPON SEIKI CO., LTD.
+
+OUI:70B3D5C0C*
+ ID_OUI_FROM_DATABASE=Tech4Race
+
+OUI:70B3D55D8*
+ ID_OUI_FROM_DATABASE=LYNX Technik AG
+
+OUI:70B3D5374*
+ ID_OUI_FROM_DATABASE=OOO NPP Mars-Energo
+
+OUI:70B3D54A5*
+ ID_OUI_FROM_DATABASE=Intermind Inc.
+
+OUI:70B3D5C1D*
+ ID_OUI_FROM_DATABASE=Kranze Technology Solutions
+
+OUI:70B3D5CC3*
+ ID_OUI_FROM_DATABASE=Fidalia Networks Inc
+
+OUI:70B3D507F*
+ ID_OUI_FROM_DATABASE=Abalance Corporation
+
+OUI:70B3D56E8*
+ ID_OUI_FROM_DATABASE=Blu Wireless Technology Ltd
+
+OUI:70B3D5CD3*
+ ID_OUI_FROM_DATABASE=Controlrad
+
+OUI:70B3D54E5*
+ ID_OUI_FROM_DATABASE=viZaar industrial imaging AG
+
+OUI:70B3D5DE6*
+ ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
+
 OUI:70B3D58AB*
  ID_OUI_FROM_DATABASE=EMAC, Inc.
 
@@ -5192,9 +5759,6 @@ OUI:70B3D53C2*
 OUI:70B3D5EF9*
  ID_OUI_FROM_DATABASE=Critical Link
 
-OUI:001BC50B2*
- ID_OUI_FROM_DATABASE=SKODA electric a.s.
-
 OUI:001BC50B6*
  ID_OUI_FROM_DATABASE=Veilux inc.
 
@@ -5726,12 +6290,12 @@ OUI:70B3D520D*
 OUI:70B3D5D55*
  ID_OUI_FROM_DATABASE=WM Design s.r.o
 
-OUI:70B3D5523*
- ID_OUI_FROM_DATABASE=Tibit Communications
-
 OUI:70B3D5E67*
  ID_OUI_FROM_DATABASE=APPLIED PROCESSING
 
+OUI:70B3D5523*
+ ID_OUI_FROM_DATABASE=Tibit Communications
+
 OUI:70B3D5241*
  ID_OUI_FROM_DATABASE=Bolide Technology Group, Inc.
 
@@ -5762,15 +6326,15 @@ OUI:70B3D5A05*
 OUI:70B3D5AA6*
  ID_OUI_FROM_DATABASE=Proximus
 
+OUI:70B3D51D4*
+ ID_OUI_FROM_DATABASE=Brinkmann Audio GmbH
+
 OUI:70B3D55E5*
  ID_OUI_FROM_DATABASE=HAIYANG OLIX CO.,LTD.
 
 OUI:70B3D5E2C*
  ID_OUI_FROM_DATABASE=Fourth Frontier Technologies Private Limited
 
-OUI:70B3D51D4*
- ID_OUI_FROM_DATABASE=Brinkmann Audio GmbH
-
 OUI:70B3D55CA*
  ID_OUI_FROM_DATABASE=ACD Elekronik GmbH
 
@@ -5804,12 +6368,12 @@ OUI:70B3D5EC8*
 OUI:70B3D53F0*
  ID_OUI_FROM_DATABASE=Intervala
 
-OUI:70B3D5B1A*
- ID_OUI_FROM_DATABASE=Aaronia AG
-
 OUI:70B3D5BD1*
  ID_OUI_FROM_DATABASE=CableLabs
 
+OUI:70B3D5B1A*
+ ID_OUI_FROM_DATABASE=Aaronia AG
+
 OUI:70B3D5F0D*
  ID_OUI_FROM_DATABASE=MeQ Inc.
 
@@ -5852,6 +6416,138 @@ OUI:70B3D5442*
 OUI:70B3D5C74*
  ID_OUI_FROM_DATABASE=Qtechnology A/S
 
+OUI:70B3D5E16*
+ ID_OUI_FROM_DATABASE=China Entropy Co., Ltd.
+
+OUI:70B3D502E*
+ ID_OUI_FROM_DATABASE=Monnit Corporation
+
+OUI:70B3D5370*
+ ID_OUI_FROM_DATABASE=Inphi Corporation
+
+OUI:70B3D57E8*
+ ID_OUI_FROM_DATABASE=Mannkind Corporation
+
+OUI:70B3D53F3*
+ ID_OUI_FROM_DATABASE=SPEA SPA
+
+OUI:70B3D5549*
+ ID_OUI_FROM_DATABASE=Procon automatic systems GmbH
+
+OUI:70B3D5831*
+ ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp
+
+OUI:70B3D5D8E*
+ ID_OUI_FROM_DATABASE=Axatel SrL
+
+OUI:70B3D5A28*
+ ID_OUI_FROM_DATABASE=PEEK TRAFFIC
+
+OUI:70B3D5AC7*
+ ID_OUI_FROM_DATABASE=vivaMOS
+
+OUI:70B3D5DB2*
+ ID_OUI_FROM_DATABASE=Micro Electroninc Products
+
+OUI:70B3D5967*
+ ID_OUI_FROM_DATABASE=TATTILE SRL
+
+OUI:70B3D5C16*
+ ID_OUI_FROM_DATABASE=Southern Innovation
+
+OUI:70B3D590F*
+ ID_OUI_FROM_DATABASE=DTRON Communications (Pty) Ltd
+
+OUI:70B3D5E22*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:70B3D5408*
+ ID_OUI_FROM_DATABASE=Comrod AS
+
+OUI:70B3D5945*
+ ID_OUI_FROM_DATABASE=Symboticware Incorporated
+
+OUI:70B3D5D4D*
+ ID_OUI_FROM_DATABASE=The Morey Corporation
+
+OUI:70B3D5192*
+ ID_OUI_FROM_DATABASE=ASPT, INC.
+
+OUI:70B3D5807*
+ ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak
+
+OUI:70B3D5DD1*
+ ID_OUI_FROM_DATABASE=em-tec GmbH
+
+OUI:70B3D5ED1*
+ ID_OUI_FROM_DATABASE=Przemyslowy Instytut Automatyki i Pomiarow
+
+OUI:70B3D514A*
+ ID_OUI_FROM_DATABASE=ExSens Technology (Pty) Ltd.
+
+OUI:70B3D5A69*
+ ID_OUI_FROM_DATABASE=Leviathan Solutions Ltd.
+
+OUI:70B3D5A9A*
+ ID_OUI_FROM_DATABASE=Amphenol Advanced Sensors
+
+OUI:70B3D5715*
+ ID_OUI_FROM_DATABASE=RIOT
+
+OUI:70B3D5FF8*
+ ID_OUI_FROM_DATABASE=Dutile, Glines and Higgins Corporation
+
+OUI:70B3D5413*
+ ID_OUI_FROM_DATABASE=Axess AG
+
+OUI:70B3D5E5E*
+ ID_OUI_FROM_DATABASE=Critical Link LLC
+
+OUI:70B3D5E7D*
+ ID_OUI_FROM_DATABASE=Nanjing Dandick Science&technology development co., LTD
+
+OUI:70B3D5D98*
+ ID_OUI_FROM_DATABASE=ACD Elekronik GmbH
+
+OUI:70B3D5FA6*
+ ID_OUI_FROM_DATABASE=RFL Electronics, Inc.
+
+OUI:70B3D5D43*
+ ID_OUI_FROM_DATABASE=EZSYS Co., Ltd.
+
+OUI:70B3D5A35*
+ ID_OUI_FROM_DATABASE=Sicon srl
+
+OUI:70B3D5359*
+ ID_OUI_FROM_DATABASE=Boutronic
+
+OUI:70B3D5279*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:001BC50B2*
+ ID_OUI_FROM_DATABASE=SKODA ELECTRIC a.s.
+
+OUI:70B3D5035*
+ ID_OUI_FROM_DATABASE=HKW-Elektronik GmbH
+
+OUI:70B3D5DFA*
+ ID_OUI_FROM_DATABASE=Newtouch Electronics (Shanghai) Co.,Ltd.
+
+OUI:70B3D5EC7*
+ ID_OUI_FROM_DATABASE=Neoptix Inc.
+
+OUI:70B3D55B8*
+ ID_OUI_FROM_DATABASE=Hella Gutmann Solutions GmbH
+
+OUI:70B3D5203*
+ ID_OUI_FROM_DATABASE=WOOJIN Inc
+
+OUI:70B3D5845*
+ ID_OUI_FROM_DATABASE=Harborside Technology
+
+OUI:70B3D52F4*
+ ID_OUI_FROM_DATABASE=Radixon s.r.o.
+
 OUI:1C8776D*
  ID_OUI_FROM_DATABASE=Qivivo
 
@@ -6110,9 +6806,6 @@ OUI:28FD803*
 OUI:E818635*
  ID_OUI_FROM_DATABASE=WETEK ELECTRONICS LIMITED
 
-OUI:E818632*
- ID_OUI_FROM_DATABASE=AVCON Information Technology Co.,Ltd
-
 OUI:B8D812D*
  ID_OUI_FROM_DATABASE=Lam Research
 
@@ -6368,9 +7061,6 @@ OUI:CCD31E3*
 OUI:D0D94F9*
  ID_OUI_FROM_DATABASE=Hangzhou xiaoben technology co.,Ltd
 
-OUI:D0D94F7*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:D0D94F0*
  ID_OUI_FROM_DATABASE=Perfant Technology Co., Ltd
 
@@ -6392,39 +7082,18 @@ OUI:283638A*
 OUI:CC1BE0F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:F40E11F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:D07650F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:E81863F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:F80278F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:9802D8F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:90C682F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:283638D*
  ID_OUI_FROM_DATABASE=APPEAK Technology System Co.Ltd.
 
-OUI:1CCAE3F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:2836389*
  ID_OUI_FROM_DATABASE=Shenzhen  Zhi Hua  Creative Technology  Co., Ltd.
 
 OUI:B0C5CA7*
  ID_OUI_FROM_DATABASE=SHENZHEN KTC TECHNOLOGY GROUP
 
-OUI:283638E*
- ID_OUI_FROM_DATABASE=SCA Hygiene Products AB
-
 OUI:F0ACD73*
  ID_OUI_FROM_DATABASE=Med-Pat/Inn-Phone
 
@@ -6611,12 +7280,12 @@ OUI:40F3854*
 OUI:40F3859*
  ID_OUI_FROM_DATABASE=Fast Precision Technologies Co. Ltd.
 
-OUI:1CA0D32*
- ID_OUI_FROM_DATABASE=NovTech, Inc.
-
 OUI:40F3850*
  ID_OUI_FROM_DATABASE=SubPac
 
+OUI:1CA0D32*
+ ID_OUI_FROM_DATABASE=NovTech, Inc.
+
 OUI:38FDFEC*
  ID_OUI_FROM_DATABASE=New Garden Co., Ltd.
 
@@ -6656,12 +7325,12 @@ OUI:98AAFC8*
 OUI:98AAFCC*
  ID_OUI_FROM_DATABASE=dots Inc.
 
-OUI:08ED026*
- ID_OUI_FROM_DATABASE=SANGO ELECTRONICS CO
-
 OUI:08ED023*
  ID_OUI_FROM_DATABASE=Jiangsu Logread Network Technology Co., LTD.
 
+OUI:08ED026*
+ ID_OUI_FROM_DATABASE=SANGO ELECTRONICS CO
+
 OUI:08ED024*
  ID_OUI_FROM_DATABASE=Fio Corporation
 
@@ -6695,6 +7364,162 @@ OUI:8C147DC*
 OUI:8C147D0*
  ID_OUI_FROM_DATABASE=Nio
 
+OUI:A0C5F26*
+ ID_OUI_FROM_DATABASE=ShenZhen JuWangShi Tech
+
+OUI:A0C5F22*
+ ID_OUI_FROM_DATABASE=Speedgoat GmbH
+
+OUI:A0C5F24*
+ ID_OUI_FROM_DATABASE=AiCare Corp.
+
+OUI:4C65A8A*
+ ID_OUI_FROM_DATABASE=Suzhou Embedded Electronic Technology Co., Ltd.
+
+OUI:F88A3C8*
+ ID_OUI_FROM_DATABASE=Cadmus Electronic Co.,Ltd.
+
+OUI:7CBACCB*
+ ID_OUI_FROM_DATABASE=Briowireless Inc.
+
+OUI:7CBACC3*
+ ID_OUI_FROM_DATABASE=Izkare
+
+OUI:F40E11F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:78D8001*
+ ID_OUI_FROM_DATABASE=Shenzhen Envicool Information Technology Co., Ltd
+
+OUI:78D8003*
+ ID_OUI_FROM_DATABASE=Shenzhen Scodeno Technology Co,. Ltd.
+
+OUI:78D8007*
+ ID_OUI_FROM_DATABASE=NimbeLink Corp
+
+OUI:78D800A*
+ ID_OUI_FROM_DATABASE=Insignal Co., Ltd.
+
+OUI:78D8008*
+ ID_OUI_FROM_DATABASE=Salunda Ltd
+
+OUI:78D800E*
+ ID_OUI_FROM_DATABASE=CL International
+
+OUI:28F5378*
+ ID_OUI_FROM_DATABASE=1MORE, INC.
+
+OUI:28F5379*
+ ID_OUI_FROM_DATABASE=Herbert Waldmann GmbH & Co. KG
+
+OUI:28F5375*
+ ID_OUI_FROM_DATABASE=Atomrock LLC
+
+OUI:1CCAE3F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:90C682F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:9802D8F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:F80278F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:D07650F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:28F537C*
+ ID_OUI_FROM_DATABASE=Matricx Singapore Pte Ltd
+
+OUI:28F537B*
+ ID_OUI_FROM_DATABASE=LogiM GmbH Software und Entwicklung
+
+OUI:E818632*
+ ID_OUI_FROM_DATABASE=AVCON Information Technology Co.,Ltd
+
+OUI:34298F6*
+ ID_OUI_FROM_DATABASE=Bellman & Symfon
+
+OUI:34298F5*
+ ID_OUI_FROM_DATABASE=Highlite International B.V.
+
+OUI:34298FC*
+ ID_OUI_FROM_DATABASE=Albert Handtmann Maschinenfabrik GmbH&Co.KG
+
+OUI:34298F8*
+ ID_OUI_FROM_DATABASE=Nanjing Sandemarine Electric Co.,Ltd
+
+OUI:189BA5A*
+ ID_OUI_FROM_DATABASE=SHENZHEN FIONEXX TECHNOLOGIES LTD.
+
+OUI:189BA57*
+ ID_OUI_FROM_DATABASE=Beijing Xinertel Technology Co., Ltd.
+
+OUI:904E915*
+ ID_OUI_FROM_DATABASE=mcf88 SRL
+
+OUI:904E917*
+ ID_OUI_FROM_DATABASE=IBM
+
+OUI:904E916*
+ ID_OUI_FROM_DATABASE=Nuwa Robotics (HK) Limited Taiwan Branch
+
+OUI:904E910*
+ ID_OUI_FROM_DATABASE=Spirtech
+
+OUI:2C279ED*
+ ID_OUI_FROM_DATABASE=Jiangsu JianHu Science & Technology Co., Ltd.
+
+OUI:904E91E*
+ ID_OUI_FROM_DATABASE=Shenzhen Cloudynamo Internet Technologies Co.,LTD.
+
+OUI:2C279E0*
+ ID_OUI_FROM_DATABASE=Changzhou WEBO Weighing Device & System CO.,LTD
+
+OUI:904E91D*
+ ID_OUI_FROM_DATABASE=SKODA ELECTRIC a.s.
+
+OUI:2C279EC*
+ ID_OUI_FROM_DATABASE=WAYCOM Technology Co.,Ltd
+
+OUI:283638E*
+ ID_OUI_FROM_DATABASE=SCA Hygiene Products AB
+
+OUI:2C279E2*
+ ID_OUI_FROM_DATABASE=Kunyi electronic technology (Shanghai) Co., Ltd.
+
+OUI:2C279E9*
+ ID_OUI_FROM_DATABASE=octoScope, Inc.
+
+OUI:D0D94F7*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:CC2237C*
+ ID_OUI_FROM_DATABASE=Hebei ZHSF Technology Co.,Ltd.
+
+OUI:CC2237A*
+ ID_OUI_FROM_DATABASE=shenzhen zonglian network technology limited
+
+OUI:CC22375*
+ ID_OUI_FROM_DATABASE=Beijing Safesoft Greatmaker Co.,ltd
+
+OUI:CC22378*
+ ID_OUI_FROM_DATABASE=Safilo S.p.A.
+
+OUI:741AE00*
+ ID_OUI_FROM_DATABASE=Huano International Technology Limited
+
+OUI:741AE07*
+ ID_OUI_FROM_DATABASE=BÄR Bahnsicherung AG
+
+OUI:741AE01*
+ ID_OUI_FROM_DATABASE=Socionext Inc.
+
+OUI:741AE0A*
+ ID_OUI_FROM_DATABASE=SAIERCOM CORPORATION
+
 OUI:1C8776C*
  ID_OUI_FROM_DATABASE=Strone Technology
 
@@ -6755,9 +7580,6 @@ OUI:CC1BE0B*
 OUI:CC1BE07*
  ID_OUI_FROM_DATABASE=Sichuan Dianjia network technology Co.Ltd.
 
-OUI:CC1BE00*
- ID_OUI_FROM_DATABASE=MICROTECH SYSTEM
-
 OUI:DC44270*
  ID_OUI_FROM_DATABASE=Suritel
 
@@ -7265,9 +8087,6 @@ OUI:C0D3916*
 OUI:C0D3912*
  ID_OUI_FROM_DATABASE=Hofon Automation Co.,Ltd
 
-OUI:C0D391B*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:84E0F40*
  ID_OUI_FROM_DATABASE=ShenZhen Panrich Technology Limited
 
@@ -7322,9 +8141,6 @@ OUI:D02212F*
 OUI:100723F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:B0C5CAF*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:2836383*
  ID_OUI_FROM_DATABASE=Sabinetek
 
@@ -7334,15 +8150,6 @@ OUI:2836380*
 OUI:8C192D7*
  ID_OUI_FROM_DATABASE=SRETT
 
-OUI:7C70BCF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:A43BFAF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:B01F81F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:0055DAF*
  ID_OUI_FROM_DATABASE=Private
 
@@ -7472,15 +8279,15 @@ OUI:40F3855*
 OUI:1CA0D35*
  ID_OUI_FROM_DATABASE=Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd.
 
-OUI:1CA0D33*
- ID_OUI_FROM_DATABASE=SAVELEC
-
 OUI:1CA0D37*
  ID_OUI_FROM_DATABASE=Private
 
 OUI:A411634*
  ID_OUI_FROM_DATABASE=AlterG, Inc.
 
+OUI:1CA0D33*
+ ID_OUI_FROM_DATABASE=SAVELEC
+
 OUI:A411631*
  ID_OUI_FROM_DATABASE=INTER CONTROL Hermann Köhler Elektrik GmbH & Co.KG
 
@@ -7520,24 +8327,141 @@ OUI:60D7E31*
 OUI:04714B1*
  ID_OUI_FROM_DATABASE=uAvionix Corporation
 
-OUI:04714B2*
- ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd.
-
 OUI:04714B8*
  ID_OUI_FROM_DATABASE=Energport Inc
 
-OUI:8C147D5*
- ID_OUI_FROM_DATABASE=Unwired Networks
-
 OUI:F023B94*
  ID_OUI_FROM_DATABASE=EZVIS LIMITED
 
 OUI:F023B9A*
  ID_OUI_FROM_DATABASE=annapurnalabs
 
+OUI:8C147D5*
+ ID_OUI_FROM_DATABASE=Unwired Networks
+
 OUI:8C147D2*
  ID_OUI_FROM_DATABASE=Agilent S.p.A
 
+OUI:8C147DE*
+ ID_OUI_FROM_DATABASE=Electrical & Automation Larsen & Toubro Limited
+
+OUI:A0C5F29*
+ ID_OUI_FROM_DATABASE=Impulse Networks Pte Ltd
+
+OUI:A0C5F2B*
+ ID_OUI_FROM_DATABASE=Oray.com co., LTD.
+
+OUI:4C65A89*
+ ID_OUI_FROM_DATABASE=SHENZHEN LISAIER TRONICS CO.,LTD
+
+OUI:4C65A86*
+ ID_OUI_FROM_DATABASE=Nuviz Oy
+
+OUI:A0C5F23*
+ ID_OUI_FROM_DATABASE=Shenzhen Feima Robotics Technology Co.,Ltd
+
+OUI:7C70BCF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:B01F81F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:7CBACC5*
+ ID_OUI_FROM_DATABASE=Fortem Technologies, Inc.
+
+OUI:78D8006*
+ ID_OUI_FROM_DATABASE=Alango Technologies Ltd
+
+OUI:78D800C*
+ ID_OUI_FROM_DATABASE=Shenzhen Chenzhuo Technology Co., Ltd.
+
+OUI:28F5374*
+ ID_OUI_FROM_DATABASE=Phyn LLC
+
+OUI:A43BFAF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:28F5376*
+ ID_OUI_FROM_DATABASE=MyOmega Systems GmbH
+
+OUI:28F5377*
+ ID_OUI_FROM_DATABASE=Shenzhen Modern Cowboy Technology Co.,Ltd.
+
+OUI:28F537A*
+ ID_OUI_FROM_DATABASE=Honeywell Safety Products USA, Inc
+
+OUI:B0C5CAF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:34008A4*
+ ID_OUI_FROM_DATABASE=Fotonic i Norden AB
+
+OUI:34008A7*
+ ID_OUI_FROM_DATABASE=uberGARD Pte. Ltd.
+
+OUI:34008A8*
+ ID_OUI_FROM_DATABASE=Shenzhen Andakai Technologies Co., Ltd.
+
+OUI:34008A0*
+ ID_OUI_FROM_DATABASE=Angee Technologies Ltd.
+
+OUI:34008AC*
+ ID_OUI_FROM_DATABASE=Shenzhen Eternal Idea Tech Co.,Ltd
+
+OUI:34298F0*
+ ID_OUI_FROM_DATABASE=BlackEdge Capital
+
+OUI:34298F1*
+ ID_OUI_FROM_DATABASE=Chengdu Meross Technology Co., Ltd.
+
+OUI:CC1BE00*
+ ID_OUI_FROM_DATABASE=Microtech System,Inc
+
+OUI:189BA56*
+ ID_OUI_FROM_DATABASE=Mantra Softech India Pvt Ltd
+
+OUI:189BA52*
+ ID_OUI_FROM_DATABASE=Airprotec
+
+OUI:189BA50*
+ ID_OUI_FROM_DATABASE=Dectris Ltd.
+
+OUI:189BA5B*
+ ID_OUI_FROM_DATABASE=Eutron SPA
+
+OUI:189BA58*
+ ID_OUI_FROM_DATABASE=Shenzhen Tong Tai Yi information Technology Co.,Ltd
+
+OUI:C0D391B*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:904E918*
+ ID_OUI_FROM_DATABASE=CommandScape, Inc.
+
+OUI:2C279E6*
+ ID_OUI_FROM_DATABASE=Rutledge Omni Services Pte Ltd
+
+OUI:CC22372*
+ ID_OUI_FROM_DATABASE=Apeiron Data Systems
+
+OUI:04714B2*
+ ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd.
+
+OUI:741AE04*
+ ID_OUI_FROM_DATABASE=Revl Inc.
+
+OUI:741AE09*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:741AE0B*
+ ID_OUI_FROM_DATABASE=SHEN ZHEN YINGJIACHUANG ELECTRONICS TECHNOLOGY CO.,LTD.
+
+OUI:741AE05*
+ ID_OUI_FROM_DATABASE=FUJIAN TAILI COMMUNICATION TECHNOLOGY CO.,LTD
+
+OUI:741AE0C*
+ ID_OUI_FROM_DATABASE=bistos.co.ltd
+
 OUI:1C87765*
  ID_OUI_FROM_DATABASE=Zhuhai MYZR Technology Co.,Ltd
 
@@ -7826,9 +8750,6 @@ OUI:2C265F0*
 OUI:F80278D*
  ID_OUI_FROM_DATABASE=Dueton Systems s.r.o.
 
-OUI:0CEFAFB*
- ID_OUI_FROM_DATABASE=Hubei Century Network Technology Co .Ltd
-
 OUI:A44F291*
  ID_OUI_FROM_DATABASE=Olssen B.V.
 
@@ -8135,27 +9056,12 @@ OUI:8C192DC*
 OUI:8C192D9*
  ID_OUI_FROM_DATABASE=ViaWear, Inc.
 
-OUI:BC3400F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:7419F8F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:1C21D1F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:DC4427F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:C88ED1F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:80E4DAF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:885D90F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:2836385*
  ID_OUI_FROM_DATABASE=CHARGELIB
 
@@ -8342,12 +9248,12 @@ OUI:1CA0D3B*
 OUI:1CA0D3D*
  ID_OUI_FROM_DATABASE=ERATO (HK) Corporation Limited
 
-OUI:1CA0D3A*
- ID_OUI_FROM_DATABASE=DSM Messtechnik GmbH
-
 OUI:1CA0D38*
  ID_OUI_FROM_DATABASE=Desarrollos y Soluciones Guinea I+D S.L.
 
+OUI:1CA0D3A*
+ ID_OUI_FROM_DATABASE=DSM Messtechnik GmbH
+
 OUI:A411638*
  ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc.
 
@@ -8357,12 +9263,12 @@ OUI:A411639*
 OUI:A41163A*
  ID_OUI_FROM_DATABASE=ISE GmbH
 
-OUI:A411635*
- ID_OUI_FROM_DATABASE=Carbon, Inc.
-
 OUI:4CE1731*
  ID_OUI_FROM_DATABASE=Nexoforge Inc.
 
+OUI:A411635*
+ ID_OUI_FROM_DATABASE=Carbon, Inc.
+
 OUI:144FD70*
  ID_OUI_FROM_DATABASE=annapurnalabs
 
@@ -8417,6 +9323,129 @@ OUI:F023B99*
 OUI:F023B91*
  ID_OUI_FROM_DATABASE=Ubiant
 
+OUI:8C147D7*
+ ID_OUI_FROM_DATABASE=UrbanHello
+
+OUI:8C147D9*
+ ID_OUI_FROM_DATABASE=Anyware Solutions ApS
+
+OUI:A0C5F27*
+ ID_OUI_FROM_DATABASE=Viettronimex JSC
+
+OUI:A0C5F25*
+ ID_OUI_FROM_DATABASE=Tango Wave
+
+OUI:A0C5F2C*
+ ID_OUI_FROM_DATABASE=Glooko inc
+
+OUI:4C65A83*
+ ID_OUI_FROM_DATABASE=Roost
+
+OUI:4C65A8D*
+ ID_OUI_FROM_DATABASE=Qingping Technology (Beijing) Co., Ltd.
+
+OUI:F88A3C4*
+ ID_OUI_FROM_DATABASE=GO-LINK TECHNOLOGY CO., LTD.
+
+OUI:F88A3C0*
+ ID_OUI_FROM_DATABASE=ART SPA
+
+OUI:F88A3CE*
+ ID_OUI_FROM_DATABASE=Avateq Corp.
+
+OUI:F88A3CA*
+ ID_OUI_FROM_DATABASE=Protos GmbH
+
+OUI:7CBACC0*
+ ID_OUI_FROM_DATABASE=TGT Limited
+
+OUI:7CBACCA*
+ ID_OUI_FROM_DATABASE=annapurnalabs
+
+OUI:7CBACC4*
+ ID_OUI_FROM_DATABASE=Sun Asia Trade Co.
+
+OUI:885D90F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:BC3400F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:28F537D*
+ ID_OUI_FROM_DATABASE=Skyrockettoys LLC
+
+OUI:7419F8F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:80E4DAF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:28F5373*
+ ID_OUI_FROM_DATABASE=PRIMETECH ENGINEERING CORP.
+
+OUI:34008A2*
+ ID_OUI_FROM_DATABASE=RPE Monitor
+
+OUI:0CEFAFB*
+ ID_OUI_FROM_DATABASE=Hubei Century Network Technology Co., Ltd
+
+OUI:34008AB*
+ ID_OUI_FROM_DATABASE=Project Engineering srl
+
+OUI:34298FA*
+ ID_OUI_FROM_DATABASE=Virtual Trunk Pte Ltd
+
+OUI:DC4427F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:189BA5C*
+ ID_OUI_FROM_DATABASE=Christ Electronic System GmbH
+
+OUI:189BA59*
+ ID_OUI_FROM_DATABASE=APANA Inc.
+
+OUI:189BA51*
+ ID_OUI_FROM_DATABASE=ChengDu Vantron Technology, Ltd.
+
+OUI:189BA5D*
+ ID_OUI_FROM_DATABASE=legendsky tech
+
+OUI:904E911*
+ ID_OUI_FROM_DATABASE=Apollo Video Technology
+
+OUI:904E91B*
+ ID_OUI_FROM_DATABASE=Shanghai JaWay Information Technology Co., Ltd.
+
+OUI:904E912*
+ ID_OUI_FROM_DATABASE=North Pole Engineering, Inc.
+
+OUI:2C279E3*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:2C279EA*
+ ID_OUI_FROM_DATABASE=Exegy Inc
+
+OUI:2C279E1*
+ ID_OUI_FROM_DATABASE=Electronique Bluewave Inc.
+
+OUI:2C279E8*
+ ID_OUI_FROM_DATABASE=Institut Dr. Foerster GmbH & Co. KG
+
+OUI:CC2237D*
+ ID_OUI_FROM_DATABASE=SHENZHEN HOOENERGY TECHNOLOGY CO.,LTD
+
+OUI:CC22371*
+ ID_OUI_FROM_DATABASE=Terma Sp. z o.o.
+
+OUI:CC2237B*
+ ID_OUI_FROM_DATABASE=Tolomatic, Inc.
+
+OUI:AC1DDF6*
+ ID_OUI_FROM_DATABASE=Shenzheng SenseTime Technology Co. Ltd
+
+OUI:741AE02*
+ ID_OUI_FROM_DATABASE=NURA HOLDINGS PTY LTD
+
 OUI:1C8776B*
  ID_OUI_FROM_DATABASE=Hekatron Vertriebs GmbH
 
@@ -8912,9 +9941,6 @@ OUI:38B8EB1*
 OUI:38B8EBA*
  ID_OUI_FROM_DATABASE=SECAD SA
 
-OUI:38B8EB7*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:38FDFE6*
  ID_OUI_FROM_DATABASE=Inspero Inc
 
@@ -9029,9 +10055,6 @@ OUI:F0ACD70*
 OUI:F0ACD7E*
  ID_OUI_FROM_DATABASE=Fiziico Co., Ltd.
 
-OUI:58E8760*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:58E8761*
  ID_OUI_FROM_DATABASE=Beijing Perabytes IS Technology Co., Ltd
 
@@ -9119,45 +10142,15 @@ OUI:8C192DA*
 OUI:A03E6BF*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:58FCDBF*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:283638C*
  ID_OUI_FROM_DATABASE=Swisson AG
 
-OUI:E4956EF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:74F8DBF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:BC6641F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:74E14AF*
  ID_OUI_FROM_DATABASE=Private
 
 OUI:B8D812F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:2C265FF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:2C6A6FF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:64FB81F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:28FD80F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:A0BB3EF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:2CD141F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:2836388*
  ID_OUI_FROM_DATABASE=Havells India Limited
 
@@ -9338,6 +10331,159 @@ OUI:8C147DA*
 OUI:8C147D1*
  ID_OUI_FROM_DATABASE=Private
 
+OUI:8C147DB*
+ ID_OUI_FROM_DATABASE=Bausch Datacom NV/SA
+
+OUI:A0C5F2D*
+ ID_OUI_FROM_DATABASE=UnaliWear, Inc.
+
+OUI:A0C5F20*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:A0C5F2E*
+ ID_OUI_FROM_DATABASE=Synapsys Solutions Ltd.
+
+OUI:4C65A88*
+ ID_OUI_FROM_DATABASE=Instant Byte, S.L.
+
+OUI:4C65A82*
+ ID_OUI_FROM_DATABASE=Orica Europe Pty Ltd & Co KG
+
+OUI:4C65A84*
+ ID_OUI_FROM_DATABASE=Plus One Japan Limited
+
+OUI:4C65A8C*
+ ID_OUI_FROM_DATABASE=Fuse
+
+OUI:F88A3C7*
+ ID_OUI_FROM_DATABASE=Josh.ai
+
+OUI:F88A3C1*
+ ID_OUI_FROM_DATABASE=Carefree of Colorado
+
+OUI:F88A3C5*
+ ID_OUI_FROM_DATABASE=KOKKIA INC
+
+OUI:F88A3C9*
+ ID_OUI_FROM_DATABASE=withus
+
+OUI:7CBACCC*
+ ID_OUI_FROM_DATABASE=Flying Loft Inc.
+
+OUI:7CBACCD*
+ ID_OUI_FROM_DATABASE=SIGMA-ELEKTRO GmbH
+
+OUI:7CBACC2*
+ ID_OUI_FROM_DATABASE=Maco Lighting Pty. Ltd.
+
+OUI:7CBACC9*
+ ID_OUI_FROM_DATABASE=Yongguan Electronic Technology (D.G)LTD
+
+OUI:74F8DBF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:7CBACCE*
+ ID_OUI_FROM_DATABASE=ALPHA TECHNOLOGIES, LLC
+
+OUI:78D8009*
+ ID_OUI_FROM_DATABASE=SightLine Applications
+
+OUI:78D8005*
+ ID_OUI_FROM_DATABASE=Björkviks Consulting AB
+
+OUI:78D8002*
+ ID_OUI_FROM_DATABASE=Shanghai Espacetime Technology Co.,Ltd.
+
+OUI:28F5372*
+ ID_OUI_FROM_DATABASE=Unicair Communication Tec Co., Ltd.
+
+OUI:78D8000*
+ ID_OUI_FROM_DATABASE=Kverneland Group Mechatronics
+
+OUI:28F5371*
+ ID_OUI_FROM_DATABASE=Umojo
+
+OUI:64FB81F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:58FCDBF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:2C265FF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:28FD80F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:2CD141F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:2C6A6FF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:A0BB3EF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:BC6641F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:34008AA*
+ ID_OUI_FROM_DATABASE=Hibertek International Limited
+
+OUI:34008A6*
+ ID_OUI_FROM_DATABASE=Sithon Technologies SAS
+
+OUI:34298FD*
+ ID_OUI_FROM_DATABASE=Keystone Electronic Solutions
+
+OUI:34298F7*
+ ID_OUI_FROM_DATABASE=Dongguan Kingtron Electronics Tech Co., Ltd
+
+OUI:58E8760*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:34298FE*
+ ID_OUI_FROM_DATABASE=ARC Technology Co., Ltd
+
+OUI:189BA53*
+ ID_OUI_FROM_DATABASE=PHINETWORKS
+
+OUI:189BA55*
+ ID_OUI_FROM_DATABASE=Starfire Industries LLC
+
+OUI:E4956EF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:189BA5E*
+ ID_OUI_FROM_DATABASE=Taiwan Name Plate Co.,LTD
+
+OUI:904E914*
+ ID_OUI_FROM_DATABASE=Wrtnode technology Inc.
+
+OUI:2C279E4*
+ ID_OUI_FROM_DATABASE=Shijiazhuang King Transportation Equipment Co.,Ltd
+
+OUI:2C279E5*
+ ID_OUI_FROM_DATABASE=AudioNord Distribution A/S
+
+OUI:38B8EB7*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:CC22377*
+ ID_OUI_FROM_DATABASE=Shanghai Doit IOT Technology Co.,Ltd.
+
+OUI:34298FB*
+ ID_OUI_FROM_DATABASE=Schnick-Schnack-Systems GmbH
+
+OUI:741AE0D*
+ ID_OUI_FROM_DATABASE=Voltaware Services Limited
+
+OUI:741AE0E*
+ ID_OUI_FROM_DATABASE=ITS Partner (O.B.S) S.L.
+
+OUI:AC1DDF5*
+ ID_OUI_FROM_DATABASE=Shenzhen Ouzheng Electronic Tech Co,.Ltd
+
 OUI:1C87740*
  ID_OUI_FROM_DATABASE=Philips Personal Health Solutions
 
@@ -9797,9 +10943,6 @@ OUI:7C477C6*
 OUI:7C477CD*
  ID_OUI_FROM_DATABASE=Speedifi Inc
 
-OUI:986D359*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:986D353*
  ID_OUI_FROM_DATABASE=DH Mechatronic AG
 
@@ -9905,24 +11048,6 @@ OUI:2836387*
 OUI:800A80F*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:B437D1F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:0CEFAFF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:78C2C0F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:141FBAF*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:549A11F*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:807B85F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:2836386*
  ID_OUI_FROM_DATABASE=Georg Neumann GmbH
 
@@ -10139,15 +11264,186 @@ OUI:8C147D3*
 OUI:8C147D4*
  ID_OUI_FROM_DATABASE=Nanjing bilian information Technology Co.,Ltd.
 
+OUI:8C147D6*
+ ID_OUI_FROM_DATABASE=Shenzhen Meidou Technology Co, Ltd.
+
+OUI:8C147D8*
+ ID_OUI_FROM_DATABASE=V2 S.p.A.
+
+OUI:A0C5F28*
+ ID_OUI_FROM_DATABASE=CoolR Group Inc
+
+OUI:A0C5F2A*
+ ID_OUI_FROM_DATABASE=Serious Integrated, Inc.
+
+OUI:A0C5F21*
+ ID_OUI_FROM_DATABASE=KNS Group LLC (YADRO Company)
+
+OUI:4C65A81*
+ ID_OUI_FROM_DATABASE=Beijing Bluehalo Internet Inc.
+
+OUI:4C65A80*
+ ID_OUI_FROM_DATABASE=WELT Corporation
+
+OUI:4C65A87*
+ ID_OUI_FROM_DATABASE=Wuhan MoreQuick Network Technology Co., Ltd.
+
+OUI:4C65A85*
+ ID_OUI_FROM_DATABASE=TEL-Electronics Ltd
+
+OUI:4C65A8B*
+ ID_OUI_FROM_DATABASE=ZMIN Technologies
+
+OUI:F88A3CC*
+ ID_OUI_FROM_DATABASE=EXCETOP TECHNOLOGY (BEIJING) CO., LTD.
+
+OUI:F88A3C3*
+ ID_OUI_FROM_DATABASE=Shenzhen Shengyuan Tech Ltd.
+
+OUI:F88A3C6*
+ ID_OUI_FROM_DATABASE=Beijing Zhong Chuang Communication Technology Ltd.
+
+OUI:4C65A8E*
+ ID_OUI_FROM_DATABASE=High Infinity Germany
+
+OUI:F88A3C2*
+ ID_OUI_FROM_DATABASE=KLATU Networks Inc
+
+OUI:F88A3CD*
+ ID_OUI_FROM_DATABASE=THK Co.,LTD.
+
+OUI:F88A3CB*
+ ID_OUI_FROM_DATABASE=FARA AS
+
+OUI:7CBACC7*
+ ID_OUI_FROM_DATABASE=Virgin Orbit
+
+OUI:7CBACC1*
+ ID_OUI_FROM_DATABASE=Changsha SUNYE Electric Co., Ltd.
+
+OUI:807B85F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:549A11F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:141FBAF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:B437D1F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:7CBACC8*
+ ID_OUI_FROM_DATABASE=Collinear Networks Inc.
+
+OUI:7CBACC6*
+ ID_OUI_FROM_DATABASE=Fossil Power Systems Inc
+
+OUI:78D8004*
+ ID_OUI_FROM_DATABASE=CS Instruments GmbH
+
+OUI:78D800D*
+ ID_OUI_FROM_DATABASE=Korea Micro Wireless Co.,Ltd.
+
+OUI:78D800B*
+ ID_OUI_FROM_DATABASE=Maddalena S.p.A.
+
+OUI:28F5370*
+ ID_OUI_FROM_DATABASE=Valeo Siemens eAutomotive Norway
+
+OUI:78C2C0F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:0CEFAFF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:28F537E*
+ ID_OUI_FROM_DATABASE=Performance Motion Devices
+
+OUI:34008A9*
+ ID_OUI_FROM_DATABASE=Keruyun Technoligies(Beijing) Corporation Limited
+
+OUI:986D359*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:34008A3*
+ ID_OUI_FROM_DATABASE=Globex 99 LTD
+
+OUI:34008AD*
+ ID_OUI_FROM_DATABASE=ChengDu HuiZhong Cloud Information Technology Co., Ltd.
+
+OUI:34008A1*
+ ID_OUI_FROM_DATABASE=ZQAM Communications
+
+OUI:34008A5*
+ ID_OUI_FROM_DATABASE=Federal Aviation Administration
+
+OUI:34298F2*
+ ID_OUI_FROM_DATABASE=Shenzhen Advance River System Technology Co., Ltd
+
+OUI:34008AE*
+ ID_OUI_FROM_DATABASE=SHENZHEN WXL ELECTRONICS CO., LTD.
+
+OUI:34298F9*
+ ID_OUI_FROM_DATABASE=Wiesheu GmbH
+
+OUI:34298F3*
+ ID_OUI_FROM_DATABASE=Beijing Vorx Telecommunications Co., Ltd.
+
+OUI:34298F4*
+ ID_OUI_FROM_DATABASE=ISRA Vision AG
+
+OUI:189BA54*
+ ID_OUI_FROM_DATABASE=Innominds Software Inc
+
+OUI:904E91C*
+ ID_OUI_FROM_DATABASE=Showtacle s.r.o.
+
+OUI:904E913*
+ ID_OUI_FROM_DATABASE=Teleepoch Ltd
+
+OUI:904E91A*
+ ID_OUI_FROM_DATABASE=Kaertech Limited
+
+OUI:904E919*
+ ID_OUI_FROM_DATABASE=CUTTER Systems spol. s r.o.
+
+OUI:2C279EE*
+ ID_OUI_FROM_DATABASE=Amaryllo International Inc.
+
+OUI:CC22374*
+ ID_OUI_FROM_DATABASE=SHANGHAI CARGOA M.&E.EQUIPMENT CO.LTD
+
+OUI:CC22376*
+ ID_OUI_FROM_DATABASE=Siemens AG Austria
+
+OUI:CC22370*
+ ID_OUI_FROM_DATABASE=MEDCOM sp. z o.o.
+
+OUI:CC22379*
+ ID_OUI_FROM_DATABASE=E Ink Corp
+
+OUI:CC22373*
+ ID_OUI_FROM_DATABASE=XConnect Professional Services
+
+OUI:CC2237E*
+ ID_OUI_FROM_DATABASE=MANUFACTURAS Y TRANSFORMADOS AB, S.L.
+
+OUI:741AE08*
+ ID_OUI_FROM_DATABASE=Broadcast Wireless Systems Ltd
+
+OUI:741AE06*
+ ID_OUI_FROM_DATABASE=Blocks Wearables Inc.
+
+OUI:741AE03*
+ ID_OUI_FROM_DATABASE=Philips Personal Health Solutions
+
 OUI:E043DB*
  ID_OUI_FROM_DATABASE=Shenzhen ViewAt Technology Co.,Ltd.
 
 OUI:2405F5*
  ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
 
-OUI:2C3033*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:3CD92B*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
@@ -10208,9 +11504,6 @@ OUI:348AAE*
 OUI:BCEC23*
  ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
 
-OUI:8CE748*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:AC06C7*
  ID_OUI_FROM_DATABASE=ServerNet S.r.l.
 
@@ -10397,15 +11690,6 @@ OUI:006057*
 OUI:0007D8*
  ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
 
-OUI:0012F2*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:001BED*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:002438*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:84742A*
  ID_OUI_FROM_DATABASE=zte corporation
 
@@ -11006,9 +12290,6 @@ OUI:70BF3E*
 OUI:D848EE*
  ID_OUI_FROM_DATABASE=Hangzhou Xueji Technology Co., Ltd.
 
-OUI:88947E*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:88C242*
  ID_OUI_FROM_DATABASE=Poynt Co.
 
@@ -11060,9 +12341,6 @@ OUI:C8A9FC*
 OUI:C49FF3*
  ID_OUI_FROM_DATABASE=Mciao Technologies, Inc.
 
-OUI:80739F*
- ID_OUI_FROM_DATABASE=KYOCERA Corporation
-
 OUI:7C2BE1*
  ID_OUI_FROM_DATABASE=Shenzhen Ferex Electrical Co.,Ltd
 
@@ -11084,9 +12362,6 @@ OUI:2CA539*
 OUI:FC335F*
  ID_OUI_FROM_DATABASE=Polyera
 
-OUI:FCC233*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:A8C87F*
  ID_OUI_FROM_DATABASE=Roqos, Inc.
 
@@ -11144,9 +12419,6 @@ OUI:DC3CF6*
 OUI:3C3178*
  ID_OUI_FROM_DATABASE=Qolsys Inc.
 
-OUI:F4573E*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:083A5C*
  ID_OUI_FROM_DATABASE=Junilab, Inc.
 
@@ -11171,18 +12443,12 @@ OUI:6459F8*
 OUI:082CB0*
  ID_OUI_FROM_DATABASE=Network Instruments
 
-OUI:F0AB54*
- ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
-
 OUI:485073*
  ID_OUI_FROM_DATABASE=Microsoft Corporation
 
 OUI:3CA31A*
  ID_OUI_FROM_DATABASE=Oilfind International LLC
 
-OUI:ACFD93*
- ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd.
-
 OUI:A424DD*
  ID_OUI_FROM_DATABASE=Cambrionix Ltd
 
@@ -11330,9 +12596,6 @@ OUI:38C70A*
 OUI:60E6BC*
  ID_OUI_FROM_DATABASE=Sino-Telecom Technology Co.,Ltd.
 
-OUI:1CA532*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
 OUI:486EFB*
  ID_OUI_FROM_DATABASE=Davit System Technology Co., Ltd.
 
@@ -11453,9 +12716,6 @@ OUI:8CDF9D*
 OUI:F8E903*
  ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:F0B052*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:6828F6*
  ID_OUI_FROM_DATABASE=Vubiq Networks, Inc.
 
@@ -11588,9 +12848,6 @@ OUI:74F413*
 OUI:34F0CA*
  ID_OUI_FROM_DATABASE=Shenzhen Linghangyuan Digital Technology Co.,Ltd.
 
-OUI:84183A*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:30B5F1*
  ID_OUI_FROM_DATABASE=Aitexin Technology Co., Ltd
 
@@ -11678,9 +12935,6 @@ OUI:34E42A*
 OUI:20A787*
  ID_OUI_FROM_DATABASE=Bointec Taiwan Corporation Limited
 
-OUI:6CAAB3*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:A481EE*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
@@ -11735,9 +12989,6 @@ OUI:9451BF*
 OUI:4C7F62*
  ID_OUI_FROM_DATABASE=Nokia Corporation
 
-OUI:841766*
- ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd
-
 OUI:F03FF8*
  ID_OUI_FROM_DATABASE=R L Drake
 
@@ -12029,9 +13280,6 @@ OUI:F42896*
 OUI:1C7B21*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
-OUI:BC9680*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
 OUI:9C2840*
  ID_OUI_FROM_DATABASE=Discovery Technology,LTD..
 
@@ -12155,9 +13403,6 @@ OUI:C47F51*
 OUI:E8D4E0*
  ID_OUI_FROM_DATABASE=Beijing BenyWave Technology Co., Ltd.
 
-OUI:3889DC*
- ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V.
-
 OUI:681D64*
  ID_OUI_FROM_DATABASE=Sunwave Communications Co., Ltd
 
@@ -12167,9 +13412,6 @@ OUI:F4CD90*
 OUI:E438F2*
  ID_OUI_FROM_DATABASE=Advantage Controls
 
-OUI:24C9A1*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:C8F386*
  ID_OUI_FROM_DATABASE=Shenzhen Xiaoniao Technology Co.,Ltd
 
@@ -12551,9 +13793,6 @@ OUI:58CF4B*
 OUI:C4393A*
  ID_OUI_FROM_DATABASE=SMC Networks Inc
 
-OUI:C4017C*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:D45C70*
  ID_OUI_FROM_DATABASE=Wi-Fi Alliance
 
@@ -12773,9 +14012,6 @@ OUI:18F87A*
 OUI:142DF5*
  ID_OUI_FROM_DATABASE=Amphitech
 
-OUI:C08ADE*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:90F72F*
  ID_OUI_FROM_DATABASE=Phillips Machine & Welding Co., Inc.
 
@@ -12917,9 +14153,6 @@ OUI:AC3FA4*
 OUI:0C130B*
  ID_OUI_FROM_DATABASE=Uniqoteq Ltd.
 
-OUI:14CF8D*
- ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO., LTD.
-
 OUI:808698*
  ID_OUI_FROM_DATABASE=Netronics Technologies Inc.
 
@@ -13307,9 +14540,6 @@ OUI:685E6B*
 OUI:4C32D9*
  ID_OUI_FROM_DATABASE=M Rutty Holdings Pty. Ltd.
 
-OUI:50A733*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:603FC5*
  ID_OUI_FROM_DATABASE=COX CO., LTD
 
@@ -13472,9 +14702,6 @@ OUI:802275*
 OUI:BC8199*
  ID_OUI_FROM_DATABASE=BASIC Co.,Ltd.
 
-OUI:000726*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co., Ltd.
-
 OUI:24470E*
  ID_OUI_FROM_DATABASE=PentronicAB
 
@@ -13616,9 +14843,6 @@ OUI:707EDE*
 OUI:CCBE71*
  ID_OUI_FROM_DATABASE=OptiLogix BV
 
-OUI:D8B12A*
- ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co., Ltd.
-
 OUI:7CDD90*
  ID_OUI_FROM_DATABASE=Shenzhen Ogemray Technology Co., Ltd.
 
@@ -13880,9 +15104,6 @@ OUI:84DB2F*
 OUI:A45055*
  ID_OUI_FROM_DATABASE=busware.de
 
-OUI:2CD2E7*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
 OUI:C89383*
  ID_OUI_FROM_DATABASE=Embedded Automation, Inc.
 
@@ -14399,9 +15620,6 @@ OUI:0025EF*
 OUI:0025E9*
  ID_OUI_FROM_DATABASE=i-mate Development, Inc.
 
-OUI:0025DF*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:002690*
  ID_OUI_FROM_DATABASE=I DO IT
 
@@ -14978,9 +16196,6 @@ OUI:00229A*
 OUI:002299*
  ID_OUI_FROM_DATABASE=SeaMicro Inc.
 
-OUI:002294*
- ID_OUI_FROM_DATABASE=Kyocera Corporation
-
 OUI:0021FA*
  ID_OUI_FROM_DATABASE=A4SP Technologies Ltd.
 
@@ -15146,9 +16361,6 @@ OUI:001F3E*
 OUI:001F42*
  ID_OUI_FROM_DATABASE=Etherstack plc
 
-OUI:001F41*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:001F39*
  ID_OUI_FROM_DATABASE=Construcciones y Auxiliar de Ferrocarriles, S.A.
 
@@ -16151,9 +17363,6 @@ OUI:001890*
 OUI:001884*
  ID_OUI_FROM_DATABASE=Fon Technology S.L.
 
-OUI:00187D*
- ID_OUI_FROM_DATABASE=Armorlink shanghai Co. Ltd
-
 OUI:00187F*
  ID_OUI_FROM_DATABASE=ZODIANET
 
@@ -16181,9 +17390,6 @@ OUI:0016AB*
 OUI:0016A6*
  ID_OUI_FROM_DATABASE=Dovado FZ-LLC
 
-OUI:0017C8*
- ID_OUI_FROM_DATABASE=KYOCERA Document Solutions Inc.
-
 OUI:0017CF*
  ID_OUI_FROM_DATABASE=iMCA-GmbH
 
@@ -16241,9 +17447,6 @@ OUI:00175F*
 OUI:001751*
  ID_OUI_FROM_DATABASE=Online Corporation
 
-OUI:001753*
- ID_OUI_FROM_DATABASE=nFore Technology Inc.
-
 OUI:001758*
  ID_OUI_FROM_DATABASE=ThruVision Ltd
 
@@ -16499,9 +17702,6 @@ OUI:001531*
 OUI:001538*
  ID_OUI_FROM_DATABASE=RFID, Inc.
 
-OUI:00152A*
- ID_OUI_FROM_DATABASE=Nokia GmbH
-
 OUI:00161D*
  ID_OUI_FROM_DATABASE=Innovative Wireless Technologies, Inc.
 
@@ -17081,9 +18281,6 @@ OUI:001137*
 OUI:00112D*
  ID_OUI_FROM_DATABASE=iPulse Systems
 
-OUI:111111*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:001123*
  ID_OUI_FROM_DATABASE=Appointech, Inc.
 
@@ -18776,9 +19973,6 @@ OUI:0004D1*
 OUI:0004CB*
  ID_OUI_FROM_DATABASE=Tdsoft Communication, Ltd.
 
-OUI:0004BF*
- ID_OUI_FROM_DATABASE=VersaLogic Corp.
-
 OUI:0004C5*
  ID_OUI_FROM_DATABASE=ASE Technologies, USA
 
@@ -19223,9 +20417,6 @@ OUI:00015A*
 OUI:000166*
  ID_OUI_FROM_DATABASE=TC GROUP A/S
 
-OUI:00016D*
- ID_OUI_FROM_DATABASE=CarrierComm Inc.
-
 OUI:00015F*
  ID_OUI_FROM_DATABASE=DIGITAL DESIGN GmbH
 
@@ -21083,9 +22274,6 @@ OUI:080076*
 OUI:080072*
  ID_OUI_FROM_DATABASE=XEROX CORP UNIV GRANT PROGRAM
 
-OUI:080070*
- ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRIC CORP.
-
 OUI:080068*
  ID_OUI_FROM_DATABASE=RIDGE COMPUTERS
 
@@ -21227,9 +22415,6 @@ OUI:00004C*
 OUI:00003B*
  ID_OUI_FROM_DATABASE=i Controls, Inc.
 
-OUI:0000FE*
- ID_OUI_FROM_DATABASE=ANNAPOLIS MICRO SYSTEMS
-
 OUI:080013*
  ID_OUI_FROM_DATABASE=Exxon
 
@@ -21314,15 +22499,6 @@ OUI:C8CD72*
 OUI:E8BE81*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
-OUI:28FAA0*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
-OUI:3CA348*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
-OUI:F42981*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:C4282D*
  ID_OUI_FROM_DATABASE=Embedded Intellect Pty Ltd
 
@@ -21479,9 +22655,6 @@ OUI:9C4E36*
 OUI:541473*
  ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited
 
-OUI:14144B*
- ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD
-
 OUI:001C50*
  ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd.
 
@@ -21674,12 +22847,6 @@ OUI:E839DF*
 OUI:00138F*
  ID_OUI_FROM_DATABASE=Asiarock Technology Limited
 
-OUI:2CB05D*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:00146C*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:1C69A5*
  ID_OUI_FROM_DATABASE=BlackBerry RTS
 
@@ -21695,21 +22862,9 @@ OUI:002308*
 OUI:880355*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
-OUI:A42B8C*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:04A151*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:28C68E*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:5CDC96*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
-OUI:504A6E*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:D0D04B*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
@@ -21827,9 +22982,6 @@ OUI:000B3B*
 OUI:001D20*
  ID_OUI_FROM_DATABASE=Comtrend Corporation
 
-OUI:6C38A1*
- ID_OUI_FROM_DATABASE=Ubee Interactive Corp.
-
 OUI:140C76*
  ID_OUI_FROM_DATABASE=FREEBOX SAS
 
@@ -21971,9 +23123,6 @@ OUI:000BA2*
 OUI:30CBF8*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:2C4D79*
- ID_OUI_FROM_DATABASE=GoerTek Inc.
-
 OUI:40D357*
  ID_OUI_FROM_DATABASE=Ison Technology Co., Ltd.
 
@@ -22067,9 +23216,6 @@ OUI:349971*
 OUI:24615A*
  ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
 
-OUI:B0E2E5*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:AC0D1B*
  ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
 
@@ -22301,9 +23447,6 @@ OUI:045604*
 OUI:10BD55*
  ID_OUI_FROM_DATABASE=Q-Lab Corporation
 
-OUI:C449BB*
- ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
-
 OUI:8C6D50*
  ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD
 
@@ -22346,9 +23489,6 @@ OUI:680715*
 OUI:A09E1A*
  ID_OUI_FROM_DATABASE=Polar Electro Oy
 
-OUI:3CB6B7*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:D0B2C4*
  ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
 
@@ -22472,9 +23612,6 @@ OUI:0050C2*
 OUI:CC79CF*
  ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
 
-OUI:544E45*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:6CB9C5*
  ID_OUI_FROM_DATABASE=Delta Networks, Inc.
 
@@ -22778,9 +23915,6 @@ OUI:98F058*
 OUI:24E43F*
  ID_OUI_FROM_DATABASE=Wenzhou Kunmei Communication Technology Co.,Ltd.
 
-OUI:A00460*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:240AC4*
  ID_OUI_FROM_DATABASE=Espressif Inc.
 
@@ -23009,9 +24143,6 @@ OUI:C80E14*
 OUI:E0686D*
  ID_OUI_FROM_DATABASE=Raybased AB
 
-OUI:A45385*
- ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd.
-
 OUI:98B039*
  ID_OUI_FROM_DATABASE=Nokia
 
@@ -23099,9 +24230,6 @@ OUI:FCCAC4*
 OUI:04BA36*
  ID_OUI_FROM_DATABASE=Li Seng Technology Ltd
 
-OUI:DCF090*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:4409B8*
  ID_OUI_FROM_DATABASE=Salcomp (Shenzhen) CO., LTD.
 
@@ -23180,9 +24308,6 @@ OUI:484D7E*
 OUI:F4B549*
  ID_OUI_FROM_DATABASE=Xiamen Yeastar Information Technology Co., Ltd.
 
-OUI:9C3DCF*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:28EED3*
  ID_OUI_FROM_DATABASE=Shenzhen Super D Technology Co., Ltd
 
@@ -23318,9 +24443,6 @@ OUI:A03D6F*
 OUI:40605A*
  ID_OUI_FROM_DATABASE=Hawkeye Tech Co. Ltd
 
-OUI:5419C8*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:C0210D*
  ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
 
@@ -23342,9 +24464,6 @@ OUI:1840A4*
 OUI:9C50EE*
  ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
 
-OUI:1077B0*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:F015B9*
  ID_OUI_FROM_DATABASE=PlayFusion Limited
 
@@ -23450,9 +24569,6 @@ OUI:3407FB*
 OUI:6CB4A7*
  ID_OUI_FROM_DATABASE=Landauer, Inc.
 
-OUI:1C398A*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:F8A5C5*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -23537,9 +24653,6 @@ OUI:2C3311*
 OUI:503A7D*
  ID_OUI_FROM_DATABASE=AlphaTech PLC Int’l Co., Ltd.
 
-OUI:BC024A*
- ID_OUI_FROM_DATABASE=HMD Global Oy
-
 OUI:9CFCD1*
  ID_OUI_FROM_DATABASE=Aetheris Technology (Shanghai) Co., Ltd.
 
@@ -23969,9 +25082,6 @@ OUI:FC4D8C*
 OUI:B01F29*
  ID_OUI_FROM_DATABASE=Helvetia INC.
 
-OUI:CC0677*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:28070D*
  ID_OUI_FROM_DATABASE=GUANGZHOU WINSOUND INFORMATION TECHNOLOGY CO.,LTD.
 
@@ -24011,6 +25121,486 @@ OUI:E0D848*
 OUI:145BE1*
  ID_OUI_FROM_DATABASE=nyantec UG (haftungsbeschränkt)
 
+OUI:00187D*
+ ID_OUI_FROM_DATABASE=Armorlink Co .Ltd
+
+OUI:F42981*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:3CA348*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:A40E2B*
+ ID_OUI_FROM_DATABASE=Facebook Inc
+
+OUI:28FAA0*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:3CB6B7*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:5419C8*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:F4B7B3*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:1C4D70*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:E43A6E*
+ ID_OUI_FROM_DATABASE=Shenzhen Zeroone Technology CO.,LTD
+
+OUI:60DA83*
+ ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
+
+OUI:2C5731*
+ ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited
+
+OUI:F46BEF*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:085114*
+ ID_OUI_FROM_DATABASE=QINGDAO TOPSCOMM COMMUNICATION CO., LTD
+
+OUI:D05A00*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:70F11C*
+ ID_OUI_FROM_DATABASE=Shenzhen Ogemray Technology Co.,Ltd
+
+OUI:14144B*
+ ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD
+
+OUI:70DF2F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:6447E0*
+ ID_OUI_FROM_DATABASE=Feitian Technologies Co., Ltd
+
+OUI:001753*
+ ID_OUI_FROM_DATABASE=nFore Technology Inc.
+
+OUI:58C583*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
+OUI:E86D65*
+ ID_OUI_FROM_DATABASE=AUDIO MOBIL Elektronik GmbH
+
+OUI:E86FF2*
+ ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
+
+OUI:00016D*
+ ID_OUI_FROM_DATABASE=CarrierComm Inc.
+
+OUI:F0B052*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:84183A*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:6CAAB3*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:C4017C*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:70DEF9*
+ ID_OUI_FROM_DATABASE=FAI WAH INTERNATIONAL (HONG KONG) LIMITED
+
+OUI:001F41*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:C08ADE*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:50A733*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:24C9A1*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:245880*
+ ID_OUI_FROM_DATABASE=VIZEO
+
+OUI:000726*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:BC9680*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:1CA532*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:0000FE*
+ ID_OUI_FROM_DATABASE=Annapolis Micro Systems, Inc.
+
+OUI:188090*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:BC024A*
+ ID_OUI_FROM_DATABASE=HMD Global Oy
+
+OUI:90A365*
+ ID_OUI_FROM_DATABASE=HMD Global Oy
+
+OUI:C444A0*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:F83441*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:5C0339*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:044F4C*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:1C151F*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:544E45*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:DCEB53*
+ ID_OUI_FROM_DATABASE=Wuhan QianXiao Elecronic Technology CO.,LTD
+
+OUI:94E36D*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:74819A*
+ ID_OUI_FROM_DATABASE=PT. Hartono Istana Teknologi
+
+OUI:0835B2*
+ ID_OUI_FROM_DATABASE=CoreEdge Networks Co., Ltd
+
+OUI:6C38A1*
+ ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited
+
+OUI:B40F3B*
+ ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch
+
+OUI:1062D0*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:7802B1*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:309935*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:94D9B3*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:409BCD*
+ ID_OUI_FROM_DATABASE=D-Link International
+
+OUI:005C86*
+ ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD
+
+OUI:1CAB34*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
+OUI:5C0979*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:002EC7*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:488EEF*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:002438*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:001BED*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:0012F2*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:04A151*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:A42B8C*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:A00460*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:9C3DCF*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:2CB05D*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:504A6E*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:28C68E*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:2C3033*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:00146C*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:ACFD93*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:A45385*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:2C4D79*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:841766*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:741C27*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
+OUI:111111*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:FCC233*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:2830AC*
+ ID_OUI_FROM_DATABASE=Frontiir Co. Ltd.
+
+OUI:9050CA*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
+
+OUI:0004BF*
+ ID_OUI_FROM_DATABASE=VersaLogic Corp.
+
+OUI:D8B12A*
+ ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd.
+
+OUI:64B5C6*
+ ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
+
+OUI:A41115*
+ ID_OUI_FROM_DATABASE=Robert Bosch Engineering and Business Solutions pvt. Ltd.
+
+OUI:EC0441*
+ ID_OUI_FROM_DATABASE=ShenZhen TIGO Semiconductor Co., Ltd.
+
+OUI:BC88C3*
+ ID_OUI_FROM_DATABASE=Ningbo Dooya Mechanic & Electronic Technology Co., Ltd
+
+OUI:A8BE27*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:B8634D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:6C96CF*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:3035AD*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:681F40*
+ ID_OUI_FROM_DATABASE=Blu Wireless Technology Ltd
+
+OUI:48C58D*
+ ID_OUI_FROM_DATABASE=Lear Corporation GmbH
+
+OUI:90ADF7*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:982D68*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd
+
+OUI:2CD2E7*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:00152A*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:5CEA1D*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:A43412*
+ ID_OUI_FROM_DATABASE=Thales Alenia Space
+
+OUI:ECD09F*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:9C65EE*
+ ID_OUI_FROM_DATABASE=DASAN Network Solutions
+
+OUI:80739F*
+ ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
+
+OUI:3889DC*
+ ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V.
+
+OUI:38E2DD*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:74E5F9*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:0017C8*
+ ID_OUI_FROM_DATABASE=KYOCERA Display Corporation
+
+OUI:002294*
+ ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
+
+OUI:3C11B2*
+ ID_OUI_FROM_DATABASE=Fraunhofer FIT
+
+OUI:080070*
+ ID_OUI_FROM_DATABASE=Mitsubishi Precision Co.,LTd.
+
+OUI:DCF090*
+ ID_OUI_FROM_DATABASE=Nubia Technology Co.,Ltd.
+
+OUI:DC6AEA*
+ ID_OUI_FROM_DATABASE=Infinix mobility limited
+
+OUI:0025DF*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:D8A01D*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
+OUI:8CE38E*
+ ID_OUI_FROM_DATABASE=Toshiba Memory Corporation
+
+OUI:74EAC8*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
+OUI:A434F1*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:C4F312*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:44EAD8*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:8C5F48*
+ ID_OUI_FROM_DATABASE=Continental Intelligent Transportation Systems LLC
+
+OUI:A0D86F*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:3890A5*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:4C1365*
+ ID_OUI_FROM_DATABASE=Emplus Technologies
+
+OUI:2054FA*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:989C57*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E4A7C5*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:104400*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:88DA1A*
+ ID_OUI_FROM_DATABASE=Redpine Signals, Inc.
+
+OUI:14CF8D*
+ ID_OUI_FROM_DATABASE=OHSUNG
+
+OUI:8CE748*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:48D35D*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:E446DA*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:500F80*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:F4F5DB*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:38A6CE*
+ ID_OUI_FROM_DATABASE=BSkyB Ltd
+
+OUI:1077B0*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:1C398A*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:CC0677*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:C84029*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:28BF89*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:F4573E*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:88947E*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:B0E2E5*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:F0AB54*
+ ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
+
+OUI:C449BB*
+ ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
+
+OUI:B430C0*
+ ID_OUI_FROM_DATABASE=York Instruments Ltd
+
+OUI:C468D0*
+ ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd.
+
+OUI:48D6D5*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
+OUI:F0BD2E*
+ ID_OUI_FROM_DATABASE=H+S Polatis Ltd
+
+OUI:842C80*
+ ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd.
+
+OUI:182D98*
+ ID_OUI_FROM_DATABASE=Jinwoo Industrial system
+
+OUI:0C1C20*
+ ID_OUI_FROM_DATABASE=Kakao Corp
+
+OUI:40498A*
+ ID_OUI_FROM_DATABASE=Synapticon GmbH
+
+OUI:D80831*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:24F27F*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:00B69F*
+ ID_OUI_FROM_DATABASE=Latch
+
+OUI:A88200*
+ ID_OUI_FROM_DATABASE=Hisense Electric Co.,Ltd
+
+OUI:F449EF*
+ ID_OUI_FROM_DATABASE=EMSTONE
+
 OUI:0C6F9C*
  ID_OUI_FROM_DATABASE=Shaw Communications Inc.
 
@@ -24245,18 +25835,6 @@ OUI:241EEB*
 OUI:F431C3*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:C4F57C*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:8C7CFF*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:000CDB*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:006069*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:C87B5B*
  ID_OUI_FROM_DATABASE=zte corporation
 
@@ -24875,9 +26453,6 @@ OUI:74D7CA*
 OUI:1CCDE5*
  ID_OUI_FROM_DATABASE=Shanghai Wind Technologies Co.,Ltd
 
-OUI:20896F*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:D494E8*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
@@ -24896,9 +26471,6 @@ OUI:ECB870*
 OUI:3095E3*
  ID_OUI_FROM_DATABASE=SHANGHAI SIMCOM LIMITED
 
-OUI:401B5F*
- ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd.
-
 OUI:4040A7*
  ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
 
@@ -24941,9 +26513,6 @@ OUI:B88687*
 OUI:68F956*
  ID_OUI_FROM_DATABASE=Objetivos y Servicio de Valor Añadido
 
-OUI:58B633*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:F4E926*
  ID_OUI_FROM_DATABASE=Tianjin Zanpu Technology Inc.
 
@@ -25100,9 +26669,6 @@ OUI:64DB81*
 OUI:C4BAA3*
  ID_OUI_FROM_DATABASE=Beijing Winicssec Technologies Co., Ltd.
 
-OUI:A013CB*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:20635F*
  ID_OUI_FROM_DATABASE=Abeeway
 
@@ -25142,9 +26708,6 @@ OUI:C43ABE*
 OUI:18B169*
  ID_OUI_FROM_DATABASE=Sonicwall
 
-OUI:D4684D*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:1CC72D*
  ID_OUI_FROM_DATABASE=Shenzhen Huapu Digital CO.,Ltd
 
@@ -25565,9 +27128,6 @@ OUI:7C1A03*
 OUI:481842*
  ID_OUI_FROM_DATABASE=Shanghai Winaas Co. Equipment Co. Ltd.
 
-OUI:E817FC*
- ID_OUI_FROM_DATABASE=NIFTY Corporation
-
 OUI:D09C30*
  ID_OUI_FROM_DATABASE=Foster Electric Company, Limited
 
@@ -25898,9 +27458,6 @@ OUI:78CB33*
 OUI:507691*
  ID_OUI_FROM_DATABASE=Tekpea, Inc.
 
-OUI:C421C8*
- ID_OUI_FROM_DATABASE=KYOCERA Corporation
-
 OUI:A4C0C7*
  ID_OUI_FROM_DATABASE=ShenZhen Hitom Communication Technology Co..LTD
 
@@ -25997,9 +27554,6 @@ OUI:2C7B84*
 OUI:540536*
  ID_OUI_FROM_DATABASE=Vivago Oy
 
-OUI:2CE6CC*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:E0FAEC*
  ID_OUI_FROM_DATABASE=Platan sp. z o.o. sp. k.
 
@@ -26408,9 +27962,6 @@ OUI:80D733*
 OUI:8C3330*
  ID_OUI_FROM_DATABASE=EmFirst Co., Ltd.
 
-OUI:8C0C90*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:08E5DA*
  ID_OUI_FROM_DATABASE=NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD.
 
@@ -26495,9 +28046,6 @@ OUI:9C3178*
 OUI:48BE2D*
  ID_OUI_FROM_DATABASE=Symanitron
 
-OUI:38E595*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
 OUI:B86091*
  ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC
 
@@ -26588,9 +28136,6 @@ OUI:A4D18F*
 OUI:0C565C*
  ID_OUI_FROM_DATABASE=HyBroad Vision (Hong Kong) Technology Co Ltd
 
-OUI:647C34*
- ID_OUI_FROM_DATABASE=Ubee Interactive Corp.
-
 OUI:649FF7*
  ID_OUI_FROM_DATABASE=Kone OYj
 
@@ -26648,9 +28193,6 @@ OUI:1848D8*
 OUI:702393*
  ID_OUI_FROM_DATABASE=fos4X GmbH
 
-OUI:D8AFF1*
- ID_OUI_FROM_DATABASE=Panasonic Appliances Company
-
 OUI:58ECE1*
  ID_OUI_FROM_DATABASE=Newport Corporation
 
@@ -26867,9 +28409,6 @@ OUI:240917*
 OUI:DC37D2*
  ID_OUI_FROM_DATABASE=Hunan HKT Electronic Technology Co., Ltd
 
-OUI:048B42*
- ID_OUI_FROM_DATABASE=Skspruce Technology Limited
-
 OUI:5076A6*
  ID_OUI_FROM_DATABASE=Ecil Informatica Ind. Com. Ltda
 
@@ -26987,9 +28526,6 @@ OUI:94E0D0*
 OUI:DCF858*
  ID_OUI_FROM_DATABASE=Lorent Networks, Inc.
 
-OUI:589396*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:A05E6B*
  ID_OUI_FROM_DATABASE=MELPER Co., Ltd.
 
@@ -27431,9 +28967,6 @@ OUI:6879ED*
 OUI:9CC0D2*
  ID_OUI_FROM_DATABASE=Conductix-Wampfler GmbH
 
-OUI:408BF6*
- ID_OUI_FROM_DATABASE=Shenzhen TCL New Technology Co; Ltd.
-
 OUI:447E95*
  ID_OUI_FROM_DATABASE=Alpha and Omega, Inc
 
@@ -27716,9 +29249,6 @@ OUI:E8757F*
 OUI:C83EA7*
  ID_OUI_FROM_DATABASE=KUNBUS GmbH
 
-OUI:A8D3C8*
- ID_OUI_FROM_DATABASE=Wachendorff Elektronik  GmbH & Co. KG
-
 OUI:E0CF2D*
  ID_OUI_FROM_DATABASE=Gemintek Corporation
 
@@ -27758,9 +29288,6 @@ OUI:D46CDA*
 OUI:C4F464*
  ID_OUI_FROM_DATABASE=Spica international
 
-OUI:74911A*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:544A05*
  ID_OUI_FROM_DATABASE=wenglor sensoric gmbh
 
@@ -28415,9 +29942,6 @@ OUI:002609*
 OUI:00268C*
  ID_OUI_FROM_DATABASE=StarLeaf Ltd.
 
-OUI:002692*
- ID_OUI_FROM_DATABASE=Mitsubishi Electric Co.
-
 OUI:002686*
  ID_OUI_FROM_DATABASE=Quantenna Communcations, Inc.
 
@@ -28535,9 +30059,6 @@ OUI:002489*
 OUI:00248E*
  ID_OUI_FROM_DATABASE=Infoware ZRt.
 
-OUI:002482*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:002476*
  ID_OUI_FROM_DATABASE=TAP.tv
 
@@ -28742,9 +30263,6 @@ OUI:00228B*
 OUI:002284*
  ID_OUI_FROM_DATABASE=DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD
 
-OUI:00227F*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:002277*
  ID_OUI_FROM_DATABASE=NEC Australia Pty Ltd
 
@@ -28814,9 +30332,6 @@ OUI:002385*
 OUI:00237E*
  ID_OUI_FROM_DATABASE=ELSTER GMBH
 
-OUI:00237F*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
 OUI:002379*
  ID_OUI_FROM_DATABASE=Union Business Machines Co. Ltd.
 
@@ -29630,9 +31145,6 @@ OUI:001BE6*
 OUI:001BDF*
  ID_OUI_FROM_DATABASE=Iskra Sistemi d.d.
 
-OUI:001BD3*
- ID_OUI_FROM_DATABASE=Panasonic Corp. AVC Company
-
 OUI:001BD8*
  ID_OUI_FROM_DATABASE=DVTel LTD
 
@@ -29699,9 +31211,6 @@ OUI:001B1E*
 OUI:001B12*
  ID_OUI_FROM_DATABASE=Apprion
 
-OUI:001B17*
- ID_OUI_FROM_DATABASE=Palo Alto Networks
-
 OUI:001B0B*
  ID_OUI_FROM_DATABASE=Phidgets Inc.
 
@@ -30386,9 +31895,6 @@ OUI:001534*
 OUI:001440*
  ID_OUI_FROM_DATABASE=ATOMIC Corporation
 
-OUI:001439*
- ID_OUI_FROM_DATABASE=Blonder Tongue Laboratories, Inc.
-
 OUI:001434*
  ID_OUI_FROM_DATABASE=Keri Systems, Inc
 
@@ -32087,9 +33593,6 @@ OUI:000903*
 OUI:0008FE*
  ID_OUI_FROM_DATABASE=UNIK C&C Co.,Ltd.
 
-OUI:0008FA*
- ID_OUI_FROM_DATABASE=Karl E.Brinkmann GmbH
-
 OUI:0008EE*
  ID_OUI_FROM_DATABASE=Logic Product Development
 
@@ -32144,9 +33647,6 @@ OUI:0008C0*
 OUI:0008C5*
  ID_OUI_FROM_DATABASE=Liontech Co., Ltd.
 
-OUI:0008C9*
- ID_OUI_FROM_DATABASE=TechniSat Digital GmbH
-
 OUI:0008CA*
  ID_OUI_FROM_DATABASE=TwinHan Technology Co.,Ltd
 
@@ -33419,9 +34919,6 @@ OUI:00302D*
 OUI:003025*
  ID_OUI_FROM_DATABASE=CHECKOUT COMPUTER SYSTEMS, LTD
 
-OUI:00D01F*
- ID_OUI_FROM_DATABASE=Senetas Security
-
 OUI:003012*
  ID_OUI_FROM_DATABASE=DIGITAL ENGINEERING LTD.
 
@@ -33956,9 +35453,6 @@ OUI:001032*
 OUI:001025*
  ID_OUI_FROM_DATABASE=Grayhill, Inc
 
-OUI:001009*
- ID_OUI_FROM_DATABASE=HORO QUARTZ
-
 OUI:0010F8*
  ID_OUI_FROM_DATABASE=TEXIO TECHNOLOGY CORPORATION
 
@@ -34223,9 +35717,6 @@ OUI:00601E*
 OUI:0060F8*
  ID_OUI_FROM_DATABASE=Loran International Technologies Inc.
 
-OUI:006088*
- ID_OUI_FROM_DATABASE=WHITE MOUNTAIN DSP, INC.
-
 OUI:00609A*
  ID_OUI_FROM_DATABASE=NJK TECHNO CO.
 
@@ -34625,9 +36116,6 @@ OUI:00C0DF*
 OUI:00C0F6*
  ID_OUI_FROM_DATABASE=CELAN TECHNOLOGY INC.
 
-OUI:00C08F*
- ID_OUI_FROM_DATABASE=Panasonic Electric Works Co., Ltd.
-
 OUI:00C012*
  ID_OUI_FROM_DATABASE=NETSPAN CORPORATION
 
@@ -35207,9 +36695,6 @@ OUI:00789E*
 OUI:44E9DD*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
-OUI:10F681*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:B888E3*
  ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
 
@@ -35507,18 +36992,6 @@ OUI:FCB4E6*
 OUI:F05C19*
  ID_OUI_FROM_DATABASE=Aruba Networks
 
-OUI:C43DC7*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:000FB5*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:00095B*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:F87394*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:70AAB2*
  ID_OUI_FROM_DATABASE=BlackBerry RTS
 
@@ -35540,15 +37013,6 @@ OUI:745AAA*
 OUI:7C1CF1*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:C0FFD4*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:405D82*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:803773*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:00264D*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
@@ -35807,9 +37271,6 @@ OUI:3CBEE1*
 OUI:047E4A*
  ID_OUI_FROM_DATABASE=moobox CO., Ltd.
 
-OUI:F01B6C*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:E0C767*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -35876,9 +37337,6 @@ OUI:54D0B4*
 OUI:D017C2*
  ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
 
-OUI:10DA43*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:001625*
  ID_OUI_FROM_DATABASE=Impinj, Inc.
 
@@ -35900,15 +37358,6 @@ OUI:2C2D48*
 OUI:E4A471*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:60B617*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:18A3E8*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:741E93*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:00A0F4*
  ID_OUI_FROM_DATABASE=GE
 
@@ -35933,9 +37382,6 @@ OUI:0CBF3F*
 OUI:84FEDC*
  ID_OUI_FROM_DATABASE=Borqs Beijing Ltd.
 
-OUI:F03E90*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:D8D723*
  ID_OUI_FROM_DATABASE=IDS, Inc
 
@@ -36128,9 +37574,6 @@ OUI:E8A7F2*
 OUI:D8209F*
  ID_OUI_FROM_DATABASE=Cubro Acronet GesmbH
 
-OUI:CC500A*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:A860B6*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -36245,9 +37688,6 @@ OUI:588BF3*
 OUI:D8B02E*
  ID_OUI_FROM_DATABASE=Guangzhou Zonerich Business Machine Co., LTD.
 
-OUI:DC1AC5*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:849D64*
  ID_OUI_FROM_DATABASE=SMC Corporation
 
@@ -36458,9 +37898,6 @@ OUI:00C017*
 OUI:D49B5C*
  ID_OUI_FROM_DATABASE=Chongqing Miedu Technology Co., Ltd.
 
-OUI:EC8CA2*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:C411E0*
  ID_OUI_FROM_DATABASE=Bull Group Co., Ltd
 
@@ -36623,9 +38060,6 @@ OUI:8CEA1B*
 OUI:001650*
  ID_OUI_FROM_DATABASE=Kratos EPD
 
-OUI:9CFBD5*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:583112*
  ID_OUI_FROM_DATABASE=DRUST
 
@@ -36755,12 +38189,6 @@ OUI:B08900*
 OUI:640DCE*
  ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
 
-OUI:00A085*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:ACDE48*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:6063F9*
  ID_OUI_FROM_DATABASE=Ciholas, Inc.
 
@@ -37058,9 +38486,6 @@ OUI:500959*
 OUI:143365*
  ID_OUI_FROM_DATABASE=TEM Mobile Limited
 
-OUI:205D47*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:C0F945*
  ID_OUI_FROM_DATABASE=Toshiba Toko Meter Systems Co., LTD.
 
@@ -37100,12 +38525,6 @@ OUI:C83DD4*
 OUI:487B6B*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:3087D9*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
-OUI:A8E705*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:9C62AB*
  ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd
 
@@ -37544,9 +38963,6 @@ OUI:E442A6*
 OUI:6045CB*
  ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
 
-OUI:74C9A3*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:84AFEC*
  ID_OUI_FROM_DATABASE=BUFFALO.INC
 
@@ -37580,9 +38996,6 @@ OUI:B03D96*
 OUI:B02628*
  ID_OUI_FROM_DATABASE=Broadcom Limited
 
-OUI:24792A*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:0080E7*
  ID_OUI_FROM_DATABASE=Leonardo Tactical Systems.
 
@@ -37871,6 +39284,474 @@ OUI:A009ED*
 OUI:90FB5B*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
+OUI:3C0CDB*
+ ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD
+
+OUI:C81FEA*
+ ID_OUI_FROM_DATABASE=Avaya Inc
+
+OUI:10F681*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:F01B6C*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:DC1AC5*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:205D47*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:9CFBD5*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:886AE3*
+ ID_OUI_FROM_DATABASE=Alpha Networks Inc.
+
+OUI:9061AE*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:A4F3E7*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
+OUI:A0239F*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:D8DF7A*
+ ID_OUI_FROM_DATABASE=Quest Software, Inc.
+
+OUI:30B62D*
+ ID_OUI_FROM_DATABASE=Mojo Networks, Inc.
+
+OUI:001B17*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:9828A6*
+ ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
+
+OUI:B0EABC*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
+OUI:94C691*
+ ID_OUI_FROM_DATABASE=EliteGroup Computer Systems Co., LTD
+
+OUI:9C6F52*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:A09D86*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
+
+OUI:E0CBBC*
+ ID_OUI_FROM_DATABASE=Cisco Meraki
+
+OUI:00D01F*
+ ID_OUI_FROM_DATABASE=Senetas Corporation Ltd
+
+OUI:A40450*
+ ID_OUI_FROM_DATABASE=nFore Technology Inc.
+
+OUI:4CB008*
+ ID_OUI_FROM_DATABASE=Shenzhen Gwelltimes Technology Co.,Ltd
+
+OUI:58B633*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:D4684D*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:2CE6CC*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:8C0C90*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:842096*
+ ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD.
+
+OUI:3087D9*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:24792A*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:589396*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:74911A*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:00227F*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:002482*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:F03E90*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:EC8CA2*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:30F77F*
+ ID_OUI_FROM_DATABASE=S Mobile Devices Limited
+
+OUI:38E595*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:5C5181*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:389AF6*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:E0AA96*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:507705*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:C4CB6B*
+ ID_OUI_FROM_DATABASE=Airista Flow, Inc.
+
+OUI:B05508*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:008BFC*
+ ID_OUI_FROM_DATABASE=mixi,Inc.
+
+OUI:2C4053*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:ACDE48*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:00A085*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:D09466*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:F0EFD2*
+ ID_OUI_FROM_DATABASE=TF PAYMENT SERVICE CO., LTD
+
+OUI:30C01B*
+ ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd
+
+OUI:647C34*
+ ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited
+
+OUI:747D24*
+ ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd.
+
+OUI:E817FC*
+ ID_OUI_FROM_DATABASE=Fujitsu Cloud Technologies Limited
+
+OUI:001009*
+ ID_OUI_FROM_DATABASE=HORANET
+
+OUI:6432A8*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:78BC1A*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:E4F004*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:60F677*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:288CB8*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:0C72D9*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:602E20*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E472E2*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E86819*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:48BCA6*
+ ID_OUI_FROM_DATABASE=​ASUNG TECHNO CO.,Ltd
+
+OUI:8C7CFF*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:C4F57C*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:00237F*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:00095B*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:000FB5*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:006069*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:000CDB*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:803773*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:405D82*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:C0FFD4*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:10DA43*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:B03956*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:C43DC7*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:F87394*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:401B5F*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:AC512C*
+ ID_OUI_FROM_DATABASE=Infinix mobility limited
+
+OUI:90B1E0*
+ ID_OUI_FROM_DATABASE=Beijing Nebula Link Technology Co., Ltd
+
+OUI:6C090A*
+ ID_OUI_FROM_DATABASE=GEMATICA SRL
+
+OUI:001439*
+ ID_OUI_FROM_DATABASE=Blonder Tongue Laboratories, Inc
+
+OUI:107B44*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
+OUI:9C4FCF*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
+
+OUI:001BD3*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+
+OUI:00C08F*
+ ID_OUI_FROM_DATABASE=Panasonic Electric Works Co., Ltd.
+
+OUI:0008C9*
+ ID_OUI_FROM_DATABASE=TechniSat Digital GmbH Daun
+
+OUI:20A6CD*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:F4F3AA*
+ ID_OUI_FROM_DATABASE=JBL GmbH & Co. KG
+
+OUI:38CD07*
+ ID_OUI_FROM_DATABASE=Beijing FaceCam Technology Co., Ltd.
+
+OUI:B009DA*
+ ID_OUI_FROM_DATABASE=Ring Solutions
+
+OUI:444AB0*
+ ID_OUI_FROM_DATABASE=Zhejiang Moorgen Intelligence Technology Co., Ltd
+
+OUI:844167*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:B4F61C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:ECFA03*
+ ID_OUI_FROM_DATABASE=FCA
+
+OUI:78E103*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
+OUI:90324B*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:78A6E1*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:F4D7B2*
+ ID_OUI_FROM_DATABASE=LGS Innovations, LLC
+
+OUI:20040F*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:2C7360*
+ ID_OUI_FROM_DATABASE=Earda Technologies co Ltd
+
+OUI:048B42*
+ ID_OUI_FROM_DATABASE=Skspruce Technologies
+
+OUI:C421C8*
+ ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
+
+OUI:9C63ED*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:002692*
+ ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation
+
+OUI:F03D03*
+ ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+
+OUI:006088*
+ ID_OUI_FROM_DATABASE=Analog Devices, Inc.
+
+OUI:084ACF*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:1CDDEA*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:ECEBB8*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:5CE8B7*
+ ID_OUI_FROM_DATABASE=Oraimo Technology Limited
+
+OUI:D89EF3*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:CC66B2*
+ ID_OUI_FROM_DATABASE=Nokia
+
+OUI:C0742B*
+ ID_OUI_FROM_DATABASE=SHENZHEN XUNLONG SOFTWARE CO.,LIMITED
+
+OUI:D8AFF1*
+ ID_OUI_FROM_DATABASE=Panasonic Appliances Company
+
+OUI:7086C1*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:A072E4*
+ ID_OUI_FROM_DATABASE=NJ SYSTEM CO.,LTD
+
+OUI:A8E824*
+ ID_OUI_FROM_DATABASE=INIM ELECTRONICS S.R.L.
+
+OUI:6CB749*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:A0FE61*
+ ID_OUI_FROM_DATABASE=Vivint Wireless Inc.
+
+OUI:601803*
+ ID_OUI_FROM_DATABASE=Daikin Air-conditioning (Shanghai) Co., Ltd.
+
+OUI:08152F*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. ARTIK
+
+OUI:408BF6*
+ ID_OUI_FROM_DATABASE=Shenzhen TCL New Technology Co., Ltd
+
+OUI:F46E24*
+ ID_OUI_FROM_DATABASE=NEC Personal Computers, Ltd.
+
+OUI:888279*
+ ID_OUI_FROM_DATABASE=Shenzhen RB-LINK Intelligent Technology Co.Ltd
+
+OUI:78321B*
+ ID_OUI_FROM_DATABASE=D-Link International
+
+OUI:EC51BC*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:F079E8*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:741E93*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:18A3E8*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:60B617*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:CC500A*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:A8E705*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:74C9A3*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:A013CB*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:20896F*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:D8A534*
+ ID_OUI_FROM_DATABASE=Spectronix Corporation
+
+OUI:583879*
+ ID_OUI_FROM_DATABASE=RICOH COMPANY, LTD.
+
+OUI:94282E*
+ ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd
+
+OUI:887598*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:D0B128*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:FCEEE6*
+ ID_OUI_FROM_DATABASE=FORMIKE ELECTRONIC CO., LTD
+
+OUI:D843ED*
+ ID_OUI_FROM_DATABASE=Suzuken
+
+OUI:2C431A*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
+OUI:A8D3C8*
+ ID_OUI_FROM_DATABASE=Topcon Electronics GmbH & Co. KG
+
+OUI:389F5A*
+ ID_OUI_FROM_DATABASE=C-Kur TV Inc.
+
+OUI:24B209*
+ ID_OUI_FROM_DATABASE=Avaya Inc
+
+OUI:24E124*
+ ID_OUI_FROM_DATABASE=Xiamen Ursaconn Technology Co. , Ltd.
+
+OUI:DC68EB*
+ ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
+
+OUI:9441C1*
+ ID_OUI_FROM_DATABASE=Mini-Cam Limited
+
+OUI:E8D819*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
+OUI:0008FA*
+ ID_OUI_FROM_DATABASE=KEB Automation KG
+
+OUI:18396E*
+ ID_OUI_FROM_DATABASE=SUNSEA TELECOMMUNICATIONS CO.,LTD.
+
+OUI:E8DF70*
+ ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
+
 OUI:5846E1*
  ID_OUI_FROM_DATABASE=Baxter International Inc
 
@@ -38174,9 +40055,6 @@ OUI:808917*
 OUI:5C899A*
  ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
-OUI:E422A5*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
 OUI:1C994C*
  ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
 
@@ -38222,18 +40100,6 @@ OUI:44A7CF*
 OUI:0013E0*
  ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
 
-OUI:748EF8*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:00E052*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:000480*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:000088*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:344B50*
  ID_OUI_FROM_DATABASE=zte corporation
 
@@ -38399,12 +40265,6 @@ OUI:80E86F*
 OUI:E4AA5D*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:000389*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
-OUI:0CE0E4*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
 OUI:B0AA77*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -38900,9 +40760,6 @@ OUI:68EDA4*
 OUI:B899B0*
  ID_OUI_FROM_DATABASE=Cohere Technologies
 
-OUI:2CC5D3*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:80C5E6*
  ID_OUI_FROM_DATABASE=Microsoft Corporation
 
@@ -38945,9 +40802,6 @@ OUI:BCF811*
 OUI:A8827F*
  ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd
 
-OUI:609C9F*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:900A39*
  ID_OUI_FROM_DATABASE=Wiio, Inc.
 
@@ -39059,9 +40913,6 @@ OUI:60F189*
 OUI:74A34A*
  ID_OUI_FROM_DATABASE=ZIMI CORPORATION
 
-OUI:98F5A9*
- ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO.,LTD.
-
 OUI:D89341*
  ID_OUI_FROM_DATABASE=General Electric Global Research
 
@@ -39197,9 +41048,6 @@ OUI:B43934*
 OUI:DCC622*
  ID_OUI_FROM_DATABASE=BUHEUNG SYSTEM
 
-OUI:5C2BF5*
- ID_OUI_FROM_DATABASE=Vivint
-
 OUI:D062A0*
  ID_OUI_FROM_DATABASE=China Essence Technology (Zhumadian) Co., Ltd.
 
@@ -39254,9 +41102,6 @@ OUI:94B40F*
 OUI:4C2C83*
  ID_OUI_FROM_DATABASE=Zhejiang KaNong Network Technology Co.,Ltd.
 
-OUI:BCC342*
- ID_OUI_FROM_DATABASE=Panasonic System Networks Co., Ltd.
-
 OUI:E89606*
  ID_OUI_FROM_DATABASE=testo Instruments (Shenzhen) Co., Ltd.
 
@@ -39557,9 +41402,6 @@ OUI:387B47*
 OUI:7CCD11*
  ID_OUI_FROM_DATABASE=MS-Magnet
 
-OUI:94FBB2*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
 OUI:4CE1BB*
  ID_OUI_FROM_DATABASE=Zhuhai HiFocus Technology Co., Ltd.
 
@@ -39665,9 +41507,6 @@ OUI:D46867*
 OUI:68692E*
  ID_OUI_FROM_DATABASE=Zycoo Co.,Ltd
 
-OUI:A875E2*
- ID_OUI_FROM_DATABASE=Aventura Technologies, Inc.
-
 OUI:38BF2F*
  ID_OUI_FROM_DATABASE=Espec Corp.
 
@@ -39812,9 +41651,6 @@ OUI:DC1792*
 OUI:7C8306*
  ID_OUI_FROM_DATABASE=Glen Dimplex Nordic as
 
-OUI:84253F*
- ID_OUI_FROM_DATABASE=Silex Technology, Inc
-
 OUI:907A0A*
  ID_OUI_FROM_DATABASE=Gebr. Bode GmbH & Co KG
 
@@ -39917,9 +41753,6 @@ OUI:A05B21*
 OUI:50B8A2*
  ID_OUI_FROM_DATABASE=ImTech Technologies LLC,
 
-OUI:A41566*
- ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd
-
 OUI:B04C05*
  ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH
 
@@ -40376,9 +42209,6 @@ OUI:7093F8*
 OUI:305D38*
  ID_OUI_FROM_DATABASE=Beissbarth
 
-OUI:FCD6BD*
- ID_OUI_FROM_DATABASE=Robert Bosch GmbH
-
 OUI:044A50*
  ID_OUI_FROM_DATABASE=Ramaxel Technology (Shenzhen) limited company
 
@@ -40865,9 +42695,6 @@ OUI:64808B*
 OUI:7C6B52*
  ID_OUI_FROM_DATABASE=Tigaro Wireless
 
-OUI:48C1AC*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
 OUI:046D42*
  ID_OUI_FROM_DATABASE=Bryston Ltd.
 
@@ -40925,9 +42752,6 @@ OUI:FC2E2D*
 OUI:E84E06*
  ID_OUI_FROM_DATABASE=EDUP INTERNATIONAL (HK) CO., LTD
 
-OUI:70B921*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:E8C320*
  ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd
 
@@ -41063,9 +42887,6 @@ OUI:040A83*
 OUI:B42A39*
  ID_OUI_FROM_DATABASE=ORBIT MERRET, spol. s r. o.
 
-OUI:B80B9D*
- ID_OUI_FROM_DATABASE=ROPEX Industrie-Elektronik GmbH
-
 OUI:18AEBB*
  ID_OUI_FROM_DATABASE=Siemens Convergence Creators GmbH&Co.KG
 
@@ -41117,9 +42938,6 @@ OUI:C0A26D*
 OUI:205B2A*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:18B430*
- ID_OUI_FROM_DATABASE=Nest Labs Inc.
-
 OUI:F8769B*
  ID_OUI_FROM_DATABASE=Neopis Co., Ltd.
 
@@ -41195,9 +43013,6 @@ OUI:94E848*
 OUI:AC5E8C*
  ID_OUI_FROM_DATABASE=Utillink
 
-OUI:CC7EE7*
- ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
-
 OUI:BC99BC*
  ID_OUI_FROM_DATABASE=FonSee Technology Inc.
 
@@ -41324,9 +43139,6 @@ OUI:A036FA*
 OUI:EC836C*
  ID_OUI_FROM_DATABASE=RM Tech Co., Ltd.
 
-OUI:C0C520*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:6083B2*
  ID_OUI_FROM_DATABASE=GkWare e.K.
 
@@ -41627,9 +43439,6 @@ OUI:389F83*
 OUI:8C541D*
  ID_OUI_FROM_DATABASE=LGE
 
-OUI:601283*
- ID_OUI_FROM_DATABASE=Soluciones Tecnologicas para la Salud y el Bienestar SA
-
 OUI:003A9D*
  ID_OUI_FROM_DATABASE=NEC Platforms, Ltd.
 
@@ -41816,9 +43625,6 @@ OUI:889821*
 OUI:CC5076*
  ID_OUI_FROM_DATABASE=Ocom Communications, Inc.
 
-OUI:705812*
- ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
-
 OUI:7C2CF3*
  ID_OUI_FROM_DATABASE=Secure Electrans Ltd
 
@@ -42785,9 +44591,6 @@ OUI:001DDA*
 OUI:001DDF*
  ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd.
 
-OUI:001DCC*
- ID_OUI_FROM_DATABASE=Hetra Secure Solutions
-
 OUI:001DC7*
  ID_OUI_FROM_DATABASE=L-3 Communications Geneva Aerospace
 
@@ -43031,9 +44834,6 @@ OUI:001D07*
 OUI:001D01*
  ID_OUI_FROM_DATABASE=Neptune Digital
 
-OUI:001CFA*
- ID_OUI_FROM_DATABASE=Alarm.com
-
 OUI:001CEE*
  ID_OUI_FROM_DATABASE=SHARP Corporation
 
@@ -43418,9 +45218,6 @@ OUI:00198E*
 OUI:001980*
  ID_OUI_FROM_DATABASE=Gridpoint Systems
 
-OUI:001987*
- ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co., Ltd.
-
 OUI:00197B*
  ID_OUI_FROM_DATABASE=Picotest Corp.
 
@@ -43532,9 +45329,6 @@ OUI:001898*
 OUI:001891*
  ID_OUI_FROM_DATABASE=Zhongshan General K-mate Electronics Co., Ltd
 
-OUI:001885*
- ID_OUI_FROM_DATABASE=Avigilon Corporation
-
 OUI:00188C*
  ID_OUI_FROM_DATABASE=Mobile Action Technology Inc.
 
@@ -43745,9 +45539,6 @@ OUI:001741*
 OUI:001733*
  ID_OUI_FROM_DATABASE=SFR
 
-OUI:00173A*
- ID_OUI_FROM_DATABASE=Reach Systems Inc.
-
 OUI:00172E*
  ID_OUI_FROM_DATABASE=FXC Inc.
 
@@ -44039,9 +45830,6 @@ OUI:00152C*
 OUI:00151F*
  ID_OUI_FROM_DATABASE=Multivision Intelligent Surveillance (Hong Kong) Ltd
 
-OUI:001526*
- ID_OUI_FROM_DATABASE=Remote Technologies Inc
-
 OUI:00151A*
  ID_OUI_FROM_DATABASE=Hunter Engineering Company
 
@@ -44303,9 +46091,6 @@ OUI:001343*
 OUI:00133D*
  ID_OUI_FROM_DATABASE=Micro Memory Curtiss Wright Co
 
-OUI:00139D*
- ID_OUI_FROM_DATABASE=Marvell Hispana S.L.
-
 OUI:00138B*
  ID_OUI_FROM_DATABASE=Phantom Technologies LLC
 
@@ -44417,9 +46202,6 @@ OUI:00122B*
 OUI:001212*
  ID_OUI_FROM_DATABASE=PLUS  Corporation
 
-OUI:001219*
- ID_OUI_FROM_DATABASE=Ahead Communication Systems Inc
-
 OUI:0012D8*
  ID_OUI_FROM_DATABASE=International Games System Co., Ltd.
 
@@ -46988,9 +48770,6 @@ OUI:00507C*
 OUI:005065*
  ID_OUI_FROM_DATABASE=TDK-Lambda Corporation
 
-OUI:0050C7*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:0050F4*
  ID_OUI_FROM_DATABASE=SIGMATEK GMBH & CO. KG
 
@@ -47120,9 +48899,6 @@ OUI:00D06F*
 OUI:00D04B*
  ID_OUI_FROM_DATABASE=LA CIE GROUP S.A.
 
-OUI:00D060*
- ID_OUI_FROM_DATABASE=Panasonic Europe Ltd.
-
 OUI:00D002*
  ID_OUI_FROM_DATABASE=DITECH CORPORATION
 
@@ -48017,9 +49793,6 @@ OUI:00C083*
 OUI:00C005*
  ID_OUI_FROM_DATABASE=LIVINGSTON ENTERPRISES, INC.
 
-OUI:00C064*
- ID_OUI_FROM_DATABASE=GENERAL DATACOMM IND. INC.
-
 OUI:00C0C8*
  ID_OUI_FROM_DATABASE=MICRO BYTE PTY. LTD.
 
@@ -48356,9 +50129,6 @@ OUI:00405A*
 OUI:00404C*
  ID_OUI_FROM_DATABASE=HYPERTEC PTY LTD.
 
-OUI:00C0EE*
- ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
-
 OUI:00C0CB*
  ID_OUI_FROM_DATABASE=CONTROL TECHNOLOGY CORPORATION
 
@@ -48728,9 +50498,6 @@ OUI:080053*
 OUI:08004F*
  ID_OUI_FROM_DATABASE=CYGNET SYSTEMS
 
-OUI:F8E71E*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:00194B*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
@@ -48746,12 +50513,6 @@ OUI:A01B29*
 OUI:90013B*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
-OUI:ECDF3A*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
-OUI:E45AA2*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:00235A*
  ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
 
@@ -49064,24 +50825,6 @@ OUI:000B6A*
 OUI:40BA61*
  ID_OUI_FROM_DATABASE=ARIMA Communications Corp.
 
-OUI:841B5E*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:204E7F*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:A021B7*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:0024B2*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:C03F0E*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:001F33*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:1883BF*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
@@ -49121,15 +50864,6 @@ OUI:002675*
 OUI:001F3F*
  ID_OUI_FROM_DATABASE=AVM GmbH
 
-OUI:506A03*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:6CB0CE*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:100D7F*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:0020D6*
  ID_OUI_FROM_DATABASE=Breezecom, Ltd.
 
@@ -49487,9 +51221,6 @@ OUI:A89352*
 OUI:AC5F3E*
  ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
 
-OUI:B07FB9*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:70661B*
  ID_OUI_FROM_DATABASE=Sonova AG
 
@@ -49550,21 +51281,6 @@ OUI:405EE1*
 OUI:10F005*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:BC9889*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:E42F26*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:344B3D*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:FCF647*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:1088CE*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:D463FE*
  ID_OUI_FROM_DATABASE=Arcadyan Corporation
 
@@ -49811,18 +51527,12 @@ OUI:042758*
 OUI:3C92DC*
  ID_OUI_FROM_DATABASE=Octopod Technology Co. Ltd.
 
-OUI:74CC39*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:6038E0*
  ID_OUI_FROM_DATABASE=Belkin International Inc.
 
 OUI:F0FDA0*
  ID_OUI_FROM_DATABASE=Acurix Networks Pty Ltd
 
-OUI:1CB9C4*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:3876D1*
  ID_OUI_FROM_DATABASE=Euronda SpA
 
@@ -50075,9 +51785,6 @@ OUI:A84E3F*
 OUI:00A742*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:6CA858*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:001478*
  ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
 
@@ -50984,56 +52691,50 @@ OUI:F87588*
 OUI:BC3F8F*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:E4A749*
- ID_OUI_FROM_DATABASE=Palo Alto Networks
-
 OUI:04DEF2*
  ID_OUI_FROM_DATABASE=Shenzhen ECOM Technology Co. Ltd
 
 OUI:00D071*
  ID_OUI_FROM_DATABASE=ECHELON CORP.
 
+OUI:504061*
+ ID_OUI_FROM_DATABASE=Nokia
+
 OUI:0030C5*
  ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC.
 
-OUI:504061*
- ID_OUI_FROM_DATABASE=Nokia
+OUI:54E3F6*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent
 
 OUI:7467F7*
  ID_OUI_FROM_DATABASE=Extreme Networks
 
+OUI:B0C205*
+ ID_OUI_FROM_DATABASE=BIONIME
+
+OUI:0C61CF*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
 OUI:B4C799*
  ID_OUI_FROM_DATABASE=Extreme Networks
 
-OUI:54E3F6*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent
-
 OUI:5C0E8B*
  ID_OUI_FROM_DATABASE=Extreme Networks
 
 OUI:00E02B*
  ID_OUI_FROM_DATABASE=Extreme Networks
 
-OUI:B0C205*
- ID_OUI_FROM_DATABASE=BIONIME
-
-OUI:0C61CF*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
 OUI:7C2664*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
-OUI:E47DEB*
- ID_OUI_FROM_DATABASE=Shanghai Notion Information Technology CO.,LTD.
-
 OUI:A002DC*
  ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
 
 OUI:0C47C9*
  ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
 
-OUI:28EF01*
- ID_OUI_FROM_DATABASE=Private
+OUI:E47DEB*
+ ID_OUI_FROM_DATABASE=Shanghai Notion Information Technology CO.,LTD.
 
 OUI:747548*
  ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
@@ -51086,18 +52787,9 @@ OUI:4C82CF*
 OUI:F49634*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:F470AB*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
-OUI:341A35*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:6C4B90*
  ID_OUI_FROM_DATABASE=LiteON
 
-OUI:08028E*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:F8FF0B*
  ID_OUI_FROM_DATABASE=Electronic Technology Inc.
 
@@ -51110,15 +52802,15 @@ OUI:90F305*
 OUI:00093A*
  ID_OUI_FROM_DATABASE=Molex
 
+OUI:C8F86D*
+ ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
+
 OUI:B8D50B*
  ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd
 
 OUI:28A6DB*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:C8F86D*
- ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd
-
 OUI:D45F25*
  ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
 
@@ -51143,6 +52835,12 @@ OUI:F4DE0C*
 OUI:BC8AE8*
  ID_OUI_FROM_DATABASE=QING DAO HAIER TELECOM CO.,LTD.
 
+OUI:A81B5A*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:DC6DCD*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
 OUI:440444*
  ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
 
@@ -51158,11 +52856,8 @@ OUI:38295A*
 OUI:4C1A3D*
  ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
 
-OUI:A81B5A*
- ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
-
-OUI:DC6DCD*
- ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+OUI:185207*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD
 
 OUI:70D379*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@@ -51170,9 +52865,6 @@ OUI:70D379*
 OUI:7C4F7D*
  ID_OUI_FROM_DATABASE=Sawwave
 
-OUI:185207*
- ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD
-
 OUI:9874DA*
  ID_OUI_FROM_DATABASE=Infinix mobility limited
 
@@ -51200,38 +52892,38 @@ OUI:EC363F*
 OUI:54FA3E*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:0C8910*
+OUI:B8BBAF*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:FCF136*
+OUI:60C5AD*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:981DFA*
+OUI:28395E*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:84A466*
+OUI:C4AE12*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:1867B0*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+OUI:10D07A*
+ ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
 
-OUI:CCB11A*
+OUI:0C8910*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:B8BBAF*
+OUI:FCF136*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:60C5AD*
+OUI:981DFA*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:28395E*
+OUI:84A466*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:C4AE12*
+OUI:1867B0*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:10D07A*
- ID_OUI_FROM_DATABASE=AMPAK Technology, Inc.
+OUI:CCB11A*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
 OUI:80B234*
  ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
@@ -51239,18 +52931,9 @@ OUI:80B234*
 OUI:B877C3*
  ID_OUI_FROM_DATABASE=METER Group
 
-OUI:003676*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:84E058*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
 OUI:F07485*
  ID_OUI_FROM_DATABASE=NGD Systems, Inc.
 
-OUI:347A60*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
 OUI:BC644B*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
@@ -51275,24 +52958,6 @@ OUI:745612*
 OUI:E46449*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:C005C2*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:6455B1*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:203D66*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:D404CD*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:446AB7*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:2C9924*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
 OUI:001BDD*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
@@ -51380,11 +53045,35 @@ OUI:8C09F4*
 OUI:3CDFA9*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:105611*
+OUI:003676*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:2C3AE8*
- ID_OUI_FROM_DATABASE=Espressif Inc.
+OUI:84E058*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:347A60*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:C005C2*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:6455B1*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:203D66*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:D404CD*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:446AB7*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:2C9924*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:105611*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
 OUI:DC74A8*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@@ -51392,30 +53081,33 @@ OUI:DC74A8*
 OUI:C087EB*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
+OUI:2C3AE8*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
+OUI:74F61C*
+ ID_OUI_FROM_DATABASE=HTC Corporation
+
 OUI:E8B6C2*
  ID_OUI_FROM_DATABASE=Juniper Networks
 
 OUI:B0DAF9*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:74F61C*
- ID_OUI_FROM_DATABASE=HTC Corporation
-
 OUI:3438B7*
  ID_OUI_FROM_DATABASE=HUMAX Co., Ltd.
 
 OUI:5C1A6F*
  ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd.
 
+OUI:487D2E*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
 OUI:B089C2*
  ID_OUI_FROM_DATABASE=Zyptonite
 
 OUI:F0D4F6*
  ID_OUI_FROM_DATABASE=Lars Thrane A/S
 
-OUI:487D2E*
- ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
-
 OUI:0403D6*
  ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
 
@@ -51431,14 +53123,14 @@ OUI:6C60EB*
 OUI:AC4E2E*
  ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd
 
-OUI:B40016*
- ID_OUI_FROM_DATABASE=INGENICO TERMINALS SAS
-
 OUI:0027E3*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:A0341B*
- ID_OUI_FROM_DATABASE=TrackR, Inc
+OUI:488D36*
+ ID_OUI_FROM_DATABASE=Arcadyan Corporation
+
+OUI:B40016*
+ ID_OUI_FROM_DATABASE=INGENICO TERMINALS SAS
 
 OUI:FCA667*
  ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
@@ -51446,8 +53138,8 @@ OUI:FCA667*
 OUI:784501*
  ID_OUI_FROM_DATABASE=Biamp Systems
 
-OUI:488D36*
- ID_OUI_FROM_DATABASE=Arcadyan Corporation
+OUI:A0341B*
+ ID_OUI_FROM_DATABASE=TrackR, Inc
 
 OUI:986F60*
  ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
@@ -51455,6 +53147,12 @@ OUI:986F60*
 OUI:4C189A*
  ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
 
+OUI:6CA849*
+ ID_OUI_FROM_DATABASE=Avaya Inc
+
+OUI:A4251B*
+ ID_OUI_FROM_DATABASE=Avaya Inc
+
 OUI:E45D52*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
@@ -51473,7 +53171,7 @@ OUI:14612F*
 OUI:707C69*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:A47886*
+OUI:FC8399*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
 OUI:44322A*
@@ -51482,17 +53180,488 @@ OUI:44322A*
 OUI:048A15*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:6CA849*
+OUI:00040D*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:A4251B*
+OUI:A47886*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:00040D*
- ID_OUI_FROM_DATABASE=Avaya Inc
+OUI:001CFA*
+ ID_OUI_FROM_DATABASE=Alarm.com
 
-OUI:FC8399*
- ID_OUI_FROM_DATABASE=Avaya Inc
+OUI:60313B*
+ ID_OUI_FROM_DATABASE=Sunnovo International Limited
+
+OUI:B4E62A*
+ ID_OUI_FROM_DATABASE=LG Innotek
+
+OUI:E45AA2*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:ECDF3A*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:F470AB*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:50184C*
+ ID_OUI_FROM_DATABASE=Platina Systems Inc.
+
+OUI:E4A749*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:786D94*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:CC4639*
+ ID_OUI_FROM_DATABASE=WAAV, Inc.
+
+OUI:30B164*
+ ID_OUI_FROM_DATABASE=Power Electronics International Inc.
+
+OUI:18B430*
+ ID_OUI_FROM_DATABASE=Nest Labs Inc.
+
+OUI:3CF591*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:602101*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:604762*
+ ID_OUI_FROM_DATABASE=Beijing Sensoro Technology Co.,Ltd.
+
+OUI:7CE2CA*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:B0DFC1*
+ ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch
+
+OUI:70788B*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:001DCC*
+ ID_OUI_FROM_DATABASE=Ayon Cyber Security, Inc
+
+OUI:7065A3*
+ ID_OUI_FROM_DATABASE=Kandao lightforge Co., Ltd.
+
+OUI:706E6D*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:FC2F6B*
+ ID_OUI_FROM_DATABASE=Everspin Technologies, Inc.
+
+OUI:B4C170*
+ ID_OUI_FROM_DATABASE=Yi chip Microelectronics (Hangzhou) Co., Ltd
+
+OUI:540237*
+ ID_OUI_FROM_DATABASE=Teltronic AG
+
+OUI:2CC5D3*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:F8E71E*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:1CB9C4*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:C0C520*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:A89675*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+
+OUI:94F128*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:94FBB2*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:A47B9D*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
+OUI:608E08*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:7C2EDD*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:3CF7A4*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:342D0D*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:EC3DFD*
+ ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
+
+OUI:001885*
+ ID_OUI_FROM_DATABASE=Avigilon Corporation
+
+OUI:18742E*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
+OUI:8886C2*
+ ID_OUI_FROM_DATABASE=STABILO International GmbH
+
+OUI:04FA3F*
+ ID_OUI_FROM_DATABASE=Opticore Inc.
+
+OUI:308454*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:FC7F56*
+ ID_OUI_FROM_DATABASE=CoSyst Control Systems GmbH
+
+OUI:8C2505*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:94D029*
+ ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
+
+OUI:4C49E3*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:28D436*
+ ID_OUI_FROM_DATABASE=Jiangsu dewosi electric co., LTD
+
+OUI:149346*
+ ID_OUI_FROM_DATABASE=PNI sensor corporation
+
+OUI:18B81F*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:00C064*
+ ID_OUI_FROM_DATABASE=General Datacomm LLC
+
+OUI:601283*
+ ID_OUI_FROM_DATABASE=TSB REAL TIME LOCATION SYSTEMS S.L.
+
+OUI:E06089*
+ ID_OUI_FROM_DATABASE=Cloudleaf, Inc.
+
+OUI:001219*
+ ID_OUI_FROM_DATABASE=General Datacomm LLC
+
+OUI:BC54FC*
+ ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
+
+OUI:547595*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:18BC5A*
+ ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
+
+OUI:00869C*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:00139D*
+ ID_OUI_FROM_DATABASE=MaxLinear Hispania S.L.U.
+
+OUI:4C16FC*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:609C9F*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:000088*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:000480*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:00E052*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:748EF8*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:48C1AC*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:0CE0E4*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:000389*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:E422A5*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:001F33*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:C03F0E*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:0024B2*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:A021B7*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:204E7F*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:841B5E*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:100D7F*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:6CB0CE*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:506A03*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:B07FB9*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:08028E*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:D8C497*
+ ID_OUI_FROM_DATABASE=Quanta Computer Inc.
+
+OUI:444E6D*
+ ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
+
+OUI:A41566*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:74E60F*
+ ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED
+
+OUI:0050C7*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:B80B9D*
+ ID_OUI_FROM_DATABASE=ROPEX Industrie-Elektronik GmbH
+
+OUI:001526*
+ ID_OUI_FROM_DATABASE=Remote Technologies Inc
+
+OUI:409922*
+ ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
+
+OUI:B8DB1C*
+ ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
+
+OUI:3C10E6*
+ ID_OUI_FROM_DATABASE=PHAZR Inc.
+
+OUI:001987*
+ ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd.
+
+OUI:BCC342*
+ ID_OUI_FROM_DATABASE=Panasonic Communications Co., Ltd.
+
+OUI:705812*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+
+OUI:CC7EE7*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+
+OUI:00D060*
+ ID_OUI_FROM_DATABASE=Panasonic Europe Ltd.
+
+OUI:84253F*
+ ID_OUI_FROM_DATABASE=silex technology, Inc.
+
+OUI:40017A*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:40D63C*
+ ID_OUI_FROM_DATABASE=Equitech Industrial(DongGuan)Co.,Ltd
+
+OUI:A4E975*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:C0A53E*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:9800C6*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:787B8A*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:3866F0*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:20EE28*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:08F4AB*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:8C8590*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:FC017C*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:2CB21A*
+ ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd.
+
+OUI:00C0EE*
+ ID_OUI_FROM_DATABASE=KYOCERA Display Corporation
+
+OUI:28840E*
+ ID_OUI_FROM_DATABASE=silicon valley immigration service
+
+OUI:CC5A53*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:BC2E48*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:940006*
+ ID_OUI_FROM_DATABASE=jinyoung
+
+OUI:5C6776*
+ ID_OUI_FROM_DATABASE=IDS Imaging Development Systems GmbH
+
+OUI:28EF01*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:A875E2*
+ ID_OUI_FROM_DATABASE=Aventura Technologies, Inc.
+
+OUI:DC0C2D*
+ ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
+
+OUI:00173A*
+ ID_OUI_FROM_DATABASE=Cloudastructure Inc
+
+OUI:38D620*
+ ID_OUI_FROM_DATABASE=Limidea Concept Pte. Ltd.
+
+OUI:745C4B*
+ ID_OUI_FROM_DATABASE=GN Audio A/S
+
+OUI:64FB50*
+ ID_OUI_FROM_DATABASE=RoomReady/Zdi, Inc.
+
+OUI:940E6B*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:38378B*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:5C2BF5*
+ ID_OUI_FROM_DATABASE=Vivint Wireless Inc.
+
+OUI:00FC8B*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
+OUI:10F163*
+ ID_OUI_FROM_DATABASE=TNK CO.,LTD
+
+OUI:98F5A9*
+ ID_OUI_FROM_DATABASE=OHSUNG
+
+OUI:5033F0*
+ ID_OUI_FROM_DATABASE=YICHEN (SHENZHEN) TECHNOLOGY CO.LTD
+
+OUI:50F722*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:90FD9F*
+ ID_OUI_FROM_DATABASE=Silicon Laboratories
+
+OUI:504EDC*
+ ID_OUI_FROM_DATABASE=Ping Communication
+
+OUI:344B3D*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:E42F26*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:BC9889*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:1088CE*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:FCF647*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:74CC39*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:6CA858*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:341A35*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:18D225*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:185282*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:BC4101*
+ ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp.
+
+OUI:5C8D2D*
+ ID_OUI_FROM_DATABASE=Shanghai Wellpay Information Technology Co., Ltd
+
+OUI:70B921*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:C850E9*
+ ID_OUI_FROM_DATABASE=Raisecom Technology CO., LTD
+
+OUI:BC825D*
+ ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
+
+OUI:5CA176*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD
+
+OUI:C8E7F0*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:087808*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:D03169*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:BC5451*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:24F5A2*
+ ID_OUI_FROM_DATABASE=Belkin International Inc.
+
+OUI:782D7E*
+ ID_OUI_FROM_DATABASE=TRENDnet, Inc.
+
+OUI:BCC31B*
+ ID_OUI_FROM_DATABASE=Kygo Life AS
+
+OUI:FCD6BD*
+ ID_OUI_FROM_DATABASE=Robert Bosch GmbH
+
+OUI:48BA4E*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:FC65DE*
+ ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
+
+OUI:B06EBF*
+ ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
+
+OUI:28AD3E*
+ ID_OUI_FROM_DATABASE=Shenzhen TONG BO WEI Technology CO.,LTD
+
+OUI:F092B4*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD
 
 OUI:D86CE9*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@@ -51659,9 +53828,6 @@ OUI:94659C*
 OUI:1002B5*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:A468BC*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:441EA1*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
@@ -51719,9 +53885,6 @@ OUI:403DEC*
 OUI:E84DD0*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:D81FCC*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:140467*
  ID_OUI_FROM_DATABASE=SNK Technologies Co.,Ltd.
 
@@ -51791,24 +53954,6 @@ OUI:ACE87B*
 OUI:688F84*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:889471*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:CC4E24*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:50EB1A*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:0027F8*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:000533*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:0060DF*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:4CAC0A*
  ID_OUI_FROM_DATABASE=zte corporation
 
@@ -52349,12 +54494,6 @@ OUI:B4EF04*
 OUI:049645*
  ID_OUI_FROM_DATABASE=WUXI SKY CHIP INTERCONNECTION TECHNOLOGY CO.,LTD.
 
-OUI:5CE3B6*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:9C88AD*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:C8C2C6*
  ID_OUI_FROM_DATABASE=Shanghai Airm2m Communication Technology Co., Ltd
 
@@ -52394,9 +54533,6 @@ OUI:044169*
 OUI:ACC51B*
  ID_OUI_FROM_DATABASE=Zhuhai Pantum Electronics Co., Ltd.
 
-OUI:4473D6*
- ID_OUI_FROM_DATABASE=Logitech
-
 OUI:E80734*
  ID_OUI_FROM_DATABASE=Champion Optical Network Engineering, LLC
 
@@ -52424,9 +54560,6 @@ OUI:CC20E8*
 OUI:E435C8*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:38FF36*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:D47208*
  ID_OUI_FROM_DATABASE=Bragi GmbH
 
@@ -52598,12 +54731,6 @@ OUI:4CEEB0*
 OUI:188EF9*
  ID_OUI_FROM_DATABASE=G2C Co. Ltd.
 
-OUI:809FAB*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:D00492*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:F4E9D4*
  ID_OUI_FROM_DATABASE=QLogic Corporation
 
@@ -52874,9 +55001,6 @@ OUI:70FC8C*
 OUI:902CC7*
  ID_OUI_FROM_DATABASE=C-MAX Asia Limited
 
-OUI:1C965A*
- ID_OUI_FROM_DATABASE=Weifang goertek Electronics CO.,LTD
-
 OUI:188219*
  ID_OUI_FROM_DATABASE=Alibaba Cloud Computing Ltd.
 
@@ -53282,9 +55406,6 @@ OUI:38CA97*
 OUI:84A783*
  ID_OUI_FROM_DATABASE=Alcatel Lucent
 
-OUI:2C5D93*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:1CC11A*
  ID_OUI_FROM_DATABASE=Wavetronix
 
@@ -53501,12 +55622,6 @@ OUI:B0793C*
 OUI:20CEC4*
  ID_OUI_FROM_DATABASE=Peraso Technologies
 
-OUI:04848A*
- ID_OUI_FROM_DATABASE=7INOVA TECHNOLOGY LIMITED
-
-OUI:20C6EB*
- ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
-
 OUI:700FEC*
  ID_OUI_FROM_DATABASE=Poindus Systems Corp.
 
@@ -53705,9 +55820,6 @@ OUI:E0C6B3*
 OUI:FCDB96*
  ID_OUI_FROM_DATABASE=ENERVALLEY CO., LTD
 
-OUI:FC8B97*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
 OUI:882E5A*
  ID_OUI_FROM_DATABASE=storONE
 
@@ -53759,9 +55871,6 @@ OUI:D0CDE1*
 OUI:94756E*
  ID_OUI_FROM_DATABASE=QinetiQ North America
 
-OUI:543D37*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:0C5521*
  ID_OUI_FROM_DATABASE=Axiros GmbH
 
@@ -53837,9 +55946,6 @@ OUI:E4EEFD*
 OUI:105CBF*
  ID_OUI_FROM_DATABASE=DuroByte Inc
 
-OUI:88A3CC*
- ID_OUI_FROM_DATABASE=Amatis Controls
-
 OUI:EC89F5*
  ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd.
 
@@ -54110,12 +56216,6 @@ OUI:E804F3*
 OUI:B85810*
  ID_OUI_FROM_DATABASE=NUMERA, INC.
 
-OUI:2CAB25*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
-OUI:AC6E1A*
- ID_OUI_FROM_DATABASE=Shenzhen Gongjin Electronics Co.,Ltd
-
 OUI:9886B1*
  ID_OUI_FROM_DATABASE=Flyaudio corporation (China)
 
@@ -54257,9 +56357,6 @@ OUI:04F17D*
 OUI:A0DC04*
  ID_OUI_FROM_DATABASE=Becker-Antriebe GmbH
 
-OUI:8CC121*
- ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
-
 OUI:2CBE97*
  ID_OUI_FROM_DATABASE=Ingenieurbuero Bickele und Buehler GmbH
 
@@ -54584,9 +56681,6 @@ OUI:902B34*
 OUI:48E1AF*
  ID_OUI_FROM_DATABASE=Vity
 
-OUI:245FDF*
- ID_OUI_FROM_DATABASE=KYOCERA Corporation
-
 OUI:C0A0DE*
  ID_OUI_FROM_DATABASE=Multi Touch Oy
 
@@ -54872,18 +56966,12 @@ OUI:0CE82F*
 OUI:C0626B*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:74D0DC*
- ID_OUI_FROM_DATABASE=ERICSSON AB
-
 OUI:B4B88D*
  ID_OUI_FROM_DATABASE=Thuh Company
 
 OUI:60F59C*
  ID_OUI_FROM_DATABASE=CRU-Dataport
 
-OUI:C4108A*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:4C73A5*
  ID_OUI_FROM_DATABASE=KOVE
 
@@ -55115,18 +57203,12 @@ OUI:64F987*
 OUI:3C7437*
  ID_OUI_FROM_DATABASE=RIM
 
-OUI:04209A*
- ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company
-
 OUI:64DC01*
  ID_OUI_FROM_DATABASE=Static Systems Group PLC
 
 OUI:1CF5E7*
  ID_OUI_FROM_DATABASE=Turtle Industry Co., Ltd.
 
-OUI:9C4A7B*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
 OUI:2C8065*
  ID_OUI_FROM_DATABASE=HARTING Inc. of North America
 
@@ -55139,9 +57221,6 @@ OUI:E41C4B*
 OUI:E0143E*
  ID_OUI_FROM_DATABASE=Modoosis Inc.
 
-OUI:5C6984*
- ID_OUI_FROM_DATABASE=NUVICO
-
 OUI:204AAA*
  ID_OUI_FROM_DATABASE=Hanscan Spain S.A.
 
@@ -55202,9 +57281,6 @@ OUI:0006F6*
 OUI:ACAB8D*
  ID_OUI_FROM_DATABASE=Lyngso Marine A/S
 
-OUI:181456*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
 OUI:E8995A*
  ID_OUI_FROM_DATABASE=PiiGAB, Processinformation i Goteborg AB
 
@@ -55385,9 +57461,6 @@ OUI:DCFAD5*
 OUI:D84606*
  ID_OUI_FROM_DATABASE=Silicon Valley Global Marketing
 
-OUI:689234*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:D0E347*
  ID_OUI_FROM_DATABASE=Yoga
 
@@ -55466,9 +57539,6 @@ OUI:30694B*
 OUI:AC5135*
  ID_OUI_FROM_DATABASE=MPI TECH
 
-OUI:E4EC10*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
 OUI:00D38D*
  ID_OUI_FROM_DATABASE=Hotel Technology Next Generation
 
@@ -55712,9 +57782,6 @@ OUI:64A837*
 OUI:B4B5AF*
  ID_OUI_FROM_DATABASE=Minsung Electronics
 
-OUI:044FAA*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:44568D*
  ID_OUI_FROM_DATABASE=PNC Technologies  Co., Ltd.
 
@@ -55880,9 +57947,6 @@ OUI:0025D1*
 OUI:0025CB*
  ID_OUI_FROM_DATABASE=Reiner SCT
 
-OUI:0025C4*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:0025BF*
  ID_OUI_FROM_DATABASE=Wireless Cables Inc.
 
@@ -56837,9 +58901,6 @@ OUI:001EF1*
 OUI:001F9E*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:001F92*
- ID_OUI_FROM_DATABASE=VideoIQ, Inc.
-
 OUI:001F97*
  ID_OUI_FROM_DATABASE=BERTANA srl
 
@@ -57014,9 +59075,6 @@ OUI:001D64*
 OUI:001D5D*
  ID_OUI_FROM_DATABASE=Control Dynamics Pty. Ltd.
 
-OUI:001D2E*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:001D21*
  ID_OUI_FROM_DATABASE=Alcad SL
 
@@ -57929,9 +59987,6 @@ OUI:0016F4*
 OUI:0016E8*
  ID_OUI_FROM_DATABASE=Sigma Designs, Inc.
 
-OUI:0016ED*
- ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc
-
 OUI:0016DC*
  ID_OUI_FROM_DATABASE=ARCHOS
 
@@ -59312,9 +61367,6 @@ OUI:0009C9*
 OUI:0009D0*
  ID_OUI_FROM_DATABASE=Solacom Technologies Inc.
 
-OUI:0009BC*
- ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc
-
 OUI:0009C1*
  ID_OUI_FROM_DATABASE=PROCES-DATA A/S
 
@@ -61262,9 +63314,6 @@ OUI:005008*
 OUI:005001*
  ID_OUI_FROM_DATABASE=YAMASHITA SYSTEMS CORP.
 
-OUI:0050B5*
- ID_OUI_FROM_DATABASE=FICHET-BAUCHE
-
 OUI:0050B0*
  ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORPORATION
 
@@ -61832,9 +63881,6 @@ OUI:00A07F*
 OUI:00A03E*
  ID_OUI_FROM_DATABASE=ATM FORUM
 
-OUI:00A050*
- ID_OUI_FROM_DATABASE=CYPRESS SEMICONDUCTOR
-
 OUI:00A098*
  ID_OUI_FROM_DATABASE=NetApp
 
@@ -62687,9 +64733,6 @@ OUI:5464D9*
 OUI:00023F*
  ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC.
 
-OUI:C46699*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:383BC8*
  ID_OUI_FROM_DATABASE=2Wire Inc
 
@@ -63005,21 +65048,6 @@ OUI:C0D962*
 OUI:00150C*
  ID_OUI_FROM_DATABASE=AVM GmbH
 
-OUI:744401*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:E091F5*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:001B2F*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:00223F*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:E0469A*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:F40B93*
  ID_OUI_FROM_DATABASE=BlackBerry RTS
 
@@ -63053,24 +65081,6 @@ OUI:C02506*
 OUI:0896D7*
  ID_OUI_FROM_DATABASE=AVM GmbH
 
-OUI:008EF2*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:4494FC*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:20E52A*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:9CD36D*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:C40415*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:08BD43*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:4C09D4*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
@@ -63218,9 +65228,6 @@ OUI:78CB68*
 OUI:001A7F*
  ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD
 
-OUI:00054F*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:D04D2C*
  ID_OUI_FROM_DATABASE=Roku, Inc.
 
@@ -63338,9 +65345,6 @@ OUI:84683E*
 OUI:C88722*
  ID_OUI_FROM_DATABASE=Lumenpulse
 
-OUI:FC1A11*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:30A9DE*
  ID_OUI_FROM_DATABASE=LG Innotek
 
@@ -63407,27 +65411,9 @@ OUI:8801F2*
 OUI:FC084A*
  ID_OUI_FROM_DATABASE=FUJITSU LIMITED
 
-OUI:D4AD2D*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:48555F*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:847BEB*
  ID_OUI_FROM_DATABASE=Dell Inc.
 
-OUI:F8C96C*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:34BF90*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:D467E7*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
-OUI:04C1B9*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:689361*
  ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd.
 
@@ -63671,9 +65657,6 @@ OUI:749D8F*
 OUI:346AC2*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:8CD2E9*
- ID_OUI_FROM_DATABASE=NIPPON SMT Co.Ltd
-
 OUI:C83DFC*
  ID_OUI_FROM_DATABASE=Pioneer DJ Corporation
 
@@ -63806,9 +65789,6 @@ OUI:38BC1A*
 OUI:0004A3*
  ID_OUI_FROM_DATABASE=Microchip Technology Inc.
 
-OUI:E0DDC0*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:982F3C*
  ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd.
 
@@ -64004,9 +65984,6 @@ OUI:6CEFC6*
 OUI:002A10*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:886AB1*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:44D6E1*
  ID_OUI_FROM_DATABASE=Snuza International Pty. Ltd.
 
@@ -64151,9 +66128,6 @@ OUI:08010F*
 OUI:CCA260*
  ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD
 
-OUI:0015FF*
- ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc.
-
 OUI:203CAE*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -64166,9 +66140,6 @@ OUI:00D78F*
 OUI:A03BE3*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
-OUI:18E29F*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:886B0F*
  ID_OUI_FROM_DATABASE=Bluegiga Technologies OY
 
@@ -64271,15 +66242,9 @@ OUI:000BA1*
 OUI:AC587B*
  ID_OUI_FROM_DATABASE=JCT Healthcare
 
-OUI:B0B98A*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:30E171*
  ID_OUI_FROM_DATABASE=Hewlett Packard
 
-OUI:D490E0*
- ID_OUI_FROM_DATABASE=Wachendorff Automation GmbH & Co KG
-
 OUI:8C3C4A*
  ID_OUI_FROM_DATABASE=NAKAYO Inc
 
@@ -64415,12 +66380,6 @@ OUI:54D272*
 OUI:9CA3A9*
  ID_OUI_FROM_DATABASE=Guangzhou Juan Optical and Electronical Tech Joint Stock Co., Ltd
 
-OUI:1100AA*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:002067*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:9893CC*
  ID_OUI_FROM_DATABASE=LG ELECTRONICS INC
 
@@ -64715,9 +66674,6 @@ OUI:9CAED3*
 OUI:341E6B*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:48F97C*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:B47447*
  ID_OUI_FROM_DATABASE=CoreOS
 
@@ -64829,9 +66785,6 @@ OUI:C87324*
 OUI:3CF862*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:0823B2*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:88C3B3*
  ID_OUI_FROM_DATABASE=SOVICO
 
@@ -64895,15 +66848,15 @@ OUI:9800C1*
 OUI:3034D2*
  ID_OUI_FROM_DATABASE=Availink, Inc.
 
+OUI:40B034*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
 OUI:CCCE1E*
  ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
 
 OUI:501E2D*
  ID_OUI_FROM_DATABASE=StreamUnlimited Engineering GmbH
 
-OUI:40B034*
- ID_OUI_FROM_DATABASE=Hewlett Packard
-
 OUI:FC0A81*
  ID_OUI_FROM_DATABASE=Extreme Networks
 
@@ -64913,9 +66866,6 @@ OUI:C8B5AD*
 OUI:88E628*
  ID_OUI_FROM_DATABASE=Shenzhen Kezhonglong Optoelectronic Technology Co.,Ltd
 
-OUI:6091F3*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:9CDA3E*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
@@ -64925,6 +66875,12 @@ OUI:3CA067*
 OUI:D8325A*
  ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
 
+OUI:F04F7C*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:10AE60*
+ ID_OUI_FROM_DATABASE=Private
+
 OUI:44650D*
  ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
 
@@ -64940,18 +66896,9 @@ OUI:40B4CD*
 OUI:2C86D2*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:F04F7C*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:10AE60*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:802689*
  ID_OUI_FROM_DATABASE=D-Link International
 
-OUI:BC2F3D*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:409F38*
  ID_OUI_FROM_DATABASE=AzureWave Technology Inc.
 
@@ -64961,6 +66908,12 @@ OUI:C4D197*
 OUI:58821D*
  ID_OUI_FROM_DATABASE=H. Schomäcker GmbH
 
+OUI:B8D7AF*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+
+OUI:3096FB*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
 OUI:CCBE59*
  ID_OUI_FROM_DATABASE=Calix Inc.
 
@@ -64970,23 +66923,14 @@ OUI:EC4F82*
 OUI:000631*
  ID_OUI_FROM_DATABASE=Calix Inc.
 
-OUI:B8D7AF*
- ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
-
-OUI:3096FB*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
 OUI:F0EE10*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:A8A198*
- ID_OUI_FROM_DATABASE=TCT mobile ltd
-
 OUI:107D1A*
  ID_OUI_FROM_DATABASE=Dell Inc.
 
-OUI:C0D012*
- ID_OUI_FROM_DATABASE=Apple, Inc.
+OUI:A8A198*
+ ID_OUI_FROM_DATABASE=TCT mobile ltd
 
 OUI:D4DCCD*
  ID_OUI_FROM_DATABASE=Apple, Inc.
@@ -65000,6 +66944,9 @@ OUI:F80377*
 OUI:14BD61*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
+OUI:C0D012*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
 OUI:0827CE*
  ID_OUI_FROM_DATABASE=NAGANO KEIKI CO., LTD.
 
@@ -65018,33 +66965,33 @@ OUI:00143F*
 OUI:F8BE0D*
  ID_OUI_FROM_DATABASE=A2UICT Co.,Ltd.
 
+OUI:5CC6E9*
+ ID_OUI_FROM_DATABASE=Edifier International
+
 OUI:08EA40*
  ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD
 
 OUI:00E0DA*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise
 
-OUI:5CC6E9*
- ID_OUI_FROM_DATABASE=Edifier International
+OUI:1868CB*
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
 
 OUI:E8C1D7*
  ID_OUI_FROM_DATABASE=Philips
 
-OUI:1868CB*
- ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
-
 OUI:F80BCB*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
+OUI:24EA40*
+ ID_OUI_FROM_DATABASE=Helmholz GmbH & Co. KG
+
 OUI:9CC8AE*
  ID_OUI_FROM_DATABASE=Becton, Dickinson  and Company
 
 OUI:B0359F*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:24EA40*
- ID_OUI_FROM_DATABASE=Helmholz GmbH & Co. KG
-
 OUI:84A9C4*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
@@ -65081,24 +67028,18 @@ OUI:FC539E*
 OUI:9CAF6F*
  ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
 
-OUI:105887*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+OUI:907065*
+ ID_OUI_FROM_DATABASE=Texas Instruments
 
 OUI:9C061B*
  ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
 
-OUI:907065*
- ID_OUI_FROM_DATABASE=Texas Instruments
-
-OUI:C4ABB2*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+OUI:A08E78*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
 OUI:B8FFB3*
  ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
 
-OUI:A08E78*
- ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
-
 OUI:E0D55E*
  ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
 
@@ -65111,24 +67052,24 @@ OUI:90F1AA*
 OUI:78BDBC*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:20F452*
- ID_OUI_FROM_DATABASE=Shanghai IUV Software Development Co. Ltd
-
 OUI:D47AE2*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
+OUI:20F452*
+ ID_OUI_FROM_DATABASE=Shanghai IUV Software Development Co. Ltd
+
 OUI:88D274*
  ID_OUI_FROM_DATABASE=zte corporation
 
 OUI:986DC8*
  ID_OUI_FROM_DATABASE=TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION
 
-OUI:982DBA*
- ID_OUI_FROM_DATABASE=Fibergate Inc.
-
 OUI:0040AA*
  ID_OUI_FROM_DATABASE=Valmet Automation
 
+OUI:982DBA*
+ ID_OUI_FROM_DATABASE=Fibergate Inc.
+
 OUI:0080C2*
  ID_OUI_FROM_DATABASE=IEEE 802.1 Working Group
 
@@ -65171,6 +67112,36 @@ OUI:145BD1*
 OUI:6CC1D2*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
+OUI:D82522*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:70B14E*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:14D4FE*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:707630*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:90C792*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:789684*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:CC65AD*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:986B3D*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:5CE30E*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:7823AE*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
 OUI:F80BBE*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
@@ -65219,15 +67190,6 @@ OUI:001DD0*
 OUI:5C571A*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:D82522*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:70B14E*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:14D4FE*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
 OUI:002374*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
@@ -65258,39 +67220,18 @@ OUI:901ACA*
 OUI:E8ED05*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:707630*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:90C792*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:789684*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:CC65AD*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:986B3D*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
-OUI:5CE30E*
+OUI:2C7E81*
  ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
 
-OUI:7823AE*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+OUI:84C0EF*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
 OUI:447F77*
  ID_OUI_FROM_DATABASE=Connected Home
 
-OUI:2C7E81*
- ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
-
 OUI:009AD2*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
-OUI:84C0EF*
- ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
-
 OUI:7C1C68*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
@@ -65306,15 +67247,15 @@ OUI:7C8BCA*
 OUI:88B111*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
-OUI:54D751*
- ID_OUI_FROM_DATABASE=Proximus
-
 OUI:D8F1F0*
  ID_OUI_FROM_DATABASE=Pepxim International Limited
 
 OUI:0019F0*
  ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD
 
+OUI:54D751*
+ ID_OUI_FROM_DATABASE=Proximus
+
 OUI:506E92*
  ID_OUI_FROM_DATABASE=Innocent Technology Co., Ltd.
 
@@ -65327,6 +67268,9 @@ OUI:900A1A*
 OUI:CC03D9*
  ID_OUI_FROM_DATABASE=Cisco Meraki
 
+OUI:BCADAB*
+ ID_OUI_FROM_DATABASE=Avaya Inc
+
 OUI:506184*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
@@ -65336,18 +67280,522 @@ OUI:F81547*
 OUI:A01290*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:B4A95A*
+OUI:3C3A73*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:BCADAB*
+OUI:B4A95A*
  ID_OUI_FROM_DATABASE=Avaya Inc
 
-OUI:3C3A73*
- ID_OUI_FROM_DATABASE=Avaya Inc
+OUI:6CB227*
+ ID_OUI_FROM_DATABASE=Sony Video & Sound Products Inc.
 
 OUI:60271C*
  ID_OUI_FROM_DATABASE=VIDEOR E. Hartig GmbH
 
+OUI:C46699*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:FC1A11*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:E0DDC0*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:886AB1*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:18E29F*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:F81D90*
+ ID_OUI_FROM_DATABASE=Solidwintech
+
+OUI:0823B2*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:6091F3*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:BC2F3D*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:C4ABB2*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:C8DB26*
+ ID_OUI_FROM_DATABASE=Logitech
+
+OUI:4473D6*
+ ID_OUI_FROM_DATABASE=Logitech
+
+OUI:70F35A*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:EC42B4*
+ ID_OUI_FROM_DATABASE=ADC Corporation
+
+OUI:10CDB6*
+ ID_OUI_FROM_DATABASE=Essential Products, Inc.
+
+OUI:08306B*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:6CF9D2*
+ ID_OUI_FROM_DATABASE=Chengdu Goods for the Road Electronic Technology C
+
+OUI:641666*
+ ID_OUI_FROM_DATABASE=Nest Labs Inc.
+
+OUI:3817E1*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:94147A*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:74D0DC*
+ ID_OUI_FROM_DATABASE=Ericsson AB
+
+OUI:88A3CC*
+ ID_OUI_FROM_DATABASE=Amatis Controls
+
+OUI:8C9F3B*
+ ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd.
+
+OUI:404229*
+ ID_OUI_FROM_DATABASE=Layer3TV, Inc
+
+OUI:B090D4*
+ ID_OUI_FROM_DATABASE=Shenzhen Hoin Internet Technology Co., Ltd
+
+OUI:348F27*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:001D2E*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:689234*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:044FAA*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:0025C4*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:38FF36*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:2C5D93*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:543D37*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:C4108A*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:D463C6*
+ ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
+
+OUI:00A050*
+ ID_OUI_FROM_DATABASE=CYPRESS SEMICONDUCTOR
+
+OUI:54666C*
+ ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd
+
+OUI:A44CC8*
+ ID_OUI_FROM_DATABASE=Dell Inc.
+
+OUI:0840F3*
+ ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch
+
+OUI:103034*
+ ID_OUI_FROM_DATABASE=Cara Systems
+
+OUI:FC8B97*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:2CAB25*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:AC6E1A*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:24A534*
+ ID_OUI_FROM_DATABASE=SynTrust Tech International Ltd.
+
+OUI:F844E3*
+ ID_OUI_FROM_DATABASE=Taicang T&W Electronics
+
+OUI:001F92*
+ ID_OUI_FROM_DATABASE=Avigilon Corporation
+
+OUI:0C8FFF*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:54B121*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:786256*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:A80C63*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:5CC307*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:08A8A1*
+ ID_OUI_FROM_DATABASE=Cyclotronics Power Concepts, Inc
+
+OUI:887A31*
+ ID_OUI_FROM_DATABASE=Velankani Electronics Pvt. Ltd.
+
+OUI:8C0F6F*
+ ID_OUI_FROM_DATABASE=PEGATRON CORPORATION
+
+OUI:283545*
+ ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD
+
+OUI:A82BB5*
+ ID_OUI_FROM_DATABASE=Edgecore Networks Corporation
+
+OUI:88365F*
+ ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
+
+OUI:0015FF*
+ ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc.
+
+OUI:788C4D*
+ ID_OUI_FROM_DATABASE=Indyme Solutions, LLC
+
+OUI:A8B2DA*
+ ID_OUI_FROM_DATABASE=FUJITSU LIMITED
+
+OUI:0CB937*
+ ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited
+
+OUI:2880A2*
+ ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc.
+
+OUI:0CB459*
+ ID_OUI_FROM_DATABASE=Marketech International Corp.
+
+OUI:84AA9C*
+ ID_OUI_FROM_DATABASE=MitraStar Technology Corp.
+
+OUI:0C4B54*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:C47154*
+ ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
+
+OUI:44EA4B*
+ ID_OUI_FROM_DATABASE=Actlas Inc.
+
+OUI:5C6984*
+ ID_OUI_FROM_DATABASE=NUVICO
+
+OUI:F86EEE*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:E4FB5D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:5C546D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:508F4C*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:0027F8*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:50EB1A*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:CC4E24*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:889471*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:D81FCC*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:002067*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:0060DF*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:000533*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:00223F*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:001B2F*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:E091F5*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:744401*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:E0469A*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:08BD43*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:C40415*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:9CD36D*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:20E52A*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:4494FC*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:008EF2*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:B0B98A*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:1100AA*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:1C965A*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:104E89*
+ ID_OUI_FROM_DATABASE=Garmin International
+
+OUI:30053F*
+ ID_OUI_FROM_DATABASE=JTI Co.,Ltd.
+
+OUI:0050B5*
+ ID_OUI_FROM_DATABASE=FICHET SECURITE ELECTRONIQUE
+
+OUI:04209A*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+
+OUI:8CC121*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+
+OUI:20C6EB*
+ ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company
+
+OUI:B0350B*
+ ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD
+
+OUI:28A6AC*
+ ID_OUI_FROM_DATABASE=seca gmbh & co. kg
+
+OUI:00054F*
+ ID_OUI_FROM_DATABASE=Garmin International
+
+OUI:40CE24*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:24C42F*
+ ID_OUI_FROM_DATABASE=Philips Lifeline
+
+OUI:E048D3*
+ ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD
+
+OUI:B8EE0E*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:78886D*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:A85C2C*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:00DB70*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:181456*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:E4EC10*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:9C4A7B*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:386EA2*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:58B42D*
+ ID_OUI_FROM_DATABASE=YSTen Technology Co.,Ltd
+
+OUI:48EC5B*
+ ID_OUI_FROM_DATABASE=Nokia
+
+OUI:D86162*
+ ID_OUI_FROM_DATABASE=Wistron Neweb Corporation
+
+OUI:80615F*
+ ID_OUI_FROM_DATABASE=Beijing Sinead Technology Co., Ltd.
+
+OUI:0009BC*
+ ID_OUI_FROM_DATABASE=Utility, Inc
+
+OUI:0016ED*
+ ID_OUI_FROM_DATABASE=Utility, Inc
+
+OUI:74F661*
+ ID_OUI_FROM_DATABASE=Schneider Electric Fire & Security Oy
+
+OUI:245FDF*
+ ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
+
+OUI:885DFB*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:608CE6*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:8CD2E9*
+ ID_OUI_FROM_DATABASE=YOKOTE SEIKO CO., LTD.
+
+OUI:186024*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:74F91A*
+ ID_OUI_FROM_DATABASE=Onface
+
+OUI:706BB9*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:6CC147*
+ ID_OUI_FROM_DATABASE=Xiamen Hanin Electronic Technology Co., Ltd
+
+OUI:8CFEB4*
+ ID_OUI_FROM_DATABASE=VSOONTECH ELECTRONICS CO., LIMITED
+
+OUI:CCF957*
+ ID_OUI_FROM_DATABASE=u-blox AG
+
+OUI:74373B*
+ ID_OUI_FROM_DATABASE=UNINET Co.,Ltd.
+
+OUI:7C6456*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:448F17*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. ARTIK
+
+OUI:0076B1*
+ ID_OUI_FROM_DATABASE=Somfy-Protect By Myfox SAS
+
+OUI:D0666D*
+ ID_OUI_FROM_DATABASE=Shenzhen Bus-Lan Technology Co., Ltd.
+
+OUI:B8D94D*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:10FCB6*
+ ID_OUI_FROM_DATABASE=mirusystems CO.,LTD
+
+OUI:04D6AA*
+ ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
+
+OUI:08661F*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:0C5842*
+ ID_OUI_FROM_DATABASE=DME Micro
+
+OUI:A468BC*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:80C755*
+ ID_OUI_FROM_DATABASE=Panasonic Appliances Company
+
+OUI:A0648F*
+ ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
+
+OUI:D467E7*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:34BF90*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:F8C96C*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:48555F*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:D4AD2D*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:D00492*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:809FAB*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:9C88AD*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:48F97C*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:105887*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:5CE3B6*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:04C1B9*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:04848A*
+ ID_OUI_FROM_DATABASE=7INOVA TECHNOLOGY LIMITED
+
+OUI:E81DA8*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:3CC079*
+ ID_OUI_FROM_DATABASE=Shenzhen One-Nine Intelligent Electronic Science and Technology Co., Ltd
+
+OUI:746EE4*
+ ID_OUI_FROM_DATABASE=Asia Vital Components Co.,Ltd.
+
+OUI:F44C70*
+ ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd
+
+OUI:98C5DB*
+ ID_OUI_FROM_DATABASE=Ericsson AB
+
+OUI:043A0D*
+ ID_OUI_FROM_DATABASE=SM Optics S.r.l.
+
+OUI:9CE063*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:9C9C40*
+ ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD
+
+OUI:D490E0*
+ ID_OUI_FROM_DATABASE=Topcon Electronics GmbH & Co. KG
+
+OUI:E8361D*
+ ID_OUI_FROM_DATABASE=Sense Labs, Inc.
+
+OUI:EC7D11*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
 OUI:2C3996*
  ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
 
@@ -65600,9 +68048,6 @@ OUI:20906F*
 OUI:1C7839*
  ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd.
 
-OUI:D837BE*
- ID_OUI_FROM_DATABASE=Shanghai Gongjing Telecom Technology Co,LTD
-
 OUI:A4516F*
  ID_OUI_FROM_DATABASE=Microsoft Mobile Oy
 
@@ -65648,18 +68093,6 @@ OUI:0C96BF*
 OUI:9CC172*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
-OUI:0014C9*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:00010F*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:080088*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
-OUI:00051E*
- ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
-
 OUI:384608*
  ID_OUI_FROM_DATABASE=zte corporation
 
@@ -66488,9 +68921,6 @@ OUI:9CB6D0*
 OUI:D0C0BF*
  ID_OUI_FROM_DATABASE=Actions Microelectronics Co., Ltd
 
-OUI:94F665*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:E04B45*
  ID_OUI_FROM_DATABASE=Hi-P Electronics Pte Ltd
 
@@ -66668,9 +69098,6 @@ OUI:887033*
 OUI:8C7967*
  ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:D083D4*
- ID_OUI_FROM_DATABASE=XTel ApS
-
 OUI:78F944*
  ID_OUI_FROM_DATABASE=Private
 
@@ -66734,9 +69161,6 @@ OUI:6CF5E8*
 OUI:70FF5C*
  ID_OUI_FROM_DATABASE=Cheerzing Communication(Xiamen)Technology Co.,Ltd
 
-OUI:E0107F*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:08115E*
  ID_OUI_FROM_DATABASE=Bitel Co., Ltd.
 
@@ -66785,9 +69209,6 @@ OUI:D4EC86*
 OUI:20A99B*
  ID_OUI_FROM_DATABASE=Microsoft Corporation
 
-OUI:6C7660*
- ID_OUI_FROM_DATABASE=KYOCERA Corporation
-
 OUI:A0A3E2*
  ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
 
@@ -66830,9 +69251,6 @@ OUI:7CB177*
 OUI:8C5D60*
  ID_OUI_FROM_DATABASE=UCI Corporation Co.,Ltd.
 
-OUI:104B46*
- ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation
-
 OUI:4C0BBE*
  ID_OUI_FROM_DATABASE=Microsoft
 
@@ -66926,9 +69344,6 @@ OUI:D05AF1*
 OUI:481A84*
  ID_OUI_FROM_DATABASE=Pointer Telocation Ltd
 
-OUI:E4F4C6*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:DC663A*
  ID_OUI_FROM_DATABASE=Apacer Technology Inc.
 
@@ -67064,9 +69479,6 @@ OUI:4CF45B*
 OUI:B06971*
  ID_OUI_FROM_DATABASE=DEI Sales, Inc.
 
-OUI:58493B*
- ID_OUI_FROM_DATABASE=Palo Alto Networks
-
 OUI:580528*
  ID_OUI_FROM_DATABASE=LABRIS NETWORKS
 
@@ -67790,9 +70202,6 @@ OUI:20B5C6*
 OUI:AC3CB4*
  ID_OUI_FROM_DATABASE=Nilan A/S
 
-OUI:A830AD*
- ID_OUI_FROM_DATABASE=Wei Fang Goertek Electronics Co.,Ltd
-
 OUI:8007A2*
  ID_OUI_FROM_DATABASE=Esson Technology Inc.
 
@@ -68249,9 +70658,6 @@ OUI:00E8AB*
 OUI:18421D*
  ID_OUI_FROM_DATABASE=Private
 
-OUI:78617C*
- ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD
-
 OUI:C401B1*
  ID_OUI_FROM_DATABASE=SeekTech INC
 
@@ -68741,9 +71147,6 @@ OUI:DCA6BD*
 OUI:58E808*
  ID_OUI_FROM_DATABASE=AUTONICS CORPORATION
 
-OUI:B8C716*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:8058C5*
  ID_OUI_FROM_DATABASE=NovaTec Kommunikationstechnik GmbH
 
@@ -68978,9 +71381,6 @@ OUI:5C9AD8*
 OUI:144C1A*
  ID_OUI_FROM_DATABASE=Max Communication GmbH
 
-OUI:FCE557*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
 OUI:BC6E76*
  ID_OUI_FROM_DATABASE=Green Energy Options Ltd
 
@@ -69095,9 +71495,6 @@ OUI:7076F0*
 OUI:48C8B6*
  ID_OUI_FROM_DATABASE=SysTec GmbH
 
-OUI:303855*
- ID_OUI_FROM_DATABASE=Nokia Corporation
-
 OUI:9C4563*
  ID_OUI_FROM_DATABASE=DIMEP Sistemas
 
@@ -69131,9 +71528,6 @@ OUI:64E8E6*
 OUI:34A183*
  ID_OUI_FROM_DATABASE=AWare, Inc
 
-OUI:740ABC*
- ID_OUI_FROM_DATABASE=JSJS Designs (Europe) Limited
-
 OUI:588D09*
  ID_OUI_FROM_DATABASE=Cisco Systems, Inc
 
@@ -69404,9 +71798,6 @@ OUI:0CC9C6*
 OUI:B45861*
  ID_OUI_FROM_DATABASE=CRemote, LLC
 
-OUI:AC6706*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:B8653B*
  ID_OUI_FROM_DATABASE=Bolymin, Inc.
 
@@ -71312,9 +73703,6 @@ OUI:00198B*
 OUI:00198D*
  ID_OUI_FROM_DATABASE=Ocean Optics, Inc.
 
-OUI:00197F*
- ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
-
 OUI:001986*
  ID_OUI_FROM_DATABASE=Cheng Hongjian
 
@@ -72197,9 +74585,6 @@ OUI:00139F*
 OUI:001398*
  ID_OUI_FROM_DATABASE=TrafficSim Co.,Ltd
 
-OUI:001392*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:00138C*
  ID_OUI_FROM_DATABASE=Kumyoung.Co.Ltd
 
@@ -72980,9 +75365,6 @@ OUI:000BFC*
 OUI:000BFE*
  ID_OUI_FROM_DATABASE=CASTEL Broadband Limited
 
-OUI:000C03*
- ID_OUI_FROM_DATABASE=HDMI Licensing, LLC
-
 OUI:000CA4*
  ID_OUI_FROM_DATABASE=Prompttec Product Management GmbH
 
@@ -75452,9 +77834,6 @@ OUI:00A0AD*
 OUI:00A0F6*
  ID_OUI_FROM_DATABASE=AutoGas Systems Inc.
 
-OUI:00A096*
- ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO., LTD.
-
 OUI:00A006*
  ID_OUI_FROM_DATABASE=IMAGE DATA PROCESSING SYSTEM GROUP
 
@@ -76961,36 +79340,12 @@ OUI:00040E*
 OUI:0016E3*
  ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP
 
-OUI:30469A*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:0026F2*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:00184D*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:001E2A*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:E8FCAF*
- ID_OUI_FROM_DATABASE=NETGEAR
-
-OUI:4C60DE*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:00300A*
  ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd
 
-OUI:A06391*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:9CC7A6*
  ID_OUI_FROM_DATABASE=AVM GmbH
 
-OUI:DCEF09*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:743170*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
@@ -77003,9 +79358,6 @@ OUI:7C4FB5*
 OUI:0012BF*
  ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation
 
-OUI:200CC8*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:04FE8D*
  ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
 
@@ -77306,9 +79658,6 @@ OUI:BC44B0*
 OUI:7864E6*
  ID_OUI_FROM_DATABASE=Green Motive Technology Limited
 
-OUI:743E2B*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:C0CCF8*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -77393,9 +79742,6 @@ OUI:000594*
 OUI:000AC2*
  ID_OUI_FROM_DATABASE=Wuhan FiberHome Digital Technology Co.,Ltd.
 
-OUI:F08CFB*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:D4F207*
  ID_OUI_FROM_DATABASE=DIAODIAO(Beijing)Technology CO.,Ltd
 
@@ -77474,9 +79820,6 @@ OUI:00208F*
 OUI:9CDF03*
  ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH
 
-OUI:F0407B*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:94885E*
  ID_OUI_FROM_DATABASE=Surfilter Network Technology Co., Ltd.
 
@@ -78263,9 +80606,6 @@ OUI:0005CD*
 OUI:8C9351*
  ID_OUI_FROM_DATABASE=Jigowatts Inc.
 
-OUI:D838FC*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:00248D*
  ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc.
 
@@ -78284,12 +80624,6 @@ OUI:40D855*
 OUI:48DF37*
  ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
 
-OUI:9C93E4*
- ID_OUI_FROM_DATABASE=Private
-
-OUI:005079*
- ID_OUI_FROM_DATABASE=Private
-
 OUI:0028F8*
  ID_OUI_FROM_DATABASE=Intel Corporate
 
@@ -78350,9 +80684,6 @@ OUI:002597*
 OUI:882BD7*
  ID_OUI_FROM_DATABASE=ADDÉNERGIE  TECHNOLOGIES
 
-OUI:9CA5C0*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:B4A5EF*
  ID_OUI_FROM_DATABASE=Sercomm Corporation.
 
@@ -78368,9 +80699,6 @@ OUI:38A28C*
 OUI:58528A*
  ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation
 
-OUI:BCC00F*
- ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
-
 OUI:B0C287*
  ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
 
@@ -78779,9 +81107,6 @@ OUI:3805AC*
 OUI:F8BBBF*
  ID_OUI_FROM_DATABASE=eero inc.
 
-OUI:0CF4D5*
- ID_OUI_FROM_DATABASE=Ruckus Wireless
-
 OUI:000130*
  ID_OUI_FROM_DATABASE=Extreme Networks
 
@@ -78848,9 +81173,6 @@ OUI:4827EA*
 OUI:049573*
  ID_OUI_FROM_DATABASE=zte corporation
 
-OUI:001D44*
- ID_OUI_FROM_DATABASE=Krohne
-
 OUI:48BF6B*
  ID_OUI_FROM_DATABASE=Apple, Inc.
 
@@ -78890,9 +81212,6 @@ OUI:64D154*
 OUI:0020DA*
  ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise
 
-OUI:1CDA27*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:345BBB*
  ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd.
 
@@ -78929,9 +81248,6 @@ OUI:C83A6B*
 OUI:B4C6F8*
  ID_OUI_FROM_DATABASE=Axilspot Communication
 
-OUI:70D923*
- ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
-
 OUI:B83A08*
  ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch
 
@@ -79016,9 +81332,6 @@ OUI:E47DBD*
 OUI:503DA1*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
-OUI:A040A0*
- ID_OUI_FROM_DATABASE=NETGEAR
-
 OUI:508569*
  ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
 
@@ -79264,3 +81577,459 @@ OUI:78B28D*
 
 OUI:000CAB*
  ID_OUI_FROM_DATABASE=Commend International GmbH
+
+OUI:00EC0A*
+ ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd
+
+OUI:A86B7C*
+ ID_OUI_FROM_DATABASE=SHENZHEN FENGLIAN TECHNOLOGY CO., LTD.
+
+OUI:9CA5C0*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:1CDA27*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:70D923*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
+
+OUI:F430B9*
+ ID_OUI_FROM_DATABASE=Hewlett Packard
+
+OUI:2C9EEC*
+ ID_OUI_FROM_DATABASE=Jabil Circuit Penang
+
+OUI:943FC2*
+ ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
+
+OUI:A06A44*
+ ID_OUI_FROM_DATABASE=Vizio, Inc
+
+OUI:B44F96*
+ ID_OUI_FROM_DATABASE=Zhejiang Xinzailing Technology co., ltd
+
+OUI:D822F4*
+ ID_OUI_FROM_DATABASE=Avnet Silica
+
+OUI:58493B*
+ ID_OUI_FROM_DATABASE=Palo Alto Networks
+
+OUI:D083D4*
+ ID_OUI_FROM_DATABASE=Xtel Wireless ApS
+
+OUI:7CEB7F*
+ ID_OUI_FROM_DATABASE=Dmet Products Corp.
+
+OUI:8C8580*
+ ID_OUI_FROM_DATABASE=Smart Innovation LLC
+
+OUI:C4571F*
+ ID_OUI_FROM_DATABASE=June Life Inc
+
+OUI:FC5A1D*
+ ID_OUI_FROM_DATABASE=Hitron Technologies. Inc
+
+OUI:287B09*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:4859A4*
+ ID_OUI_FROM_DATABASE=zte corporation
+
+OUI:3894E0*
+ ID_OUI_FROM_DATABASE=Syrotech Networks. Ltd.
+
+OUI:34F64B*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:ACED5C*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:18204C*
+ ID_OUI_FROM_DATABASE=Kummler+Matter AG
+
+OUI:740ABC*
+ ID_OUI_FROM_DATABASE=LightwaveRF Technology Ltd
+
+OUI:54BD79*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:D86C63*
+ ID_OUI_FROM_DATABASE=Google, Inc.
+
+OUI:743E2B*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:D838FC*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:0CF4D5*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:AC6706*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:94F665*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:E0107F*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:001392*
+ ID_OUI_FROM_DATABASE=Ruckus Wireless
+
+OUI:7811DC*
+ ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD
+
+OUI:D837BE*
+ ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT
+
+OUI:DC44B6*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:1007B6*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:F4939F*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd.
+
+OUI:000C03*
+ ID_OUI_FROM_DATABASE=HDMI Licensing, LLC
+
+OUI:CC2F71*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:F82819*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:F4B520*
+ ID_OUI_FROM_DATABASE=Biostar Microtech international corp.
+
+OUI:9C93E4*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:D4B27A*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:F0F8F2*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:341513*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:64CFD9*
+ ID_OUI_FROM_DATABASE=Texas Instruments
+
+OUI:24B2DE*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
+OUI:50E971*
+ ID_OUI_FROM_DATABASE=Jibo, Inc.
+
+OUI:50642B*
+ ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD
+
+OUI:909D7D*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:84A1D1*
+ ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
+
+OUI:783690*
+ ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd
+
+OUI:788102*
+ ID_OUI_FROM_DATABASE=Sercomm Corporation.
+
+OUI:58A0CB*
+ ID_OUI_FROM_DATABASE=TrackNet, Inc
+
+OUI:586163*
+ ID_OUI_FROM_DATABASE=Quantum Networks (SG) Pte. Ltd.
+
+OUI:3C7843*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:A47758*
+ ID_OUI_FROM_DATABASE=Ningbo Freewings Technologies Co.,Ltd
+
+OUI:00051E*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:080088*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:00010F*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:00197F*
+ ID_OUI_FROM_DATABASE=PLANTRONICS, INC.
+
+OUI:E4F4C6*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:001E2A*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:0014C9*
+ ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc.
+
+OUI:00184D*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:0026F2*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:30469A*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:4C60DE*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:E8FCAF*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:200CC8*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:DCEF09*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:A06391*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:A040A0*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:8C3BAD*
+ ID_OUI_FROM_DATABASE=NETGEAR
+
+OUI:005079*
+ ID_OUI_FROM_DATABASE=Private
+
+OUI:F86465*
+ ID_OUI_FROM_DATABASE=Anova Applied Electronics, Inc.
+
+OUI:A830AD*
+ ID_OUI_FROM_DATABASE=Weifang GoerTek Technology Co.,Ltd.
+
+OUI:70E1FD*
+ ID_OUI_FROM_DATABASE=FLEXTRONICS
+
+OUI:001D44*
+ ID_OUI_FROM_DATABASE=Krohne
+
+OUI:D4D2E5*
+ ID_OUI_FROM_DATABASE=BKAV Corporation
+
+OUI:C06D1A*
+ ID_OUI_FROM_DATABASE=Tianjin Henxinhuifeng Technology Co.,Ltd.
+
+OUI:3432E6*
+ ID_OUI_FROM_DATABASE=Panasonic Industrial Devices Europe GmbH
+
+OUI:40A3CC*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:E470B8*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:B019C6*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:58E28F*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:AC1F74*
+ ID_OUI_FROM_DATABASE=Apple, Inc.
+
+OUI:303855*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:FCE557*
+ ID_OUI_FROM_DATABASE=Nokia Corporation
+
+OUI:9C305B*
+ ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
+
+OUI:00289F*
+ ID_OUI_FROM_DATABASE=Semptian Co., Ltd.
+
+OUI:8C4500*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+
+OUI:6C7660*
+ ID_OUI_FROM_DATABASE=KYOCERA CORPORATION
+
+OUI:104B46*
+ ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation
+
+OUI:903DBD*
+ ID_OUI_FROM_DATABASE=SECURE METERS LIMITED
+
+OUI:384F49*
+ ID_OUI_FROM_DATABASE=Juniper Networks
+
+OUI:A491B1*
+ ID_OUI_FROM_DATABASE=Technicolor
+
+OUI:8CD48E*
+ ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED
+
+OUI:642B8A*
+ ID_OUI_FROM_DATABASE=ALL BEST Industrial Co., Ltd.
+
+OUI:68ECC5*
+ ID_OUI_FROM_DATABASE=Intel Corporate
+
+OUI:CC9891*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:1C7022*
+ ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd.
+
+OUI:947EB9*
+ ID_OUI_FROM_DATABASE=National Narrowband Network Communications Pty Ltd
+
+OUI:4CBD8F*
+ ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
+
+OUI:B4D64E*
+ ID_OUI_FROM_DATABASE=Caldero Limited
+
+OUI:F89DBB*
+ ID_OUI_FROM_DATABASE=Tintri
+
+OUI:D4389C*
+ ID_OUI_FROM_DATABASE=Sony Mobile Communications AB
+
+OUI:104963*
+ ID_OUI_FROM_DATABASE=HARTING K.K.
+
+OUI:646E69*
+ ID_OUI_FROM_DATABASE=Liteon Technology Corporation
+
+OUI:BC3D85*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:B0E17E*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:74D21D*
+ ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
+
+OUI:44C874*
+ ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd.
+
+OUI:98EF9B*
+ ID_OUI_FROM_DATABASE=OHSUNG
+
+OUI:84E327*
+ ID_OUI_FROM_DATABASE=TAILYN TECHNOLOGIES INC
+
+OUI:7091F3*
+ ID_OUI_FROM_DATABASE=Universal Electronics, Inc.
+
+OUI:68C63A*
+ ID_OUI_FROM_DATABASE=Espressif Inc.
+
+OUI:F4E204*
+ ID_OUI_FROM_DATABASE=Traqueur
+
+OUI:3456FE*
+ ID_OUI_FROM_DATABASE=Cisco Meraki
+
+OUI:08674E*
+ ID_OUI_FROM_DATABASE=Hisense broadband multimedia technology Co.,Ltd
+
+OUI:F08CFB*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:F0407B*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:BCC00F*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:6405E9*
+ ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd.
+
+OUI:B8C716*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:50A83A*
+ ID_OUI_FROM_DATABASE=S Mobile Devices Limited
+
+OUI:EC8AC7*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:E084F3*
+ ID_OUI_FROM_DATABASE=High Grade Controls Corporation
+
+OUI:74BBD3*
+ ID_OUI_FROM_DATABASE=Shenzhen xeme Communication Co., Ltd.
+
+OUI:D8ED1C*
+ ID_OUI_FROM_DATABASE=Magna Technology SL
+
+OUI:78617C*
+ ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
+
+OUI:00A096*
+ ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD.
+
+OUI:A07099*
+ ID_OUI_FROM_DATABASE=Beijing Huacan Electronics Co., Ltd
+
+OUI:B0935B*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:20F19E*
+ ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
+
+OUI:389D92*
+ ID_OUI_FROM_DATABASE=Seiko Epson Corporation
+
+OUI:74860B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:C0174D*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:A407B6*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:149F3C*
+ ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
+
+OUI:149FB6*
+ ID_OUI_FROM_DATABASE=GUANGDONG GENIUS TECHNOLOGY CO.,LTD.
+
+OUI:7C1C4E*
+ ID_OUI_FROM_DATABASE=LG Innotek
+
+OUI:70708B*
+ ID_OUI_FROM_DATABASE=Cisco Systems, Inc
+
+OUI:BC903A*
+ ID_OUI_FROM_DATABASE=Robert Bosch GmbH
+
+OUI:603D26*
+ ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
+
+OUI:3820A8*
+ ID_OUI_FROM_DATABASE=ColorTokens, Inc.
+
+OUI:705896*
+ ID_OUI_FROM_DATABASE=InShow Technology
+
+OUI:D05995*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:54DF24*
+ ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
+
+OUI:78870D*
+ ID_OUI_FROM_DATABASE=Unifiedgateways India Private Limited
+
+OUI:3CA616*
+ ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd.
index 886e61aa3820a1486622eb8de19ef5a375a80308..64634478e6b6855068dd6916e7afdc88c4d2eef8 100644 (file)
@@ -42,6 +42,9 @@ acpi:ATML*:
 acpi:AUTH*:
  ID_VENDOR_FROM_DATABASE=AuthenTec
 
+acpi:BOOT*:
+ ID_VENDOR_FROM_DATABASE=Coreboot Project
+
 acpi:BOSC*:
  ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH
 
@@ -72,6 +75,9 @@ acpi:ELAN*:
 acpi:ESSX*:
  ID_VENDOR_FROM_DATABASE=Everest Semiconductor Co., Ltd.
 
+acpi:EXAR*:
+ ID_VENDOR_FROM_DATABASE=Exar Corporation
+
 acpi:FRSC*:
  ID_VENDOR_FROM_DATABASE=Freescale, Inc
 
@@ -141,6 +147,9 @@ acpi:MCHP*:
 acpi:MIPI*:
  ID_VENDOR_FROM_DATABASE=MIPI Alliance
 
+acpi:MRVL*:
+ ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd.
+
 acpi:MSAY*:
  ID_VENDOR_FROM_DATABASE=Microsoft Corporation
 
@@ -951,6 +960,9 @@ acpi:BBH*:
 acpi:BBL*:
  ID_VENDOR_FROM_DATABASE=Brain Boxes Limited
 
+acpi:BBX*:
+ ID_VENDOR_FROM_DATABASE=Black Box Corporation
+
 acpi:BCC*:
  ID_VENDOR_FROM_DATABASE=Beaver Computer Corporaton
 
@@ -1326,6 +1338,9 @@ acpi:CHO*:
 acpi:CHP*:
  ID_VENDOR_FROM_DATABASE=CH Products
 
+acpi:CHR*:
+ ID_VENDOR_FROM_DATABASE=christmann informationstechnik + medien GmbH & Co. KG
+
 acpi:CHS*:
  ID_VENDOR_FROM_DATABASE=Agentur Chairos
 
@@ -2721,6 +2736,9 @@ acpi:GFN*:
 acpi:GGL*:
  ID_VENDOR_FROM_DATABASE=Google Inc.
 
+acpi:GGT*:
+ ID_VENDOR_FROM_DATABASE=G2TOUCH KOREA
+
 acpi:GIC*:
  ID_VENDOR_FROM_DATABASE=General Inst. Corporation
 
@@ -3099,6 +3117,9 @@ acpi:HYC*:
 acpi:HYD*:
  ID_VENDOR_FROM_DATABASE=Hydis Technologies.Co.,LTD
 
+acpi:HYL*:
+ ID_VENDOR_FROM_DATABASE=Shanghai Chai Ming Huang Info&Tech Co, Ltd
+
 acpi:HYO*:
  ID_VENDOR_FROM_DATABASE=HYC CO., LTD.
 
@@ -4530,6 +4551,9 @@ acpi:MVM*:
 acpi:MVN*:
  ID_VENDOR_FROM_DATABASE=Meta Company
 
+acpi:MVR*:
+ ID_VENDOR_FROM_DATABASE=MediCapture, Inc.
+
 acpi:MVS*:
  ID_VENDOR_FROM_DATABASE=Microvision
 
@@ -5220,6 +5244,9 @@ acpi:PMD*:
 acpi:PMM*:
  ID_VENDOR_FROM_DATABASE=Point Multimedia System
 
+acpi:PMS*:
+ ID_VENDOR_FROM_DATABASE=Pabian Embedded Systems
+
 acpi:PMT*:
  ID_VENDOR_FROM_DATABASE=Promate Electronic Co., Ltd.
 
@@ -5238,6 +5265,9 @@ acpi:PNR*:
 acpi:PNS*:
  ID_VENDOR_FROM_DATABASE=PanaScope
 
+acpi:PNT*:
+ ID_VENDOR_FROM_DATABASE=HOYA Corporation PENTAX Lifecare Division
+
 acpi:PNX*:
  ID_VENDOR_FROM_DATABASE=Phoenix Technologies, Ltd.
 
@@ -6414,6 +6444,9 @@ acpi:TCD*:
 acpi:TCE*:
  ID_VENDOR_FROM_DATABASE=Century Corporation
 
+acpi:TCF*:
+ ID_VENDOR_FROM_DATABASE=Televic Conference
+
 acpi:TCH*:
  ID_VENDOR_FROM_DATABASE=Interaction Systems, Inc
 
@@ -6489,6 +6522,9 @@ acpi:TEK*:
 acpi:TEL*:
  ID_VENDOR_FROM_DATABASE=Promotion and Display Technology Ltd.
 
+acpi:TEN*:
+ ID_VENDOR_FROM_DATABASE=Tencent
+
 acpi:TER*:
  ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH
 
@@ -6570,6 +6606,9 @@ acpi:TLK*:
 acpi:TLL*:
  ID_VENDOR_FROM_DATABASE=Thinklogical
 
+acpi:TLN*:
+ ID_VENDOR_FROM_DATABASE=Techlogix Networx
+
 acpi:TLS*:
  ID_VENDOR_FROM_DATABASE=Teleste Educational OY
 
@@ -6696,6 +6735,9 @@ acpi:TRM*:
 acpi:TRN*:
  ID_VENDOR_FROM_DATABASE=Datacommunicatie Tron B.V.
 
+acpi:TRP*:
+ ID_VENDOR_FROM_DATABASE=TRAPEZE GROUP
+
 acpi:TRS*:
  ID_VENDOR_FROM_DATABASE=Torus Systems Ltd
 
index 83ff9f36688e501c6f2c2c4b425f3e1b5594de89..482853dbca5c22ca57d2b8af7db62aad49e99def 100644 (file)
@@ -144,34 +144,34 @@ pci:v00000B0B*
  ID_VENDOR_FROM_DATABASE=Rhino Equipment Corp.
 
 pci:v00000B0Bd00000105*
- ID_MODEL_FROM_DATABASE=Rhino R1T1
+ ID_MODEL_FROM_DATABASE=R1T1
 
 pci:v00000B0Bd00000205*
- ID_MODEL_FROM_DATABASE=Rhino R4FXO
+ ID_MODEL_FROM_DATABASE=R4FXO
 
 pci:v00000B0Bd00000206*
  ID_MODEL_FROM_DATABASE=RCB4FXO 4-channel FXO analog telphony card
 
 pci:v00000B0Bd00000305*
- ID_MODEL_FROM_DATABASE=Rhino R4T1
+ ID_MODEL_FROM_DATABASE=R4T1
 
 pci:v00000B0Bd00000405*
- ID_MODEL_FROM_DATABASE=Rhino R8FXX
+ ID_MODEL_FROM_DATABASE=R8FXX
 
 pci:v00000B0Bd00000406*
  ID_MODEL_FROM_DATABASE=RCB8FXX 8-channel modular analog telphony card
 
 pci:v00000B0Bd00000505*
- ID_MODEL_FROM_DATABASE=Rhino R24FXX
+ ID_MODEL_FROM_DATABASE=R24FXX
 
 pci:v00000B0Bd00000506*
  ID_MODEL_FROM_DATABASE=RCB24FXS 24-Channel FXS analog telphony card
 
 pci:v00000B0Bd00000605*
- ID_MODEL_FROM_DATABASE=Rhino R2T1
+ ID_MODEL_FROM_DATABASE=R2T1
 
 pci:v00000B0Bd00000705*
- ID_MODEL_FROM_DATABASE=Rhino R24FXS
+ ID_MODEL_FROM_DATABASE=R24FXS
 
 pci:v00000B0Bd00000706*
  ID_MODEL_FROM_DATABASE=RCB24FXO 24-Channel FXO analog telphony card
@@ -659,6 +659,9 @@ pci:v00001000d00000014sv00001028sd00001FD4*
 pci:v00001000d00000014sv00001D49sd00000602*
  ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (ThinkSystem RAID 930-16i 4GB Flash PCIe 12Gb Adapter)
 
+pci:v00001000d00000014sv00001D49sd00000604*
+ ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter)
+
 pci:v00001000d00000015*
  ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3416
 
@@ -1199,6 +1202,9 @@ pci:v00001000d00000062sv00001000sd00000062*
 pci:v00001000d00000064*
  ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor]
 
+pci:v00001000d00000064sv00001000sd000030C0*
+ ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] (SAS 9201-16i)
+
 pci:v00001000d00000065*
  ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor]
 
@@ -1541,6 +1547,9 @@ pci:v00001000d00000097sv00001000sd00003090*
 pci:v00001000d00000097sv00001000sd000030E0*
  ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS9300-8i)
 
+pci:v00001000d00000097sv00001000sd00003130*
+ ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS 9300-16i)
+
 pci:v00001000d00000097sv00001028sd00001F45*
  ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 Adapter)
 
@@ -1583,6 +1592,9 @@ pci:v00001000d000000AFsv00001D49sd00000200*
 pci:v00001000d000000AFsv00001D49sd00000202*
  ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-8e SAS/SATA 12Gb HBA)
 
+pci:v00001000d000000AFsv00001D49sd00000204*
+ ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-8i SAS/SATA 12Gb Dense HBA)
+
 pci:v00001000d000000BE*
  ID_MODEL_FROM_DATABASE=SAS3504 Fusion-MPT Tri-Mode RAID On Chip (ROC)
 
@@ -3207,7 +3219,7 @@ pci:v00001002d00004C46sv00001002sd00000155*
  ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (IBM Thinkpad A22p)
 
 pci:v00001002d00004C46sv00001014sd00000155*
- ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (IBM Thinkpad A22p)
+ ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (Thinkpad A22p)
 
 pci:v00001002d00004C46sv00001028sd000000B1*
  ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (Latitude C600)
@@ -6287,9 +6299,6 @@ pci:v00001002d00006798sv00001787sd00002317*
 pci:v00001002d00006798sv00001787sd00003000*
  ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition])
 
-pci:v00001002d00006799*
- ID_MODEL_FROM_DATABASE=New Zealand [Radeon HD 7900 Series]
-
 pci:v00001002d0000679A*
  ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
 
@@ -6306,19 +6315,19 @@ pci:v00001002d0000679Asv0000174Bsd0000A003*
  ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon R9 280)
 
 pci:v00001002d0000679B*
- ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990]
+ ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM]
 
 pci:v00001002d0000679Bsv00001002sd00000B28*
- ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 8990 OEM)
+ ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 8990 OEM)
 
 pci:v00001002d0000679Bsv00001002sd00000B2A*
- ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 7990)
+ ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 7990)
 
 pci:v00001002d0000679Bsv00001462sd00008036*
- ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 8990 OEM)
+ ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 8990 OEM)
 
 pci:v00001002d0000679Bsv0000148Csd00008990*
- ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990] (Radeon HD 8990 OEM)
+ ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 8990 OEM)
 
 pci:v00001002d0000679E*
  ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT]
@@ -6486,11 +6495,17 @@ pci:v00001002d000067BE*
  ID_MODEL_FROM_DATABASE=Hawaii LE
 
 pci:v00001002d000067C0*
- ID_MODEL_FROM_DATABASE=Ellesmere [Polaris10]
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100]
 
 pci:v00001002d000067C4*
  ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100]
 
+pci:v00001002d000067C4sv00001002sd00000336*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100] (Radeon Pro Duo)
+
+pci:v00001002d000067C4sv00001002sd00001336*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100] (Radeon Pro Duo)
+
 pci:v00001002d000067C7*
  ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 5100]
 
@@ -6504,49 +6519,64 @@ pci:v00001002d000067CF*
  ID_MODEL_FROM_DATABASE=Ellesmere [Polaris10]
 
 pci:v00001002d000067DF*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480]
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580]
 
 pci:v00001002d000067DFsv00001002sd00000B37*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
 
 pci:v00001002d000067DFsv00001043sd000004A8*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
 
 pci:v00001002d000067DFsv00001043sd000004B0*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
 
 pci:v00001002d000067DFsv00001043sd000004FB*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+
+pci:v00001002d000067DFsv00001043sd000004FD*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480 8GB)
+
+pci:v00001002d000067DFsv00001458sd000022F0*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 570)
 
 pci:v00001002d000067DFsv00001462sd00003411*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
 
 pci:v00001002d000067DFsv00001462sd00003413*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
 
 pci:v00001002d000067DFsv0000148Csd00002372*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
 
 pci:v00001002d000067DFsv0000148Csd00002373*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
 
 pci:v00001002d000067DFsv00001682sd00009470*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
 
 pci:v00001002d000067DFsv00001682sd00009480*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+
+pci:v00001002d000067DFsv00001682sd00009588*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 580 XTR)
 
 pci:v00001002d000067DFsv0000174Bsd0000E347*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470/480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470/480)
 
 pci:v00001002d000067DFsv0000174Bsd0000E349*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
 
 pci:v00001002d000067DFsv00001787sd0000A470*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 470)
 
 pci:v00001002d000067DFsv00001787sd0000A480*
- ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480)
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 480)
+
+pci:v00001002d000067DFsv00001DA2sd0000E353*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Sapphire Radeon RX 580 Pulse 8GB)
+
+pci:v00001002d000067DFsv00001DA2sd0000E366*
+ ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/580] (Radeon RX 570)
 
 pci:v00001002d000067E0*
  ID_MODEL_FROM_DATABASE=Baffin [Polaris11]
@@ -6570,7 +6600,7 @@ pci:v00001002d000067EF*
  ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460]
 
 pci:v00001002d000067FF*
- ID_MODEL_FROM_DATABASE=Baffin [Polaris11]
+ ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 560]
 
 pci:v00001002d00006800*
  ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M]
@@ -7157,6 +7187,12 @@ pci:v00001002d00006842*
 pci:v00001002d00006843*
  ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7670M]
 
+pci:v00001002d00006863*
+ ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Vega Frontier Edition]
+
+pci:v00001002d0000687F*
+ ID_MODEL_FROM_DATABASE=Vega [Radeon RX Vega]
+
 pci:v00001002d00006888*
  ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V8800]
 
@@ -8676,7 +8712,7 @@ pci:v00001002d00006981*
  ID_MODEL_FROM_DATABASE=Polaris12
 
 pci:v00001002d00006985*
- ID_MODEL_FROM_DATABASE=Polaris12
+ ID_MODEL_FROM_DATABASE=Lexa XT [Radeon PRO WX 3100]
 
 pci:v00001002d00006986*
  ID_MODEL_FROM_DATABASE=Polaris12
@@ -8684,8 +8720,11 @@ pci:v00001002d00006986*
 pci:v00001002d00006987*
  ID_MODEL_FROM_DATABASE=Polaris12
 
+pci:v00001002d00006995*
+ ID_MODEL_FROM_DATABASE=Lexa XT [Radeon PRO WX 2100]
+
 pci:v00001002d0000699F*
- ID_MODEL_FROM_DATABASE=Polaris12
+ ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon RX 550]
 
 pci:v00001002d0000700F*
  ID_MODEL_FROM_DATABASE=RS100 AGP Bridge
@@ -11234,6 +11273,9 @@ pci:v00001014d00000302*
 pci:v00001014d00000308*
  ID_MODEL_FROM_DATABASE=CalIOC2 PCI-E Root Port
 
+pci:v00001014d00000311*
+ ID_MODEL_FROM_DATABASE=FC 5740/1954 4-Port 10/100/1000 Base-TX PCI-X Adapter for POWER
+
 pci:v00001014d00000314*
  ID_MODEL_FROM_DATABASE=ZISC 036 Neural accelerator card
 
@@ -11324,6 +11366,9 @@ pci:v00001014d0000034Asv00001014sd000004C8*
 pci:v00001014d0000034Asv00001014sd000004C9*
  ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD))
 
+pci:v00001014d000003DC*
+ ID_MODEL_FROM_DATABASE=POWER8 Host Bridge (PHB3)
+
 pci:v00001014d0000044B*
  ID_MODEL_FROM_DATABASE=GenWQE Accelerator Adapter
 
@@ -11693,6 +11738,9 @@ pci:v00001022d00001439*
 pci:v00001022d0000145B*
  ID_MODEL_FROM_DATABASE=Zeppelin Non-Transparent Bridge
 
+pci:v00001022d0000145C*
+ ID_MODEL_FROM_DATABASE=USB3 Host Controller
+
 pci:v00001022d00001510*
  ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex
 
@@ -11945,6 +11993,9 @@ pci:v00001022d000043A2*
 pci:v00001022d000043A3*
  ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 3)
 
+pci:v00001022d000043BB*
+ ID_MODEL_FROM_DATABASE=USB 3.1 XHCI Controller
+
 pci:v00001022d00007006*
  ID_MODEL_FROM_DATABASE=AMD-751 [Irongate] System Controller
 
@@ -13295,6 +13346,12 @@ pci:v0000102Bd00000533sv0000103Csd00003381*
 pci:v0000102Bd00000534*
  ID_MODEL_FROM_DATABASE=G200eR2
 
+pci:v0000102Bd00000538*
+ ID_MODEL_FROM_DATABASE=G200eH
+
+pci:v0000102Bd00000538sv00001590sd000000E4*
+ ID_MODEL_FROM_DATABASE=G200eH (iLO5 VGA)
+
 pci:v0000102Bd00000540*
  ID_MODEL_FROM_DATABASE=M91XX
 
@@ -14825,6 +14882,12 @@ pci:v0000103Cd00001302*
 pci:v0000103Cd00001303*
  ID_MODEL_FROM_DATABASE=RMP-3 (Remote Management Processor)
 
+pci:v0000103Cd000022F6*
+ ID_MODEL_FROM_DATABASE=iLO5 Virtual USB Controller
+
+pci:v0000103Cd000022F6sv00001590sd000000E4*
+ ID_MODEL_FROM_DATABASE=iLO5 Virtual USB Controller (iLO5 Standard Virtual USB Controller)
+
 pci:v0000103Cd00002910*
  ID_MODEL_FROM_DATABASE=E2910A PCIBus Exerciser
 
@@ -15971,6 +16034,9 @@ pci:v0000104Cd00008240*
 pci:v0000104Cd00008241*
  ID_MODEL_FROM_DATABASE=TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller
 
+pci:v0000104Cd00008241sv00001014sd000004B2*
+ ID_MODEL_FROM_DATABASE=TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller (S824 (8286-42A))
+
 pci:v0000104Cd00008400*
  ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface
 
@@ -17807,6 +17873,9 @@ pci:v00001077d00001656sv00001077sd0000E4F6*
 pci:v00001077d00001656sv00001077sd0000E4F7*
  ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (FastLinQ QL45212H 25GbE Adapter)
 
+pci:v00001077d00001656sv00001590sd00000223*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (Synergy 6810C 25/50Gb Ethernet Adapter)
+
 pci:v00001077d0000165C*
  ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FCoE)
 
@@ -17856,13 +17925,13 @@ pci:v00001077d00002031*
  ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter
 
 pci:v00001077d00002031sv0000103Csd000017E7*
- ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP SN1000Q 16Gb Single Port Fibre Channel Adapter)
+ ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (SN1000Q 16Gb Single Port Fibre Channel Adapter)
 
 pci:v00001077d00002031sv0000103Csd000017E8*
- ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP SN1000Q 16Gb Dual Port Fibre Channel Adapter)
+ ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (SN1000Q 16Gb Dual Port Fibre Channel Adapter)
 
 pci:v00001077d00002031sv0000103Csd00001939*
- ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (HP QMH2672 16Gb Dual Port Fibre Channel Adapter)
+ ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (QMH2672 16Gb Dual Port Fibre Channel Adapter)
 
 pci:v00001077d00002031sv0000103Csd00008002*
  ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (3830C 16G Fibre Channel Host Bus Adapter)
@@ -17922,16 +17991,16 @@ pci:v00001077d00002261sv00001077sd000002AC*
  ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2742 Dual Port 32Gb FC to PCIe Gen3 x8 Adapter)
 
 pci:v00001077d00002261sv00001590sd000000F9*
- ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (HPE StoreFabric SN1100Q 16Gb Single Port Fibre Channel Host Bus Adapter)
+ ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1100Q 16Gb Single Port Fibre Channel Host Bus Adapter)
 
 pci:v00001077d00002261sv00001590sd000000FA*
- ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (HPE StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter)
+ ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter)
 
 pci:v00001077d00002261sv00001590sd00000203*
- ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (HPE StoreFabric SN1600Q 32Gb Single Port Fibre Channel Host Bus Adapter)
+ ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1600Q 32Gb Single Port Fibre Channel Host Bus Adapter)
 
 pci:v00001077d00002261sv00001590sd00000204*
- ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (HPE StoreFabric SN1600Q 32Gb Dual Port Fibre Channel Host Bus Adapter)
+ ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1600Q 32Gb Dual Port Fibre Channel Host Bus Adapter)
 
 pci:v00001077d00002300*
  ID_MODEL_FROM_DATABASE=QLA2300 64-bit Fibre Channel Adapter
@@ -17966,17 +18035,29 @@ pci:v00001077d00002432sv0000103Csd00007040*
 pci:v00001077d00002532*
  ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA
 
+pci:v00001077d00002532sv00001014sd0000041E*
+ ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (FC EN0Y/EN12 PCIe2 LP 8 Gb 4-port Fibre Channel Adapter for POWER)
+
 pci:v00001077d00002532sv0000103Csd00003262*
  ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StorageWorks 81Q)
 
 pci:v00001077d00002532sv0000103Csd00003263*
  ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StorageWorks 82Q)
 
+pci:v00001077d00002532sv00001077sd0000015C*
+ ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QLE2560 PCI Express to 8Gb FC Single Channel)
+
+pci:v00001077d00002532sv00001077sd0000015D*
+ ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QLE2562 PCI Express to 8Gb FC Dual Channel)
+
+pci:v00001077d00002532sv00001077sd0000015E*
+ ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QLE2564 PCI Express to 8Gb FC Quad Channel)
+
 pci:v00001077d00002532sv00001077sd00000167*
  ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QME2572 Dual Port FC8 HBA Mezzanine)
 
 pci:v00001077d00002532sv00001590sd000000FC*
- ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (HPE StoreFabric 84Q 8Gb Quad Port Fibre Channel Host Bus Adapter)
+ ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StoreFabric 84Q 8Gb Quad Port Fibre Channel Host Bus Adapter)
 
 pci:v00001077d00003022*
  ID_MODEL_FROM_DATABASE=ISP4022-based Ethernet NIC
@@ -18014,6 +18095,9 @@ pci:v00001077d00008000*
 pci:v00001077d00008001*
  ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (FCoE)
 
+pci:v00001077d00008001sv00001014sd000003AF*
+ ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (FCoE) (FC 5708/5270 10 Gb FCoE PCIe Dual Port Adapter for POWER)
+
 pci:v00001077d00008020*
  ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller
 
@@ -18083,6 +18167,15 @@ pci:v00001077d00008032*
 pci:v00001077d00008070*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller
 
+pci:v00001077d00008070sv00001077sd00000001*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GE 2P QL41162HxRJ-DE Adapter)
+
+pci:v00001077d00008070sv00001077sd00000002*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GE 2P QL41112HxCU-DE Adapter)
+
+pci:v00001077d00008070sv00001077sd0000000B*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (25GE 2P QL41262HxCU-DE Adapter)
+
 pci:v00001077d00008070sv00001077sd00000011*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FastLinQ QL41212H 25GbE Adapter)
 
@@ -18092,6 +18185,15 @@ pci:v00001077d00008070sv00001077sd00000012*
 pci:v00001077d00008080*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE)
 
+pci:v00001077d00008080sv00001077sd00000001*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GE 2P QL41162HxRJ-DE Adapter)
+
+pci:v00001077d00008080sv00001077sd00000002*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GE 2P QL41112HxCU-DE Adapter)
+
+pci:v00001077d00008080sv00001077sd0000000B*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (25GE 2P QL41262HxCU-DE Adapter)
+
 pci:v00001077d00008080sv00001077sd0000000D*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (FastLinQ QL41262H 25GbE FCoE Adapter)
 
@@ -18101,6 +18203,15 @@ pci:v00001077d00008080sv00001077sd0000000E*
 pci:v00001077d00008084*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI)
 
+pci:v00001077d00008084sv00001077sd00000001*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GE 2P QL41162HxRJ-DE Adapter)
+
+pci:v00001077d00008084sv00001077sd00000002*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GE 2P QL41112HxCU-DE Adapter)
+
+pci:v00001077d00008084sv00001077sd0000000B*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (25GE 2P QL41262HxCU-DE Adapter)
+
 pci:v00001077d00008084sv00001077sd0000000D*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (FastLinQ QL41262H 25GbE iSCSI Adapter)
 
@@ -18110,6 +18221,15 @@ pci:v00001077d00008084sv00001077sd0000000E*
 pci:v00001077d00008090*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF)
 
+pci:v00001077d00008090sv00001077sd00000001*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (25GE 2P QL41262HxCU-DE Adapter)
+
+pci:v00001077d00008090sv00001077sd00000002*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10GE 2P QL41112HxCU-DE Adapter)
+
+pci:v00001077d00008090sv00001077sd0000000B*
+ ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (25GE 2P QL41262HxCU-DE Adapter)
+
 pci:v00001077d00008090sv00001077sd0000000D*
  ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL41262H 25GbE FCoE Adapter (SR-IOV VF))
 
@@ -26553,7 +26673,7 @@ pci:v000010DEd00000398*
  ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600]
 
 pci:v000010DEd00000398sv00001025sd0000006C*
- ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600] (Acer 9814 WKMI)
+ ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600] (Aspire 9814WKMi)
 
 pci:v000010DEd00000399*
  ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600 GT]
@@ -29417,6 +29537,9 @@ pci:v000010DEd00000DFC*
 pci:v000010DEd00000E08*
  ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller
 
+pci:v000010DEd00000E08sv00001043sd000083A0*
+ ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller (ENGT520 SILENT)
+
 pci:v000010DEd00000E08sv000010B0sd0000104A*
  ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller (Gainward GeForce GT 610)
 
@@ -29498,6 +29621,12 @@ pci:v000010DEd00000F06*
 pci:v000010DEd00000FB0*
  ID_MODEL_FROM_DATABASE=GM200 High Definition Audio
 
+pci:v000010DEd00000FB8*
+ ID_MODEL_FROM_DATABASE=GP108 High Definition Audio Controller
+
+pci:v000010DEd00000FB9*
+ ID_MODEL_FROM_DATABASE=GP107GL High Definition Audio Controller
+
 pci:v000010DEd00000FBB*
  ID_MODEL_FROM_DATABASE=GM204 High Definition Audio Controller
 
@@ -29789,6 +29918,9 @@ pci:v000010DEd0000103C*
 pci:v000010DEd00001040*
  ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 520]
 
+pci:v000010DEd00001040sv00001043sd000083A0*
+ ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 520] (ENGT520 SILENT)
+
 pci:v000010DEd00001042*
  ID_MODEL_FROM_DATABASE=GF119 [GeForce 510]
 
@@ -29996,6 +30128,9 @@ pci:v000010DEd000010EF*
 pci:v000010DEd000010F0*
  ID_MODEL_FROM_DATABASE=GP104 High Definition Audio Controller
 
+pci:v000010DEd000010F1*
+ ID_MODEL_FROM_DATABASE=GP106 High Definition Audio Controller
+
 pci:v000010DEd00001140*
  ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M]
 
@@ -31478,6 +31613,9 @@ pci:v000010DEd0000137A*
 pci:v000010DEd0000137Asv000017AAsd0000505A*
  ID_MODEL_FROM_DATABASE=GM108GLM [Quadro K620M / Quadro M500M] (Quadro M500M)
 
+pci:v000010DEd0000137B*
+ ID_MODEL_FROM_DATABASE=GM108GLM [Quadro M520 Mobile]
+
 pci:v000010DEd0000137D*
  ID_MODEL_FROM_DATABASE=GM108M [GeForce 940A]
 
@@ -31613,6 +31751,9 @@ pci:v000010DEd000013D9*
 pci:v000010DEd000013DA*
  ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980]
 
+pci:v000010DEd000013E7*
+ ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 980 Engineering Sample]
+
 pci:v000010DEd000013F0*
  ID_MODEL_FROM_DATABASE=GM204GL [Quadro M5000]
 
@@ -31665,7 +31806,7 @@ pci:v000010DEd00001436*
  ID_MODEL_FROM_DATABASE=GM206GLM [Quadro M2200 Mobile]
 
 pci:v000010DEd000015F0*
- ID_MODEL_FROM_DATABASE=GP100GL
+ ID_MODEL_FROM_DATABASE=GP100GL [Quadro GP100]
 
 pci:v000010DEd000015F1*
  ID_MODEL_FROM_DATABASE=GP100GL
@@ -31689,7 +31830,7 @@ pci:v000010DEd00001619*
  ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M]
 
 pci:v000010DEd0000161A*
- ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980]
+ ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980 Mobile]
 
 pci:v000010DEd00001667*
  ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M]
@@ -31724,6 +31865,12 @@ pci:v000010DEd00001B00*
 pci:v000010DEd00001B01*
  ID_MODEL_FROM_DATABASE=GP102
 
+pci:v000010DEd00001B02*
+ ID_MODEL_FROM_DATABASE=GP102 [TITAN Xp]
+
+pci:v000010DEd00001B06*
+ ID_MODEL_FROM_DATABASE=GP102 [GeForce GTX 1080 Ti]
+
 pci:v000010DEd00001B30*
  ID_MODEL_FROM_DATABASE=GP102GL [Quadro P6000]
 
@@ -31761,7 +31908,7 @@ pci:v000010DEd00001BB0*
  ID_MODEL_FROM_DATABASE=GP104GL [Quadro P5000]
 
 pci:v000010DEd00001BB1*
- ID_MODEL_FROM_DATABASE=GP104GL
+ ID_MODEL_FROM_DATABASE=GP104GL [Quadro P4000]
 
 pci:v000010DEd00001BB3*
  ID_MODEL_FROM_DATABASE=GP104GL [Tesla P4]
@@ -31800,7 +31947,7 @@ pci:v000010DEd00001C20*
  ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060 Mobile]
 
 pci:v000010DEd00001C30*
- ID_MODEL_FROM_DATABASE=GP106GL
+ ID_MODEL_FROM_DATABASE=GP106GL [Quadro P2000]
 
 pci:v000010DEd00001C35*
  ID_MODEL_FROM_DATABASE=GP106
@@ -31808,6 +31955,12 @@ pci:v000010DEd00001C35*
 pci:v000010DEd00001C60*
  ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060 Mobile]
 
+pci:v000010DEd00001C61*
+ ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1050 Ti Mobile]
+
+pci:v000010DEd00001C62*
+ ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1050 Mobile]
+
 pci:v000010DEd00001C70*
  ID_MODEL_FROM_DATABASE=GP106GL
 
@@ -31838,8 +31991,23 @@ pci:v000010DEd00001CA8*
 pci:v000010DEd00001CAA*
  ID_MODEL_FROM_DATABASE=GP107GL
 
+pci:v000010DEd00001CB1*
+ ID_MODEL_FROM_DATABASE=GP107GL [Quadro P1000]
+
+pci:v000010DEd00001CB2*
+ ID_MODEL_FROM_DATABASE=GP107GL [Quadro P600]
+
+pci:v000010DEd00001CB3*
+ ID_MODEL_FROM_DATABASE=GP107GL [Quadro P400]
+
 pci:v000010DEd00001D01*
- ID_MODEL_FROM_DATABASE=GP108
+ ID_MODEL_FROM_DATABASE=GP108 [GeForce GT 1030]
+
+pci:v000010DEd00001D10*
+ ID_MODEL_FROM_DATABASE=GP108 [GeForce MX150]
+
+pci:v000010DEd00001D81*
+ ID_MODEL_FROM_DATABASE=GV100
 
 pci:v000010DF*
  ID_VENDOR_FROM_DATABASE=Emulex Corporation
@@ -31908,7 +32076,10 @@ pci:v000010DFd0000E180*
  ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter
 
 pci:v000010DFd0000E200*
- ID_MODEL_FROM_DATABASE=Lancer-X: LightPulse Fibre Channel Host Adapter
+ ID_MODEL_FROM_DATABASE=LightPulse LPe16002
+
+pci:v000010DFd0000E200sv00001014sd000003F1*
+ ID_MODEL_FROM_DATABASE=LightPulse LPe16002 (PCIe2 16 Gb 2-port Fibre Channel Adapter (FC EL5B; CCIN 577F))
 
 pci:v000010DFd0000E208*
  ID_MODEL_FROM_DATABASE=LightPulse 16Gb Fibre Channel Host Adapter (Lancer-VF)
@@ -31934,6 +32105,24 @@ pci:v000010DFd0000E268*
 pci:v000010DFd0000E300*
  ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter
 
+pci:v000010DFd0000E300sv000010DFsd0000E310*
+ ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter (Lancer Gen6: LPe31000 Fibre Channel Host Adapter)
+
+pci:v000010DFd0000E300sv000010DFsd0000E311*
+ ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter (Lancer Gen6: LPe31000 Fibre Channel Host Adapter)
+
+pci:v000010DFd0000E300sv000010DFsd0000E312*
+ ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter (Lancer Gen6: LPe31000 Fibre Channel Host Adapter)
+
+pci:v000010DFd0000E300sv000010DFsd0000E322*
+ ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter (Lancer Gen6: LPe31000 Fibre Channel Host Adapter)
+
+pci:v000010DFd0000E300sv000010DFsd0000E323*
+ ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter (Lancer Gen6: LPe31000 Fibre Channel Host Adapter)
+
+pci:v000010DFd0000E300sv000010DFsd0000E325*
+ ID_MODEL_FROM_DATABASE=Lancer Gen6: LPe32000 Fibre Channel Host Adapter (Lancer Gen6: LPe31000 Fibre Channel Host Adapter)
+
 pci:v000010DFd0000F011*
  ID_MODEL_FROM_DATABASE=Saturn: LightPulse Fibre Channel Host Adapter
 
@@ -31976,6 +32165,9 @@ pci:v000010DFd0000F0F5*
 pci:v000010DFd0000F100*
  ID_MODEL_FROM_DATABASE=Saturn-X: LightPulse Fibre Channel Host Adapter
 
+pci:v000010DFd0000F100sv00001014sd0000038A*
+ ID_MODEL_FROM_DATABASE=Saturn-X: LightPulse Fibre Channel Host Adapter (8Gb PCI Express Dual Port FC Adapter for POWER)
+
 pci:v000010DFd0000F100sv0000103Csd00003282*
  ID_MODEL_FROM_DATABASE=Saturn-X: LightPulse Fibre Channel Host Adapter (8Gb Dual-port PCI-e FC HBA)
 
@@ -32042,6 +32234,9 @@ pci:v000010DFd0000FC50*
 pci:v000010DFd0000FD00*
  ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter
 
+pci:v000010DFd0000FD00sv000010DFsd0000FD02*
+ ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter (LightPulse LP11002 Dual-port 4Gigabit PCI Fibre Channel Adapter)
+
 pci:v000010DFd0000FD11*
  ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter
 
@@ -32342,6 +32537,9 @@ pci:v000010ECd00005250*
 pci:v000010ECd0000525A*
  ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader
 
+pci:v000010ECd0000525Asv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (ThinkPad X1 Carbon 5th Gen)
+
 pci:v000010ECd00005286*
  ID_MODEL_FROM_DATABASE=RTS5286 PCI Express Card Reader
 
@@ -32657,6 +32855,9 @@ pci:v000010ECd00008168sv00001849sd00008168*
 pci:v000010ECd00008168sv00007470sd00003468*
  ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (TG-3468 Gigabit PCI Express Network Adapter)
 
+pci:v000010ECd00008168sv00008086sd00002055*
+ ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (NUC Kit DN2820FYKH)
+
 pci:v000010ECd00008168sv00008086sd0000D615*
  ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Desktop Board D510MO/D525MW)
 
@@ -32795,6 +32996,9 @@ pci:v000010ECd00008821*
 pci:v000010ECd0000B723*
  ID_MODEL_FROM_DATABASE=RTL8723BE PCIe Wireless Network Adapter
 
+pci:v000010ECd0000B723sv000010ECsd00008739*
+ ID_MODEL_FROM_DATABASE=RTL8723BE PCIe Wireless Network Adapter (Dell Wireless 1801)
+
 pci:v000010ED*
  ID_VENDOR_FROM_DATABASE=Ascii Corporation
 
@@ -34263,10 +34467,10 @@ pci:v00001106d00003059sv00001043sd000080B0*
  ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V600/K8V-X/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX]))
 
 pci:v00001106d00003059sv00001043sd000080F3*
- ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (ASUSTek SK8V motherboard)
+ ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (SK8V motherboard)
 
 pci:v00001106d00003059sv00001043sd0000810D*
- ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (Asus P5VD1-X (AD1888 codec [SoundMax]))
+ ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (P5VD1-X (AD1888 codec [SoundMax]))
 
 pci:v00001106d00003059sv00001043sd0000812A*
  ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A8V Deluxe motherboard (Realtek ALC850 codec))
@@ -36291,7 +36495,7 @@ pci:v00001131d00007133sv00001043sd00000210*
  ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (FlyTV mini Asus Digimatrix)
 
 pci:v00001131d00007133sv00001043sd00004843*
- ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (ASUS TV-FM 7133)
+ ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV-FM 7133)
 
 pci:v00001131d00007133sv00001043sd00004845*
  ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV-FM 7135)
@@ -36513,7 +36717,7 @@ pci:v00001131d00007134sv00001043sd00000210*
  ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Digimatrix TV)
 
 pci:v00001131d00007134sv00001043sd00004840*
- ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (ASUS TV-FM 7134)
+ ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (TV-FM 7134)
 
 pci:v00001131d00007134sv00001043sd00004842*
  ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (TV-FM 7134)
@@ -38649,7 +38853,7 @@ pci:v00001180d00000476sv00001043sd00001967*
  ID_MODEL_FROM_DATABASE=RL5c476 II (V6800V)
 
 pci:v00001180d00000476sv00001043sd00001987*
- ID_MODEL_FROM_DATABASE=RL5c476 II (Asus A4K and Z81K notebooks, possibly others ( mid-2005 machines ))
+ ID_MODEL_FROM_DATABASE=RL5c476 II (A4K and Z81K notebooks, possibly others ( mid-2005 machines ))
 
 pci:v00001180d00000476sv0000104Dsd000080DF*
  ID_MODEL_FROM_DATABASE=RL5c476 II (Vaio PCG-FX403)
@@ -38676,7 +38880,7 @@ pci:v00001180d00000476sv000017AAsd0000201C*
  ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad X60/X60s)
 
 pci:v00001180d00000476sv000017AAsd000020C4*
- ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad T61)
+ ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad T61/R61)
 
 pci:v00001180d00000476sv000017AAsd000020C6*
  ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad R61)
@@ -38826,7 +39030,7 @@ pci:v00001180d00000822sv00001043sd00001237*
  ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (A6J-Q008)
 
 pci:v00001180d00000822sv00001043sd00001967*
- ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ASUS V6800V)
+ ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (V6800V)
 
 pci:v00001180d00000822sv000010F7sd00008338*
  ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Panasonic CF-Y5 laptop)
@@ -38873,6 +39077,9 @@ pci:v00001180d00000832sv0000103Csd000030CC*
 pci:v00001180d00000832sv0000103Csd000030CF*
  ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Pavilion dv9668eg Laptop)
 
+pci:v00001180d00000832sv000017AAsd000020C5*
+ ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (ThinkPad R61)
+
 pci:v00001180d00000832sv000017AAsd000020C7*
  ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (ThinkPad R61)
 
@@ -38892,10 +39099,10 @@ pci:v00001180d00000843sv00001028sd000001F3*
  ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Inspiron 1420)
 
 pci:v00001180d00000843sv00001028sd000001F5*
- ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Dell Inspiron 1501)
+ ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Inspiron 1501)
 
 pci:v00001180d00000843sv00001028sd0000024F*
- ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Dell Latitude e6500)
+ ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Latitude e6500)
 
 pci:v00001180d00000843sv0000103Csd000003B5*
  ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V3242AU)
@@ -38963,6 +39170,9 @@ pci:v00001180d0000E822sv00001028sd0000040B*
 pci:v00001180d0000E823*
  ID_MODEL_FROM_DATABASE=PCIe SDXC/MMC Host Controller
 
+pci:v00001180d0000E823sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=PCIe SDXC/MMC Host Controller (ThinkPad T520)
+
 pci:v00001180d0000E832*
  ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller
 
@@ -38972,6 +39182,9 @@ pci:v00001180d0000E832sv00001028sd0000040A*
 pci:v00001180d0000E832sv00001028sd0000040B*
  ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (Latitude E6510)
 
+pci:v00001180d0000E832sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (ThinkPad T520)
+
 pci:v00001180d0000E852*
  ID_MODEL_FROM_DATABASE=PCIe xD-Picture Card Controller
 
@@ -43734,7 +43947,7 @@ pci:v000012D8*
  ID_VENDOR_FROM_DATABASE=Pericom Semiconductor
 
 pci:v000012D8d000001A7*
- ID_MODEL_FROM_DATABASE=PI7C21P100 PCI to PCI Bridge
+ ID_MODEL_FROM_DATABASE=7C21P100 2-port PCI-X to PCI-X Bridge
 
 pci:v000012D8d0000400A*
  ID_MODEL_FROM_DATABASE=PI7C9X442SL PCI Express Bridge Port
@@ -44651,6 +44864,12 @@ pci:v00001344d00005161*
 pci:v00001344d00005163*
  ID_MODEL_FROM_DATABASE=RealSSD P425m
 
+pci:v00001344d00005180*
+ ID_MODEL_FROM_DATABASE=9100 PRO NVMe SSD
+
+pci:v00001344d00005181*
+ ID_MODEL_FROM_DATABASE=9100 MAX NVMe SSD
+
 pci:v00001345*
  ID_VENDOR_FROM_DATABASE=Arescom Inc
 
@@ -44889,7 +45108,7 @@ pci:v00001360d00000208*
  ID_MODEL_FROM_DATABASE=GPS180AMC GPS Receiver (PCI Express / MicroTCA / AdvancedMC)
 
 pci:v00001360d00000209*
- ID_MODEL_FROM_DATABASE=GRC181PEX GPS/GLONASS/BEIDOU receiver (PCI Express)
+ ID_MODEL_FROM_DATABASE=GNS181PEX GPS/Galileo/GLONASS/BEIDOU receiver (PCI Express)
 
 pci:v00001360d00000301*
  ID_MODEL_FROM_DATABASE=TCR510PCI IRIG Timecode Reader
@@ -46680,7 +46899,7 @@ pci:v0000140A*
  ID_VENDOR_FROM_DATABASE=DSP Research Inc
 
 pci:v0000140B*
- ID_VENDOR_FROM_DATABASE=GE Intelligent Platforms
+ ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc.
 
 pci:v0000140C*
  ID_VENDOR_FROM_DATABASE=Elmic Systems Inc
@@ -47618,6 +47837,12 @@ pci:v00001425d0000509F*
 pci:v00001425d000050A0*
  ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Ethernet Controller
 
+pci:v00001425d000050A1*
+ ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Ethernet Controller
+
+pci:v00001425d000050A2*
+ ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Ethernet Controller
+
 pci:v00001425d00005401*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
 
@@ -47771,6 +47996,12 @@ pci:v00001425d0000549F*
 pci:v00001425d000054A0*
  ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Ethernet Controller
 
+pci:v00001425d000054A1*
+ ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Ethernet Controller
+
+pci:v00001425d000054A2*
+ ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Ethernet Controller
+
 pci:v00001425d00005501*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
 
@@ -47924,6 +48155,12 @@ pci:v00001425d0000559F*
 pci:v00001425d000055A0*
  ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Storage Controller
 
+pci:v00001425d000055A1*
+ ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Storage Controller
+
+pci:v00001425d000055A2*
+ ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Storage Controller
+
 pci:v00001425d00005601*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller
 
@@ -48077,6 +48314,12 @@ pci:v00001425d0000569F*
 pci:v00001425d000056A0*
  ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Storage Controller
 
+pci:v00001425d000056A1*
+ ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Storage Controller
+
+pci:v00001425d000056A2*
+ ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Storage Controller
+
 pci:v00001425d00005701*
  ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller
 
@@ -48347,6 +48590,12 @@ pci:v00001425d0000589F*
 pci:v00001425d000058A0*
  ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Ethernet Controller [VF]
 
+pci:v00001425d000058A1*
+ ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d000058A2*
+ ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Ethernet Controller [VF]
+
 pci:v00001425d00006001*
  ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller
 
@@ -48392,6 +48641,15 @@ pci:v00001425d00006080*
 pci:v00001425d00006081*
  ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Ethernet Controller
 
+pci:v00001425d00006082*
+ ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Ethernet Controller
+
+pci:v00001425d00006083*
+ ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Ethernet Controller
+
+pci:v00001425d00006084*
+ ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Ethernet Controller
+
 pci:v00001425d00006401*
  ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller
 
@@ -48437,6 +48695,15 @@ pci:v00001425d00006480*
 pci:v00001425d00006481*
  ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Ethernet Controller
 
+pci:v00001425d00006482*
+ ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Ethernet Controller
+
+pci:v00001425d00006483*
+ ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Ethernet Controller
+
+pci:v00001425d00006484*
+ ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Ethernet Controller
+
 pci:v00001425d00006501*
  ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller
 
@@ -48482,6 +48749,15 @@ pci:v00001425d00006580*
 pci:v00001425d00006581*
  ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Storage Controller
 
+pci:v00001425d00006582*
+ ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Storage Controller
+
+pci:v00001425d00006583*
+ ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Storage Controller
+
+pci:v00001425d00006584*
+ ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Storage Controller
+
 pci:v00001425d00006601*
  ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller
 
@@ -48527,6 +48803,15 @@ pci:v00001425d00006680*
 pci:v00001425d00006681*
  ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Storage Controller
 
+pci:v00001425d00006682*
+ ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Storage Controller
+
+pci:v00001425d00006683*
+ ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Storage Controller
+
+pci:v00001425d00006684*
+ ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Storage Controller
+
 pci:v00001425d00006801*
  ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller [VF]
 
@@ -48572,6 +48857,15 @@ pci:v00001425d00006880*
 pci:v00001425d00006881*
  ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Ethernet Controller [VF]
 
+pci:v00001425d00006882*
+ ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d00006883*
+ ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Ethernet Controller [VF]
+
+pci:v00001425d00006884*
+ ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Ethernet Controller [VF]
+
 pci:v00001425d0000A000*
  ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller
 
@@ -48830,6 +49124,36 @@ pci:v0000144Dd0000A821sv00001028sd00001FC2*
 pci:v0000144Dd0000A821sv00001028sd00001FC4*
  ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 1.6TB AIC)
 
+pci:v0000144Dd0000A822*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa
+
+pci:v0000144Dd0000A822sv00001014sd00000621*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (PCIe3 1.6TB NVMe Flash Adapter II x8)
+
+pci:v0000144Dd0000A822sv00001014sd00000622*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (PCIe3 3.2TB NVMe Flash Adapter II x8)
+
+pci:v0000144Dd0000A822sv00001028sd00001FD9*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 800GB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FDA*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 1.6TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FDB*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 3.2TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FDC*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 6.4TB SFF)
+
+pci:v0000144Dd0000A822sv00001028sd00001FDD*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 1.6TB AIC)
+
+pci:v0000144Dd0000A822sv00001028sd00001FDE*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 3.2TB AIC)
+
+pci:v0000144Dd0000A822sv00001028sd00001FDF*
+ ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa (Express Flash PM1725a 6.4TB AIC)
+
 pci:v0000144E*
  ID_VENDOR_FROM_DATABASE=OLITEC
 
@@ -49371,7 +49695,16 @@ pci:v000014CC*
  ID_VENDOR_FROM_DATABASE=NAKAYO Telecommunications Inc
 
 pci:v000014CD*
- ID_VENDOR_FROM_DATABASE=Universal Scientific Ind.
+ ID_VENDOR_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd
+
+pci:v000014CDd00000001*
+ ID_MODEL_FROM_DATABASE=USI-1514-1GbaseT [OCP1]
+
+pci:v000014CDd00000002*
+ ID_MODEL_FROM_DATABASE=USI-4227-SFP [OCP2]
+
+pci:v000014CDd00000003*
+ ID_MODEL_FROM_DATABASE=USI-X557-10GbaseT [OCP3]
 
 pci:v000014CE*
  ID_VENDOR_FROM_DATABASE=Whistle Communications
@@ -49676,6 +50009,9 @@ pci:v000014E4d0000163C*
 pci:v000014E4d0000163D*
  ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet
 
+pci:v000014E4d0000163Dsv00001043sd0000858A*
+ ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet (PEB-10G/57811-1S)
+
 pci:v000014E4d0000163E*
  ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function
 
@@ -50049,7 +50385,7 @@ pci:v000014E4d0000165A*
  ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express
 
 pci:v000014E4d0000165Asv00001014sd00000378*
- ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (IBM System x3350 (Machine type 4192))
+ ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (System x3350 (Machine type 4192))
 
 pci:v000014E4d0000165Asv00001028sd0000020F*
  ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge R300 Broadcom NetXtreme 5722)
@@ -50291,6 +50627,9 @@ pci:v000014E4d0000168D*
 pci:v000014E4d0000168E*
  ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet
 
+pci:v000014E4d0000168Esv00001014sd00000492*
+ ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (PCIe2 2-port 10 GbE BaseT RJ45 Adapter (FC EN0W; CCIN 2CC4))
+
 pci:v000014E4d0000168Esv0000103Csd00001798*
  ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Flex-10 10Gb 2-port 530FLB Adapter [Meru])
 
@@ -50345,6 +50684,9 @@ pci:v000014E4d00001693sv00001025sd00000121*
 pci:v000014E4d00001693sv0000103Csd000030C0*
  ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (6710b)
 
+pci:v000014E4d00001693sv000017AAsd000020D5*
+ ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (ThinkPad R61)
+
 pci:v000014E4d00001694*
  ID_MODEL_FROM_DATABASE=NetLink BCM57790 Gigabit Ethernet PCIe
 
@@ -50712,7 +51054,7 @@ pci:v000014E4d000016CA*
  ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller
 
 pci:v000014E4d000016CB*
- ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Ethernet Virtual Function
+ ID_MODEL_FROM_DATABASE=NetXtreme-C Ethernet Virtual Function
 
 pci:v000014E4d000016CC*
  ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E Ethernet Partition
@@ -50733,7 +51075,7 @@ pci:v000014E4d000016D2*
  ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E 10GBASE-T Ethernet Controller
 
 pci:v000014E4d000016D3*
- ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Virtual Function
+ ID_MODEL_FROM_DATABASE=NetXtreme-E Ethernet Virtual Function
 
 pci:v000014E4d000016D4*
  ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E Ethernet Partition
@@ -50747,6 +51089,12 @@ pci:v000014E4d000016D6*
 pci:v000014E4d000016D7*
  ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller
 
+pci:v000014E4d000016D7sv000014E4sd00001202*
+ ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957412M4122 OCP 1x25G Type1 wRoCE)
+
+pci:v000014E4d000016D7sv000014E4sd00001404*
+ ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957414M4142 OCP 2x25G Type1 wRoCE)
+
 pci:v000014E4d000016D7sv00001590sd0000020E*
  ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631SFP28 Adapter)
 
@@ -50769,7 +51117,7 @@ pci:v000014E4d000016D9sv0000108Esd00004866*
  ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller (Dual Port 10GBase-T Ethernet Controller)
 
 pci:v000014E4d000016DC*
- ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Ethernet Virtual Function
+ ID_MODEL_FROM_DATABASE=NetXtreme-E Ethernet Virtual Function
 
 pci:v000014E4d000016DD*
  ID_MODEL_FROM_DATABASE=NetLink BCM5781 Gigabit Ethernet PCI Express
@@ -50781,7 +51129,7 @@ pci:v000014E4d000016DF*
  ID_MODEL_FROM_DATABASE=BCM57314 NetXtreme-C 10Gb/25Gb/40Gb/50Gb RDMA Ethernet Controller
 
 pci:v000014E4d000016E1*
- ID_MODEL_FROM_DATABASE=BCM57314 NetXtreme-C Ethernet Virtual Function
+ ID_MODEL_FROM_DATABASE=NetXtreme-C Ethernet Virtual Function
 
 pci:v000014E4d000016E2*
  ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller
@@ -50792,6 +51140,9 @@ pci:v000014E4d000016E2sv0000108Esd00004866*
 pci:v000014E4d000016E3*
  ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E 10Gb RDMA Ethernet Controller
 
+pci:v000014E4d000016E5*
+ ID_MODEL_FROM_DATABASE=NetXtreme-C RDMA Virtual Function
+
 pci:v000014E4d000016E7*
  ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Partition
 
@@ -51644,6 +51995,12 @@ pci:v000014E4d0000B800*
 pci:v000014E4d0000B842*
  ID_MODEL_FROM_DATABASE=BCM56842 Trident 10GE Switch Controller
 
+pci:v000014E4d0000B850*
+ ID_MODEL_FROM_DATABASE=Broadcom BCM56850 Switch ASIC
+
+pci:v000014E4d0000B960*
+ ID_MODEL_FROM_DATABASE=Broadcom BCM56960 Switch ASIC
+
 pci:v000014E5*
  ID_VENDOR_FROM_DATABASE=Pixelfusion Ltd
 
@@ -52209,7 +52566,7 @@ pci:v000014F1d00008800sv00001002sd0000A101*
  ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (HDTV Wonder)
 
 pci:v000014F1d00008800sv00001043sd00004823*
- ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (ASUS PVR-416)
+ ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (PVR-416)
 
 pci:v000014F1d00008800sv0000107Dsd00006611*
  ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Winfast TV 2000XP Expert)
@@ -52347,7 +52704,7 @@ pci:v000014F1d00008802sv00000070sd00009600*
  ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV 88x MPEG Encoder)
 
 pci:v000014F1d00008802sv00001043sd00004823*
- ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (ASUS PVR-416)
+ ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (PVR-416)
 
 pci:v000014F1d00008802sv0000107Dsd0000663C*
  ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Leadtek PVR 2000)
@@ -53025,7 +53382,7 @@ pci:v00001541*
  ID_VENDOR_FROM_DATABASE=MACHONE Communications
 
 pci:v00001542*
- ID_VENDOR_FROM_DATABASE=Concurrent Computer Corporation
+ ID_VENDOR_FROM_DATABASE=Concurrent Real-Time
 
 pci:v00001542d00009260*
  ID_MODEL_FROM_DATABASE=RCIM-II Real-Time Clock & Interrupt Module
@@ -53621,6 +53978,39 @@ pci:v000015B3d00001003sv0000103Csd000018CF*
 pci:v000015B3d00001003sv0000103Csd000018D6*
  ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544QSFP Adapter)
 
+pci:v000015B3d00001003sv000015B3sd00000025*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 IB QDR Dual Port Mezzanine Card)
+
+pci:v000015B3d00001003sv000015B3sd00000026*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 IB FDR Dual Port Mezzanine Card)
+
+pci:v000015B3d00001003sv000015B3sd00000028*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI Dual QSFP+ Port QDR Infiniband 40Gb/s or 10Gb Ethernet)
+
+pci:v000015B3d00001003sv000015B3sd00000059*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Mezzanine Card)
+
+pci:v000015B3d00001003sv000015B3sd00000065*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Adapter)
+
+pci:v000015B3d00001003sv000015B3sd00000066*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 IB FDR10 Dual Port Mezzanine Card)
+
+pci:v000015B3d00001003sv000015B3sd00000067*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Adapter)
+
+pci:v000015B3d00001003sv000015B3sd00000071*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Mezzanine Card)
+
+pci:v000015B3d00001003sv000015B3sd00000078*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 10 GbE Dual Port KR Mezzanine Card)
+
+pci:v000015B3d00001003sv000015B3sd00000079*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 40 GbE Dual Port QSFP+ Adapter)
+
+pci:v000015B3d00001003sv000015B3sd00000080*
+ ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 10 GbE Dual Port SFP+ Adapter)
+
 pci:v000015B3d00001004*
  ID_MODEL_FROM_DATABASE=MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]
 
@@ -53657,6 +54047,15 @@ pci:v000015B3d00001007sv0000117Csd00000092*
 pci:v000015B3d00001007sv0000117Csd00000093*
  ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ12)
 
+pci:v000015B3d00001007sv000015B3sd00000078*
+ ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (ConnectX-3 Pro 10 GbE Dual Port KR Mezzanine Card)
+
+pci:v000015B3d00001007sv000015B3sd00000079*
+ ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (ConnectX-3 Pro 40 GbE Dual Port QSFP+ Adapter)
+
+pci:v000015B3d00001007sv000015B3sd00000080*
+ ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (ConnectX-3 Pro 10 GbE Dual Port SFP+ Adapter)
+
 pci:v000015B3d00001009*
  ID_MODEL_FROM_DATABASE=MT27530 Family
 
@@ -53690,12 +54089,36 @@ pci:v000015B3d00001012*
 pci:v000015B3d00001013*
  ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4]
 
+pci:v000015B3d00001013sv000015B3sd00000006*
+ ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (MCX416A-BCAT, ConnectX-4 EN, 40/56GbE 2P, PCIe3.0 x16)
+
+pci:v000015B3d00001013sv000015B3sd00000033*
+ ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 VPI IB EDR/100 GbE Single Port QSFP28 Adapter)
+
+pci:v000015B3d00001013sv000015B3sd00000034*
+ ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 VPI IB EDR/100 GbE Dual Port QSFP28 Adapter)
+
+pci:v000015B3d00001013sv000015B3sd00000050*
+ ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 100 GbE Dual Port QSFP28 Adapter)
+
 pci:v000015B3d00001014*
  ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4 Virtual Function]
 
 pci:v000015B3d00001015*
  ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx]
 
+pci:v000015B3d00001015sv000015B3sd00000016*
+ ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx 25 GbE Dual Port SFP28 Adapter)
+
+pci:v000015B3d00001015sv000015B3sd00000020*
+ ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (MCX4411A-ACQN, ConnectX-4 Lx EN OCP, 1x25Gb)
+
+pci:v000015B3d00001015sv000015B3sd00000021*
+ ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (MCX4421A-ACQN ConnectX-4 Lx EN OCP,2x25G)
+
+pci:v000015B3d00001015sv000015B3sd00000025*
+ ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx 25 GbE Dual Port SFP28 rNDC)
+
 pci:v000015B3d00001016*
  ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function]
 
@@ -53786,6 +54209,9 @@ pci:v000015B3d00006732*
 pci:v000015B3d0000673C*
  ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE]
 
+pci:v000015B3d0000673Csv00001014sd00000487*
+ ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (GX++ 1-port 4X IB QDR Adapter for Power 795)
+
 pci:v000015B3d0000673Csv0000103Csd00001782*
  ID_MODEL_FROM_DATABASE=MT26428 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE] (4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem)
 
@@ -53810,6 +54236,9 @@ pci:v000015B3d00006750sv00001014sd00000461*
 pci:v000015B3d00006750sv000015B3sd00000018*
  ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1))
 
+pci:v000015B3d00006750sv000015B3sd00006572*
+ ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (IBM Flex System EN4132 2-port 10Gb RoCE Adapter)
+
 pci:v000015B3d0000675A*
  ID_MODEL_FROM_DATABASE=MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe Gen2 5GT/s]
 
@@ -53849,6 +54278,9 @@ pci:v000015B3d0000A2D0*
 pci:v000015B3d0000A2D1*
  ID_MODEL_FROM_DATABASE=MT416842 BlueField SoC Crypto disabled
 
+pci:v000015B3d0000A2D2*
+ ID_MODEL_FROM_DATABASE=MT416842 BlueField integrated ConnectX-5 network controller
+
 pci:v000015B3d0000A2D3*
  ID_MODEL_FROM_DATABASE=MT416842 BlueField multicore SoC family VF
 
@@ -55424,6 +55856,9 @@ pci:v0000168Cd00000033sv0000168Csd0000A120*
 pci:v0000168Cd00000034*
  ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter
 
+pci:v0000168Cd00000034sv00001028sd0000020B*
+ ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter (Wireless 1601 802.11abgn Adapter)
+
 pci:v0000168Cd00000034sv00001028sd00000300*
  ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter (Wireless 1802 802.11abgn Adapter)
 
@@ -58245,31 +58680,31 @@ pci:v00001924d00000A03*
  ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller
 
 pci:v00001924d00000A03sv00001924sd00008011*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8022-R1 Flareon 8000 Series 10G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8022-R1 8000 Series 10G Adapter)
 
 pci:v00001924d00000A03sv00001924sd00008012*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R1 Flareon Ultra 8000 Series 10G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R1 8000 Series 10G Adapter)
 
 pci:v00001924d00000A03sv00001924sd00008013*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R1 Flareon 8000 Series 10/40G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R1 8000 Series 10/40G Adapter)
 
 pci:v00001924d00000A03sv00001924sd00008014*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8542-R1 Flareon Ultra 8000 Series 10/40G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8542-R1 8000 Series 10/40G Adapter)
 
 pci:v00001924d00000A03sv00001924sd00008016*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8022-R2 Flareon 8000 Series 10G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8022-R2 8000 Series 10G Adapte)
 
 pci:v00001924d00000A03sv00001924sd00008017*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R2 Flareon Ultra 8000 Series 10G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R2 8000 Series 10G Adapter)
 
 pci:v00001924d00000A03sv00001924sd00008018*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R2 Flareon 8000 Series 10/40G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R2 8000 Series 10/40G Adapter)
 
 pci:v00001924d00000A03sv00001924sd00008019*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8542-R2 Flareon Ultra 8000 Series 10/40G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8542-R2 8000 Series 10/40G Adapter)
 
 pci:v00001924d00000A03sv00001924sd0000801A*
- ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8722-R1 Flareon Ultra 8000 Series OCP 10G Adapter)
+ ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8722-R1 8000 Series OCP 10G Adapter)
 
 pci:v00001924d00001803*
  ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Virtual Function)
@@ -59013,32 +59448,50 @@ pci:v000019A2d00000222*
  ID_MODEL_FROM_DATABASE=BladeEngine3 10Gb Gen2 PCIe iSCSI Adapter
 
 pci:v000019A2d00000700*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE
 
 pci:v000019A2d00000700sv0000103Csd00001747*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC550SFP DualPort 10GbE Server Adapter)
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC550SFP DualPort 10GbE Server Adapter)
 
 pci:v000019A2d00000700sv0000103Csd00001749*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC550SFP Dual Port Server Adapter)
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC550SFP Dual Port Server Adapter)
 
 pci:v000019A2d00000700sv0000103Csd0000174A*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC551m Dual Port FlexFabric 10Gb Adapter)
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC551m Dual Port FlexFabric 10Gb Adapter)
 
 pci:v000019A2d00000700sv0000103Csd0000174B*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (StorageWorks NC550 DualPort Converged Network Adapter)
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (StorageWorks NC550 DualPort Converged Network Adapter)
 
 pci:v000019A2d00000700sv0000103Csd00003314*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (NC551i Dual Port FlexFabric 10Gb Adapter)
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC551i Dual Port FlexFabric 10Gb Adapter)
 
 pci:v000019A2d00000702*
  ID_MODEL_FROM_DATABASE=OneConnect 10Gb iSCSI Initiator
 
 pci:v000019A2d00000704*
- ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE CNA
+
+pci:v000019A2d00000704sv000010DFsd0000E602*
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE CNA (OneConnect OCe10100 10Gb CNA)
+
+pci:v000019A2d00000704sv000010DFsd0000E630*
+ ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE CNA (OneConnect OCe10102-FM-E / OCe10102-FX-E for EMC VNX Symmetrix)
 
 pci:v000019A2d00000710*
  ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3)
 
+pci:v000019A2d00000710sv00001014sd000003D0*
+ ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (PCIe2 2-port 10GbE SR Adapter for POWER)
+
+pci:v000019A2d00000710sv00001014sd000003D1*
+ ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (PCIe2 2-port 10GbE SFP+ Copper Adapter for POWER)
+
+pci:v000019A2d00000710sv00001014sd00000409*
+ ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (Integrated Multifunction Card with Dual 10GbE SR Optical + Dual 1GbE for Power 750/760)
+
+pci:v000019A2d00000710sv00001014sd0000040A*
+ ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (Integrated Multifunction Card with Dual 10GbE SR Copper + Dual 1GbE for Power 750/760)
+
 pci:v000019A2d00000710sv0000103Csd00003315*
  ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC553i 10Gb 2-port FlexFabric Converged Network Adapter)
 
@@ -59054,6 +59507,9 @@ pci:v000019A2d00000710sv0000103Csd00003345*
 pci:v000019A2d00000710sv0000103Csd0000337B*
  ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter)
 
+pci:v000019A2d00000710sv000010DFsd0000E733*
+ ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (Flex System EN4054 4-port 10Gb Ethernet Mezzanine Adapter)
+
 pci:v000019A2d00000712*
  ID_MODEL_FROM_DATABASE=OneConnect 10Gb iSCSI Initiator (be3)
 
@@ -59774,9 +60230,24 @@ pci:v00001B36d00000006*
 pci:v00001B36d00000007*
  ID_MODEL_FROM_DATABASE=PCI SD Card Host Controller Interface
 
+pci:v00001B36d00000008*
+ ID_MODEL_FROM_DATABASE=QEMU PCIe Host bridge
+
+pci:v00001B36d00000009*
+ ID_MODEL_FROM_DATABASE=QEMU PCI Expander bridge
+
 pci:v00001B36d0000000A*
  ID_MODEL_FROM_DATABASE=PCI-PCI bridge (multiseat)
 
+pci:v00001B36d0000000B*
+ ID_MODEL_FROM_DATABASE=QEMU PCIe Expander bridge
+
+pci:v00001B36d0000000C*
+ ID_MODEL_FROM_DATABASE=QEMU PCIe Root port
+
+pci:v00001B36d0000000D*
+ ID_MODEL_FROM_DATABASE=QEMU XHCI Host Controller
+
 pci:v00001B36d00000100*
  ID_MODEL_FROM_DATABASE=QXL paravirtual graphic card
 
@@ -59822,6 +60293,9 @@ pci:v00001B37d0000001F*
 pci:v00001B37d00000020*
  ID_MODEL_FROM_DATABASE=ADQ14
 
+pci:v00001B37d00000023*
+ ID_MODEL_FROM_DATABASE=ADQ7
+
 pci:v00001B37d00002014*
  ID_MODEL_FROM_DATABASE=TX320
 
@@ -60014,6 +60488,9 @@ pci:v00001B85*
 pci:v00001B85d00001041*
  ID_MODEL_FROM_DATABASE=RevoDrive 3 X2 PCI-Express SSD 240 GB (Marvell Controller)
 
+pci:v00001B85d00006018*
+ ID_MODEL_FROM_DATABASE=RD400/400A SSD
+
 pci:v00001B85d00008788*
  ID_MODEL_FROM_DATABASE=RevoDrive Hybrid
 
@@ -60398,12 +60875,21 @@ pci:v00001CE4d00000005*
 pci:v00001CE4d00000006*
  ID_MODEL_FROM_DATABASE=ExaNIC X10-HPT
 
+pci:v00001CE4d00000007*
+ ID_MODEL_FROM_DATABASE=ExaNIC X40
+
 pci:v00001CF7*
  ID_VENDOR_FROM_DATABASE=Subspace Dynamics
 
 pci:v00001D00*
  ID_VENDOR_FROM_DATABASE=Pure Storage
 
+pci:v00001D18*
+ ID_VENDOR_FROM_DATABASE=RME
+
+pci:v00001D18d00000001*
+ ID_MODEL_FROM_DATABASE=Fireface UFX+
+
 pci:v00001D1D*
  ID_VENDOR_FROM_DATABASE=CNEX Labs
 
@@ -60443,6 +60929,9 @@ pci:v00001D44d0000A400*
 pci:v00001D49*
  ID_VENDOR_FROM_DATABASE=Lenovo
 
+pci:v00001D4C*
+ ID_VENDOR_FROM_DATABASE=Diamanti, Inc.
+
 pci:v00001D5C*
  ID_VENDOR_FROM_DATABASE=Fantasia Trading LLC
 
@@ -60518,6 +61007,9 @@ pci:v00001D78*
 pci:v00001D7C*
  ID_VENDOR_FROM_DATABASE=Aerotech, Inc.
 
+pci:v00001D87*
+ ID_VENDOR_FROM_DATABASE=Rockchip Inc. RK3399 PCI Express Root Port
+
 pci:v00001D8F*
  ID_VENDOR_FROM_DATABASE=Enyx
 
@@ -60527,6 +61019,9 @@ pci:v00001D95*
 pci:v00001DA1*
  ID_VENDOR_FROM_DATABASE=Teko Telecom S.r.l.
 
+pci:v00001DA2*
+ ID_VENDOR_FROM_DATABASE=Sapphire Technology Limited
+
 pci:v00001DE1*
  ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd.
 
@@ -60677,6 +61172,9 @@ pci:v00001FC9d00004026*
 pci:v00001FC9d00004027*
  ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter
 
+pci:v00001FC9d00004027sv00001154sd00000368*
+ ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (LGY-PCIE-MG)
+
 pci:v00001FC9d00004027sv00001432sd00008104*
  ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (10 Gigabit Ethernet PCI Express Adapter)
 
@@ -62489,6 +62987,9 @@ pci:v00005555*
 pci:v00005555d00000003*
  ID_MODEL_FROM_DATABASE=TURBOstor HFP-832 [HiPPI NIC]
 
+pci:v00005555d00003B00*
+ ID_MODEL_FROM_DATABASE=Epiphan DVI2PCIe video capture card
+
 pci:v00005646*
  ID_VENDOR_FROM_DATABASE=Vector Fabrics BV
 
@@ -62501,6 +63002,9 @@ pci:v00005678*
 pci:v00005700*
  ID_VENDOR_FROM_DATABASE=Netpower
 
+pci:v00005845*
+ ID_VENDOR_FROM_DATABASE=X-ES, Inc.
+
 pci:v0000584D*
  ID_VENDOR_FROM_DATABASE=AuzenTech Co., Ltd.
 
@@ -62817,7 +63321,7 @@ pci:v00008086d00000085*
  ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak]
 
 pci:v00008086d00000085sv00008086sd00001311*
- ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN)
+ ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 (802.11a/b/g/n))
 
 pci:v00008086d00000085sv00008086sd00001316*
  ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG)
@@ -62954,6 +63458,9 @@ pci:v00008086d00000104sv0000106Bsd000000DC*
 pci:v00008086d00000104sv0000144Dsd0000C652*
  ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (NP300E5C series laptop)
 
+pci:v00008086d00000104sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (ThinkPad T520)
+
 pci:v00008086d00000105*
  ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port
 
@@ -63005,6 +63512,9 @@ pci:v00008086d00000126*
 pci:v00008086d00000126sv00001028sd000004CC*
  ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (Vostro 3350)
 
+pci:v00008086d00000126sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (ThinkPad T520)
+
 pci:v00008086d00000150*
  ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
 
@@ -65945,6 +66455,9 @@ pci:v00008086d000010BB*
 pci:v00008086d000010BC*
  ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper)
 
+pci:v00008086d000010BCsv00001014sd00000368*
+ ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (4-Port 10/100/1000 Base-TX PCI Express Adapter for POWER)
+
 pci:v00008086d000010BCsv0000103Csd0000704B*
  ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Copper) (NC364T PCI Express Quad Port Gigabit Server Adapter)
 
@@ -67077,13 +67590,16 @@ pci:v00008086d00001501*
  ID_MODEL_FROM_DATABASE=82567V-3 Gigabit Network Connection
 
 pci:v00008086d00001502*
- ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection
+ ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville)
 
 pci:v00008086d00001502sv00001028sd000004A3*
- ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Precision M4600)
+ ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (Precision M4600)
+
+pci:v00008086d00001502sv000017AAsd000021CE*
+ ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (ThinkPad T520)
 
 pci:v00008086d00001502sv00008086sd0000357A*
- ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Server Board S1200BTS)
+ ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (Server Board S1200BTS)
 
 pci:v00008086d00001503*
  ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection
@@ -67451,6 +67967,9 @@ pci:v00008086d0000152A*
 pci:v00008086d0000152E*
  ID_MODEL_FROM_DATABASE=82599 Virtual Function
 
+pci:v00008086d0000152F*
+ ID_MODEL_FROM_DATABASE=I350 Virtual Function
+
 pci:v00008086d00001530*
  ID_MODEL_FROM_DATABASE=X540 Virtual Function
 
@@ -67496,6 +68015,12 @@ pci:v00008086d00001537sv00001059sd00000120*
 pci:v00008086d00001537sv00001059sd00000130*
  ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4009 1GbE interface)
 
+pci:v00008086d00001537sv00001059sd00000140*
+ ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T2035 1GbE interface)
+
+pci:v00008086d00001537sv00001059sd00000150*
+ ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (RD-01068 1GbE interface)
+
 pci:v00008086d00001538*
  ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection
 
@@ -67619,6 +68144,12 @@ pci:v00008086d00001563sv00008086sd00000001*
 pci:v00008086d00001563sv00008086sd0000001A*
  ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2)
 
+pci:v00008086d00001563sv00008086sd0000001B*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Server Adapter X550-T2 for OCP)
+
+pci:v00008086d00001563sv00008086sd0000001D*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 2P X550-t Adapter)
+
 pci:v00008086d00001563sv00008086sd00000022*
  ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2)
 
@@ -67677,10 +68208,10 @@ pci:v00008086d00001572sv0000103Csd00000000*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 562SFP+ Adapter)
 
 pci:v00008086d00001572sv0000103Csd000022FC*
- ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (HP Ethernet 10Gb 2-port 562FLR-SFP+ Adapter)
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 2-port 562FLR-SFP+ Adapter)
 
 pci:v00008086d00001572sv0000103Csd000022FD*
- ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (HP Ethernet 10Gb 2-port 562SFP+ Adapter)
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 2-port 562SFP+ Adapter)
 
 pci:v00008086d00001572sv00001137sd00000000*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-DA)
@@ -67745,6 +68276,9 @@ pci:v00008086d00001572sv00008086sd0000000B*
 pci:v00008086d00001572sv00008086sd0000000D*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+
 
+pci:v00008086d00001572sv00008086sd0000000E*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Server Adapter OCP X710-2)
+
 pci:v00008086d00001572sv00008086sd00000010*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710)
 
@@ -67754,6 +68288,9 @@ pci:v00008086d00001572sv00008086sd00004005*
 pci:v00008086d00001572sv00008086sd00004006*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+
 
+pci:v00008086d00001572sv00008086sd00004007*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+
+
 pci:v00008086d00001575*
  ID_MODEL_FROM_DATABASE=DSL6340 Thunderbolt 3 NHI [Alpine Ridge 2C 2015]
 
@@ -67793,6 +68330,9 @@ pci:v00008086d00001581sv00001028sd00001F98*
 pci:v00008086d00001581sv00001028sd00001F9E*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G 2P X710-k bNDC)
 
+pci:v00008086d00001581sv00001059sd00000150*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (RD-01068 10GbE-KR interface)
+
 pci:v00008086d00001581sv00001590sd00000000*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 2-port 563i Adapter)
 
@@ -67875,10 +68415,10 @@ pci:v00008086d00001587*
  ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane
 
 pci:v00008086d00001587sv0000103Csd00000000*
- ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HPE Ethernet 10/20Gb 2-port 660FLB Adapter)
+ ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet 10/20Gb 2-port 660FLB Adapter)
 
 pci:v00008086d00001587sv0000103Csd000022FE*
- ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HPE Ethernet 10/20Gb 2-port 660FLB Adapter)
+ ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet 10/20Gb 2-port 660FLB Adapter)
 
 pci:v00008086d00001588*
  ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane
@@ -67907,6 +68447,12 @@ pci:v00008086d00001589sv00008086sd00000001*
 pci:v00008086d00001589sv00008086sd00000002*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4)
 
+pci:v00008086d00001589sv00008086sd00000003*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T)
+
+pci:v00008086d00001589sv00008086sd000000A0*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4)
+
 pci:v00008086d00001589sv00008086sd00001003*
  ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T)
 
@@ -67943,6 +68489,9 @@ pci:v00008086d0000158Bsv00008086sd00000007*
 pci:v00008086d0000158Bsv00008086sd00000008*
  ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-1)
 
+pci:v00008086d0000158Bsv00008086sd00004001*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2)
+
 pci:v00008086d000015A0*
  ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-LM
 
@@ -67973,6 +68522,9 @@ pci:v00008086d000015AA*
 pci:v00008086d000015AAsv00001059sd00000120*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane (T4008 10GbE interface)
 
+pci:v00008086d000015AAsv00001059sd00000150*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane (RD-01068 10GbE interface)
+
 pci:v00008086d000015AB*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane
 
@@ -68024,9 +68576,30 @@ pci:v00008086d000015BF*
 pci:v00008086d000015C0*
  ID_MODEL_FROM_DATABASE=JHL6240 Thunderbolt 3 Bridge (Low Power) [Alpine Ridge LP 2016]
 
+pci:v00008086d000015C2*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 Backplane
+
+pci:v00008086d000015C3*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 Backplane
+
+pci:v00008086d000015C4*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 10 GbE SFP+
+
 pci:v00008086d000015C5*
  ID_MODEL_FROM_DATABASE=X553 Virtual Function
 
+pci:v00008086d000015C6*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE
+
+pci:v00008086d000015C7*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE
+
+pci:v00008086d000015C8*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553/X557-AT 10GBASE-T
+
+pci:v00008086d000015CE*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 10 GbE SFP+
+
 pci:v00008086d000015D0*
  ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-100GbE-QDA2
 
@@ -68036,6 +68609,9 @@ pci:v00008086d000015D1*
 pci:v00008086d000015D1sv00008086sd00000002*
  ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1)
 
+pci:v00008086d000015D1sv00008086sd0000001B*
+ ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Server Adapter X550-T1 for OCP)
+
 pci:v00008086d000015D1sv00008086sd00000021*
  ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1)
 
@@ -68048,6 +68624,9 @@ pci:v00008086d000015D2*
 pci:v00008086d000015D3*
  ID_MODEL_FROM_DATABASE=JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016]
 
+pci:v00008086d000015D4*
+ ID_MODEL_FROM_DATABASE=JHL6540 Thunderbolt 3 USB Controller (C step) [Alpine Ridge 4C 2016]
+
 pci:v00008086d000015D5*
  ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-25GbE-DA2
 
@@ -68063,15 +68642,36 @@ pci:v00008086d000015D7*
 pci:v00008086d000015D8*
  ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V
 
+pci:v00008086d000015D8sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d000015D9*
  ID_MODEL_FROM_DATABASE=JHL6340 Thunderbolt 3 NHI (C step) [Alpine Ridge 2C 2016]
 
 pci:v00008086d000015DA*
  ID_MODEL_FROM_DATABASE=JHL6340 Thunderbolt 3 Bridge (C step) [Alpine Ridge 2C 2016]
 
+pci:v00008086d000015DF*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (8) I219-LM
+
+pci:v00008086d000015E0*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (8) I219-V
+
+pci:v00008086d000015E1*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (9) I219-LM
+
+pci:v00008086d000015E2*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection (9) I219-V
+
 pci:v00008086d000015E3*
  ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-LM
 
+pci:v00008086d000015E4*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE
+
+pci:v00008086d000015E5*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE
+
 pci:v00008086d00001600*
  ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI
 
@@ -68186,6 +68786,9 @@ pci:v00008086d0000163D*
 pci:v00008086d0000163E*
  ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics
 
+pci:v00008086d00001889*
+ ID_MODEL_FROM_DATABASE=Ethernet Adaptive Virtual Function
+
 pci:v00008086d00001900*
  ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers
 
@@ -68234,6 +68837,9 @@ pci:v00008086d00001910*
 pci:v00008086d00001911*
  ID_MODEL_FROM_DATABASE=Skylake Gaussian Mixture Model
 
+pci:v00008086d00001911sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Skylake Gaussian Mixture Model (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00001912*
  ID_MODEL_FROM_DATABASE=HD Graphics 530
 
@@ -68493,52 +69099,58 @@ pci:v00008086d00001B48sv00008086sd0000A11F*
  ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter)
 
 pci:v00008086d00001C00*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 4 port SATA IDE Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Desktop SATA Controller (IDE mode, ports 0-3)
 
 pci:v00008086d00001C01*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 4 port SATA IDE Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Mobile SATA Controller (IDE mode, ports 0-3)
 
 pci:v00008086d00001C02*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller
 
 pci:v00008086d00001C02sv00001028sd000004AA*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller (XPS 8300)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (XPS 8300)
 
 pci:v00008086d00001C02sv00001043sd0000844D*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller (P8 series motherboard)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (P8 series motherboard)
 
 pci:v00008086d00001C02sv00008086sd00007270*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA AHCI Controller (Server Board S1200BTS)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (Server Board S1200BTS)
 
 pci:v00008086d00001C03*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller
 
 pci:v00008086d00001C03sv00001028sd000004A3*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Precision M4600)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Precision M4600)
 
 pci:v00008086d00001C03sv00001028sd000004B2*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Vostro 3350)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Vostro 3350)
 
 pci:v00008086d00001C03sv00001028sd000004DA*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Vostro 3750)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Vostro 3750)
+
+pci:v00008086d00001C03sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (ThinkPad T520)
 
 pci:v00008086d00001C03sv00008086sd00007270*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port SATA AHCI Controller (Apple MacBookPro8,2 [Core i7, 15", 2011])
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Apple MacBookPro8,2 [Core i7, 15", 2011])
 
 pci:v00008086d00001C04*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA RAID Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Desktop SATA RAID Controller
 
 pci:v00008086d00001C04sv0000103Csd00003118*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA RAID Controller (Smart Array B110i SATA RAID Controller)
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Desktop SATA RAID Controller (Smart Array B110i SATA RAID Controller)
 
 pci:v00008086d00001C05*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SATA RAID Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Mobile SATA RAID Controller
+
+pci:v00008086d00001C06*
+ ID_MODEL_FROM_DATABASE=Z68 Express Chipset SATA RAID Controller
 
 pci:v00008086d00001C08*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 2 port SATA IDE Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Desktop SATA Controller (IDE mode, ports 4-5)
 
 pci:v00008086d00001C09*
- ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 2 port SATA IDE Controller
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Mobile SATA Controller (IDE mode, ports 4-5)
 
 pci:v00008086d00001C10*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1
@@ -68552,6 +69164,9 @@ pci:v00008086d00001C10sv00001028sd000004DA*
 pci:v00008086d00001C10sv00001043sd0000844D*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (P8 series motherboard)
 
+pci:v00008086d00001C10sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (ThinkPad T520)
+
 pci:v00008086d00001C10sv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2)
 
@@ -68561,6 +69176,9 @@ pci:v00008086d00001C12*
 pci:v00008086d00001C12sv00001028sd000004AA*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (XPS 8300)
 
+pci:v00008086d00001C12sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (ThinkPad T520)
+
 pci:v00008086d00001C12sv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (Apple MacBookPro8,2 [Core i7, 15", 2011])
 
@@ -68579,12 +69197,18 @@ pci:v00008086d00001C16*
 pci:v00008086d00001C16sv00001028sd000004AA*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 (XPS 8300)
 
+pci:v00008086d00001C16sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 (ThinkPad T520)
+
 pci:v00008086d00001C18*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5
 
 pci:v00008086d00001C18sv00001028sd000004DA*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (Vostro 3750)
 
+pci:v00008086d00001C18sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (ThinkPad T520)
+
 pci:v00008086d00001C18sv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (Server Board S1200BTS)
 
@@ -68630,6 +69254,9 @@ pci:v00008086d00001C20sv00001043sd00008418*
 pci:v00008086d00001C20sv00001043sd0000841B*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (P8H67 Series Motherboard)
 
+pci:v00008086d00001C20sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (ThinkPad T520)
+
 pci:v00008086d00001C20sv00008086sd00002008*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (DQ67SW board)
 
@@ -68654,6 +69281,9 @@ pci:v00008086d00001C22sv00001028sd000004DA*
 pci:v00008086d00001C22sv00001043sd0000844D*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (P8 series motherboard)
 
+pci:v00008086d00001C22sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (ThinkPad T520)
+
 pci:v00008086d00001C22sv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2)
 
@@ -68681,6 +69311,9 @@ pci:v00008086d00001C26sv00001028sd000004DA*
 pci:v00008086d00001C26sv00001043sd0000844D*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard)
 
+pci:v00008086d00001C26sv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (ThinkPad T520)
+
 pci:v00008086d00001C26sv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2)
 
@@ -68714,6 +69347,9 @@ pci:v00008086d00001C2Dsv00001028sd000004DA*
 pci:v00008086d00001C2Dsv00001043sd0000844D*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard)
 
+pci:v00008086d00001C2Dsv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (ThinkPad T520)
+
 pci:v00008086d00001C2Dsv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2)
 
@@ -68741,6 +69377,9 @@ pci:v00008086d00001C3Asv00001028sd000004DA*
 pci:v00008086d00001C3Asv00001043sd0000844D*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (P8 series motherboard)
 
+pci:v00008086d00001C3Asv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (ThinkPad T520)
+
 pci:v00008086d00001C3Asv00008086sd00007270*
  ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Apple MacBookPro8,2 [Core i7, 15", 2011])
 
@@ -68822,6 +69461,9 @@ pci:v00008086d00001C4F*
 pci:v00008086d00001C4Fsv00001028sd000004A3*
  ID_MODEL_FROM_DATABASE=QM67 Express Chipset Family LPC Controller (Precision M4600)
 
+pci:v00008086d00001C4Fsv000017AAsd000021CF*
+ ID_MODEL_FROM_DATABASE=QM67 Express Chipset Family LPC Controller (ThinkPad T520)
+
 pci:v00008086d00001C50*
  ID_MODEL_FROM_DATABASE=B65 Express Chipset Family LPC Controller
 
@@ -69204,7 +69846,7 @@ pci:v00008086d00001E20*
  ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller
 
 pci:v00008086d00001E20sv00001028sd0000054B*
- ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (Dell XPS One 2710)
+ ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (XPS One 2710)
 
 pci:v00008086d00001E20sv00001043sd0000108D*
  ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (VivoBook X202EV)
@@ -69219,7 +69861,7 @@ pci:v00008086d00001E20sv00001043sd00008415*
  ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (P8H77-I Motherboard)
 
 pci:v00008086d00001E20sv00001043sd00008445*
- ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (ASUS P8Z77-V LX Motherboard)
+ ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (P8Z77-V LX Motherboard)
 
 pci:v00008086d00001E20sv0000144Dsd0000C652*
  ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (NP300E5C series laptop)
@@ -69663,16 +70305,16 @@ pci:v00008086d00002024*
  ID_MODEL_FROM_DATABASE=Sky Lake-E MM/Vt-d Configuration Registers
 
 pci:v00008086d00002030*
- ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1A
+ ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port A
 
 pci:v00008086d00002031*
- ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1B
+ ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port B
 
 pci:v00008086d00002032*
- ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1C
+ ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port C
 
 pci:v00008086d00002033*
- ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port 1D
+ ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port D
 
 pci:v00008086d00002035*
  ID_MODEL_FROM_DATABASE=Sky Lake-E RAS Configuration Registers
@@ -71912,6 +72554,9 @@ pci:v00008086d000024FD*
 pci:v00008086d000024FDsv00008086sd00000010*
  ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 (Dual Band Wireless-AC 8265)
 
+pci:v00008086d000024FDsv00008086sd00001130*
+ ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 (Dual Band Wireless-AC 8265)
+
 pci:v00008086d00002500*
  ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH)
 
@@ -72192,7 +72837,7 @@ pci:v00008086d00002590sv00001014sd00000575*
  ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (ThinkPad X41 / Z60t)
 
 pci:v00008086d00002590sv00001028sd00000182*
- ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Dell Latitude C610)
+ ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Latitude C610)
 
 pci:v00008086d00002590sv0000103Csd00000934*
  ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Compaq nw8240/nx8220)
@@ -73056,7 +73701,7 @@ pci:v00008086d00002668sv0000103Csd00002A09*
  ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (PufferM-UL8E)
 
 pci:v00008086d00002668sv00001043sd00001173*
- ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (Asus A6VC)
+ ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (A6VC)
 
 pci:v00008086d00002668sv00001043sd0000814E*
  ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (P5GD1-VW Mainboard)
@@ -73134,7 +73779,7 @@ pci:v00008086d0000266Esv00001028sd00000182*
  ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Latitude D610 Laptop)
 
 pci:v00008086d0000266Esv00001028sd00000187*
- ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Dell Precision M70 Laptop)
+ ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Precision M70 Laptop)
 
 pci:v00008086d0000266Esv00001028sd00000188*
  ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Inspiron 6000 laptop)
@@ -74256,7 +74901,7 @@ pci:v00008086d000027D8sv00001043sd00001123*
  ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (A6J-Q008)
 
 pci:v00008086d000027D8sv00001043sd000013C4*
- ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Asus G2P)
+ ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (G2P)
 
 pci:v00008086d000027D8sv00001043sd0000817F*
  ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5LD2-VM Mainboard (Realtek ALC 882 codec))
@@ -74310,7 +74955,7 @@ pci:v00008086d000027D8sv000017AAsd00002010*
  ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (ThinkPad R60/T60/X60 series)
 
 pci:v00008086d000027D8sv000017AAsd00003802*
- ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Lenovo 3000 C200 audio [Realtek ALC861VD])
+ ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (3000 C200 audio [Realtek ALC861VD])
 
 pci:v00008086d000027D8sv00008086sd00001112*
  ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D945GTP)
@@ -74522,6 +75167,9 @@ pci:v00008086d00002815sv0000104Dsd00009005*
 pci:v00008086d00002815sv0000104Dsd0000902D*
  ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (VAIO VGN-NR120E)
 
+pci:v00008086d00002815sv000017AAsd000020A5*
+ ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (ThinkPad R61)
+
 pci:v00008086d00002815sv000017C0sd00004083*
  ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Medion WIM 2210 Notebook PC [MD96850])
 
@@ -74600,6 +75248,9 @@ pci:v00008086d00002828sv00001028sd000001F3*
 pci:v00008086d00002828sv0000103Csd000030C0*
  ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (Compaq 6710b)
 
+pci:v00008086d00002828sv000017AAsd000020A8*
+ ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (ThinkPad R61)
+
 pci:v00008086d00002828sv0000E4BFsd0000CC47*
  ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (CCG-RUMBA)
 
@@ -74649,7 +75300,7 @@ pci:v00008086d00002830*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1
 
 pci:v00008086d00002830sv00001025sd00000121*
- ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Acer Aspire 5920G)
+ ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Aspire 5920G)
 
 pci:v00008086d00002830sv00001028sd000001DA*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (OptiPlex 745)
@@ -74829,7 +75480,7 @@ pci:v00008086d00002835*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5
 
 pci:v00008086d00002835sv00001025sd00000121*
- ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Acer Aspire 5920G)
+ ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Aspire 5920G)
 
 pci:v00008086d00002835sv00001028sd000001DA*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (OptiPlex 745)
@@ -74913,7 +75564,7 @@ pci:v00008086d0000283A*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2
 
 pci:v00008086d0000283Asv00001025sd00000121*
- ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Acer Aspire 5920G)
+ ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Aspire 5920G)
 
 pci:v00008086d0000283Asv00001028sd000001DA*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (OptiPlex 745)
@@ -75078,10 +75729,10 @@ pci:v00008086d0000284Bsv00001028sd000001F3*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Inspiron 1420)
 
 pci:v00008086d0000284Bsv00001028sd000001F9*
- ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Dell Latitude D630)
+ ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Latitude D630)
 
 pci:v00008086d0000284Bsv00001028sd000001FF*
- ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Dell Precision M4300)
+ ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Precision M4300)
 
 pci:v00008086d0000284Bsv00001028sd00000256*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Studio 1735)
@@ -75099,7 +75750,7 @@ pci:v00008086d0000284Bsv0000103Csd000030CC*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Pavilion dv6700)
 
 pci:v00008086d0000284Bsv00001043sd00001339*
- ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Asus M51S series)
+ ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (M51S series)
 
 pci:v00008086d0000284Bsv00001043sd000081EC*
  ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (P5B)
@@ -76104,7 +76755,7 @@ pci:v00008086d00002A00*
  ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub
 
 pci:v00008086d00002A00sv00001025sd00000121*
- ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Acer Aspire 5920G)
+ ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Aspire 5920G)
 
 pci:v00008086d00002A00sv00001028sd000001F3*
  ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Inspiron 1420)
@@ -76161,10 +76812,10 @@ pci:v00008086d00002A02sv0000104Dsd0000902D*
  ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (VAIO VGN-NR120E)
 
 pci:v00008086d00002A02sv000017AAsd000020B5*
- ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (ThinkPad T61/R61)
+ ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (GM965 [X3100] on ThinkPad T61/R61)
 
 pci:v00008086d00002A02sv000017C0sd00004082*
- ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Medion WIM 2210 Notebook PC [MD96850])
+ ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (GM965 on Medion WIM 2210 Notebook PC [MD96850])
 
 pci:v00008086d00002A02sv0000E4BFsd0000CC47*
  ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (CCG-RUMBA)
@@ -76185,10 +76836,10 @@ pci:v00008086d00002A03sv0000104Dsd0000902D*
  ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (VAIO VGN-NR120E)
 
 pci:v00008086d00002A03sv000017AAsd000020B5*
- ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (ThinkPad T61/R61)
+ ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (GM965 [X3100] on ThinkPad T61/R61)
 
 pci:v00008086d00002A03sv000017C0sd00004082*
- ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Medion WIM 2210 Notebook PC [MD96850])
+ ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (GM965 on Medion WIM 2210 Notebook PC [MD96850])
 
 pci:v00008086d00002A03sv0000E4BFsd0000CC47*
  ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (CCG-RUMBA)
@@ -76797,7 +77448,7 @@ pci:v00008086d00002E20*
  ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller
 
 pci:v00008086d00002E20sv00001028sd00000283*
- ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (Dell Vostro 220)
+ ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (Vostro 220)
 
 pci:v00008086d00002E20sv00001043sd000082D3*
  ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (P5Q Deluxe Motherboard)
@@ -78323,6 +78974,9 @@ pci:v00008086d000037D1sv00001590sd00000216*
 pci:v00008086d000037D1sv00001590sd00000217*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Ethernet 1Gb 2-port 368FLR-MMT Adapter)
 
+pci:v00008086d000037D1sv00001590sd00000247*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Ethernet 1Gb 4-port 369i Adapter)
+
 pci:v00008086d000037D1sv000017AAsd00004020*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Intel Ethernet Connection X722 for 1GbE)
 
@@ -78335,14 +78989,17 @@ pci:v00008086d000037D1sv000017AAsd00004022*
 pci:v00008086d000037D2*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T
 
+pci:v00008086d000037D2sv000014CDsd00000030*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Ethernet OCP 2x10G RJ45 Phy Card [USI-X557-10GbaseT])
+
 pci:v00008086d000037D2sv00001590sd00000218*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Ethernet 10Gb 2-port 568FLR-MMT Adapter)
 
 pci:v00008086d000037D2sv000017AAsd00004020*
- ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Intel Ethernet Connection X722 for 10GBASE)
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T
 
 pci:v00008086d000037D2sv000017AAsd00004021*
- ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Intel Ethernet Connection X722 for 10GBASE)
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T
 
 pci:v00008086d000037D2sv000017AAsd00004022*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T
@@ -78353,6 +79010,12 @@ pci:v00008086d000037D3*
 pci:v00008086d000037D3sv00001590sd00000219*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Ethernet 10Gb 2-port 568FLR-MMSFP+ Adapter)
 
+pci:v00008086d000037D3sv000017AAsd00004020*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+
+
+pci:v00008086d000037D3sv000017AAsd00004021*
+ ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+
+
 pci:v00008086d000037D4*
  ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE QSFP+
 
@@ -79164,7 +79827,7 @@ pci:v00008086d00003B56sv00001028sd0000040B*
  ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Latitude E6510)
 
 pci:v00008086d00003B56sv00001043sd00001373*
- ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (ASUSTek G73-series gaming laptop)
+ ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (G73-series gaming laptop)
 
 pci:v00008086d00003B56sv0000144Dsd0000C06A*
  ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (R730 Laptop)
@@ -79595,8 +80258,8 @@ pci:v00008086d00004223sv00001002sd00008086*
 pci:v00008086d00004223sv00001003sd00008086*
  ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B High-Band ZZH)
 
-pci:v00008086d00004223sv00001351sd0000103C*
- ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (Compaq NC6220)
+pci:v00008086d00004223sv0000103Csd00001351*
+ ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (Compaq nc6220)
 
 pci:v00008086d00004224*
  ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection
@@ -79608,7 +80271,7 @@ pci:v00008086d00004227sv00008086sd00001010*
  ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad R60e)
 
 pci:v00008086d00004227sv00008086sd00001011*
- ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad T60/R60e/X60s)
+ ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad T60/R60e/X60s/R61)
 
 pci:v00008086d00004227sv00008086sd00001014*
  ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection)
@@ -79961,6 +80624,30 @@ pci:v00008086d00005845*
 pci:v00008086d00005845sv00001AF4sd00001100*
  ID_MODEL_FROM_DATABASE=QEMU NVM Express Controller (QEMU Virtual Machine)
 
+pci:v00008086d00005902*
+ ID_MODEL_FROM_DATABASE=HD Graphics 610
+
+pci:v00008086d00005904*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00005904sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers (ThinkPad X1 Carbon 5th Gen)
+
+pci:v00008086d0000590F*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00005910*
+ ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
+
+pci:v00008086d00005912*
+ ID_MODEL_FROM_DATABASE=HD Graphics 630
+
+pci:v00008086d00005916*
+ ID_MODEL_FROM_DATABASE=HD Graphics 620
+
+pci:v00008086d00005916sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=HD Graphics 620 (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00005A84*
  ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Integrated Graphics Controller
 
@@ -81989,6 +82676,12 @@ pci:v00008086d00009D03sv00001028sd000006F3*
 pci:v00008086d00009D03sv000017AAsd0000382A*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (B51-80 Laptop)
 
+pci:v00008086d00009D10*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #1
+
+pci:v00008086d00009D12*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #3
+
 pci:v00008086d00009D14*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5
 
@@ -82019,6 +82712,9 @@ pci:v00008086d00009D21*
 pci:v00008086d00009D21sv00001028sd000006F3*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude 3570)
 
+pci:v00008086d00009D21sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00009D21sv000017AAsd0000382A*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (B51-80 Laptop)
 
@@ -82028,6 +82724,9 @@ pci:v00008086d00009D23*
 pci:v00008086d00009D23sv00001028sd000006F3*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude 3570)
 
+pci:v00008086d00009D23sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00009D23sv000017AAsd0000382A*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (B51-80 Laptop)
 
@@ -82061,6 +82760,9 @@ pci:v00008086d00009D31*
 pci:v00008086d00009D31sv00001028sd000006F3*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude 3570)
 
+pci:v00008086d00009D31sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00009D31sv000017AAsd0000382A*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (B51-80 Laptop)
 
@@ -82070,6 +82772,9 @@ pci:v00008086d00009D3A*
 pci:v00008086d00009D3Asv00001028sd000006F3*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude 3570)
 
+pci:v00008086d00009D3Asv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00009D3Asv000017AAsd0000382A*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (B51-80 Laptop)
 
@@ -82085,6 +82790,12 @@ pci:v00008086d00009D48*
 pci:v00008086d00009D48sv00001028sd000006F3*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (Latitude 3570)
 
+pci:v00008086d00009D58*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller
+
+pci:v00008086d00009D58sv000017AAsd0000224F*
+ ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (ThinkPad X1 Carbon 5th Gen)
+
 pci:v00008086d00009D60*
  ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0
 
@@ -82592,9 +83303,57 @@ pci:v00008086d0000A256*
 pci:v00008086d0000A282*
  ID_MODEL_FROM_DATABASE=200 Series PCH SATA controller [AHCI mode]
 
-pci:v00008086d0000A294*
+pci:v00008086d0000A286*
+ ID_MODEL_FROM_DATABASE=200 Series PCH SATA controller [RAID mode]
+
+pci:v00008086d0000A290*
  ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #1
 
+pci:v00008086d0000A291*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #2
+
+pci:v00008086d0000A292*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #3
+
+pci:v00008086d0000A293*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #4
+
+pci:v00008086d0000A294*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #5
+
+pci:v00008086d0000A295*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #6
+
+pci:v00008086d0000A296*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #7
+
+pci:v00008086d0000A297*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #8
+
+pci:v00008086d0000A298*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #9
+
+pci:v00008086d0000A299*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #10
+
+pci:v00008086d0000A29A*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #11
+
+pci:v00008086d0000A29B*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #12
+
+pci:v00008086d0000A29C*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #13
+
+pci:v00008086d0000A29D*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #14
+
+pci:v00008086d0000A29E*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #15
+
+pci:v00008086d0000A29F*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #16
+
 pci:v00008086d0000A2A1*
  ID_MODEL_FROM_DATABASE=200 Series PCH PMC
 
@@ -82625,8 +83384,20 @@ pci:v00008086d0000A2BA*
 pci:v00008086d0000A2BB*
  ID_MODEL_FROM_DATABASE=200 Series PCH CSME HECI #2
 
+pci:v00008086d0000A2C4*
+ ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (H270)
+
+pci:v00008086d0000A2C5*
+ ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (Z270)
+
 pci:v00008086d0000A2C6*
- ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller
+ ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (Q270)
+
+pci:v00008086d0000A2C7*
+ ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (Q250)
+
+pci:v00008086d0000A2C8*
+ ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (B250)
 
 pci:v00008086d0000A2E0*
  ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO I2C Controller #0
@@ -82643,6 +83414,30 @@ pci:v00008086d0000A2E3*
 pci:v00008086d0000A2E6*
  ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO UART Controller #2
 
+pci:v00008086d0000A2E7*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #17
+
+pci:v00008086d0000A2E8*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #18
+
+pci:v00008086d0000A2E9*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #19
+
+pci:v00008086d0000A2EA*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #20
+
+pci:v00008086d0000A2EB*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #21
+
+pci:v00008086d0000A2EC*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #22
+
+pci:v00008086d0000A2ED*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #23
+
+pci:v00008086d0000A2EE*
+ ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #24
+
 pci:v00008086d0000A2F0*
  ID_MODEL_FROM_DATABASE=200 Series PCH HD Audio
 
@@ -83726,6 +84521,48 @@ pci:v00009005d0000028Dsv00009005sd00000553*
 pci:v00009005d0000028Dsv00009005sd00000554*
  ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8885 - 8 internal 8 external 12G SAS Port/PCIe 3.0)
 
+pci:v00009005d0000028F*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3
+
+pci:v00009005d0000028Fsv0000103Csd00000600*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-p SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000601*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408e-p SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000602*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-a SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000603*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-c SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000650*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-p SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000651*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208e-p SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000652*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-c SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000654*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-a SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000655*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408e-m SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000700*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P204i-c SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00000701*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P204i-b SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00001100*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P816i-a SR Gen10)
+
+pci:v00009005d0000028Fsv0000103Csd00001101*
+ ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P416ie-m SR G10)
+
 pci:v00009005d00000410*
  ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID)
 
@@ -84923,6 +85760,9 @@ pci:v0000F1D0d0000CFEE*
 pci:v0000F1D0d0000DAFF*
  ID_MODEL_FROM_DATABASE=KONA LHi
 
+pci:v0000F1D0d0000DB01*
+ ID_MODEL_FROM_DATABASE=Corvid22
+
 pci:v0000F1D0d0000DB09*
  ID_MODEL_FROM_DATABASE=Corvid 24
 
@@ -84932,6 +85772,9 @@ pci:v0000F1D0d0000DCAF*
 pci:v0000F1D0d0000DFEE*
  ID_MODEL_FROM_DATABASE=Xena HD-DA
 
+pci:v0000F1D0d0000EB0E*
+ ID_MODEL_FROM_DATABASE=Corvid 44
+
 pci:v0000F1D0d0000EFAC*
  ID_MODEL_FROM_DATABASE=Xena SD-MM/SD-22-MM
 
index 6acb51bb1c9d0669f627dc7acd7d276137baa1e6..7583253777c509f2b989fa0c29aa9c7e6f75c2f4 100644 (file)
@@ -3812,6 +3812,9 @@ usb:v041Ep3121*
 usb:v041Ep3220*
  ID_MODEL_FROM_DATABASE=Sound Blaster Tactic(3D) Sigma sound card
 
+usb:v041Ep3232*
+ ID_MODEL_FROM_DATABASE=Sound Blaster Premium HD [SBX]
+
 usb:v041Ep3F00*
  ID_MODEL_FROM_DATABASE=E-Mu Xboard 25 MIDI Controller
 
@@ -4787,6 +4790,15 @@ usb:v0430pA102*
 usb:v0430pA103*
  ID_MODEL_FROM_DATABASE=remote storage for P3 chip
 
+usb:v0430pA111*
+ ID_MODEL_FROM_DATABASE=remote keyboard for P4 chip
+
+usb:v0430pA112*
+ ID_MODEL_FROM_DATABASE=remote mouse for P4 chip
+
+usb:v0430pA113*
+ ID_MODEL_FROM_DATABASE=remote storage for P4 chip
+
 usb:v0430pA4A2*
  ID_MODEL_FROM_DATABASE=Ethernet (RNDIS and CDC ethernet)
 
@@ -5285,6 +5297,12 @@ usb:v043E*
 usb:v043Ep3001*
  ID_MODEL_FROM_DATABASE=AN-WF100 802.11abgn Wireless Adapter [Broadcom BCM4323]
 
+usb:v043Ep3004*
+ ID_MODEL_FROM_DATABASE=TWFM-B003D 802.11abgn Wireless Module [Broadcom BCM43236B]
+
+usb:v043Ep3101*
+ ID_MODEL_FROM_DATABASE=AN-WF500 802.11abgn + BT Wireless Adapter [Broadcom BCM43242]
+
 usb:v043Ep42BD*
  ID_MODEL_FROM_DATABASE=Flatron 795FT Plus Monitor
 
@@ -6884,6 +6902,9 @@ usb:v045Ep075D*
 usb:v045Ep0761*
  ID_MODEL_FROM_DATABASE=LifeCam VX-2000
 
+usb:v045Ep0765*
+ ID_MODEL_FROM_DATABASE=Xbox360 Slim Internal Wireless Module (1400) [Marvell 88W8786U]
+
 usb:v045Ep0766*
  ID_MODEL_FROM_DATABASE=LifeCam VX-800
 
@@ -7319,6 +7340,9 @@ usb:v046Dp0828*
 usb:v046Dp082B*
  ID_MODEL_FROM_DATABASE=Webcam C170
 
+usb:v046Dp082C*
+ ID_MODEL_FROM_DATABASE=HD Webcam C615
+
 usb:v046Dp082D*
  ID_MODEL_FROM_DATABASE=HD Pro Webcam C920
 
@@ -7889,6 +7913,9 @@ usb:v046DpC07D*
 usb:v046DpC07E*
  ID_MODEL_FROM_DATABASE=G402 Gaming Mouse
 
+usb:v046DpC083*
+ ID_MODEL_FROM_DATABASE=G403 Prodigy Gaming Mouse
+
 usb:v046DpC101*
  ID_MODEL_FROM_DATABASE=UltraX Media Remote
 
@@ -8174,9 +8201,15 @@ usb:v046DpC31C*
 usb:v046DpC31D*
  ID_MODEL_FROM_DATABASE=Media Keyboard K200
 
+usb:v046DpC31F*
+ ID_MODEL_FROM_DATABASE=Comfort Keyboard K290
+
 usb:v046DpC332*
  ID_MODEL_FROM_DATABASE=G502 Proteus Spectrum Optical Mouse
 
+usb:v046DpC335*
+ ID_MODEL_FROM_DATABASE=G910 Orion Spectrum Mechanical Keyboard
+
 usb:v046DpC401*
  ID_MODEL_FROM_DATABASE=TrackMan Marble Wheel
 
@@ -9446,6 +9479,9 @@ usb:v048Dp9503*
 usb:v048Dp9507*
  ID_MODEL_FROM_DATABASE=ITE it9507 full featured DVB-T transmission chip [ccHDtv]
 
+usb:v048Dp9910*
+ ID_MODEL_FROM_DATABASE=IT9910 chipset based grabber
+
 usb:v048F*
  ID_VENDOR_FROM_DATABASE=Eicon Tech.
 
@@ -10466,6 +10502,9 @@ usb:v04A9p1607*
 usb:v04A9p1608*
  ID_MODEL_FROM_DATABASE=DR-2580C Scanner
 
+usb:v04A9p1609*
+ ID_MODEL_FROM_DATABASE=DR-3080CII
+
 usb:v04A9p1700*
  ID_MODEL_FROM_DATABASE=PIXMA MP110 Scanner
 
@@ -10485,10 +10524,10 @@ usb:v04A9p1706*
  ID_MODEL_FROM_DATABASE=PIXMA MP750 Scanner
 
 usb:v04A9p1707*
- ID_MODEL_FROM_DATABASE=PIXMA MP780 Scanner
+ ID_MODEL_FROM_DATABASE=PIXMA MP780/MP790
 
 usb:v04A9p1708*
- ID_MODEL_FROM_DATABASE=PIXMA MP760 Scanner
+ ID_MODEL_FROM_DATABASE=PIXMA MP760/MP770
 
 usb:v04A9p1709*
  ID_MODEL_FROM_DATABASE=PIXMA MP150 Scanner
@@ -10506,13 +10545,13 @@ usb:v04A9p170D*
  ID_MODEL_FROM_DATABASE=PIXMA MP800 Scanner
 
 usb:v04A9p170E*
- ID_MODEL_FROM_DATABASE=MP800R
+ ID_MODEL_FROM_DATABASE=PIXMA MP800R
 
 usb:v04A9p1710*
  ID_MODEL_FROM_DATABASE=MP950
 
 usb:v04A9p1712*
- ID_MODEL_FROM_DATABASE=MP530
+ ID_MODEL_FROM_DATABASE=PIXMA MP530
 
 usb:v04A9p1713*
  ID_MODEL_FROM_DATABASE=PIXMA MP830 Scanner
@@ -10521,73 +10560,259 @@ usb:v04A9p1714*
  ID_MODEL_FROM_DATABASE=MP160
 
 usb:v04A9p1715*
- ID_MODEL_FROM_DATABASE=MP180 Storage
+ ID_MODEL_FROM_DATABASE=PIXMA MP180
 
 usb:v04A9p1716*
- ID_MODEL_FROM_DATABASE=MP460 Composite
+ ID_MODEL_FROM_DATABASE=PIXMA MP460
 
 usb:v04A9p1717*
- ID_MODEL_FROM_DATABASE=MP510
+ ID_MODEL_FROM_DATABASE=PIXMA MP510
 
 usb:v04A9p1718*
- ID_MODEL_FROM_DATABASE=MP600 Storage
+ ID_MODEL_FROM_DATABASE=PIXMA MP600
+
+usb:v04A9p1719*
+ ID_MODEL_FROM_DATABASE=PIXMA MP600R
 
 usb:v04A9p171A*
- ID_MODEL_FROM_DATABASE=MP810 Storage
+ ID_MODEL_FROM_DATABASE=PIXMA MP810
 
 usb:v04A9p171B*
- ID_MODEL_FROM_DATABASE=MP960
+ ID_MODEL_FROM_DATABASE=PIXMA MP960
+
+usb:v04A9p171C*
+ ID_MODEL_FROM_DATABASE=PIXMA MX7600
 
 usb:v04A9p1721*
- ID_MODEL_FROM_DATABASE=MP210 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MP210
+
+usb:v04A9p1722*
+ ID_MODEL_FROM_DATABASE=PIXMA MP220
 
 usb:v04A9p1723*
- ID_MODEL_FROM_DATABASE=MP470 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MP470
 
 usb:v04A9p1724*
  ID_MODEL_FROM_DATABASE=PIXMA MP520 series
 
 usb:v04A9p1725*
- ID_MODEL_FROM_DATABASE=MP610 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MP610
 
 usb:v04A9p1726*
- ID_MODEL_FROM_DATABASE=MP970 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MP970
 
 usb:v04A9p1727*
- ID_MODEL_FROM_DATABASE=MX300 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MX300
 
 usb:v04A9p1728*
  ID_MODEL_FROM_DATABASE=PIXMA MX310 series
 
 usb:v04A9p1729*
- ID_MODEL_FROM_DATABASE=MX700 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MX700
 
 usb:v04A9p172B*
  ID_MODEL_FROM_DATABASE=MP140 ser
 
+usb:v04A9p172C*
+ ID_MODEL_FROM_DATABASE=PIXMA MX850
+
+usb:v04A9p172D*
+ ID_MODEL_FROM_DATABASE=PIXMA MP980
+
+usb:v04A9p172E*
+ ID_MODEL_FROM_DATABASE=PIXMA MP630
+
+usb:v04A9p172F*
+ ID_MODEL_FROM_DATABASE=PIXMA MP620
+
+usb:v04A9p1730*
+ ID_MODEL_FROM_DATABASE=PIXMA MP540
+
+usb:v04A9p1731*
+ ID_MODEL_FROM_DATABASE=PIXMA MP480
+
+usb:v04A9p1732*
+ ID_MODEL_FROM_DATABASE=PIXMA MP240
+
+usb:v04A9p1733*
+ ID_MODEL_FROM_DATABASE=PIXMA MP260
+
+usb:v04A9p1734*
+ ID_MODEL_FROM_DATABASE=PIXMA MP190
+
+usb:v04A9p1735*
+ ID_MODEL_FROM_DATABASE=PIXMA MX860
+
 usb:v04A9p1736*
  ID_MODEL_FROM_DATABASE=PIXMA MX320 series
 
+usb:v04A9p1737*
+ ID_MODEL_FROM_DATABASE=PIXMA MX330
+
 usb:v04A9p173A*
- ID_MODEL_FROM_DATABASE=MP250 series printer
+ ID_MODEL_FROM_DATABASE=PIXMA MP250
 
 usb:v04A9p173B*
  ID_MODEL_FROM_DATABASE=PIXMA MP270 All-In-One Printer
 
+usb:v04A9p173C*
+ ID_MODEL_FROM_DATABASE=PIXMA MP490
+
+usb:v04A9p173D*
+ ID_MODEL_FROM_DATABASE=PIXMA MP550
+
 usb:v04A9p173E*
- ID_MODEL_FROM_DATABASE=MP560
+ ID_MODEL_FROM_DATABASE=PIXMA MP560
 
 usb:v04A9p173F*
- ID_MODEL_FROM_DATABASE=Pixma MP640 Multifunction device
+ ID_MODEL_FROM_DATABASE=PIXMA MP640
+
+usb:v04A9p1740*
+ ID_MODEL_FROM_DATABASE=PIXMA MP990
+
+usb:v04A9p1741*
+ ID_MODEL_FROM_DATABASE=PIXMA MX340
+
+usb:v04A9p1742*
+ ID_MODEL_FROM_DATABASE=PIXMA MX350
+
+usb:v04A9p1743*
+ ID_MODEL_FROM_DATABASE=PIXMA MX870
+
+usb:v04A9p1746*
+ ID_MODEL_FROM_DATABASE=PIXMA MP280
+
+usb:v04A9p1747*
+ ID_MODEL_FROM_DATABASE=PIXMA MP495
 
 usb:v04A9p1748*
- ID_MODEL_FROM_DATABASE=Pixma MG5150
+ ID_MODEL_FROM_DATABASE=PIXMA MG5100 Series
+
+usb:v04A9p1749*
+ ID_MODEL_FROM_DATABASE=PIXMA MG5200 Series
+
+usb:v04A9p174A*
+ ID_MODEL_FROM_DATABASE=PIXMA MG6100 Series
+
+usb:v04A9p174B*
+ ID_MODEL_FROM_DATABASE=PIXMA MG8100 Series
 
 usb:v04A9p174D*
- ID_MODEL_FROM_DATABASE=MX360 ser
+ ID_MODEL_FROM_DATABASE=PIXMA MX360
+
+usb:v04A9p174E*
+ ID_MODEL_FROM_DATABASE=PIXMA MX410
+
+usb:v04A9p174F*
+ ID_MODEL_FROM_DATABASE=PIXMA MX420
+
+usb:v04A9p1750*
+ ID_MODEL_FROM_DATABASE=PIXMA MX880 Series
+
+usb:v04A9p1752*
+ ID_MODEL_FROM_DATABASE=PIXMA MG3100 Series
+
+usb:v04A9p1753*
+ ID_MODEL_FROM_DATABASE=PIXMA MG4100 Series
+
+usb:v04A9p1754*
+ ID_MODEL_FROM_DATABASE=PIXMA MG5300 Series
+
+usb:v04A9p1755*
+ ID_MODEL_FROM_DATABASE=PIXMA MG6200 Series
+
+usb:v04A9p1756*
+ ID_MODEL_FROM_DATABASE=PIXMA MG8200 Series
+
+usb:v04A9p1757*
+ ID_MODEL_FROM_DATABASE=PIXMA MP493
+
+usb:v04A9p1759*
+ ID_MODEL_FROM_DATABASE=PIXMA MX370 Series
+
+usb:v04A9p175B*
+ ID_MODEL_FROM_DATABASE=PIXMA MX430 Series
+
+usb:v04A9p175C*
+ ID_MODEL_FROM_DATABASE=PIXMA MX510 Series
+
+usb:v04A9p175D*
+ ID_MODEL_FROM_DATABASE=PIXMA MX710 Series
+
+usb:v04A9p175E*
+ ID_MODEL_FROM_DATABASE=PIXMA MX890 Series
+
+usb:v04A9p175F*
+ ID_MODEL_FROM_DATABASE=PIXMA MP230
+
+usb:v04A9p1762*
+ ID_MODEL_FROM_DATABASE=PIXMA MG3200 Series
+
+usb:v04A9p1763*
+ ID_MODEL_FROM_DATABASE=PIXMA MG4200 Series
+
+usb:v04A9p1764*
+ ID_MODEL_FROM_DATABASE=PIXMA MG5400 Series
+
+usb:v04A9p1765*
+ ID_MODEL_FROM_DATABASE=PIXMA MG6300 Series
+
+usb:v04A9p1766*
+ ID_MODEL_FROM_DATABASE=PIXMA MX390 Series
+
+usb:v04A9p1768*
+ ID_MODEL_FROM_DATABASE=PIXMA MX450 Series
+
+usb:v04A9p1769*
+ ID_MODEL_FROM_DATABASE=PIXMA MX520 Series
+
+usb:v04A9p176A*
+ ID_MODEL_FROM_DATABASE=PIXMA MX720 Series
+
+usb:v04A9p176B*
+ ID_MODEL_FROM_DATABASE=PIXMA MX920 Series
 
 usb:v04A9p176D*
- ID_MODEL_FROM_DATABASE=PIXMA MG2550
+ ID_MODEL_FROM_DATABASE=PIXMA MG2500 Series
+
+usb:v04A9p176E*
+ ID_MODEL_FROM_DATABASE=PIXMA MG3500 Series
+
+usb:v04A9p176F*
+ ID_MODEL_FROM_DATABASE=PIXMA MG6500 Series
+
+usb:v04A9p1770*
+ ID_MODEL_FROM_DATABASE=PIXMA MG6400 Series
+
+usb:v04A9p1771*
+ ID_MODEL_FROM_DATABASE=PIXMA MG5500 Series
+
+usb:v04A9p1772*
+ ID_MODEL_FROM_DATABASE=PIXMA MG7100 Series
+
+usb:v04A9p1774*
+ ID_MODEL_FROM_DATABASE=PIXMA MX470 Series
+
+usb:v04A9p1775*
+ ID_MODEL_FROM_DATABASE=PIXMA MX530 Series
+
+usb:v04A9p177C*
+ ID_MODEL_FROM_DATABASE=PIXMA MG7500 Series
+
+usb:v04A9p177E*
+ ID_MODEL_FROM_DATABASE=PIXMA MG6600 Series
+
+usb:v04A9p177F*
+ ID_MODEL_FROM_DATABASE=PIXMA MG5600 Series
+
+usb:v04A9p1780*
+ ID_MODEL_FROM_DATABASE=PIXMA MG2900 Series
+
+usb:v04A9p1787*
+ ID_MODEL_FROM_DATABASE=PIXMA MX490 Series
+
+usb:v04A9p178A*
+ ID_MODEL_FROM_DATABASE=PIXMA MG3600 Series
 
 usb:v04A9p178D*
  ID_MODEL_FROM_DATABASE=PIXMA MG6853
@@ -10773,10 +10998,10 @@ usb:v04A9p262D*
  ID_MODEL_FROM_DATABASE=iR C3200
 
 usb:v04A9p262F*
- ID_MODEL_FROM_DATABASE=MultiPASS MP730
+ ID_MODEL_FROM_DATABASE=PIXMA MP730
 
 usb:v04A9p2630*
- ID_MODEL_FROM_DATABASE=MultiPASS MP700
+ ID_MODEL_FROM_DATABASE=PIXMA MP700
 
 usb:v04A9p2631*
  ID_MODEL_FROM_DATABASE=LASER CLASS 700
@@ -10794,16 +11019,16 @@ usb:v04A9p2638*
  ID_MODEL_FROM_DATABASE=iR C3100
 
 usb:v04A9p263C*
- ID_MODEL_FROM_DATABASE=Smartbase MP360
+ ID_MODEL_FROM_DATABASE=PIXMA MP360
 
 usb:v04A9p263D*
- ID_MODEL_FROM_DATABASE=MP370
+ ID_MODEL_FROM_DATABASE=PIXMA MP370
 
 usb:v04A9p263E*
- ID_MODEL_FROM_DATABASE=MP390 FAX
+ ID_MODEL_FROM_DATABASE=PIXMA MP390
 
 usb:v04A9p263F*
- ID_MODEL_FROM_DATABASE=MP375
+ ID_MODEL_FROM_DATABASE=PIXMA MP375R
 
 usb:v04A9p2646*
  ID_MODEL_FROM_DATABASE=MF5530 Scanner Device V1.9.1
@@ -10811,6 +11036,9 @@ usb:v04A9p2646*
 usb:v04A9p2647*
  ID_MODEL_FROM_DATABASE=MF5550 Composite
 
+usb:v04A9p264C*
+ ID_MODEL_FROM_DATABASE=PIXMA MP740
+
 usb:v04A9p264D*
  ID_MODEL_FROM_DATABASE=PIXMA MP710
 
@@ -11831,6 +12059,9 @@ usb:v04A9p3278*
 usb:v04A9p327A*
  ID_MODEL_FROM_DATABASE=SELPHY CP910
 
+usb:v04A9p327B*
+ ID_MODEL_FROM_DATABASE=SELPHY CP820
+
 usb:v04A9p327D*
  ID_MODEL_FROM_DATABASE=Powershot ELPH 115 IS / IXUS 132
 
@@ -11903,12 +12134,18 @@ usb:v04A9p32B2*
 usb:v04A9p32BB*
  ID_MODEL_FROM_DATABASE=EOS M5
 
+usb:v04A9p32BF*
+ ID_MODEL_FROM_DATABASE=PowerShot SX420 IS
+
 usb:v04A9p32C1*
  ID_MODEL_FROM_DATABASE=PowerShot ELPH 180 / IXUS 175
 
 usb:v04A9p32C2*
  ID_MODEL_FROM_DATABASE=PowerShot SX720 HS
 
+usb:v04A9p32D5*
+ ID_MODEL_FROM_DATABASE=PowerShot SX430 IS
+
 usb:v04AA*
  ID_VENDOR_FROM_DATABASE=DaeWoo Telecom, Ltd
 
@@ -12137,6 +12374,9 @@ usb:v04B0p0429*
 usb:v04B0p042A*
  ID_MODEL_FROM_DATABASE=D800 (ptp)
 
+usb:v04B0p043F*
+ ID_MODEL_FROM_DATABASE=D5600
+
 usb:v04B0p0F03*
  ID_MODEL_FROM_DATABASE=PD-10 Wireless Printer Adapter
 
@@ -13871,6 +14111,9 @@ usb:v04D9p048E*
 usb:v04D9p0499*
  ID_MODEL_FROM_DATABASE=Optical Mouse
 
+usb:v04D9p1135*
+ ID_MODEL_FROM_DATABASE=Mouse [MGK-15BU/MLK-15BU]
+
 usb:v04D9p1203*
  ID_MODEL_FROM_DATABASE=Keyboard
 
@@ -13922,6 +14165,9 @@ usb:v04D9pA050*
 usb:v04D9pA055*
  ID_MODEL_FROM_DATABASE=Keyboard
 
+usb:v04D9pA100*
+ ID_MODEL_FROM_DATABASE=Mouse [HV-MS735]
+
 usb:v04D9pA11B*
  ID_MODEL_FROM_DATABASE=Mouse [MX-3200]
 
@@ -14033,6 +14279,9 @@ usb:v04DAp250D*
 usb:v04DAp3904*
  ID_MODEL_FROM_DATABASE=N5HBZ0000055 802.11abgn Wireless Adapter [Atheros AR7010+AR9280]
 
+usb:v04DAp3908*
+ ID_MODEL_FROM_DATABASE=N5HBZ0000062 802.11abgn Wireless Adapter [Atheros AR9374v1.1]
+
 usb:v04DAp3C04*
  ID_MODEL_FROM_DATABASE=JT-P100MR-20 [ePassport Reader]
 
@@ -14393,6 +14642,9 @@ usb:v04E6p5410*
 usb:v04E6p5591*
  ID_MODEL_FROM_DATABASE=SCL3711-NFC&RW
 
+usb:v04E6p5810*
+ ID_MODEL_FROM_DATABASE=uTrust 2700 R Smart Card Reader
+
 usb:v04E6pE000*
  ID_MODEL_FROM_DATABASE=SCRx31 Reader
 
@@ -14627,6 +14879,9 @@ usb:v04E8p3301*
 usb:v04E8p330C*
  ID_MODEL_FROM_DATABASE=ML-1865
 
+usb:v04E8p330F*
+ ID_MODEL_FROM_DATABASE=ML-216x Series Laser Printer
+
 usb:v04E8p3310*
  ID_MODEL_FROM_DATABASE=ML-331x Series Laser Printer
 
@@ -15443,6 +15698,9 @@ usb:v04F2pB354*
 usb:v04F2pB394*
  ID_MODEL_FROM_DATABASE=Integrated Camera
 
+usb:v04F2pB3EB*
+ ID_MODEL_FROM_DATABASE=HP 720p HD Monitor Webcam
+
 usb:v04F2pB3F6*
  ID_MODEL_FROM_DATABASE=HD WebCam (Acer)
 
@@ -18152,6 +18410,9 @@ usb:v0547p2810*
 usb:v0547p4D90*
  ID_MODEL_FROM_DATABASE=AmScope MD1900 camera
 
+usb:v0547p6010*
+ ID_MODEL_FROM_DATABASE=AmScope MU1000 camera
+
 usb:v0547p6510*
  ID_MODEL_FROM_DATABASE=Touptek UCMOS05100KPA
 
@@ -18401,6 +18662,9 @@ usb:v054Cp014D*
 usb:v054Cp0154*
  ID_MODEL_FROM_DATABASE=Eyetoy Audio Device
 
+usb:v054Cp0155*
+ ID_MODEL_FROM_DATABASE=Eyetoy Video Device
+
 usb:v054Cp015F*
  ID_MODEL_FROM_DATABASE=IC Recorder (BM)
 
@@ -18683,6 +18947,9 @@ usb:v054Cp0387*
 usb:v054Cp03BC*
  ID_MODEL_FROM_DATABASE=Webbie HD - MHS-CM1
 
+usb:v054Cp03CC*
+ ID_MODEL_FROM_DATABASE=SD Card Reader
+
 usb:v054Cp03D1*
  ID_MODEL_FROM_DATABASE=DPF-X95
 
@@ -18714,7 +18981,7 @@ usb:v054Cp0541*
  ID_MODEL_FROM_DATABASE=DSC-HX100V [Cybershot Digital Still Camera]
 
 usb:v054Cp05C4*
- ID_MODEL_FROM_DATABASE=DualShock 4
+ ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT1E]
 
 usb:v054Cp0689*
  ID_MODEL_FROM_DATABASE=Walkman NWZ-B173F
@@ -18740,6 +19007,9 @@ usb:v054Cp094E*
 usb:v054Cp0994*
  ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in charging mode
 
+usb:v054Cp09CC*
+ ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT2E]
+
 usb:v054Cp0BB5*
  ID_MODEL_FROM_DATABASE=Headset MDR-1000X
 
@@ -19622,6 +19892,24 @@ usb:v056Ap034D*
 usb:v056Ap034E*
  ID_MODEL_FROM_DATABASE=DTH-W1620 [MobileStudio Pro 16] tablet
 
+usb:v056Ap034F*
+ ID_MODEL_FROM_DATABASE=DTH-1320 [Cintiq Pro 13] tablet
+
+usb:v056Ap0350*
+ ID_MODEL_FROM_DATABASE=DTH-1620 [Cintiq Pro 16] tablet
+
+usb:v056Ap0353*
+ ID_MODEL_FROM_DATABASE=DTH-1320 [Cintiq Pro 13] touchscreen
+
+usb:v056Ap0354*
+ ID_MODEL_FROM_DATABASE=DTH-1620 [Cintiq Pro 16] touchscreen
+
+usb:v056Ap0357*
+ ID_MODEL_FROM_DATABASE=PTH-660 [Intuos Pro (M)]
+
+usb:v056Ap0358*
+ ID_MODEL_FROM_DATABASE=PTH-860 [Intuos Pro (L)]
+
 usb:v056Ap0400*
  ID_MODEL_FROM_DATABASE=PenPartner 4x5
 
@@ -20067,7 +20355,7 @@ usb:v057Cp2300*
  ID_MODEL_FROM_DATABASE=Teledat X130 DSL
 
 usb:v057Cp2800*
- ID_MODEL_FROM_DATABASE=ISDN-Connector TA
+ ID_MODEL_FROM_DATABASE=Teledat 2a/b / X120 / NetXXL ISDN Terminal Adapter
 
 usb:v057Cp3200*
  ID_MODEL_FROM_DATABASE=Teledat X130 DSL
@@ -20091,7 +20379,7 @@ usb:v057Cp3C00*
  ID_MODEL_FROM_DATABASE=FRITZ!Box WLAN
 
 usb:v057Cp3D00*
- ID_MODEL_FROM_DATABASE=Fritz!Box
+ ID_MODEL_FROM_DATABASE=FRITZ!Box Fon WLAN 7050/7140/7170/IAD3331
 
 usb:v057Cp3E01*
  ID_MODEL_FROM_DATABASE=FRITZ!Box (Annex A)
@@ -20153,6 +20441,12 @@ usb:v057Ep0305*
 usb:v057Ep0306*
  ID_MODEL_FROM_DATABASE=Wii Remote Controller RVL-003
 
+usb:v057Ep2006*
+ ID_MODEL_FROM_DATABASE=Joy-Con L
+
+usb:v057Ep2007*
+ ID_MODEL_FROM_DATABASE=Joy-Con R
+
 usb:v057F*
  ID_VENDOR_FROM_DATABASE=QuickShot, Ltd
 
@@ -21488,6 +21782,9 @@ usb:v059Fp0641*
 usb:v059Fp0829*
  ID_MODEL_FROM_DATABASE=BigDisk Extreme+
 
+usb:v059Fp1004*
+ ID_MODEL_FROM_DATABASE=Little Disk 20 GB
+
 usb:v059Fp100C*
  ID_MODEL_FROM_DATABASE=Rugged Triple Interface Mobile Hard Drive
 
@@ -21518,6 +21815,9 @@ usb:v059Fp1049*
 usb:v059Fp1052*
  ID_MODEL_FROM_DATABASE=P'9220 Mobile Drive
 
+usb:v059Fp1061*
+ ID_MODEL_FROM_DATABASE=Rugged USB3-FW
+
 usb:v059Fp1064*
  ID_MODEL_FROM_DATABASE=Rugged 16 and 32 GB
 
@@ -23387,6 +23687,9 @@ usb:v05DCpA813*
 usb:v05DCpA815*
  ID_MODEL_FROM_DATABASE=JumpDrive V10
 
+usb:v05DCpA81D*
+ ID_MODEL_FROM_DATABASE=LJDTT16G [JumpDrive 16GB]
+
 usb:v05DCpA833*
  ID_MODEL_FROM_DATABASE=JumpDrive S23 64GB
 
@@ -23876,6 +24179,9 @@ usb:v05FC*
 usb:v05FCp0001*
  ID_MODEL_FROM_DATABASE=Soundcraft Si Multi Digital Card
 
+usb:v05FCp0010*
+ ID_MODEL_FROM_DATABASE=Soundcraft Si MADI combo card
+
 usb:v05FCp7849*
  ID_MODEL_FROM_DATABASE=Harman/Kardon SoundSticks
 
@@ -24219,7 +24525,7 @@ usb:v0629*
  ID_VENDOR_FROM_DATABASE=Zida Technologies, Ltd
 
 usb:v062A*
- ID_VENDOR_FROM_DATABASE=Creative Labs
+ ID_VENDOR_FROM_DATABASE=MosArt Semiconductor Corp.
 
 usb:v062Ap0000*
  ID_MODEL_FROM_DATABASE=Optical mouse
@@ -24519,19 +24825,28 @@ usb:v064F*
  ID_VENDOR_FROM_DATABASE=WIBU-Systems AG
 
 usb:v064Fp03E9*
- ID_MODEL_FROM_DATABASE=CmStick (article no. 1001)
+ ID_MODEL_FROM_DATABASE=CmStick (MSD, article no. 1001-xx-xxx)
 
 usb:v064Fp03F2*
- ID_MODEL_FROM_DATABASE=CmStick/M (article no. 1010)
+ ID_MODEL_FROM_DATABASE=CmStick/M (MSD, article no. 1010-xx-xxx)
 
 usb:v064Fp03F3*
- ID_MODEL_FROM_DATABASE=CmStick/M (article no. 1011)
+ ID_MODEL_FROM_DATABASE=CmStick/M (MSD, article no. 1011-xx-xxx)
 
 usb:v064Fp0BD7*
- ID_MODEL_FROM_DATABASE=BOX/U
+ ID_MODEL_FROM_DATABASE=Wibu-Box/U (article no. 3031-xx-xxx)
 
 usb:v064Fp0BD8*
- ID_MODEL_FROM_DATABASE=BOX/RU
+ ID_MODEL_FROM_DATABASE=Wibu-Box/RU (article no. 3032-xx-xxx)
+
+usb:v064Fp2AF9*
+ ID_MODEL_FROM_DATABASE=CmStick (HID, article no. 1001-xx-xxx)
+
+usb:v064Fp2B03*
+ ID_MODEL_FROM_DATABASE=CmStick/M (HID, article no. 1011-xx-xxx)
+
+usb:v064Fp5213*
+ ID_MODEL_FROM_DATABASE=CmStick/M (COMPOSITE, article no. 1011-xx-xxx)
 
 usb:v0650*
  ID_VENDOR_FROM_DATABASE=Dynapro Systems
@@ -26384,6 +26699,9 @@ usb:v06D3p0393*
 usb:v06D3p0394*
  ID_MODEL_FROM_DATABASE=CP9000D/DW Port
 
+usb:v06D3p0398*
+ ID_MODEL_FROM_DATABASE=P93D
+
 usb:v06D3p03A1*
  ID_MODEL_FROM_DATABASE=CP9550D/DW Port
 
@@ -26397,7 +26715,7 @@ usb:v06D3p03AA*
  ID_MODEL_FROM_DATABASE=CP3020DA
 
 usb:v06D3p03AD*
- ID_MODEL_FROM_DATABASE=CP-9800DW-S
+ ID_MODEL_FROM_DATABASE=CP-9800D/DW
 
 usb:v06D3p03AE*
  ID_MODEL_FROM_DATABASE=CP-9800DW-S
@@ -26405,12 +26723,24 @@ usb:v06D3p03AE*
 usb:v06D3p3B10*
  ID_MODEL_FROM_DATABASE=P95D
 
+usb:v06D3p3B21*
+ ID_MODEL_FROM_DATABASE=CP-9810D/DW
+
 usb:v06D3p3B30*
  ID_MODEL_FROM_DATABASE=CP-D70DW / CP-D707DW
 
 usb:v06D3p3B31*
  ID_MODEL_FROM_DATABASE=CP-K60DW-S
 
+usb:v06D3p3B36*
+ ID_MODEL_FROM_DATABASE=CP-D80DW
+
+usb:v06D3p3B50*
+ ID_MODEL_FROM_DATABASE=CP-W5000DW
+
+usb:v06D3p3B60*
+ ID_MODEL_FROM_DATABASE=CP-D90DW
+
 usb:v06D4*
  ID_VENDOR_FROM_DATABASE=Cisco Systems
 
@@ -27173,6 +27503,12 @@ usb:v071Dp2000*
 usb:v071E*
  ID_VENDOR_FROM_DATABASE=Ariston Technologies
 
+usb:v0720*
+ ID_VENDOR_FROM_DATABASE=Keyence Corp.
+
+usb:v0720p8001*
+ ID_MODEL_FROM_DATABASE=LJ-V7001
+
 usb:v0723*
  ID_VENDOR_FROM_DATABASE=Centillium Communications Corp.
 
@@ -27605,6 +27941,9 @@ usb:v0755*
 usb:v0757*
  ID_VENDOR_FROM_DATABASE=Network Technologies, Inc.
 
+usb:v0758*
+ ID_VENDOR_FROM_DATABASE=Carl Zeiss Microscopy GmbH
+
 usb:v075B*
  ID_VENDOR_FROM_DATABASE=Sophisticated Circuits, Inc.
 
@@ -27612,7 +27951,7 @@ usb:v075Bp0001*
  ID_MODEL_FROM_DATABASE=Kick-off! Watchdog
 
 usb:v0763*
- ID_VENDOR_FROM_DATABASE=Midiman
+ ID_VENDOR_FROM_DATABASE=M-Audio
 
 usb:v0763p0115*
  ID_MODEL_FROM_DATABASE=O2 / KeyRig 25
@@ -29073,7 +29412,7 @@ usb:v07B8p5301*
  ID_MODEL_FROM_DATABASE=GW-US54ZGL 802.11bg
 
 usb:v07B8p6001*
- ID_MODEL_FROM_DATABASE=802.11bg
+ ID_MODEL_FROM_DATABASE=WUG2690 802.11bg Wireless Module [ZyDAS ZD1211+AL2230]
 
 usb:v07B8p8188*
  ID_MODEL_FROM_DATABASE=AboCom Systems Inc [WN2001 Prolink Wireless-N Nano Adapter]
@@ -30083,6 +30422,9 @@ usb:v0810p0002*
 usb:v0810p0003*
  ID_MODEL_FROM_DATABASE=PlayStation Gamepad
 
+usb:v0810pE001*
+ ID_MODEL_FROM_DATABASE=Twin controller
+
 usb:v0810pE501*
  ID_MODEL_FROM_DATABASE=SNES Gamepad
 
@@ -30611,6 +30953,9 @@ usb:v0846p9043*
 usb:v0846p9050*
  ID_MODEL_FROM_DATABASE=A6200 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526]
 
+usb:v0846p9051*
+ ID_MODEL_FROM_DATABASE=A6200v2 802.11a/b/g/n/ac (2x2) Wireless Adapter [Realtek RTL8812AU]
+
 usb:v0846p9052*
  ID_MODEL_FROM_DATABASE=A6100 AC600 DB Wireless Adapter [Realtek RTL8811AU]
 
@@ -31043,9 +31388,18 @@ usb:v0894p0010*
 usb:v0897*
  ID_VENDOR_FROM_DATABASE=Lauterbach
 
+usb:v0897p0001*
+ ID_MODEL_FROM_DATABASE=ICE In-Circuit Emulator
+
 usb:v0897p0002*
  ID_MODEL_FROM_DATABASE=Power Debug/Power Debug II
 
+usb:v0897p0004*
+ ID_MODEL_FROM_DATABASE=PowerDebug
+
+usb:v0897p0005*
+ ID_MODEL_FROM_DATABASE=PowerDebug PRO
+
 usb:v089C*
  ID_VENDOR_FROM_DATABASE=United Technologies Research Cntr.
 
@@ -32012,6 +32366,12 @@ usb:v0908p04B1*
 usb:v0908p04B2*
  ID_MODEL_FROM_DATABASE=NC interface
 
+usb:v0908p04B3*
+ ID_MODEL_FROM_DATABASE=keyboard front panel Cockpit
+
+usb:v0908p04B4*
+ ID_MODEL_FROM_DATABASE=SCR_CCID
+
 usb:v0908p2701*
  ID_MODEL_FROM_DATABASE=ShenZhen SANZHAI Technology Co.,Ltd Spy Pen VGA
 
@@ -32519,6 +32879,9 @@ usb:v0930p0A07*
 usb:v0930p0A08*
  ID_MODEL_FROM_DATABASE=WLM-20U2/GN-1080 802.11abgn Wireless Adapter [Atheros AR7010+AR9280]
 
+usb:v0930p0A0B*
+ ID_MODEL_FROM_DATABASE=WLU5053 802.11abgn Wireless Module [Broadcom BCM43236B]
+
 usb:v0930p0A13*
  ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [Toshiba]
 
@@ -32999,6 +33362,9 @@ usb:v0951p1625*
 usb:v0951p162A*
  ID_MODEL_FROM_DATABASE=DataTraveler 112 4GB Pen Drive
 
+usb:v0951p162B*
+ ID_MODEL_FROM_DATABASE=DataTraveler HyperX 3.0
+
 usb:v0951p162D*
  ID_MODEL_FROM_DATABASE=DataTraveler 102
 
@@ -33039,22 +33405,34 @@ usb:v0954*
  ID_VENDOR_FROM_DATABASE=RPM Systems Corp.
 
 usb:v0955*
- ID_VENDOR_FROM_DATABASE=NVidia Corp.
+ ID_VENDOR_FROM_DATABASE=NVIDIA Corp.
 
 usb:v0955p7018*
- ID_MODEL_FROM_DATABASE=APX
+ ID_MODEL_FROM_DATABASE=T186 [Tegra Parker]
+
+usb:v0955p701A*
+ ID_MODEL_FROM_DATABASE=U-Boot running on Tegra
+
+usb:v0955p7020*
+ ID_MODEL_FROM_DATABASE=L4T (Linux for Tegra) running on Tegra
 
 usb:v0955p7030*
- ID_MODEL_FROM_DATABASE=Tegra 3 (recovery mode)
+ ID_MODEL_FROM_DATABASE=T30 [Tegra 3] recovery mode
 
 usb:v0955p7100*
  ID_MODEL_FROM_DATABASE=Tegra Device
 
+usb:v0955p7140*
+ ID_MODEL_FROM_DATABASE=T124 [Tegra K1/Logan 32-bit]
+
 usb:v0955p7210*
  ID_MODEL_FROM_DATABASE=SHIELD Controller
 
+usb:v0955p7721*
+ ID_MODEL_FROM_DATABASE=T210 [Tegra Erista]
+
 usb:v0955p7820*
- ID_MODEL_FROM_DATABASE=Tegra 2 AC100 developer mode
+ ID_MODEL_FROM_DATABASE=T20 [Tegra 2] recovery mode
 
 usb:v0955pB400*
  ID_MODEL_FROM_DATABASE=SHIELD (debug)
@@ -33137,6 +33515,9 @@ usb:v095D*
 usb:v095Dp0001*
  ID_MODEL_FROM_DATABASE=Polycom ViaVideo
 
+usb:v0964*
+ ID_VENDOR_FROM_DATABASE=BITRAN
+
 usb:v0967*
  ID_VENDOR_FROM_DATABASE=Acer NeWeb Corp.
 
@@ -34428,7 +34809,10 @@ usb:v0A5Cp6410*
  ID_MODEL_FROM_DATABASE=BCM20703A1 Bluetooth 4.1 + LE
 
 usb:v0A5CpBD11*
- ID_MODEL_FROM_DATABASE=TiVo AG0100 802.11bg Wireless Adapter [Broadcom BCM4320]
+ ID_MODEL_FROM_DATABASE=BCM4320 802.11bg Wireless Adapter
+
+usb:v0A5CpBD12*
+ ID_MODEL_FROM_DATABASE=BCM4326U 802.11bg Wireless Adapter
 
 usb:v0A5CpBD13*
  ID_MODEL_FROM_DATABASE=BCM4323 802.11abgn Wireless Adapter
@@ -34439,6 +34823,15 @@ usb:v0A5CpBD16*
 usb:v0A5CpBD17*
  ID_MODEL_FROM_DATABASE=BCM43236 802.11abgn Wireless Adapter
 
+usb:v0A5CpBD1D*
+ ID_MODEL_FROM_DATABASE=BCM43526 802.11a/b/g/n/ac (2x2) Wireless Adapter
+
+usb:v0A5CpBD1E*
+ ID_MODEL_FROM_DATABASE=BCM43143 802.11bgn (1x1) Wireless Adapter
+
+usb:v0A5CpBD1F*
+ ID_MODEL_FROM_DATABASE=BCM43242 802.11abgn Wireless Adapter
+
 usb:v0A5CpD11B*
  ID_MODEL_FROM_DATABASE=Eminent EM4045 [Broadcom 4320 USB]
 
@@ -35366,6 +35759,9 @@ usb:v0B05*
 usb:v0B05p0001*
  ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (CD-ROM mode)
 
+usb:v0B05p0301*
+ ID_MODEL_FROM_DATABASE=MyPal A696 GPS PDA
+
 usb:v0B05p1101*
  ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC4S)
 
@@ -35382,7 +35778,7 @@ usb:v0B05p170B*
  ID_MODEL_FROM_DATABASE=Multi card reader
 
 usb:v0B05p170C*
- ID_MODEL_FROM_DATABASE=WL-159g 802.11bg
+ ID_MODEL_FROM_DATABASE=WL-159g 802.11bg [ZyDAS ZD1211B+AL2230]
 
 usb:v0B05p170D*
  ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter
@@ -35418,7 +35814,7 @@ usb:v0B05p1726*
  ID_MODEL_FROM_DATABASE=Laptop OLED Display
 
 usb:v0B05p172A*
- ID_MODEL_FROM_DATABASE=ASUS 802.11n Network Adapter
+ ID_MODEL_FROM_DATABASE=802.11n Network Adapter
 
 usb:v0B05p172B*
  ID_MODEL_FROM_DATABASE=802.11n Network Adapter
@@ -35430,7 +35826,7 @@ usb:v0B05p1732*
  ID_MODEL_FROM_DATABASE=802.11n Network Adapter
 
 usb:v0B05p1734*
- ID_MODEL_FROM_DATABASE=ASUS AF-200
+ ID_MODEL_FROM_DATABASE=AF-200
 
 usb:v0B05p173C*
  ID_MODEL_FROM_DATABASE=BT-183 Bluetooth 2.0
@@ -35508,11 +35904,29 @@ usb:v0B05p17CB*
  ID_MODEL_FROM_DATABASE=Broadcom BCM20702A0 Bluetooth
 
 usb:v0B05p17D1*
- ID_MODEL_FROM_DATABASE=AC51 802.11a/b/g/n/ac Wireless Adapter [Mediatek MT7610/Ralink RT2870]
+ ID_MODEL_FROM_DATABASE=AC51 802.11a/b/g/n/ac Wireless Adapter [Mediatek MT7610U]
+
+usb:v0B05p17D2*
+ ID_MODEL_FROM_DATABASE=USB-AC56 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU]
+
+usb:v0B05p17D3*
+ ID_MODEL_FROM_DATABASE=USB-N10 v2 802.11b/g/n Wireless Adapter [MediaTek MT7601U]
+
+usb:v0B05p17DB*
+ ID_MODEL_FROM_DATABASE=USB-AC50 802.11a/b/g/n/ac (1x1) Wireless Adapter [MediaTek MT7610U]
+
+usb:v0B05p17E8*
+ ID_MODEL_FROM_DATABASE=USB-N14 802.11b/g/n (2x2) Wireless Adapter [Ralink RT5372]
+
+usb:v0B05p17EB*
+ ID_MODEL_FROM_DATABASE=USB-AC55 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7612U]
 
 usb:v0B05p180A*
  ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Single-Chip Bluetooth 4.0 + LE
 
+usb:v0B05p1817*
+ ID_MODEL_FROM_DATABASE=USB-AC68 802.11a/b/g/n/ac (4x4) Wireless Adapter [Realtek RTL8814AU]
+
 usb:v0B05p1825*
  ID_MODEL_FROM_DATABASE=Qualcomm Bluetooth 4.1
 
@@ -35556,22 +35970,22 @@ usb:v0B05p620A*
  ID_MODEL_FROM_DATABASE=Remote NDIS Device
 
 usb:v0B05p7772*
- ID_MODEL_FROM_DATABASE=ASUS Zenfone GO (ZB500KL) (MTP mode)
+ ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (MTP mode)
 
 usb:v0B05p7773*
- ID_MODEL_FROM_DATABASE=ASUS Zenfone GO (ZB500KL) (Debug, MTP mode)
+ ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (Debug, MTP mode)
 
 usb:v0B05p7774*
- ID_MODEL_FROM_DATABASE=ASUS Zenfone GO (ZB500KL) (RNDIS mode)
+ ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (RNDIS mode)
 
 usb:v0B05p7775*
- ID_MODEL_FROM_DATABASE=ASUS Zenfone GO (ZB500KL) (Debug, RNDIS mode)
+ ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (Debug, RNDIS mode)
 
 usb:v0B05p7776*
- ID_MODEL_FROM_DATABASE=ASUS Zenfone GO (ZB500KL) (PTP mode)
+ ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (PTP mode)
 
 usb:v0B05p7777*
- ID_MODEL_FROM_DATABASE=ASUS Zenfone GO (ZB500KL) (Debug, PTP mode)
+ ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (Debug, PTP mode)
 
 usb:v0B05pB700*
  ID_MODEL_FROM_DATABASE=Broadcom Bluetooth 2.1
@@ -35702,6 +36116,9 @@ usb:v0B33p0020*
 usb:v0B33p0030*
  ID_MODEL_FROM_DATABASE=ShuttlePro v2
 
+usb:v0B33p0401*
+ ID_MODEL_FROM_DATABASE=RollerMouse Free 2
+
 usb:v0B33p0700*
  ID_MODEL_FROM_DATABASE=RollerMouse Pro
 
@@ -36935,6 +37352,9 @@ usb:v0BC2p3312*
 usb:v0BC2p3320*
  ID_MODEL_FROM_DATABASE=SRD00F2 [Expansion Desktop Drive]
 
+usb:v0BC2p3322*
+ ID_MODEL_FROM_DATABASE=SRD0NF2 [Expansion Desktop Drive]
+
 usb:v0BC2p3332*
  ID_MODEL_FROM_DATABASE=Expansion
 
@@ -36971,6 +37391,12 @@ usb:v0BC2p5121*
 usb:v0BC2p5161*
  ID_MODEL_FROM_DATABASE=FreeAgent GoFlex dock
 
+usb:v0BC2p6126*
+ ID_MODEL_FROM_DATABASE=Maxtor D3 Station 5TB
+
+usb:v0BC2p61B6*
+ ID_MODEL_FROM_DATABASE=Maxtor HX-M101TCB/GM [M3 Portable 1TB]
+
 usb:v0BC2p61B7*
  ID_MODEL_FROM_DATABASE=Maxtor M3 Portable
 
@@ -36986,6 +37412,9 @@ usb:v0BC2pA0A4*
 usb:v0BC2pAB00*
  ID_MODEL_FROM_DATABASE=Slim Portable Drive
 
+usb:v0BC2pAB1E*
+ ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive
+
 usb:v0BC2pAB20*
  ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive
 
@@ -36995,6 +37424,9 @@ usb:v0BC2pAB21*
 usb:v0BC2pAB24*
  ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive
 
+usb:v0BC2pAB26*
+ ID_MODEL_FROM_DATABASE=Backup Plus Slim Portable Drive 1 TB
+
 usb:v0BC2pAB31*
  ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive (5TB)
 
@@ -37190,6 +37622,9 @@ usb:v0BDAp0301*
 usb:v0BDAp0307*
  ID_MODEL_FROM_DATABASE=Card Reader
 
+usb:v0BDAp0326*
+ ID_MODEL_FROM_DATABASE=Card reader
+
 usb:v0BDAp1724*
  ID_MODEL_FROM_DATABASE=RTL8723AU 802.11n WLAN Adapter
 
@@ -37223,6 +37658,9 @@ usb:v0BDAp57B3*
 usb:v0BDAp57DA*
  ID_MODEL_FROM_DATABASE=Built-In Video Camera
 
+usb:v0BDAp58C8*
+ ID_MODEL_FROM_DATABASE=Integrated Webcam HD
+
 usb:v0BDAp8150*
  ID_MODEL_FROM_DATABASE=RTL8150 Fast Ethernet Adapter
 
@@ -37263,7 +37701,7 @@ usb:v0BDAp8189*
  ID_MODEL_FROM_DATABASE=RTL8187B Wireless 802.11g 54Mbps Network Adapter
 
 usb:v0BDAp818B*
- ID_MODEL_FROM_DATABASE=ACT-WNP-UA-005 802.11b/g/n WLAN Adapter
+ ID_MODEL_FROM_DATABASE=RTL8192EU 802.11b/g/n WLAN Adapter
 
 usb:v0BDAp8192*
  ID_MODEL_FROM_DATABASE=RTL8191SU 802.11n Wireless Adapter
@@ -37281,7 +37719,13 @@ usb:v0BDAp8199*
  ID_MODEL_FROM_DATABASE=RTL8187SU 802.11g WLAN Adapter
 
 usb:v0BDAp8812*
- ID_MODEL_FROM_DATABASE=RTL8812AU 802.11a/b/g/n/ac WLAN Adapter
+ ID_MODEL_FROM_DATABASE=RTL8812AU 802.11a/b/g/n/ac 2T2R DB WLAN Adapter
+
+usb:v0BDAp8813*
+ ID_MODEL_FROM_DATABASE=RTL8814AU 802.11a/b/g/n/ac Wireless Adapter
+
+usb:v0BDApA811*
+ ID_MODEL_FROM_DATABASE=RTL8811AU 802.11a/b/g/n/ac WLAN Adapter
 
 usb:v0BDB*
  ID_VENDOR_FROM_DATABASE=Ericsson Business Mobile Networks BV
@@ -37682,6 +38126,12 @@ usb:v0C2Ep0B6A*
 usb:v0C2Ep0B81*
  ID_MODEL_FROM_DATABASE=Barcode scanner Voyager 1400g Series
 
+usb:v0C30*
+ ID_VENDOR_FROM_DATABASE=Mutoh Industries Ltd
+
+usb:v0C30p6010*
+ ID_MODEL_FROM_DATABASE=Kona 1400 Cutting Plotter
+
 usb:v0C35*
  ID_VENDOR_FROM_DATABASE=Eagletron, Inc.
 
@@ -38126,6 +38576,9 @@ usb:v0C45p6419*
 usb:v0C45p641D*
  ID_MODEL_FROM_DATABASE=1.3 MPixel Integrated Webcam
 
+usb:v0C45p6433*
+ ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam HD (Composite Device)
+
 usb:v0C45p643F*
  ID_MODEL_FROM_DATABASE=Dell Integrated HD Webcam
 
@@ -38672,6 +39125,9 @@ usb:v0CAD*
 usb:v0CADp1007*
  ID_MODEL_FROM_DATABASE=APX Series Consolette
 
+usb:v0CADp1020*
+ ID_MODEL_FROM_DATABASE=MOTOTRBO Series Radio (Portable)
+
 usb:v0CADp1030*
  ID_MODEL_FROM_DATABASE=APX Series Radio (Portable)
 
@@ -39309,7 +39765,7 @@ usb:v0D28*
  ID_VENDOR_FROM_DATABASE=NXP
 
 usb:v0D28p0204*
- ID_MODEL_FROM_DATABASE=LPC1768
+ ID_MODEL_FROM_DATABASE=ARM mbed
 
 usb:v0D32*
  ID_VENDOR_FROM_DATABASE=Leo Hui Electric Wire & Cable Co., Ltd
@@ -39371,6 +39827,9 @@ usb:v0D46p2012*
 usb:v0D46p3003*
  ID_MODEL_FROM_DATABASE=mIDentity Light / KAAN SIM III
 
+usb:v0D46p3014*
+ ID_MODEL_FROM_DATABASE=Smart Token
+
 usb:v0D46p4000*
  ID_MODEL_FROM_DATABASE=mIDentity (mass storage)
 
@@ -39593,6 +40052,9 @@ usb:v0D64p3105*
 usb:v0D64p3108*
  ID_MODEL_FROM_DATABASE=Digicam Mass Storage Device
 
+usb:v0D64p5566*
+ ID_MODEL_FROM_DATABASE=Contour Roam Model 1600
+
 usb:v0D65*
  ID_VENDOR_FROM_DATABASE=KMJP Co., Ltd
 
@@ -39749,6 +40211,9 @@ usb:v0D8Cp0002*
 usb:v0D8Cp0003*
  ID_MODEL_FROM_DATABASE=Sound Device
 
+usb:v0D8Cp0005*
+ ID_MODEL_FROM_DATABASE=Blue Snowball
+
 usb:v0D8Cp0006*
  ID_MODEL_FROM_DATABASE=Storm HP-USB500 5.1 Headset
 
@@ -40088,6 +40553,12 @@ usb:v0DB0p3713*
 usb:v0DB0p3801*
  ID_MODEL_FROM_DATABASE=Motorola Bluetooth 2.1+EDR Device
 
+usb:v0DB0p3870*
+ ID_MODEL_FROM_DATABASE=MS-3870 802.11bgn Wireless Module [Ralink RT3070]
+
+usb:v0DB0p3871*
+ ID_MODEL_FROM_DATABASE=MS-3871 802.11bgn Wireless Module [Ralink RT8070]
+
 usb:v0DB0p4011*
  ID_MODEL_FROM_DATABASE=Medion Flash XL V2.0 Card Reader
 
@@ -40949,6 +41420,9 @@ usb:v0E4Cp7288*
 usb:v0E50*
  ID_VENDOR_FROM_DATABASE=TechnoData Interware
 
+usb:v0E50p0001*
+ ID_MODEL_FROM_DATABASE=Matrix USB-Key
+
 usb:v0E50p0002*
  ID_MODEL_FROM_DATABASE=Matrixlock Dongle (HID)
 
@@ -41048,6 +41522,9 @@ usb:v0E6Ap030C*
 usb:v0E6Ap6001*
  ID_MODEL_FROM_DATABASE=GEMBIRD Flexible keyboard KB-109F-B-DE
 
+usb:v0E6Ap7F5C*
+ ID_MODEL_FROM_DATABASE=BPF-015 Key Chain Photo Frame
+
 usb:v0E6F*
  ID_VENDOR_FROM_DATABASE=Logic3
 
@@ -41183,6 +41660,9 @@ usb:v0E8Fp0022*
 usb:v0E8Fp0201*
  ID_MODEL_FROM_DATABASE=SmartJoy Frag Xpad/PS2 adaptor
 
+usb:v0E8Fp300A*
+ ID_MODEL_FROM_DATABASE=steering Wheel
+
 usb:v0E90*
  ID_VENDOR_FROM_DATABASE=WiebeTech, LLC
 
@@ -43226,6 +43706,21 @@ usb:v1058p259D*
 usb:v1058p259F*
  ID_MODEL_FROM_DATABASE=My Passport Ultra (WD10JMVW)
 
+usb:v1058p25A1*
+ ID_MODEL_FROM_DATABASE=Elements / My Passport (WD20NMVW)
+
+usb:v1058p25A2*
+ ID_MODEL_FROM_DATABASE=Elements 25A2
+
+usb:v1058p25A3*
+ ID_MODEL_FROM_DATABASE=Elements Desktop (WDBWLG)
+
+usb:v1058p25E2*
+ ID_MODEL_FROM_DATABASE=My Passport (WD40NMZW)
+
+usb:v1058p30A0*
+ ID_MODEL_FROM_DATABASE=SATA adapter cable
+
 usb:v1059*
  ID_VENDOR_FROM_DATABASE=Giesecke & Devrient GmbH
 
@@ -43271,6 +43766,12 @@ usb:v1065p0020*
 usb:v1065p2136*
  ID_MODEL_FROM_DATABASE=EasyDisk ED1064
 
+usb:v1068*
+ ID_VENDOR_FROM_DATABASE=Micropi Elettronica
+
+usb:v1068p0001*
+ ID_MODEL_FROM_DATABASE=CPUSB - V 1.8 - software-rights management key
+
 usb:v106A*
  ID_VENDOR_FROM_DATABASE=Loyal Legend, Ltd
 
@@ -43541,12 +44042,99 @@ usb:v1082*
 usb:v1083*
  ID_VENDOR_FROM_DATABASE=Canon Electronics, Inc.
 
+usb:v1083p160C*
+ ID_MODEL_FROM_DATABASE=CR-55
+
+usb:v1083p160F*
+ ID_MODEL_FROM_DATABASE=DR-1210C
+
+usb:v1083p1614*
+ ID_MODEL_FROM_DATABASE=DR-4010C
+
+usb:v1083p1617*
+ ID_MODEL_FROM_DATABASE=DR-2510C
+
+usb:v1083p1618*
+ ID_MODEL_FROM_DATABASE=DR-X10C
+
+usb:v1083p161A*
+ ID_MODEL_FROM_DATABASE=CR-25
+
 usb:v1083p161B*
  ID_MODEL_FROM_DATABASE=DR-2010C Scanner
 
+usb:v1083p161D*
+ ID_MODEL_FROM_DATABASE=DR-3010C
+
+usb:v1083p1620*
+ ID_MODEL_FROM_DATABASE=DR-7090C
+
+usb:v1083p1622*
+ ID_MODEL_FROM_DATABASE=DR-9050C
+
+usb:v1083p1623*
+ ID_MODEL_FROM_DATABASE=DR-7550C
+
+usb:v1083p1624*
+ ID_MODEL_FROM_DATABASE=DR-6050C
+
+usb:v1083p1626*
+ ID_MODEL_FROM_DATABASE=DR-6010C
+
 usb:v1083p162C*
  ID_MODEL_FROM_DATABASE=P-150 Scanner
 
+usb:v1083p1638*
+ ID_MODEL_FROM_DATABASE=DR-6030C
+
+usb:v1083p1639*
+ ID_MODEL_FROM_DATABASE=CR-135i
+
+usb:v1083p163E*
+ ID_MODEL_FROM_DATABASE=DR-M160
+
+usb:v1083p163F*
+ ID_MODEL_FROM_DATABASE=DR-M140
+
+usb:v1083p1640*
+ ID_MODEL_FROM_DATABASE=DR-C125
+
+usb:v1083p1641*
+ ID_MODEL_FROM_DATABASE=DR-P215
+
+usb:v1083p1648*
+ ID_MODEL_FROM_DATABASE=FSU-201
+
+usb:v1083p164A*
+ ID_MODEL_FROM_DATABASE=DR-C130
+
+usb:v1083p164B*
+ ID_MODEL_FROM_DATABASE=DR-P208
+
+usb:v1083p164F*
+ ID_MODEL_FROM_DATABASE=DR-G1130
+
+usb:v1083p1650*
+ ID_MODEL_FROM_DATABASE=DR-G1100
+
+usb:v1083p1651*
+ ID_MODEL_FROM_DATABASE=DR-C120
+
+usb:v1083p1654*
+ ID_MODEL_FROM_DATABASE=DR-F120
+
+usb:v1083p1657*
+ ID_MODEL_FROM_DATABASE=DR-M1060
+
+usb:v1083p1658*
+ ID_MODEL_FROM_DATABASE=DR-C225
+
+usb:v1083p1659*
+ ID_MODEL_FROM_DATABASE=DR-P215II
+
+usb:v1083p165D*
+ ID_MODEL_FROM_DATABASE=DR-P208II
+
 usb:v1084*
  ID_VENDOR_FROM_DATABASE=Pantech Co., Ltd
 
@@ -43565,6 +44153,12 @@ usb:v108C*
 usb:v108E*
  ID_VENDOR_FROM_DATABASE=Lotes Co., Ltd.
 
+usb:v1091*
+ ID_VENDOR_FROM_DATABASE=Numerik Jena
+
+usb:v1091p8101*
+ ID_MODEL_FROM_DATABASE=Absoflex
+
 usb:v1099*
  ID_VENDOR_FROM_DATABASE=Surface Optics Corp.
 
@@ -43764,16 +44358,16 @@ usb:v10B8*
  ID_VENDOR_FROM_DATABASE=DiBcom
 
 usb:v10B8p0BB8*
- ID_MODEL_FROM_DATABASE=DiBcom USB DVB-T reference design (MOD300) (cold)
+ ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD300) (cold)
 
 usb:v10B8p0BB9*
- ID_MODEL_FROM_DATABASE=DiBcom USB DVB-T reference design (MOD300) (warm)
+ ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD300) (warm)
 
 usb:v10B8p0BC6*
- ID_MODEL_FROM_DATABASE=DiBcom USB2.0 DVB-T reference design (MOD3000P) (cold)
+ ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD3000P) (cold)
 
 usb:v10B8p0BC7*
- ID_MODEL_FROM_DATABASE=DiBcom USB2.0 DVB-T reference design (MOD3000P) (warm)
+ ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD3000P) (warm)
 
 usb:v10BB*
  ID_VENDOR_FROM_DATABASE=TM Technology, Inc.
@@ -43811,6 +44405,12 @@ usb:v10C4p0002*
 usb:v10C4p0003*
  ID_MODEL_FROM_DATABASE=CommandIR
 
+usb:v10C4p800A*
+ ID_MODEL_FROM_DATABASE=SPORTident
+
+usb:v10C4p800B*
+ ID_MODEL_FROM_DATABASE=AES
+
 usb:v10C4p8030*
  ID_MODEL_FROM_DATABASE=K4JRG Ham Radio devices
 
@@ -43823,6 +44423,9 @@ usb:v10C4p804E*
 usb:v10C4p80A9*
  ID_MODEL_FROM_DATABASE=CP210x to UART Bridge Controller
 
+usb:v10C4p80C4*
+ ID_MODEL_FROM_DATABASE=Infrared Thermometer Adapter
+
 usb:v10C4p80CA*
  ID_MODEL_FROM_DATABASE=ATM2400 Sensor Device
 
@@ -43844,12 +44447,21 @@ usb:v10C4p818A*
 usb:v10C4p81E8*
  ID_MODEL_FROM_DATABASE=Zephyr BioHarness
 
+usb:v10C4p834B*
+ ID_MODEL_FROM_DATABASE=Infrared Online Sensor Adapter
+
+usb:v10C4p834E*
+ ID_MODEL_FROM_DATABASE=Infrared Sensor Adapter
+
 usb:v10C4p8460*
  ID_MODEL_FROM_DATABASE=Sangoma Wanpipe VoiceTime
 
 usb:v10C4p8461*
  ID_MODEL_FROM_DATABASE=Sangoma U100
 
+usb:v10C4p8470*
+ ID_MODEL_FROM_DATABASE=Juniper Networks BX Series System Console
+
 usb:v10C4p8477*
  ID_MODEL_FROM_DATABASE=Balluff RFID Reader
 
@@ -43859,9 +44471,18 @@ usb:v10C4p8496*
 usb:v10C4p8497*
  ID_MODEL_FROM_DATABASE=SiLabs Cypress EVB
 
+usb:v10C4p84FB*
+ ID_MODEL_FROM_DATABASE=Infrared Blackbody Adapter
+
+usb:v10C4p8508*
+ ID_MODEL_FROM_DATABASE=RS485 Adapter
+
 usb:v10C4p8605*
  ID_MODEL_FROM_DATABASE=dilitronics ESoLUX solar lighting controller
 
+usb:v10C4p8660*
+ ID_MODEL_FROM_DATABASE=Netronics CANdoISO
+
 usb:v10C4p86BC*
  ID_MODEL_FROM_DATABASE=C8051F34x AudioDelay [AD-340]
 
@@ -43877,17 +44498,23 @@ usb:v10C4p8863*
 usb:v10C4p8897*
  ID_MODEL_FROM_DATABASE=C8051F38x HDMI Splitter [UHBX]
 
+usb:v10C4p88C9*
+ ID_MODEL_FROM_DATABASE=AES HID device
+
 usb:v10C4p8918*
  ID_MODEL_FROM_DATABASE=C8051F38x HDMI Audio Extractor [VSA-HA-DP]
 
 usb:v10C4p8973*
  ID_MODEL_FROM_DATABASE=C8051F38x HDMI Extender [UHBX-8X]
 
+usb:v10C4p89C6*
+ ID_MODEL_FROM_DATABASE=SPORTident HID device
+
 usb:v10C4p89E1*
  ID_MODEL_FROM_DATABASE=C8051F38x HDMI Extender [UHBX-SW3-WP]
 
 usb:v10C4pEA60*
- ID_MODEL_FROM_DATABASE=CP210x UART Bridge / myAVR mySmartUSB light
+ ID_MODEL_FROM_DATABASE=CP2102/CP2109 UART Bridge Controller [CP210x family]
 
 usb:v10C4pEA61*
  ID_MODEL_FROM_DATABASE=CP210x UART Bridge
@@ -43898,6 +44525,12 @@ usb:v10C4pEA70*
 usb:v10C4pEA80*
  ID_MODEL_FROM_DATABASE=CP210x UART Bridge
 
+usb:v10C4pEAC9*
+ ID_MODEL_FROM_DATABASE=EFM8UB1 Bootloader
+
+usb:v10C4pEACA*
+ ID_MODEL_FROM_DATABASE=EFM8UB2 Bootloader
+
 usb:v10C5*
  ID_VENDOR_FROM_DATABASE=Sanei Electric, Inc.
 
@@ -43922,9 +44555,21 @@ usb:v10CD*
 usb:v10CE*
  ID_VENDOR_FROM_DATABASE=Silicon Labs
 
+usb:v10CEp0007*
+ ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S1245
+
 usb:v10CEp000E*
  ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S2145
 
+usb:v10CEp0019*
+ ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S6145
+
+usb:v10CEp001D*
+ ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S6245
+
+usb:v10CEp001E*
+ ID_MODEL_FROM_DATABASE=Ciaat Brava 21
+
 usb:v10CEpEA6A*
  ID_MODEL_FROM_DATABASE=MobiData EDGE USB Modem
 
@@ -44048,6 +44693,9 @@ usb:v10F1p1A1E*
 usb:v10F1p1A2A*
  ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam
 
+usb:v10F1p1A2E*
+ ID_MODEL_FROM_DATABASE=HP Truevision HD Integrated Webcam
+
 usb:v10F5*
  ID_VENDOR_FROM_DATABASE=Turtle Beach
 
@@ -44213,6 +44861,9 @@ usb:v1130p6604*
 usb:v1130p660C*
  ID_MODEL_FROM_DATABASE=Foot Pedal/Thermometer
 
+usb:v1130p6626*
+ ID_MODEL_FROM_DATABASE=Key
+
 usb:v1130p6806*
  ID_MODEL_FROM_DATABASE=Keychain photo frame
 
@@ -44273,6 +44924,15 @@ usb:v113C*
 usb:v113D*
  ID_VENDOR_FROM_DATABASE=Mapower Electronics Co., Ltd
 
+usb:v113F*
+ ID_VENDOR_FROM_DATABASE=Integrated Biometrics, LLC
+
+usb:v113Fp1020*
+ ID_MODEL_FROM_DATABASE=Watson Two-Finger Roll Scanner
+
+usb:v113Fp1100*
+ ID_MODEL_FROM_DATABASE=Columbo Single-Finger Scanner
+
 usb:v1141*
  ID_VENDOR_FROM_DATABASE=V One Multimedia, Pte., Ltd
 
@@ -44573,6 +45233,9 @@ usb:v1199p9009*
 usb:v1199p900A*
  ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem
 
+usb:v1199p9013*
+ ID_MODEL_FROM_DATABASE=Sierra Wireless Gobi 3000 Modem device (MC8355)
+
 usb:v1199p9055*
  ID_MODEL_FROM_DATABASE=Gobi 9x15 Multimode 3G/4G LTE Modem (NAT mode)
 
@@ -44630,6 +45293,12 @@ usb:v11BE*
 usb:v11BEpF0A0*
  ID_MODEL_FROM_DATABASE=Martin Maxxyz DMX
 
+usb:v11C0*
+ ID_VENDOR_FROM_DATABASE=Betop
+
+usb:v11C0p5506*
+ ID_MODEL_FROM_DATABASE=Gamepad
+
 usb:v11C5*
  ID_VENDOR_FROM_DATABASE=Inmax
 
@@ -44717,6 +45386,9 @@ usb:v1209p1005*
 usb:v1209p1006*
  ID_MODEL_FROM_DATABASE=Mini IO-Board
 
+usb:v1209p1AB5*
+ ID_MODEL_FROM_DATABASE=Arachnid Labs Tsunami
+
 usb:v1209p2000*
  ID_MODEL_FROM_DATABASE=Zygmunt Krynicki Lantern Brightness Sensor
 
@@ -44732,6 +45404,12 @@ usb:v1209p2300*
 usb:v1209p2301*
  ID_MODEL_FROM_DATABASE=Keyboardio Keyboardio Model 01
 
+usb:v1209p2327*
+ ID_MODEL_FROM_DATABASE=K.T.E.C.Bootloader Device
+
+usb:v1209p2328*
+ ID_MODEL_FROM_DATABASE=K.T.E.C. Keyboard Device
+
 usb:v1209p2337*
  ID_MODEL_FROM_DATABASE=/Dev or SlashDev /Net
 
@@ -44744,15 +45422,33 @@ usb:v1209p3333*
 usb:v1209p5222*
  ID_MODEL_FROM_DATABASE=telavivmakers attami
 
+usb:v1209p53C0*
+ ID_MODEL_FROM_DATABASE=SatoshiLabs TREZOR Bootloader
+
+usb:v1209p53C1*
+ ID_MODEL_FROM_DATABASE=SatoshiLabs TREZOR
+
 usb:v1209p5A22*
  ID_MODEL_FROM_DATABASE=ikari_01 sd2snes
 
+usb:v1209p7530*
+ ID_MODEL_FROM_DATABASE=Refflion - IoT Board - Bootloader
+
+usb:v1209p7531*
+ ID_MODEL_FROM_DATABASE=Refflion - IoT Board - Sketch
+
 usb:v1209p7BD0*
  ID_MODEL_FROM_DATABASE=pokey9000 Tiny Bit Dingus
 
 usb:v1209pABD0*
  ID_MODEL_FROM_DATABASE=tibounise ADB converter
 
+usb:v1209pACED*
+ ID_MODEL_FROM_DATABASE=Open Lighting Project - Ja Rule Device
+
+usb:v1209pACEE*
+ ID_MODEL_FROM_DATABASE=Open Lighting Project - Ja Rule Bootloader
+
 usb:v1209pBEEF*
  ID_MODEL_FROM_DATABASE=Modal MC-USB
 
@@ -44810,6 +45506,21 @@ usb:v121E*
 usb:v121Ep3403*
  ID_MODEL_FROM_DATABASE=Muzio JM250 Audio Player
 
+usb:v1220*
+ ID_VENDOR_FROM_DATABASE=TC Electronic
+
+usb:v1220p000A*
+ ID_MODEL_FROM_DATABASE=Hall of Fame Reverb
+
+usb:v1220p002A*
+ ID_MODEL_FROM_DATABASE=Polytune
+
+usb:v1220p0032*
+ ID_MODEL_FROM_DATABASE=Ditto X2 Looper
+
+usb:v1220p0039*
+ ID_MODEL_FROM_DATABASE=Alter Ego X4 Vintage Echo
+
 usb:v1221*
  ID_VENDOR_FROM_DATABASE=Unknown manufacturer
 
@@ -44960,6 +45671,15 @@ usb:v1235p8012*
 usb:v1235p8014*
  ID_MODEL_FROM_DATABASE=Scarlett 18i8
 
+usb:v1235p8016*
+ ID_MODEL_FROM_DATABASE=Focusrite Scarlett 2i2
+
+usb:v1235p8203*
+ ID_MODEL_FROM_DATABASE=Focusrite Scarlett 6i6
+
+usb:v1235p8204*
+ ID_MODEL_FROM_DATABASE=Scarlett 18i8 2nd Gen
+
 usb:v1241*
  ID_VENDOR_FROM_DATABASE=Belkin
 
@@ -45056,6 +45776,9 @@ usb:v125FpC96A*
 usb:v125FpCB10*
  ID_MODEL_FROM_DATABASE=Dash Drive UV100
 
+usb:v125FpCB20*
+ ID_MODEL_FROM_DATABASE=DashDrive UV110
+
 usb:v1260*
  ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp.
 
@@ -45078,7 +45801,7 @@ usb:v1267p0103*
  ID_MODEL_FROM_DATABASE=G-720 Keyboard
 
 usb:v1267p0201*
- ID_MODEL_FROM_DATABASE=A4Tech SWOP-3 Mouse
+ ID_MODEL_FROM_DATABASE=Mouse
 
 usb:v1267p0210*
  ID_MODEL_FROM_DATABASE=LG Optical Mouse 3D-310
@@ -45227,6 +45950,9 @@ usb:v1286p2001*
 usb:v1286p2006*
  ID_MODEL_FROM_DATABASE=88W8362 802.11n WLAN
 
+usb:v1286p203C*
+ ID_MODEL_FROM_DATABASE=K30326 802.11bgn Wireless Module [Marvell 88W8786U]
+
 usb:v1286p8001*
  ID_MODEL_FROM_DATABASE=BLOB boot loader firmware
 
@@ -45245,6 +45971,9 @@ usb:v1292*
 usb:v1292p0258*
  ID_MODEL_FROM_DATABASE=Creative Labs VoIP Blaster
 
+usb:v1292p4154*
+ ID_MODEL_FROM_DATABASE=Retro Link Atari cable
+
 usb:v1293*
  ID_VENDOR_FROM_DATABASE=Belkin Components [hex]
 
@@ -45260,6 +45989,12 @@ usb:v1294*
 usb:v1294p1320*
  ID_MODEL_FROM_DATABASE=Webmail Notifier
 
+usb:v1297*
+ ID_VENDOR_FROM_DATABASE=DekTec
+
+usb:v1297p020F*
+ ID_MODEL_FROM_DATABASE=DTU-215 Multi-Standard Modulator
+
 usb:v129B*
  ID_VENDOR_FROM_DATABASE=CyberTAN Technology
 
@@ -45293,6 +46028,12 @@ usb:v12B9*
 usb:v12BA*
  ID_VENDOR_FROM_DATABASE=Licensed by Sony Computer Entertainment America
 
+usb:v12BAp0032*
+ ID_MODEL_FROM_DATABASE=Wireless Stereo Headset
+
+usb:v12BAp0042*
+ ID_MODEL_FROM_DATABASE=Wireless Stereo Headset
+
 usb:v12BAp00FF*
  ID_MODEL_FROM_DATABASE=Rocksmith Guitar Adapter
 
@@ -45314,6 +46055,9 @@ usb:v12BD*
 usb:v12BDpD012*
  ID_MODEL_FROM_DATABASE=JPD Shockforce gamepad
 
+usb:v12BDpD015*
+ ID_MODEL_FROM_DATABASE=Generic 4-button NES USB Controller
+
 usb:v12C4*
  ID_VENDOR_FROM_DATABASE=Autocue Group Ltd
 
@@ -45329,11 +46073,14 @@ usb:v12CF*
 usb:v12CFp0170*
  ID_MODEL_FROM_DATABASE=Tt eSPORTS BLACK Gaming mouse
 
+usb:v12CFp600B*
+ ID_MODEL_FROM_DATABASE=Cougar 600M Gaming Mouse
+
 usb:v12D1*
  ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Ltd.
 
 usb:v12D1p1001*
- ID_MODEL_FROM_DATABASE=E169/E620/E800 HSDPA Modem
+ ID_MODEL_FROM_DATABASE=E161/E169/E620/E800 HSDPA Modem
 
 usb:v12D1p1003*
  ID_MODEL_FROM_DATABASE=E220 HSDPA Modem / E230/E270/E870 HSDPA/HSUPA Modem
@@ -45362,6 +46109,9 @@ usb:v12D1p1038*
 usb:v12D1p1039*
  ID_MODEL_FROM_DATABASE=Ideos (tethering mode)
 
+usb:v12D1p1052*
+ ID_MODEL_FROM_DATABASE=MT7-L09
+
 usb:v12D1p1404*
  ID_MODEL_FROM_DATABASE=EM770W miniPCI WCDMA Modem
 
@@ -45381,11 +46131,14 @@ usb:v12D1p1436*
  ID_MODEL_FROM_DATABASE=Broadband stick
 
 usb:v12D1p1446*
- ID_MODEL_FROM_DATABASE=Broadband stick (modem on)
+ ID_MODEL_FROM_DATABASE=HSPA modem
 
 usb:v12D1p1465*
  ID_MODEL_FROM_DATABASE=K3765 HSPA
 
+usb:v12D1p14AC*
+ ID_MODEL_FROM_DATABASE=E815
+
 usb:v12D1p14C3*
  ID_MODEL_FROM_DATABASE=K5005 Vodafone LTE/UMTS/GSM Modem/Networkcard
 
@@ -45494,6 +46247,12 @@ usb:v12EF*
 usb:v12EFp0100*
  ID_MODEL_FROM_DATABASE=Tapwave Handheld [Tapwave Zodiac]
 
+usb:v12F2*
+ ID_VENDOR_FROM_DATABASE=ViewPlus Technologies, Inc.
+
+usb:v12F2p000A*
+ ID_MODEL_FROM_DATABASE=Braille embosser [SpotDot Emprint]
+
 usb:v12F5*
  ID_VENDOR_FROM_DATABASE=Dynamic System Electronics Corp.
 
@@ -45531,7 +46290,7 @@ usb:v1307p0190*
  ID_MODEL_FROM_DATABASE=Ut190 8 GB Flash Drive with MicroSD reader
 
 usb:v1307p0310*
- ID_MODEL_FROM_DATABASE=SD/MicroSD CardReader [hama]
+ ID_MODEL_FROM_DATABASE=SD/MicroSD CardReader [hama]/IT1327E [Basic Line flash drive]
 
 usb:v1307p0330*
  ID_MODEL_FROM_DATABASE=63-in-1 Multi-Card Reader/Writer
@@ -45614,6 +46373,15 @@ usb:v1313p8030*
 usb:v1313p8070*
  ID_MODEL_FROM_DATABASE=PM100D
 
+usb:v1313p8072*
+ ID_MODEL_FROM_DATABASE=PM100USB Power and Energy Meter Interface
+
+usb:v1313p8078*
+ ID_MODEL_FROM_DATABASE=PM100D Compact Power and Energy Meter Console
+
+usb:v1313p8080*
+ ID_MODEL_FROM_DATABASE=CCS100 - Compact Spectrometer
+
 usb:v131D*
  ID_VENDOR_FROM_DATABASE=Natural Point
 
@@ -45623,6 +46391,12 @@ usb:v131Dp0155*
 usb:v131Dp0156*
  ID_MODEL_FROM_DATABASE=TrackIR 4 Pro Head Tracker
 
+usb:v131Dp0158*
+ ID_MODEL_FROM_DATABASE=TrackIR 5 Pro Head Tracker
+
+usb:v1325*
+ ID_VENDOR_FROM_DATABASE=ams AG
+
 usb:v132A*
  ID_VENDOR_FROM_DATABASE=Envara Inc.
 
index fd9078393bca88b983b3599a93a1ec443a3b42e7..4f01d88c350357c356f955137f2c6a8cb77917ed 100644 (file)
@@ -115,6 +115,13 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pn?550C?:*
  EVDEV_ABS_35=::31
  EVDEV_ABS_36=::30
 
+# Asus UX301L
+evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX301LAA:*
+ EVDEV_ABS_00=::30
+ EVDEV_ABS_01=::29
+ EVDEV_ABS_35=::30
+ EVDEV_ABS_36=::29
+
 # Asus UX305
 evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX305UA:*
  EVDEV_ABS_00=0:3097:32
@@ -152,6 +159,13 @@ evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLati
  EVDEV_ABS_35=79:1841:22
  EVDEV_ABS_36=140:1325:29
 
+# Dell Latitude E7470
+evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*
+ EVDEV_ABS_00=39:5856:59
+ EVDEV_ABS_01=10:1532:29
+ EVDEV_ABS_35=39:5856:59
+ EVDEV_ABS_36=10:1532:29
+
 # Dell Precision 5510
 evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnPrecision5510*
  EVDEV_ABS_00=::42
@@ -178,6 +192,15 @@ evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPSM1530*
  EVDEV_ABS_00=85:947:15
  EVDEV_ABS_01=154:726:18
 
+#####
+# Sun
+#####
+
+# Fujitsu Component - USB Touch Panel
+evdev:input:b0003v0430p0530*
+ EVDEV_ABS_00=0:4096:16
+ EVDEV_ABS_01=0:4096:16
+
 #########################################
 # Google
 #########################################
@@ -268,6 +291,20 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon4th*
  EVDEV_ABS_35=1262:5679:44
  EVDEV_ABS_36=1101:4824:65
 
+# Lenovo Thinkpad Carbon X1 5th gen.
+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th*
+ EVDEV_ABS_00=::44
+ EVDEV_ABS_01=::65
+ EVDEV_ABS_35=::44
+ EVDEV_ABS_36=::65
+
+# Lenovo Thinkpad Carbon X1 5th gen. (rmi4)
+evdev:name:Synaptics TM3289-002:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th*
+ EVDEV_ABS_00=::19
+ EVDEV_ABS_01=::19
+ EVDEV_ABS_35=::19
+ EVDEV_ABS_36=::19
+
 # Lenovo T460
 evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T460*
  EVDEV_ABS_00=1266:5677:44
@@ -338,6 +375,13 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/
  EVDEV_ABS_35=0:2480:28
  EVDEV_ABS_36=0:1116:24
 
+# Samsung 880Z5E
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E*
+ EVDEV_ABS_00=::30
+ EVDEV_ABS_01=::29
+ EVDEV_ABS_35=::30
+ EVDEV_ABS_36=::29
+
 #########################################
 # Toshiba
 #########################################
@@ -346,3 +390,12 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/
 evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnTOSHIBA:pnTECRAM11*
  EVDEV_ABS_00=90:962:11
  EVDEV_ABS_01=51:681:14
+
+#########################################
+# Waltop
+#########################################
+
+# WALTOP International Corp. Slim Tablet
+evdev:input:b0003v172Fp0031*
+ EVDEV_ABS_00=0:10000:400
+ EVDEV_ABS_01=0:6250:400
index 1aa729f04797379f6c74367dff94af5a6d59f1b0..881a531b67b8229363055b97f8797c015a07066c 100644 (file)
@@ -1,7 +1,14 @@
 # This file is part of systemd.
 #
-# Keyboard mapping of scan codes to key codes, and
-# scan codes to add to the AT keyboard's 'force-release' list.
+# This file contains 3 types of metadata to apply to keyboards and
+# keyboard-like input devices:
+# - Key mapping
+# - Hard-coded layouts
+# - Absence of modifier LEDs
+#
+# The matching process is the same for the different types of metadata.
+#
+# ########################### MATCHING #######################################
 #
 # The lookup keys are composed in:
 #   60-evdev.rules
 #    /sys/class/input/input?/capabilities/ev" and <vendor> is the
 #    firmware-provided string exported by the kernel DMI modalias,
 #    see /sys/class/dmi/id/modalias
+
+
+# ######################### KEY MAPPING ######################################
+#
+# Keyboard mapping of scan codes to key codes, and
+# scan codes to add to the AT keyboard's 'force-release' list.
 #
 # Scan codes are specified as:
 #   KEYBOARD_KEY_<hex scan code>=<key code identifier>
 # The scan code should be expressed in hex lowercase. The key codes
 # are retrieved and normalized from the kernel input API header.
+# Keycodes are either KEY_* defines in lowercase with the key_ prefix
+# optionally removed or BTN_ defines in lowercase with btn_ preserved.
 #
 # An '!' as the first character of the key identifier string
 # will add the scan code to the AT keyboard's list of scan codes
@@ -67,7 +82,8 @@
 #   systemd-hwdb update
 #   udevadm trigger /dev/input/eventXX
 # where /dev/input/eventXX is the keyboard in question. If in
-# doubt, simply use /dev/input/event* to reload all input rules.
+# doubt, simply reload all input rules
+#   udevadm trigger --verbose --sysname-match="event*"
 #
 # If your changes are generally applicable, preferably send them as a pull
 # request to
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr*
+ KEYBOARD_KEY_86=wlan                                   # Fn+F3 or Fn+Q for comunication key
  KEYBOARD_KEY_a5=help                                   # Fn+F1
  KEYBOARD_KEY_a6=setup                                  # Fn+F2 Acer eSettings
  KEYBOARD_KEY_a7=battery                                # Fn+F3 Power Management
@@ -105,6 +122,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr*
  KEYBOARD_KEY_f3=prog2                                  # "P2" programmable button
  KEYBOARD_KEY_f4=prog1                                  # "P1" programmable button
  KEYBOARD_KEY_f5=presentation
+ KEYBOARD_KEY_f6=power                                  # Power button
  KEYBOARD_KEY_f8=fn
  KEYBOARD_KEY_f9=prog1                                  # Launch NTI shadow
 
@@ -144,6 +162,10 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr*
  KEYBOARD_KEY_6b=fn
  KEYBOARD_KEY_6c=screenlock                             # FIXME: lock tablet device/buttons
 
+# Travelmate P648-G2-MG
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G2-MG*:pvr*
+ KEYBOARD_KEY_8a=f20                                    # Microphone mute button; should be micmute
+
 # on some models this isn't brightnessup
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5210*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5220*:pvr*
@@ -158,6 +180,10 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1640:*
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:pvr*
  KEYBOARD_KEY_a9=!switchvideomode                       # Fn+F5
 
+# Easynote models
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pnEasynote*:pvr*
+ KEYBOARD_KEY_86=wlan                                   # Fn+F3 or Fn+Q for comunication key
+
 ###########################################################
 # Alienware
 ###########################################################
@@ -222,7 +248,7 @@ evdev:input:b0003v049Fp0051*
 ###########################################################
 
 evdev:name:gpio-keys:phys:gpio-keys/input0:ev:3:dmi:bvn*:bvr*:bd*:svncube:pni1-TF:*
- KEYBOARD_KEY_0=home
+ KEYBOARD_KEY_0=leftmeta
  KEYBOARD_KEY_1=power
 
 ###########################################################
@@ -291,6 +317,10 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:pvr*
  KEYBOARD_KEY_88=!                                      # wireless switch
  KEYBOARD_KEY_9e=!f21
 
+# Dell Latitude E7*
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*E7*:pvr*
+ KEYBOARD_KEY_88=unknown                                # Fn-PrtScr rfkill - handled in HW
+
 # Dell XPS
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS*:pvr*
  KEYBOARD_KEY_8c=!unknown
@@ -831,6 +861,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:pvr*
 ###########################################################
 
 # Akoya
+evdev:atkbd:dmi:bvn*:bvr*:svnMEDION*:pnS3409*:pvr*
 evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnAkoya*:pvr*
  KEYBOARD_KEY_a0=!mute
  KEYBOARD_KEY_ae=!volumedown
@@ -1274,9 +1305,13 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDIXONSP:pnDIXON*:pvr*
  KEYBOARD_KEY_ae=!                                      # volume down
  KEYBOARD_KEY_b0=!                                      # volume up
 
-###########################################################
-# Fixed layout devices
-###########################################################
+######################### FIXED LAYOUT DEVICES #############################
+# This section lists devices for which only one keyboard layout is possible
+# or useful such as devices which "type" expecting the user's keymap to match
+# a particular one. For example, barcode readers and OTP keys.
+#
+# The layout must be an xkb compatible layout (defined with XKB_FIXED_LAYOUT),
+# with an accompanying variant (defined with XKB_FIXED_VARIANT) if necessary.
 
 # Yubico Yubico Yubikey II"
 evdev:input:b0003v1050p0010*
@@ -1288,3 +1323,16 @@ evdev:input:b0003v1050p0116*
 evdev:input:b0003v05FEp1010*
  XKB_FIXED_LAYOUT="us"
  XKB_FIXED_VARIANT=""
+
+######################### LACK OF MODIFIER LEDS ############################
+# This section lists keyboard which do not have their own LEDs for some
+# modifiers. Only Caps-Lock (KEYBOARD_LED_CAPSLOCK) and Num-Lock
+# (KEYBOARD_LED_CAPSLOCK) are currently handled and need their values set
+# to "0" to indicate the absence of LED.
+#
+# Presence of a LED is implicit when the property is absent.
+
+# Logitech K750
+evdev:input:b0003v046Dp4002*
+ KEYBOARD_LED_NUMLOCK=0
+ KEYBOARD_LED_CAPSLOCK=0
index fcbdcabf30f3e2c31282b96009c0a2712c45da28..dab22dc643bedfc150a094bcffae73202e5aef0d 100644 (file)
 sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 0
 
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LJ*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+
+#########################################
+# Endless
+#########################################
+sensor:modalias:acpi:ACCE0001*:dmi:*svnEndless*:*pnELT-NL3*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 0, 0, -1; -1, 0, 0
+
+#########################################
+# HP
+#########################################
+sensor:modalias:platform:lis3lv02d:dmi:*svn*Hewlett-Packard*:*pn*HPEliteBook8540w*
+sensor:modalias:platform:lis3lv02d:dmi:*svn*Hewlett-Packard*:*pn*HPEliteBook8560w*
+  ACCEL_MOUNT_MATRIX=1, 0, 0; 0, 0, -1; 0, 1, 0
+
 #########################################
 # Winbook
 #########################################
 sensor:modalias:acpi:BMA250*:dmi:*svn*WinBook*:*pn*TW100*
  ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 0
+
+#########################################
+# Cytrix (Mytrix)
+#########################################
+sensor:modalias:acpi:*KIOX000A*:dmi:*svn*CytrixTechnology:*pn*Complex11t*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
diff --git a/hwdb/70-joystick.hwdb b/hwdb/70-joystick.hwdb
new file mode 100644 (file)
index 0000000..9d5c4fc
--- /dev/null
@@ -0,0 +1,50 @@
+# This file is part of systemd.
+#
+# Database for joystick device information that cannot be queried directly.
+#
+# The lookup keys are composed in:
+#   70-joystick.rules
+#
+# Note: The format of the "joystick:" 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:
+# joystick:<bustype>:v<vid>p<pid>:name:<name>:
+#
+# vid/pid as 4-digit hex lowercase vendor/product
+#
+# To add local entries, create a new file
+#   /etc/udev/hwdb.d/71-joystick-local.hwdb
+# and add your rules there. To load the new rules execute (as root):
+#   systemd-hwdb update
+#   udevadm trigger /dev/input/eventXX
+# where /dev/input/eventXX is the joystick in question. If in
+# doubt, simply use /dev/input/event* to reload all input rules.
+#
+# If your changes are generally applicable, preferably send them as a pull
+# request to
+#   https://github.com/systemd/systemd
+# or create a bug report on https://github.com/systemd/systemd/issues and
+# include your new rules, a description of the device, and the output of
+#   udevadm info /dev/input/eventXX.
+#
+# Permitted keys:
+#   Specify if a joystick is a built-in one or external:
+#   ID_INPUT_JOYSTICK_INTEGRATION=internal|external
+#
+#   If the property is missing, user-space can assume:
+#   ID_INPUT_JOYSTICK_INTEGRATION=external
+
+joystick:bluetooth:*
+ ID_INPUT_JOYSTICK_INTEGRATION=external
+
+###########################################################
+# GPD
+###########################################################
+
+# GPD Win, Classic and XBox 360 compat modes
+joystick:usb:v11c5p5507*
+joystick:usb:v045ep028e*
+ ID_INPUT_JOYSTICK_INTEGRATION=internal
index 772534f4958f9f9bd81f9f7e97a69fe12332ebe1..d5cccb9bdbedec9998eafe7f4b9e1c51770e2081 100644 (file)
@@ -213,6 +213,14 @@ mouse:usb:v0461p4d46:name:USB Optical Mouse:
 mouse:usb:v0461p4d16:name:USB Optical Mouse:
  MOUSE_DPI=500@125
 
+##########################################
+# Future Technology Devices International
+##########################################
+
+# SNES Mouse plugged into a Retrode 2
+mouse:usb:v0403p97c1:name:Retrode SNES Mouse:
+ MOUSE_DPI=235@126
+
 ##########################################
 # HandShoe Mouse
 ##########################################
@@ -243,6 +251,14 @@ mouse:usb:v093ap2510:name:PixArt USB Optical Mouse:
 mouse:usb:v093ap2510:name:PIXART USB OPTICAL MOUSE:
  MOUSE_DPI=1000@125
 
+##########################################
+# IBM
+##########################################
+
+# IBM USB Travel Mouse (MO32BO)
+mouse:usb:v04b3p3107:name:*
+ MOUSE_DPI=800@125
+
 ##########################################
 # Lenovo
 ##########################################
index 65c87aeac71c36c8c2374e32521cdf0aa9433137..f1a86ff20bb3ac3b899d36bf5bfb88430ceb3a93 100644 (file)
@@ -126,10 +126,16 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Ta
  POINTINGSTICK_SENSITIVITY=200
  POINTINGSTICK_CONST_ACCEL=1.0
 
-# Lenovo Thinkpad X200s / X201s
+# Lenovo Thinkpad X200/X201/X200s/X201s
 # Note these come with 2 revisions of keyboard, with the trackpoints having a
 # different sensitivity in the different revisions. 1.25 is a bit slow for the
 # least sensitive revision, but it is better to be a bit slow than too fast.
-evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20?s:*
+evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20?:*
+evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20??:*
  POINTINGSTICK_SENSITIVITY=200
  POINTINGSTICK_CONST_ACCEL=1.25
+
+# Lenovo UltraNav SK-8845 (USB keyboard)
+evdev:input:b0003v06CBp0009*
+ POINTINGSTICK_CONST_ACCEL=2.5
+ POINTINGSTICK_SENSITIVITY=200
index 82a4b7a575ed9b9131474c2637618ab8356a70fc..12d97de69b2043052f39d69879a2c8274ab7467a 100644 (file)
@@ -53,3 +53,10 @@ touchpad:usb:v05ac*
 ###########################################################
 touchpad:usb:v056a*
  ID_INPUT_TOUCHPAD_INTEGRATION=external
+
+###########################################################
+# Microsoft (Surface Type Covers)
+###########################################################
+touchpad:usb:v045ep07*
+ ID_INPUT_TOUCHPAD_INTEGRATION=internal
index 50da531dc659de9d189a9f9deae0caa2c14c722e..2c23b057fb2c43d9d286f2547c002b7c259c087f 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 
 from html.parser import HTMLParser
 from enum import Enum
diff --git a/hwdb/meson.build b/hwdb/meson.build
new file mode 100644 (file)
index 0000000..74a93f9
--- /dev/null
@@ -0,0 +1,43 @@
+hwdb_files = files('''
+        20-pci-vendor-model.hwdb
+        20-pci-classes.hwdb
+        20-usb-vendor-model.hwdb
+        20-usb-classes.hwdb
+        20-sdio-vendor-model.hwdb
+        20-sdio-classes.hwdb
+        20-bluetooth-vendor-product.hwdb
+        20-acpi-vendor.hwdb
+        20-OUI.hwdb
+        20-net-ifname.hwdb
+        60-evdev.hwdb
+        60-keyboard.hwdb
+        60-sensor.hwdb
+        70-mouse.hwdb
+        70-pointingstick.hwdb
+        70-touchpad.hwdb
+'''.split())
+
+if conf.get('ENABLE_HWDB', false)
+        install_data(hwdb_files,
+                     install_dir : udevhwdbdir)
+
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format(join_paths(sysconfdir, 'udev/hwdb.d')))
+
+        meson.add_install_script('sh', '-c',
+                                 'test -n "$DESTDIR" || @0@/systemd-hwdb update'
+                                 .format(rootbindir))
+endif
+
+############################################################
+
+parse_hwdb_py = find_program('parse_hwdb.py')
+test('parse-hwdb',
+     parse_hwdb_py,
+     timeout : 90)
+
+############################################################
+
+run_target(
+        'update',
+        command : [hwdb_update_sh, meson.current_source_dir()])
index b57e6f75aa2160ab58601e3b22a732b2df308ada..c7b49b83df66ac32cff6f39b695ed8abd581b21c 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 # This file is part of systemd. It is distrubuted under the MIT license, see
@@ -66,6 +66,7 @@ UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
 TYPES = {'mouse':    ('usb', 'bluetooth', 'ps2', '*'),
          'evdev':    ('name', 'atkbd', 'input'),
          'touchpad': ('i8042', 'rmi', 'bluetooth', 'usb'),
+         'joystick': ('i8042', 'rmi', 'bluetooth', 'usb'),
          'keyboard': ('name', ),
          'sensor':   ('modalias', ),
         }
@@ -109,9 +110,12 @@ def property_grammar():
              ('MOUSE_WHEEL_TILT_VERTICAL', Literal('1')),
              ('POINTINGSTICK_SENSITIVITY', INTEGER),
              ('POINTINGSTICK_CONST_ACCEL', REAL),
+             ('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))),
              ('ID_INPUT_TOUCHPAD_INTEGRATION', Or(('internal', 'external'))),
              ('XKB_FIXED_LAYOUT', STRING),
              ('XKB_FIXED_VARIANT', STRING),
+             ('KEYBOARD_LED_NUMLOCK', Literal('0')),
+             ('KEYBOARD_LED_CAPSLOCK', Literal('0')),
              ('ACCEL_MOUNT_MATRIX', mount_matrix),
             )
     fixed_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE')
@@ -168,7 +172,9 @@ def check_one_keycode(prop, value):
     if value != '!' and ecodes is not None:
         key = 'KEY_' + value.upper()
         if key not in ecodes:
-            error('Keycode {} unknown', key)
+            key = value.upper()
+            if key not in ecodes:
+                error('Keycode {} unknown', key)
 
 def check_properties(groups):
     grammar = property_grammar()
index c6ff32210f6753034e6f18715da471ba20c15631..7537d5e915812194c8c5b7b45b75cd3b19b19532 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 
 """
 
diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in
new file mode 100644 (file)
index 0000000..0257c2a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!ENTITY MOUNT_PATH @MOUNT_PATH@>
+<!ENTITY UMOUNT_PATH @UMOUNT_PATH@>
+<!ENTITY systemgeneratordir @SYSTEM_GENERATOR_PATH@>
+<!ENTITY usergeneratordir @USER_GENERATOR_PATH@>
+<!ENTITY systemenvgeneratordir @SYSTEM_ENV_GENERATOR_PATH@>
+<!ENTITY userenvgeneratordir @USER_ENV_GENERATOR_PATH@>
index be7758a2f92d05b3a136428cf1c2bf5c062c3399..ad9db1666f40266b1ca2ebc2c00c225eb9c5bebc 100644 (file)
@@ -20,7 +20,8 @@
   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="environment.d" xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="environment.d" conditional='ENABLE_ENVIRONMENT_D'
+    xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
     <title>environment.d</title>
         <programlisting>
         FOO_DEBUG=force-software-gl,log-verbose
         PATH=/opt/foo/bin:$PATH
-        LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}/opt/foo/lib
+        LD_LIBRARY_PATH=/opt/foo/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
         XDG_DATA_DIRS=/opt/foo/share:${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}
         </programlisting>
       </example>
index cae5312db25e2876ee488c93eb359411eb53826c..444b9160735043155643e0e5d5d153fd2e1aae97 100644 (file)
 
             <varlistentry>
               <term>
-                <option>short-precise</option>
+                <option>short-iso-precise</option>
               </term>
               <listitem>
-                <para>is very similar, but shows timestamps with full
+                <para>as for <option>short-iso</option> but includes full
                 microsecond precision.</para>
               </listitem>
             </varlistentry>
 
+            <varlistentry>
+              <term>
+                <option>short-precise</option>
+              </term>
+              <listitem>
+                <para>is very similar, but shows classic syslog timestamps
+                with full microsecond precision.</para>
+              </listitem>
+            </varlistentry>
+
             <varlistentry>
               <term>
                 <option>short-monotonic</option>
index f02ca3e7bc999138ff933995c22dff5385adf39d..00fb6f6c0d013bc6602f67ff3dcf072e16ef2d52 100644 (file)
@@ -59,8 +59,8 @@
     kernel command line arguments.</para>
 
     <para>For command line parameters understood by the kernel, please
-    see <ulink
-    url="https://www.kernel.org/doc/Documentation/kernel-parameters.txt"><filename>kernel-parameters.txt</filename></ulink>
+    see
+    <ulink url="https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html"><filename>kernel-parameters.html</filename></ulink>
     and
     <citerefentry project='man-pages'><refentrytitle>bootparam</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
 
index 1f34cbc1bfe3ec492dcefb639dfed1711ba5dfed..396481c937253335fffa586ecf0c93c287476f44 100644 (file)
@@ -12,8 +12,8 @@
       <listitem><para>Pager to use when <option>--no-pager</option> is not given; overrides
       <varname>$PAGER</varname>. If neither <varname>$SYSTEMD_PAGER</varname> nor <varname>$PAGER</varname> are set, a
       set of well-known pager implementations are tried in turn, including
-      <citerefentry><refentrytitle>less</refentrytitle><manvolnum>1</manvolnum></citerefentry> and
-      <citerefentry><refentrytitle>more</refentrytitle><manvolnum>1</manvolnum></citerefentry>, until one is found. If
+      <citerefentry project='man-pages'><refentrytitle>less</refentrytitle><manvolnum>1</manvolnum></citerefentry> and
+      <citerefentry project='man-pages'><refentrytitle>more</refentrytitle><manvolnum>1</manvolnum></citerefentry>, until one is found. If
       no pager implementation is discovered no pager is invoked. Setting this environment variable to an empty string
       or the value <literal>cat</literal> is equivalent to passing <option>--no-pager</option>.</para></listitem>
     </varlistentry>
index 2fe731113a00625d8a41ca683d0c1b866787fe48..1405dda3fd817f9ea983cb75179c946edb9f61e4 100644 (file)
     might be checked for locale configuration as well, however only as
     fallback.</para>
 
-    <para><citerefentry project='man-pages'><refentrytitle>localectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+    <para><filename>/etc/vconsole.conf</filename> is usually created and updated
+    using
+    <citerefentry><refentrytitle>systemd-localed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+    <citerefentry project='man-pages'><refentrytitle>localectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     may be used to alter the settings in this file during runtime from
     the command line. Use
     <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-    to initialize them on mounted (but not booted) system
-    images.</para>
+    to initialize them on mounted (but not booted) system images.</para>
   </refsect1>
 
   <refsect1>
index 994e0e114041a6a19d1549e63116e45d0f81725e..16f51af72c43615bb19c21969e8d743b8ab9d4f5 100644 (file)
 
         <para>A different application may disable logind's handling of system power and
         sleep keys and the lid switch by taking a low-level inhibitor lock
-        ("handle-power-key", "handle-suspend-key", "handle-hibernate-key",
-        "handle-lid-switch"). This is most commonly used by graphical desktop environments
+        (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>,
+        <literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>).
+        This is most commonly used by graphical desktop environments
         to take over suspend and hibernation handling, and to use their own configuration
         mechanisms. If a low-level inhibitor lock is taken, logind will not take any
         action when that key or switch is triggered and the <varname>Handle*=</varname>
         <listitem><para>Controls whether actions that <command>systemd-logind</command>
         takes when the power and sleep keys and the lid switch are triggered are subject
         to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor
-        locks ("handle-*-key"), are always honored, irrespective of this setting.</para>
+        locks (<literal>handle-power-key</literal>, <literal>handle-suspend-key</literal>,
+        <literal>handle-hibernate-key</literal>, <literal>handle-lid-switch</literal>),
+        are always honored, irrespective of this setting.</para>
 
         <para>These settings take boolean arguments. If <literal>no</literal>, the
         inhibitor locks taken by applications are respected. If <literal>yes</literal>,
index 7a159aecdc782001a231c17bb6d0fc105643e358..46dcb44ca675ab4f058ca61294adf5eb8edaac81 100644 (file)
         is automatically derived from the last component of the URL,
         with its suffix removed.</para>
 
-        <para>The image is verified before it is made available,
-        unless <option>--verify=no</option> is specified. Verification
-        is done via SHA256SUMS and SHA256SUMS.gpg files that need to
-        be made available on the same web server, under the same URL
-        as the <filename>.tar</filename> file, but with the last
-        component (the filename) of the URL replaced. With
-        <option>--verify=checksum</option>, only the SHA256 checksum
-        for the file is verified, based on the
-        <filename>SHA256SUMS</filename> file. With
-        <option>--verify=signature</option>, the SHA256SUMS file is
-        first verified with detached GPG signature file
-        <filename>SHA256SUMS.gpg</filename>. The public key for this
-        verification step needs to be available in
+        <para>The image is verified before it is made available, unless
+        <option>--verify=no</option> is specified.
+        Verification is done either via an inline signed file with the name
+        of the image and the suffix <filename>.sha256</filename> or via
+        separate <filename>SHA256SUMS</filename> and
+        <filename>SHA256SUMS.gpg</filename> files.
+        The signature files need to be made available on the same web
+        server, under the same URL as the <filename>.tar</filename> file.
+        With <option>--verify=checksum</option>, only the SHA256 checksum
+        for the file is verified, based on the <filename>.sha256</filename>
+        suffixed file or the<filename>SHA256SUMS</filename> file.
+        With <option>--verify=signature</option>, the sha checksum file is
+        first verified with the inline signature in the
+        <filename>.sha256</filename> file or the detached GPG signature file
+        <filename>SHA256SUMS.gpg</filename>.
+        The public key for this verification step needs to be available in
         <filename>/usr/lib/systemd/import-pubring.gpg</filename> or
         <filename>/etc/systemd/import-pubring.gpg</filename>.</para>
 
diff --git a/man/meson.build b/man/meson.build
new file mode 100644 (file)
index 0000000..4f2ddad
--- /dev/null
@@ -0,0 +1,204 @@
+# This is lame, I know, but meson has no other include mechanism
+subdir('rules')
+
+want_man = get_option('man')
+want_html = get_option('html')
+xsltproc = find_program('xsltproc',
+                        required : want_man == 'true' or want_html == 'true')
+want_man = want_man != 'false' and xsltproc.found()
+want_html = want_html != 'false' and xsltproc.found()
+
+xsltproc_flags = [
+        '--nonet',
+        '--xinclude',
+        '--stringparam', 'man.output.quietly', '1',
+        '--stringparam', 'funcsynopsis.style', 'ansi',
+        '--stringparam', 'man.authors.section.enabled', '0',
+        '--stringparam', 'man.copyright.section.enabled', '0',
+        '--stringparam', 'systemd.version', '@0@'.format(meson.project_version()),
+        '--path',
+        '@0@:@1@'.format(meson.current_build_dir(), meson.current_source_dir())]
+
+custom_man_xsl = files('custom-man.xsl')
+custom_html_xsl = files('custom-html.xsl')
+xslt_cmd = [xsltproc, '-o', '@OUTPUT0@'] + xsltproc_flags
+
+custom_entities_ent = configure_file(
+        input : 'custom-entities.ent.in',
+        output : 'custom-entities.ent',
+        configuration : conf)
+
+man_pages = []
+html_pages = []
+source_xml_files = []
+foreach tuple : manpages
+        stem = tuple[0]
+        section = tuple[1]
+        aliases = tuple[2]
+        condition = tuple[3]
+
+        xml = stem + '.xml'
+        html = stem + '.html'
+        man = stem + '.' + section
+
+        manaliases = []
+        htmlaliases = []
+        foreach alias : aliases
+                manaliases += [alias + '.' + section]
+                htmlaliases += [alias + '.html']
+        endforeach
+
+        mandirn = join_paths(get_option('mandir'), 'man' + section)
+
+        if condition == '' or conf.get(condition, false)
+                p1 = custom_target(
+                        man,
+                        input : xml,
+                        output : [man] + manaliases,
+                        command : xslt_cmd + [custom_man_xsl, '@INPUT@'],
+                        depend_files : custom_entities_ent,
+                        install : want_man,
+                        install_dir : mandirn)
+                man_pages += [p1]
+
+                p2 = []
+                foreach htmlalias : htmlaliases
+                        link = custom_target(
+                                htmlalias,
+                                input : p2,
+                                output : htmlalias,
+                                command : ['ln', '-fs', html, '@OUTPUT@'])
+                        if want_html
+                                dst = join_paths(docdir, 'html', htmlalias)
+                                cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst)
+                                meson.add_install_script('sh', '-c', cmd)
+                                p2 += [link]
+                        endif
+                        html_pages += [link]
+                endforeach
+
+                p3 = custom_target(
+                        html,
+                        input : xml,
+                        output : html,
+                        command : xslt_cmd + [custom_html_xsl, '@INPUT@'],
+                        depend_files : custom_entities_ent,
+                        depends : p2,
+                        install : want_html,
+                        install_dir : join_paths(docdir, 'html'))
+                html_pages += [p3]
+
+                source_xml_files += files(tuple[0] + '.xml')
+        else
+                message('Skipping @0@.@1@ because @2@ is false'.format(stem, section, condition))
+        endif
+endforeach
+
+############################################################
+
+have_lxml = run_command(xml_helper_py).returncode() == 0
+if not have_lxml
+        message('python-lxml not available, not making man page indices')
+endif
+
+systemd_directives_xml = custom_target(
+        'systemd.directives.xml',
+        input : source_xml_files,
+        output : 'systemd.directives.xml',
+        command : [make_directive_index_py, '@OUTPUT@'] + source_xml_files)
+
+nonindex_xml_files = source_xml_files + [systemd_directives_xml]
+systemd_index_xml = custom_target(
+        'systemd.index.xml',
+        input : nonindex_xml_files,
+        output : 'systemd.index.xml',
+        command : [make_man_index_py, '@OUTPUT@'] + nonindex_xml_files)
+
+foreach tuple : [['systemd.directives', '7', systemd_directives_xml],
+                 ['systemd.index',      '7', systemd_index_xml]]
+        stem = tuple[0]
+        section = tuple[1]
+        xml = tuple[2]
+
+        html = stem + '.html'
+        man = stem + '.' + section
+
+        mandirn = join_paths(get_option('mandir'), 'man' + section)
+
+        p1 = custom_target(
+                man,
+                input : xml,
+                output : man,
+                command : xslt_cmd + [custom_man_xsl, '@INPUT@'],
+                install : want_man and have_lxml,
+                install_dir : mandirn)
+        man_pages += [p1]
+
+        p2 = []
+        if html == 'systemd.index.html'
+                htmlalias = 'index.html'
+                link = custom_target(
+                        htmlalias,
+                        input : p2,
+                        output : htmlalias,
+                        command : ['ln', '-fs', html, '@OUTPUT@'])
+                if want_html
+                        dst = join_paths(docdir, 'html', htmlalias)
+                        cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst)
+                        meson.add_install_script('sh', '-c', cmd)
+                        p2 += [link]
+                endif
+                html_pages += [link]
+        endif
+
+        p3 = custom_target(
+                html,
+                input : xml,
+                output : html,
+                command : xslt_cmd + [custom_html_xsl, '@INPUT@'],
+                depend_files : custom_entities_ent,
+                depends : p2,
+                install : want_html and have_lxml,
+                install_dir : join_paths(docdir, 'html'))
+        html_pages += [p3]
+endforeach
+
+# cannot use run_target until https://github.com/mesonbuild/meson/issues/1644 is resolved
+man = custom_target(
+        'man',
+        output : 'man',
+        depends : man_pages,
+        command : ['echo'])
+
+html = run_target(
+        'html',
+        depends : html_pages,
+        output : 'html',
+        command : ['echo'])
+
+run_target(
+        'doc-sync',
+        depends : man_pages + html_pages,
+        command : ['rsync', '-rlv',
+                   '--delete-excluded',
+                   '--include=man',
+                   '--include=*.html',
+                   '--exclude=*',
+                   '--omit-dir-times',
+                   meson.current_build_dir(),
+                   get_option('www-target')])
+
+############################################################
+
+if git.found()
+        run_target(
+                'update-man-rules',
+                # slightly strange syntax because of
+                # https://github.com/mesonbuild/meson/issues/1643
+                # and https://github.com/mesonbuild/meson/issues/1512
+                command : ['sh', '-c',
+                           'cd @0@ && '.format(meson.build_root()) +
+                           'python3 @0@/tools/make-man-rules.py --meson `git ls-files ":/man/*.xml"` >t && '.format(meson.source_root()) +
+                           'mv t @0@/rules/meson.build'.format(meson.current_source_dir())],
+                depend_files : custom_entities_ent)
+endif
index 809eb7ec6ab14916496514a5343a8a361890f4f3..d4fa5e902948aaed977c9ea0a56c7f3cc7c3e46d 100644 (file)
@@ -172,14 +172,40 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
 1 neighbors listed.</programlisting></para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term>
+          <command>label</command>
+        </term>
+
+        <listitem><para>Show numerical address labels that can be used for address selection.
+        This is the same information that
+        <citerefentry><refentrytitle>ip-addrlabel</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        shows. See <ulink url="https://tools.ietf.org/html/rfc3484">RFC 3484</ulink>
+        for a discussion of address labels.</para>
+
+        <para>Produces output similar to:
+        <programlisting>Prefix/Prefixlen                          Label
+        ::/0                                  1
+    fc00::/7                                  5
+    fec0::/10                                11
+    2002::/16                                 2
+    3ffe::/16                                12
+ 2001:10::/28                                 7
+    2001::/32                                 6
+::ffff:0.0.0.0/96                             4
+        ::/96                                 3
+       ::1/128                                0</programlisting></para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
   <refsect1>
     <title>Exit status</title>
 
-    <para>On success, 0 is returned, a non-zero failure
-    code otherwise.</para>
+    <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
   </refsect1>
 
   <refsect1>
@@ -187,7 +213,8 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
     <para>
       <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     </para>
   </refsect1>
 </refentry>
index 4e102cec262f9777be919fb27d0ed4b34bdf15c0..3a4e98e88f9c020c844651bcd48c1ce8eb0d2f01 100644 (file)
     hostnames via DNS.</para>
 
     <para>To activate the NSS module, add <literal>resolve</literal> to the line starting with
-    <literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>. Specifcally, it is recommended to place
-    <literal>resolve</literal> early in <filename>/etc/nsswitch.conf</filename>' <literal>hosts:</literal> line (but
+    <literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>. Specifically, it is recommended to place
+    <literal>resolve</literal> early in <filename>/etc/nsswitch.conf</filename>'s <literal>hosts:</literal> line (but
     after the <literal>files</literal> or <literal>mymachines</literal> entries), right before the
     <literal>dns</literal> entry if it exists, followed by <literal>[!UNAVAIL=return]</literal>, to ensure DNS queries
     are always routed via
     <citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry> if it is
     running, but are routed to <command>nss-dns</command> if this service is not available.</para>
+
+    <para>Note that <command>systemd-resolved</command> will synthesize DNS resource
+    records in a few cases, for example for <literal>localhost</literal> and the
+    current hostname, see
+    <citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    for the full list. This duplicates the functionality of
+    <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+    but it is still recommended (see examples below) to keep
+    <command>nss-myhostname</command> configured in
+    <filename>/etc/nsswitch.conf</filename>, to keep those names resolveable if
+    <command>systemd-resolved</command> is not running.</para>
   </refsect1>
 
   <refsect1>
index 71aed4df83eb4a661d984a7795654e032e42bcb5..34811f0a2e6cbc373cb3f7e7ea25a43db27e084a 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="nss-systemd">
+<refentry id="nss-systemd" conditional='ENABLE_NSS_SYSTEMD'>
 
   <refentryinfo>
     <title>nss-systemd</title>
index 6e1aa0dd9a64a79f6c6c74d1afb0cfde166b7dce..cef5445c1ce4609b116df98ac8e958606228b89e 100644 (file)
@@ -88,7 +88,7 @@
       and so will the user's slice unit.</para></listitem>
 
       <listitem><para>If the last concurrent session of a user ends,
-      the <varname>$XDG_RUNTIME_DIR</varname> directory and all its
+      the user runtime directory <filename>/run/user/$UID</filename> and all its
       contents are removed, too.</para></listitem>
     </orderedlist>
 
         offers the greatest possible file system feature set the
         operating system provides. For further details, see the <ulink
         url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG
-        Base Directory Specification</ulink>.</para></listitem>
+        Base Directory Specification</ulink>. <varname>$XDG_RUNTIME_DIR</varname>
+        is not set if the current user is not the original user of the session.</para></listitem>
       </varlistentry>
 
     </variablelist>
index 4fc1ef1b33b7cb18a18990494f61dbc59c3b30c2..7babc5c5c41df64f20c78c42d9f6d5775cd757de 100644 (file)
         global setting is on.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>MulticastDNS=</varname></term>
+        <listitem><para>Takes a boolean argument or
+        <literal>resolve</literal>. Controls Multicast DNS support (<ulink
+        url="https://tools.ietf.org/html/rfc6762">RFC 6762</ulink>) on
+        the local host. If true, enables full Multicast DNS responder and
+        resolver support. If false, disables both. If set to
+        <literal>resolve</literal>, only resolution support is enabled,
+        but responding is disabled. Note that
+        <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        also maintains per-link Multicast DNS settings. Multicast DNS will be
+        enabled on a link only if the per-link and the
+        global setting is on.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>DNSSEC=</varname></term>
         <listitem><para>Takes a boolean argument or
diff --git a/man/rules/meson.build b/man/rules/meson.build
new file mode 100644 (file)
index 0000000..9f7201a
--- /dev/null
@@ -0,0 +1,766 @@
+# Do not edit. Generated by make-man-rules.py.
+manpages = [
+['binfmt.d', '5', [], 'ENABLE_BINFMT'],
+ ['bootctl', '1', [], 'ENABLE_EFI'],
+ ['bootup', '7', [], ''],
+ ['busctl', '1', [], ''],
+ ['coredump.conf', '5', ['coredump.conf.d'], 'ENABLE_COREDUMP'],
+ ['coredumpctl', '1', [], 'ENABLE_COREDUMP'],
+ ['crypttab', '5', [], 'HAVE_LIBCRYPTSETUP'],
+ ['daemon', '7', [], ''],
+ ['dnssec-trust-anchors.d',
+  '5',
+  ['systemd.negative', 'systemd.positive'],
+  'ENABLE_RESOLVED'],
+ ['environment.d', '5', [], 'ENABLE_ENVIRONMENT_D'],
+ ['file-hierarchy', '7', [], ''],
+ ['halt', '8', ['poweroff', 'reboot'], ''],
+ ['hostname', '5', [], ''],
+ ['hostnamectl', '1', [], 'ENABLE_HOSTNAMED'],
+ ['hwdb', '7', [], 'ENABLE_HWDB'],
+ ['journal-remote.conf', '5', ['journal-remote.conf.d'], 'HAVE_MICROHTTPD'],
+ ['journal-upload.conf', '5', ['journal-upload.conf.d'], 'HAVE_MICROHTTPD'],
+ ['journalctl', '1', [], ''],
+ ['journald.conf', '5', ['journald.conf.d'], ''],
+ ['kernel-command-line', '7', [], ''],
+ ['kernel-install', '8', [], ''],
+ ['libudev', '3', [], ''],
+ ['locale.conf', '5', [], ''],
+ ['localectl', '1', [], 'ENABLE_LOCALED'],
+ ['localtime', '5', [], ''],
+ ['loginctl', '1', [], 'ENABLE_LOGIND'],
+ ['logind.conf', '5', ['logind.conf.d'], 'ENABLE_LOGIND'],
+ ['machine-id', '5', [], ''],
+ ['machine-info', '5', [], ''],
+ ['machinectl', '1', [], 'ENABLE_MACHINED'],
+ ['modules-load.d', '5', [], 'HAVE_KMOD'],
+ ['networkctl', '1', [], 'ENABLE_NETWORKD'],
+ ['networkd.conf', '5', ['networkd.conf.d'], 'ENABLE_NETWORKD'],
+ ['nss-myhostname', '8', ['libnss_myhostname.so.2'], 'HAVE_MYHOSTNAME'],
+ ['nss-mymachines', '8', ['libnss_mymachines.so.2'], 'ENABLE_MACHINED'],
+ ['nss-resolve', '8', ['libnss_resolve.so.2'], 'ENABLE_RESOLVED'],
+ ['nss-systemd', '8', ['libnss_systemd.so.2'], 'ENABLE_NSS_SYSTEMD'],
+ ['os-release', '5', [], ''],
+ ['pam_systemd', '8', [], 'HAVE_PAM'],
+ ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVED'],
+ ['runlevel', '8', [], 'HAVE_UTMP'],
+ ['sd-bus-errors',
+  '3',
+  ['SD_BUS_ERROR_ACCESS_DENIED',
+   'SD_BUS_ERROR_ADDRESS_IN_USE',
+   'SD_BUS_ERROR_AUTH_FAILED',
+   'SD_BUS_ERROR_BAD_ADDRESS',
+   'SD_BUS_ERROR_DISCONNECTED',
+   'SD_BUS_ERROR_FAILED',
+   'SD_BUS_ERROR_FILE_EXISTS',
+   'SD_BUS_ERROR_FILE_NOT_FOUND',
+   'SD_BUS_ERROR_INCONSISTENT_MESSAGE',
+   'SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED',
+   'SD_BUS_ERROR_INVALID_ARGS',
+   'SD_BUS_ERROR_INVALID_SIGNATURE',
+   'SD_BUS_ERROR_IO_ERROR',
+   'SD_BUS_ERROR_LIMITS_EXCEEDED',
+   'SD_BUS_ERROR_MATCH_RULE_INVALID',
+   'SD_BUS_ERROR_MATCH_RULE_NOT_FOUND',
+   'SD_BUS_ERROR_NAME_HAS_NO_OWNER',
+   'SD_BUS_ERROR_NOT_SUPPORTED',
+   'SD_BUS_ERROR_NO_MEMORY',
+   'SD_BUS_ERROR_NO_NETWORK',
+   'SD_BUS_ERROR_NO_REPLY',
+   'SD_BUS_ERROR_NO_SERVER',
+   'SD_BUS_ERROR_PROPERTY_READ_ONLY',
+   'SD_BUS_ERROR_SERVICE_UNKNOWN',
+   'SD_BUS_ERROR_TIMEOUT',
+   'SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN',
+   'SD_BUS_ERROR_UNKNOWN_INTERFACE',
+   'SD_BUS_ERROR_UNKNOWN_METHOD',
+   'SD_BUS_ERROR_UNKNOWN_OBJECT',
+   'SD_BUS_ERROR_UNKNOWN_PROPERTY'],
+  ''],
+ ['sd-bus', '3', [], ''],
+ ['sd-daemon',
+  '3',
+  ['SD_ALERT',
+   'SD_CRIT',
+   'SD_DEBUG',
+   'SD_EMERG',
+   'SD_ERR',
+   'SD_INFO',
+   'SD_NOTICE',
+   'SD_WARNING'],
+  ''],
+ ['sd-event', '3', [], ''],
+ ['sd-id128',
+  '3',
+  ['SD_ID128_CONST_STR',
+   'SD_ID128_FORMAT_STR',
+   'SD_ID128_FORMAT_VAL',
+   'SD_ID128_MAKE',
+   'SD_ID128_MAKE_STR',
+   'SD_ID128_NULL',
+   'sd_id128_equal',
+   'sd_id128_is_null',
+   'sd_id128_t'],
+  ''],
+ ['sd-journal', '3', [], ''],
+ ['sd-login', '3', [], 'HAVE_PAM'],
+ ['sd_booted', '3', [], ''],
+ ['sd_bus_add_match', '3', [], ''],
+ ['sd_bus_creds_get_pid',
+  '3',
+  ['sd_bus_creds_get_audit_login_uid',
+   'sd_bus_creds_get_audit_session_id',
+   'sd_bus_creds_get_cgroup',
+   'sd_bus_creds_get_cmdline',
+   'sd_bus_creds_get_comm',
+   'sd_bus_creds_get_description',
+   'sd_bus_creds_get_egid',
+   'sd_bus_creds_get_euid',
+   'sd_bus_creds_get_exe',
+   'sd_bus_creds_get_fsgid',
+   'sd_bus_creds_get_fsuid',
+   'sd_bus_creds_get_gid',
+   'sd_bus_creds_get_owner_uid',
+   'sd_bus_creds_get_ppid',
+   'sd_bus_creds_get_selinux_context',
+   'sd_bus_creds_get_session',
+   'sd_bus_creds_get_sgid',
+   'sd_bus_creds_get_slice',
+   'sd_bus_creds_get_suid',
+   'sd_bus_creds_get_supplementary_gids',
+   'sd_bus_creds_get_tid',
+   'sd_bus_creds_get_tid_comm',
+   'sd_bus_creds_get_tty',
+   'sd_bus_creds_get_uid',
+   'sd_bus_creds_get_unique_name',
+   'sd_bus_creds_get_unit',
+   'sd_bus_creds_get_user_slice',
+   'sd_bus_creds_get_user_unit',
+   'sd_bus_creds_get_well_known_names',
+   'sd_bus_creds_has_bounding_cap',
+   'sd_bus_creds_has_effective_cap',
+   'sd_bus_creds_has_inheritable_cap',
+   'sd_bus_creds_has_permitted_cap'],
+  ''],
+ ['sd_bus_creds_new_from_pid',
+  '3',
+  ['sd_bus_creds_get_augmented_mask',
+   'sd_bus_creds_get_mask',
+   'sd_bus_creds_ref',
+   'sd_bus_creds_unref',
+   'sd_bus_creds_unrefp'],
+  ''],
+ ['sd_bus_default',
+  '3',
+  ['sd_bus_default_system',
+   'sd_bus_default_user',
+   'sd_bus_open',
+   'sd_bus_open_system',
+   'sd_bus_open_system_machine',
+   'sd_bus_open_system_remote',
+   'sd_bus_open_user'],
+  ''],
+ ['sd_bus_error',
+  '3',
+  ['SD_BUS_ERROR_MAKE_CONST',
+   'SD_BUS_ERROR_NULL',
+   'sd_bus_error_copy',
+   'sd_bus_error_free',
+   'sd_bus_error_get_errno',
+   'sd_bus_error_has_name',
+   'sd_bus_error_is_set',
+   'sd_bus_error_set',
+   'sd_bus_error_set_const',
+   'sd_bus_error_set_errno',
+   'sd_bus_error_set_errnof',
+   'sd_bus_error_set_errnofv',
+   'sd_bus_error_setf'],
+  ''],
+ ['sd_bus_error_add_map',
+  '3',
+  ['SD_BUS_ERROR_END', 'SD_BUS_ERROR_MAP', 'sd_bus_error_map'],
+  ''],
+ ['sd_bus_get_fd', '3', [], ''],
+ ['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''],
+ ['sd_bus_message_append_array',
+  '3',
+  ['sd_bus_message_append_array_iovec',
+   'sd_bus_message_append_array_memfd',
+   'sd_bus_message_append_array_space'],
+  ''],
+ ['sd_bus_message_append_basic', '3', [], ''],
+ ['sd_bus_message_append_string_memfd',
+  '3',
+  ['sd_bus_message_append_string_iovec', 'sd_bus_message_append_string_space'],
+  ''],
+ ['sd_bus_message_append_strv', '3', [], ''],
+ ['sd_bus_message_get_cookie', '3', ['sd_bus_message_get_reply_cookie'], ''],
+ ['sd_bus_message_get_monotonic_usec',
+  '3',
+  ['sd_bus_message_get_realtime_usec', 'sd_bus_message_get_seqnum'],
+  ''],
+ ['sd_bus_message_read_basic', '3', [], ''],
+ ['sd_bus_negotiate_fds',
+  '3',
+  ['sd_bus_negotiate_creds', 'sd_bus_negotiate_timestamp'],
+  ''],
+ ['sd_bus_new', '3', ['sd_bus_ref', 'sd_bus_unref', 'sd_bus_unrefp'], ''],
+ ['sd_bus_path_encode',
+  '3',
+  ['sd_bus_path_decode', 'sd_bus_path_decode_many', 'sd_bus_path_encode_many'],
+  ''],
+ ['sd_bus_process', '3', [], ''],
+ ['sd_bus_request_name', '3', ['sd_bus_release_name'], ''],
+ ['sd_bus_track_add_name',
+  '3',
+  ['sd_bus_track_add_sender',
+   'sd_bus_track_contains',
+   'sd_bus_track_count',
+   'sd_bus_track_count_name',
+   'sd_bus_track_count_sender',
+   'sd_bus_track_first',
+   'sd_bus_track_next',
+   'sd_bus_track_remove_name',
+   'sd_bus_track_remove_sender'],
+  ''],
+ ['sd_bus_track_new',
+  '3',
+  ['sd_bus_track_get_bus',
+   'sd_bus_track_get_recursive',
+   'sd_bus_track_get_userdata',
+   'sd_bus_track_ref',
+   'sd_bus_track_set_recursive',
+   'sd_bus_track_set_userdata',
+   'sd_bus_track_unref',
+   'sd_bus_track_unrefp'],
+  ''],
+ ['sd_event_add_child',
+  '3',
+  ['sd_event_child_handler_t', 'sd_event_source_get_child_pid'],
+  ''],
+ ['sd_event_add_defer',
+  '3',
+  ['sd_event_add_exit', 'sd_event_add_post', 'sd_event_handler_t'],
+  ''],
+ ['sd_event_add_io',
+  '3',
+  ['sd_event_io_handler_t',
+   'sd_event_source',
+   'sd_event_source_get_io_events',
+   'sd_event_source_get_io_fd',
+   'sd_event_source_get_io_revents',
+   'sd_event_source_set_io_events',
+   'sd_event_source_set_io_fd'],
+  ''],
+ ['sd_event_add_signal',
+  '3',
+  ['sd_event_signal_handler_t', 'sd_event_source_get_signal'],
+  ''],
+ ['sd_event_add_time',
+  '3',
+  ['sd_event_source_get_time',
+   'sd_event_source_get_time_accuracy',
+   'sd_event_source_get_time_clock',
+   'sd_event_source_set_time',
+   'sd_event_source_set_time_accuracy',
+   'sd_event_time_handler_t'],
+  ''],
+ ['sd_event_exit', '3', ['sd_event_get_exit_code'], ''],
+ ['sd_event_get_fd', '3', [], ''],
+ ['sd_event_new',
+  '3',
+  ['sd_event',
+   'sd_event_default',
+   'sd_event_get_tid',
+   'sd_event_ref',
+   'sd_event_unref',
+   'sd_event_unrefp'],
+  ''],
+ ['sd_event_now', '3', [], ''],
+ ['sd_event_run', '3', ['sd_event_loop'], ''],
+ ['sd_event_set_watchdog', '3', ['sd_event_get_watchdog'], ''],
+ ['sd_event_source_get_event', '3', [], ''],
+ ['sd_event_source_get_pending', '3', [], ''],
+ ['sd_event_source_set_description',
+  '3',
+  ['sd_event_source_get_description'],
+  ''],
+ ['sd_event_source_set_enabled',
+  '3',
+  ['SD_EVENT_OFF',
+   'SD_EVENT_ON',
+   'SD_EVENT_ONESHOT',
+   'sd_event_source_get_enabled'],
+  ''],
+ ['sd_event_source_set_prepare', '3', [], ''],
+ ['sd_event_source_set_priority',
+  '3',
+  ['SD_EVENT_PRIORITY_IDLE',
+   'SD_EVENT_PRIORITY_IMPORTANT',
+   'SD_EVENT_PRIORITY_NORMAL',
+   'sd_event_source_get_priority'],
+  ''],
+ ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''],
+ ['sd_event_source_unref',
+  '3',
+  ['sd_event_source_ref', 'sd_event_source_unrefp'],
+  ''],
+ ['sd_event_wait',
+  '3',
+  ['SD_EVENT_ARMED',
+   'SD_EVENT_EXITING',
+   'SD_EVENT_FINISHED',
+   'SD_EVENT_INITIAL',
+   'SD_EVENT_PENDING',
+   'SD_EVENT_PREPARING',
+   'SD_EVENT_RUNNING',
+   'sd_event_dispatch',
+   'sd_event_get_iteration',
+   'sd_event_get_state',
+   'sd_event_prepare'],
+  ''],
+ ['sd_get_seats',
+  '3',
+  ['sd_get_machine_names', 'sd_get_sessions', 'sd_get_uids'],
+  'HAVE_PAM'],
+ ['sd_id128_get_machine',
+  '3',
+  ['sd_id128_get_boot',
+   'sd_id128_get_invocation',
+   'sd_id128_get_machine_app_specific'],
+  ''],
+ ['sd_id128_randomize', '3', [], ''],
+ ['sd_id128_to_string', '3', ['sd_id128_from_string'], ''],
+ ['sd_is_fifo',
+  '3',
+  ['sd_is_mq',
+   'sd_is_socket',
+   'sd_is_socket_inet',
+   'sd_is_socket_sockaddr',
+   'sd_is_socket_unix',
+   'sd_is_special'],
+  ''],
+ ['sd_journal_add_match',
+  '3',
+  ['sd_journal_add_conjunction',
+   'sd_journal_add_disjunction',
+   'sd_journal_flush_matches'],
+  ''],
+ ['sd_journal_enumerate_fields',
+  '3',
+  ['SD_JOURNAL_FOREACH_FIELD', 'sd_journal_restart_fields'],
+  ''],
+ ['sd_journal_get_catalog', '3', ['sd_journal_get_catalog_for_message_id'], ''],
+ ['sd_journal_get_cursor', '3', ['sd_journal_test_cursor'], ''],
+ ['sd_journal_get_cutoff_realtime_usec',
+  '3',
+  ['sd_journal_get_cutoff_monotonic_usec'],
+  ''],
+ ['sd_journal_get_data',
+  '3',
+  ['SD_JOURNAL_FOREACH_DATA',
+   'sd_journal_enumerate_data',
+   'sd_journal_get_data_threshold',
+   'sd_journal_restart_data',
+   'sd_journal_set_data_threshold'],
+  ''],
+ ['sd_journal_get_fd',
+  '3',
+  ['SD_JOURNAL_APPEND',
+   'SD_JOURNAL_INVALIDATE',
+   'SD_JOURNAL_NOP',
+   'sd_journal_get_events',
+   'sd_journal_get_timeout',
+   'sd_journal_process',
+   'sd_journal_reliable_fd',
+   'sd_journal_wait'],
+  ''],
+ ['sd_journal_get_realtime_usec', '3', ['sd_journal_get_monotonic_usec'], ''],
+ ['sd_journal_get_usage', '3', [], ''],
+ ['sd_journal_has_runtime_files', '3', ['sd_journal_has_persistent_files'], ''],
+ ['sd_journal_next',
+  '3',
+  ['SD_JOURNAL_FOREACH',
+   'SD_JOURNAL_FOREACH_BACKWARDS',
+   'sd_journal_next_skip',
+   'sd_journal_previous',
+   'sd_journal_previous_skip'],
+  ''],
+ ['sd_journal_open',
+  '3',
+  ['SD_JOURNAL_CURRENT_USER',
+   'SD_JOURNAL_LOCAL_ONLY',
+   'SD_JOURNAL_OS_ROOT',
+   'SD_JOURNAL_RUNTIME_ONLY',
+   'SD_JOURNAL_SYSTEM',
+   'sd_journal',
+   'sd_journal_close',
+   'sd_journal_open_directory',
+   'sd_journal_open_directory_fd',
+   'sd_journal_open_files',
+   'sd_journal_open_files_fd'],
+  ''],
+ ['sd_journal_print',
+  '3',
+  ['SD_JOURNAL_SUPPRESS_LOCATION',
+   'sd_journal_perror',
+   'sd_journal_printv',
+   'sd_journal_send',
+   'sd_journal_sendv'],
+  ''],
+ ['sd_journal_query_unique',
+  '3',
+  ['SD_JOURNAL_FOREACH_UNIQUE',
+   'sd_journal_enumerate_unique',
+   'sd_journal_restart_unique'],
+  ''],
+ ['sd_journal_seek_head',
+  '3',
+  ['sd_journal_seek_cursor',
+   'sd_journal_seek_monotonic_usec',
+   'sd_journal_seek_realtime_usec',
+   'sd_journal_seek_tail'],
+  ''],
+ ['sd_journal_stream_fd', '3', [], ''],
+ ['sd_listen_fds',
+  '3',
+  ['SD_LISTEN_FDS_START', 'sd_listen_fds_with_names'],
+  ''],
+ ['sd_login_monitor_new',
+  '3',
+  ['sd_login_monitor',
+   'sd_login_monitor_flush',
+   'sd_login_monitor_get_events',
+   'sd_login_monitor_get_fd',
+   'sd_login_monitor_get_timeout',
+   'sd_login_monitor_unref',
+   'sd_login_monitor_unrefp'],
+  'HAVE_PAM'],
+ ['sd_machine_get_class', '3', ['sd_machine_get_ifindices'], ''],
+ ['sd_notify',
+  '3',
+  ['sd_notifyf', 'sd_pid_notify', 'sd_pid_notify_with_fds', 'sd_pid_notifyf'],
+  ''],
+ ['sd_pid_get_session',
+  '3',
+  ['sd_peer_get_cgroup',
+   'sd_peer_get_machine_name',
+   'sd_peer_get_owner_uid',
+   'sd_peer_get_session',
+   'sd_peer_get_slice',
+   'sd_peer_get_unit',
+   'sd_peer_get_user_slice',
+   'sd_peer_get_user_unit',
+   'sd_pid_get_cgroup',
+   'sd_pid_get_machine_name',
+   'sd_pid_get_owner_uid',
+   'sd_pid_get_slice',
+   'sd_pid_get_unit',
+   'sd_pid_get_user_slice',
+   'sd_pid_get_user_unit'],
+  'HAVE_PAM'],
+ ['sd_seat_get_active',
+  '3',
+  ['sd_seat_can_graphical',
+   'sd_seat_can_multi_session',
+   'sd_seat_can_tty',
+   'sd_seat_get_sessions'],
+  'HAVE_PAM'],
+ ['sd_session_is_active',
+  '3',
+  ['sd_session_get_class',
+   'sd_session_get_desktop',
+   'sd_session_get_display',
+   'sd_session_get_remote_host',
+   'sd_session_get_remote_user',
+   'sd_session_get_seat',
+   'sd_session_get_service',
+   'sd_session_get_state',
+   'sd_session_get_tty',
+   'sd_session_get_type',
+   'sd_session_get_uid',
+   'sd_session_get_vt',
+   'sd_session_is_remote'],
+  'HAVE_PAM'],
+ ['sd_uid_get_state',
+  '3',
+  ['sd_uid_get_display',
+   'sd_uid_get_seats',
+   'sd_uid_get_sessions',
+   'sd_uid_is_on_seat'],
+  'HAVE_PAM'],
+ ['sd_watchdog_enabled', '3', [], ''],
+ ['shutdown', '8', [], ''],
+ ['sysctl.d', '5', [], ''],
+ ['systemctl', '1', [], ''],
+ ['systemd-analyze', '1', [], ''],
+ ['systemd-ask-password-console.service',
+  '8',
+  ['systemd-ask-password-console.path',
+   'systemd-ask-password-wall.path',
+   'systemd-ask-password-wall.service'],
+  ''],
+ ['systemd-ask-password', '1', [], ''],
+ ['systemd-backlight@.service', '8', ['systemd-backlight'], 'ENABLE_BACKLIGHT'],
+ ['systemd-binfmt.service', '8', ['systemd-binfmt'], 'ENABLE_BINFMT'],
+ ['systemd-cat', '1', [], ''],
+ ['systemd-cgls', '1', [], ''],
+ ['systemd-cgtop', '1', [], ''],
+ ['systemd-coredump',
+  '8',
+  ['systemd-coredump.socket', 'systemd-coredump@.service'],
+  'ENABLE_COREDUMP'],
+ ['systemd-cryptsetup-generator', '8', [], 'HAVE_LIBCRYPTSETUP'],
+ ['systemd-cryptsetup@.service',
+  '8',
+  ['systemd-cryptsetup'],
+  'HAVE_LIBCRYPTSETUP'],
+ ['systemd-debug-generator', '8', [], ''],
+ ['systemd-delta', '1', [], ''],
+ ['systemd-detect-virt', '1', [], ''],
+ ['systemd-environment-d-generator',
+  '8',
+  ['30-systemd-environment-d-generator'],
+  'ENABLE_ENVIRONMENT_D'],
+ ['systemd-escape', '1', [], ''],
+ ['systemd-firstboot', '1', ['systemd-firstboot.service'], 'ENABLE_FIRSTBOOT'],
+ ['systemd-fsck@.service',
+  '8',
+  ['systemd-fsck', 'systemd-fsck-root.service'],
+  ''],
+ ['systemd-fstab-generator', '8', [], ''],
+ ['systemd-getty-generator', '8', [], ''],
+ ['systemd-gpt-auto-generator', '8', [], ''],
+ ['systemd-halt.service',
+  '8',
+  ['systemd-kexec.service',
+   'systemd-poweroff.service',
+   'systemd-reboot.service',
+   'systemd-shutdown'],
+  ''],
+ ['systemd-hibernate-resume-generator', '8', [], 'ENABLE_HIBERNATE'],
+ ['systemd-hibernate-resume@.service',
+  '8',
+  ['systemd-hibernate-resume'],
+  'ENABLE_HIBERNATE'],
+ ['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'],
+ ['systemd-hwdb', '8', [], 'ENABLE_HWDB'],
+ ['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'],
+ ['systemd-inhibit', '1', [], ''],
+ ['systemd-initctl.service',
+  '8',
+  ['systemd-initctl', 'systemd-initctl.socket'],
+  ''],
+ ['systemd-journal-gatewayd.service',
+  '8',
+  ['systemd-journal-gatewayd', 'systemd-journal-gatewayd.socket'],
+  'HAVE_MICROHTTPD'],
+ ['systemd-journal-remote', '8', [], 'HAVE_MICROHTTPD'],
+ ['systemd-journal-upload', '8', [], 'HAVE_MICROHTTPD'],
+ ['systemd-journald.service',
+  '8',
+  ['systemd-journald',
+   'systemd-journald-audit.socket',
+   'systemd-journald-dev-log.socket',
+   'systemd-journald.socket'],
+  ''],
+ ['systemd-localed.service', '8', ['systemd-localed'], 'ENABLE_LOCALED'],
+ ['systemd-logind.service', '8', ['systemd-logind'], 'ENABLE_LOGIND'],
+ ['systemd-machine-id-commit.service', '8', [], ''],
+ ['systemd-machine-id-setup', '1', [], ''],
+ ['systemd-machined.service', '8', ['systemd-machined'], 'ENABLE_MACHINED'],
+ ['systemd-modules-load.service', '8', ['systemd-modules-load'], 'HAVE_KMOD'],
+ ['systemd-mount', '1', ['systemd-umount'], ''],
+ ['systemd-networkd-wait-online.service',
+  '8',
+  ['systemd-networkd-wait-online'],
+  'ENABLE_NETWORKD'],
+ ['systemd-networkd.service', '8', ['systemd-networkd'], 'ENABLE_NETWORKD'],
+ ['systemd-notify', '1', [], ''],
+ ['systemd-nspawn', '1', [], ''],
+ ['systemd-path', '1', [], ''],
+ ['systemd-quotacheck.service',
+  '8',
+  ['systemd-quotacheck'],
+  'ENABLE_QUOTACHECK'],
+ ['systemd-random-seed.service',
+  '8',
+  ['systemd-random-seed'],
+  'ENABLE_RANDOMSEED'],
+ ['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''],
+ ['systemd-resolve', '1', [], 'ENABLE_RESOLVED'],
+ ['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVED'],
+ ['systemd-rfkill.service',
+  '8',
+  ['systemd-rfkill', 'systemd-rfkill.socket'],
+  'ENABLE_RFKILL'],
+ ['systemd-run', '1', [], ''],
+ ['systemd-sleep.conf', '5', ['sleep.conf.d'], ''],
+ ['systemd-socket-activate', '1', [], ''],
+ ['systemd-socket-proxyd', '8', [], ''],
+ ['systemd-suspend.service',
+  '8',
+  ['systemd-hibernate.service',
+   'systemd-hybrid-sleep.service',
+   'systemd-sleep'],
+  ''],
+ ['systemd-sysctl.service', '8', ['systemd-sysctl'], ''],
+ ['systemd-system-update-generator', '8', [], ''],
+ ['systemd-system.conf',
+  '5',
+  ['system.conf.d', 'systemd-user.conf', 'user.conf.d'],
+  ''],
+ ['systemd-sysusers', '8', ['systemd-sysusers.service'], ''],
+ ['systemd-sysv-generator', '8', [], 'HAVE_SYSV_COMPAT'],
+ ['systemd-timedated.service', '8', ['systemd-timedated'], 'ENABLE_TIMEDATED'],
+ ['systemd-timesyncd.service', '8', ['systemd-timesyncd'], 'ENABLE_TIMESYNCD'],
+ ['systemd-tmpfiles',
+  '8',
+  ['systemd-tmpfiles-clean.service',
+   'systemd-tmpfiles-clean.timer',
+   'systemd-tmpfiles-setup-dev.service',
+   'systemd-tmpfiles-setup.service'],
+  ''],
+ ['systemd-tty-ask-password-agent', '1', [], ''],
+ ['systemd-udevd.service',
+  '8',
+  ['systemd-udevd',
+   'systemd-udevd-control.socket',
+   'systemd-udevd-kernel.socket'],
+  ''],
+ ['systemd-update-done.service', '8', ['systemd-update-done'], ''],
+ ['systemd-update-utmp.service',
+  '8',
+  ['systemd-update-utmp', 'systemd-update-utmp-runlevel.service'],
+  'HAVE_UTMP'],
+ ['systemd-user-sessions.service', '8', ['systemd-user-sessions'], 'HAVE_PAM'],
+ ['systemd-vconsole-setup.service',
+  '8',
+  ['systemd-vconsole-setup'],
+  'ENABLE_VCONSOLE'],
+ ['systemd-veritysetup-generator', '8', [], 'HAVE_LIBCRYPTSETUP'],
+ ['systemd-veritysetup@.service',
+  '8',
+  ['systemd-veritysetup'],
+  'HAVE_LIBCRYPTSETUP'],
+ ['systemd-volatile-root.service', '8', ['systemd-volatile-root'], ''],
+ ['systemd', '1', ['init'], ''],
+ ['systemd.automount', '5', [], ''],
+ ['systemd.device', '5', [], ''],
+ ['systemd.environment-generator', '7', [], 'ENABLE_ENVIRONMENT_D'],
+ ['systemd.exec', '5', [], ''],
+ ['systemd.generator', '7', [], ''],
+ ['systemd.journal-fields', '7', [], ''],
+ ['systemd.kill', '5', [], ''],
+ ['systemd.link', '5', [], ''],
+ ['systemd.mount', '5', [], ''],
+ ['systemd.netdev', '5', [], 'ENABLE_NETWORKD'],
+ ['systemd.network', '5', [], 'ENABLE_NETWORKD'],
+ ['systemd.nspawn', '5', [], ''],
+ ['systemd.offline-updates', '7', [], ''],
+ ['systemd.path', '5', [], ''],
+ ['systemd.preset', '5', [], ''],
+ ['systemd.resource-control', '5', [], ''],
+ ['systemd.scope', '5', [], ''],
+ ['systemd.service', '5', [], ''],
+ ['systemd.slice', '5', [], ''],
+ ['systemd.socket', '5', [], ''],
+ ['systemd.special', '7', [], ''],
+ ['systemd.swap', '5', [], ''],
+ ['systemd.target', '5', [], ''],
+ ['systemd.time', '7', [], ''],
+ ['systemd.timer', '5', [], ''],
+ ['systemd.unit', '5', [], ''],
+ ['sysusers.d', '5', [], 'ENABLE_SYSUSERS'],
+ ['telinit', '8', [], ''],
+ ['timedatectl', '1', [], 'ENABLE_TIMEDATED'],
+ ['timesyncd.conf', '5', ['timesyncd.conf.d'], 'ENABLE_TIMESYNCD'],
+ ['tmpfiles.d', '5', [], ''],
+ ['udev', '7', [], ''],
+ ['udev.conf', '5', [], ''],
+ ['udev_device_get_syspath',
+  '3',
+  ['udev_device_get_action',
+   'udev_device_get_devnode',
+   'udev_device_get_devnum',
+   'udev_device_get_devpath',
+   'udev_device_get_devtype',
+   'udev_device_get_driver',
+   'udev_device_get_is_initialized',
+   'udev_device_get_parent',
+   'udev_device_get_parent_with_subsystem_devtype',
+   'udev_device_get_subsystem',
+   'udev_device_get_sysname',
+   'udev_device_get_sysnum',
+   'udev_device_get_udev'],
+  ''],
+ ['udev_device_has_tag',
+  '3',
+  ['udev_device_get_devlinks_list_entry',
+   'udev_device_get_properties_list_entry',
+   'udev_device_get_property_value',
+   'udev_device_get_sysattr_list_entry',
+   'udev_device_get_sysattr_value',
+   'udev_device_get_tags_list_entry',
+   'udev_device_set_sysattr_value'],
+  ''],
+ ['udev_device_new_from_syspath',
+  '3',
+  ['udev_device_new_from_device_id',
+   'udev_device_new_from_devnum',
+   'udev_device_new_from_environment',
+   'udev_device_new_from_subsystem_sysname',
+   'udev_device_ref',
+   'udev_device_unref'],
+  ''],
+ ['udev_enumerate_add_match_subsystem',
+  '3',
+  ['udev_enumerate_add_match_is_initialized',
+   'udev_enumerate_add_match_parent',
+   'udev_enumerate_add_match_property',
+   'udev_enumerate_add_match_sysattr',
+   'udev_enumerate_add_match_sysname',
+   'udev_enumerate_add_match_tag',
+   'udev_enumerate_add_nomatch_subsystem',
+   'udev_enumerate_add_nomatch_sysattr'],
+  ''],
+ ['udev_enumerate_new',
+  '3',
+  ['udev_enumerate_ref', 'udev_enumerate_unref'],
+  ''],
+ ['udev_enumerate_scan_devices',
+  '3',
+  ['udev_enumerate_add_syspath',
+   'udev_enumerate_get_list_entry',
+   'udev_enumerate_get_udev',
+   'udev_enumerate_scan_subsystems'],
+  ''],
+ ['udev_list_entry',
+  '3',
+  ['udev_list_entry_get_by_name',
+   'udev_list_entry_get_name',
+   'udev_list_entry_get_next',
+   'udev_list_entry_get_value'],
+  ''],
+ ['udev_monitor_filter_update',
+  '3',
+  ['udev_monitor_filter_add_match_subsystem_devtype',
+   'udev_monitor_filter_add_match_tag',
+   'udev_monitor_filter_remove'],
+  ''],
+ ['udev_monitor_new_from_netlink',
+  '3',
+  ['udev_monitor_ref', 'udev_monitor_unref'],
+  ''],
+ ['udev_monitor_receive_device',
+  '3',
+  ['udev_monitor_enable_receiving',
+   'udev_monitor_get_fd',
+   'udev_monitor_get_udev',
+   'udev_monitor_set_receive_buffer_size'],
+  ''],
+ ['udev_new', '3', ['udev_ref', 'udev_unref'], ''],
+ ['udevadm', '8', [], ''],
+ ['vconsole.conf', '5', [], 'ENABLE_VCONSOLE']
+]
+# Really, do not edit.
index 8bcf7164a0cfa6af6a05884536bbe67c095ed7b8..2014141ae34261d63c92724dae03a47a92eea51a 100644 (file)
     <title>Description</title>
 
     <para>
-      <function>sd_bus_add_match()</function> adds a match rule used to dispatch
-      incoming messages. The syntax of the rule passed in
-      <parameter>match</parameter> is described in the
-      <ulink url="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</ulink>.
+      <function>sd_bus_add_match()</function> installs a match rule for incoming messages received on the specified bus
+      connection object <parameter>bus</parameter>. The syntax of the match rule expression passed in
+      <parameter>match</parameter> is described in the <ulink
+      url="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</ulink>. The specified handler
+      function <parameter>callback</parameter> is called for eaching incoming message matching the specified
+      expression, the <parameter>userdata</parameter> parameter is passed as-is to the callback function.
     </para>
 
     <para>
-      The message <parameter>m</parameter> passed to the callback is only
-      borrowed, that is, the callback should not call
-      <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-      on it. If the callback wants to hold on to the message beyond the lifetime
-      of the callback, it needs to call
-      <citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-      to create a new reference.
+      On success, and if non-<constant>NULL</constant>, the <parameter>slot</parameter> return parameter will be set to
+      a slot object that may be used as a reference to the installed match, and may be utilized to remove it again at a
+      later time with
+      <citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
+      specified as <constant>NULL</constant> the lifetime of the match is bound to the lifetime of the bus object itself, and the match
+      cannot be removed independently.
     </para>
 
     <para>
-      If an error occurs during the callback invocation, the callback should
-      return a negative error number. If it wants other callbacks that match the
-      same rule to be called, it should return 0. Otherwise it should return a
+      The message <parameter>m</parameter> passed to the callback is only borrowed, that is, the callback should not
+      call <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry> on
+      it. If the callback wants to hold on to the message beyond the lifetime of the callback, it needs to call
+      <citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry> to create
+      a new reference.
+    </para>
+
+    <para>
+      If an error occurs during the callback invocation, the callback should return a negative error number. If it
+      wants other callbacks that match the same rule to be called, it should return 0. Otherwise it should return a
       positive integer.
     </para>
   </refsect1>
     <title>Return Value</title>
 
     <para>
-      On success, <function>sd_bus_add_match()</function> returns 0 or a
-      positive integer. On failure, it returns a negative errno-style error
-      code.
+      On success, <function>sd_bus_add_match()</function> returns 0 or a positive integer. On failure, it returns a
+      negative errno-style error code.
     </para>
   </refsect1>
 
 
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     </para>
   </refsect1>
 
index 3091e1f0194d4ab37be85b8384feec8b1ec16504..4970ce3c088ac149f3de97720234b0d24fea595d 100644 (file)
     <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.
+    <function>sd_bus_error_set_const()</function>, they will be shared.
     Otherwise, they will be copied. Returns a converted
     <varname>errno</varname>-like, negative error code.</para>
 
index 132ce66434626bb836d45b86918f4a755fcf8625..2c28ee715433fb654fd741017a9eaea9f9640a5a 100644 (file)
@@ -45,6 +45,7 @@
 
   <refnamediv>
     <refname>sd_bus_message_append</refname>
+    <refname>sd_bus_message_appendv</refname>
 
     <refpurpose>Attach fields to a D-Bus message based on a type
     string</refpurpose>
         <paramdef>const char *<parameter>types</parameter></paramdef>
         <paramdef>…</paramdef>
       </funcprototype>
+
+      <funcprototype>
+          <funcdef>int sd_bus_message_appendv</funcdef>
+          <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
+          <paramdef>const char *<parameter>types</parameter></paramdef>
+          <paramdef>va_list <parameter>ap</parameter></paramdef>
+      </funcprototype>
+
     </funcsynopsis>
   </refsynopsisdiv>
 
     values for each entry matching the element type of
     the dictionary entries.</para>
 
+    <para>The <function>sd_bus_message_appendv()</function> is equivalent to
+    the function <function>sd_bus_message_append()</function>,
+    except that it is called with a <literal>va_list</literal> instead of
+    a variable number of arguments. This function does not call the
+    <function>va_end()</function> macro. Because it invokes the
+    <function>va_arg()</function> macro, the value of ap
+    is undefined after the call.</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
@@ -238,8 +255,8 @@ sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d);</programlisting>
   <refsect1>
     <title>Return Value</title>
 
-    <para>On success, this call returns 0 or a positive
-    integer. On failure, this call returns a negative
+    <para>On success, these functions return 0 or a positive
+    integer. On failure, these functions return a negative
     errno-style error code.</para>
   </refsect1>
 
index 37eb3fc8945047de89f780bacacd7021ded1b1f3..c053144483b6b20b57cf627dd8df47bd5abb9786 100644 (file)
     <title>Description</title>
 
     <para><function>sd_get_seats()</function> may be used to determine
-    all currently available local seats. Returns a
-    <constant>NULL</constant> terminated array of seat identifiers.
+    all currently available local seats. Returns the number of seat
+    identifiers and if the input pointer is non-NULL, a
+    <constant>NULL</constant>-terminated array of seat identifiers
+    is stored at the address.
     The returned array and all strings it references need to be freed
     with the libc
     <citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
 
     <variablelist>
 
-      <varlistentry>
-        <term><constant>-EINVAL</constant></term>
-
-        <listitem><para>An input parameter was invalid (out of range,
-        or NULL, where that is not accepted).</para></listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><constant>-ENOMEM</constant></term>
 
index ab449d29378cd6c38d9f55db2e55093a23d4d4ac..852a9fd7ebbb5ebbdac2a88e591569d3de6e7808 100644 (file)
@@ -77,7 +77,7 @@
     <citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
 
     <para><citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
-    <option>--new-id</option> option may be used as a command line
+    <option>--new-id128</option> option may be used as a command line
     front-end for <function>sd_id128_randomize()</function>.</para>
   </refsect1>
 
index 604deb4e8cacc78bb15b157ddc405bdf94a6a4f9..92ed0dea069f9d58bd8e4b7d8865eaaecd3b6192 100644 (file)
 
     <para>Function <function>sd_journal_get_catalog()</function> is thread-agnostic and only a
     single thread may operate on a given <structname>sd_journal</structname> object. Function
-    <function>sd_journal_get_catalog_for_message_id() is thread-safe.</function></para>
+    <function>sd_journal_get_catalog_for_message_id()</function> is thread-safe.</para>
 
     <para>The <function>sd_journal_get_catalog()</function> and
     <function>sd_journal_get_catalog_for_message_id()</function>
index 61293f7f99d3527193b72bdca5f288b23b006938..2e686caccbc84befbd91867217e83c4722a913f3 100644 (file)
@@ -146,7 +146,7 @@ if (t == (uint64_t) -1)
 else {
   struct timespec ts;
   uint64_t n;
-  clock_getttime(CLOCK_MONOTONIC, &amp;ts);
+  clock_gettime(CLOCK_MONOTONIC, &amp;ts);
   n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
   msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
 }</programlisting>
@@ -304,7 +304,7 @@ int wait_for_changes(sd_journal *j) {
   else {
     struct timespec ts;
     uint64_t n;
-    clock_getttime(CLOCK_MONOTONIC, &amp;ts);
+    clock_gettime(CLOCK_MONOTONIC, &amp;ts);
     n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
     msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
   }
index 5625ab9207c8a0d51be9d4ff1fc797f7e0de43b3..129c99f97d9995a0ca9271560c54fb8d4fdba525 100644 (file)
@@ -203,7 +203,7 @@ if (t == (uint64_t) -1)
 else {
          struct timespec ts;
          uint64_t n;
-         clock_getttime(CLOCK_MONOTONIC, &amp;ts);
+         clock_gettime(CLOCK_MONOTONIC, &amp;ts);
          n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
          msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
 }</programlisting>
index 4dcefc4bafb8a8be375c218c997b2b7b425e0831..e8ddea2f5fba91a02dedea98ea6e1634491bc4e3 100644 (file)
       <varlistentry>
         <term>FDSTORE=1</term>
 
-        <listitem><para>Stores additional file descriptors in the service manager. File
-        descriptors sent this way will be maintained per-service by the service manager
-        and will be passed again using the usual file descriptor passing logic on the next
-        invocation of the service, see
-        <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
-        This is useful for implementing service restart schemes where services serialize
-        their state to <filename>/run</filename>, push their file descriptors to the
-        system manager, and are then restarted, retrieving their state again via socket
-        passing and <filename>/run</filename>. Note that the service manager will accept
-        messages for a service only if <varname>FileDescriptorStoreMax=</varname> is set
-        to non-zero for it (defaults to zero, see
-        <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
-        File descriptors must be pollable, see
-        <citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
-        Multiple arrays of file descriptors may be sent in separate messages, in which
-        case the arrays are combined.  Note that the service manager removes duplicate
-        file descriptors before passing them to the service. Use
-        <function>sd_pid_notify_with_fds()</function> to send messages with
-        <literal>FDSTORE=1</literal>, see below.</para></listitem>
+        <listitem><para>Stores additional file descriptors in the service manager. File descriptors sent this way will
+        be maintained per-service by the service manager and will later be handed back using the usual file descriptor
+        passing logic at the next invocation of the service, see
+        <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.  This is
+        useful for implementing services that can restart after an explicit request or a crash without losing
+        state. Any open sockets and other file descriptors which should not be closed during the restart may be stored
+        this way. Application state can either be serialized to a file in <filename>/run</filename>, or better, stored
+        in a <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> memory
+        file descriptor. Note that the service manager will accept messages for a service only if its
+        <varname>FileDescriptorStoreMax=</varname> setting is non-zero (defaults to zero, see
+        <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If file
+        descriptors sent are pollable (see
+        <citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), then any
+        <constant>EPOLLHUP</constant> or <constant>EPOLLERR</constant> event seen on them will result in their
+        automatic removal from the store. Multiple arrays of file descriptors may be sent in separate messages, in
+        which case the arrays are combined. Note that the service manager removes duplicate (pointing to the same
+        object) file descriptors before passing them to the service. Use <function>sd_pid_notify_with_fds()</function>
+        to send messages with <literal>FDSTORE=1</literal>, see below.</para></listitem>
       </varlistentry>
 
       <varlistentry>
   <refsect1>
     <title>Return Value</title>
 
-    <para>On failure, these calls return a negative errno-style error
-    code. If <varname>$NOTIFY_SOCKET</varname> was not set and hence
-    no status data could be sent, 0 is returned. If the status was
-    sent, these functions return with a positive return value. In
-    order to support both, init systems that implement this scheme and
-    those which do not, it is generally recommended to ignore the
-    return value of this call.</para>
+    <para>On failure, these calls return a negative errno-style error code. If <varname>$NOTIFY_SOCKET</varname> was
+    not set and hence no status message could be sent, 0 is returned. If the status was sent, these functions return a
+    positive value. In order to support both service managers that implement this scheme and those which do not, it is
+    generally recommended to ignore the return value of this call. Note that the return value simply indicates whether
+    the notification message was enqueued properly, it does not reflect whether the message could be processed
+    successfully. Specifically, no error is returned when a file descriptor is attempted to be stored using
+    <varname>FDSTORE=1</varname> but the service is not actually configured to permit storing of file descriptors (see
+    above).</para>
   </refsect1>
 
   <refsect1>
index 806cff34e443bf6f1180970ed5f3b315d1b7b8a0..14ebd53e36a23dab95bb5df0f49eff910af19403 100644 (file)
     processes, user processes that are shared between multiple
     sessions of the same user, or kernel threads). For processes not
     being part of a login session, this function will fail with
-    -ENODATA. The returned string needs to be freed with the libc
+    <constant>-ENODATA</constant>. 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>
     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 -ENODATA. (More specifically, this call will not
+    will fail with <constant>-ENODATA</constant>. (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>
     multiple login sessions of the same user, whereas
     <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 -ENODATA.</para>
+    of a user, this function will fail with <constant>-ENODATA</constant>.</para>
 
     <para><function>sd_pid_get_machine_name()</function> may be used
     to determine the name of the VM or container is a member of. The
     <citerefentry
     project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     call after use. For processes not part of a VM or containers, this
-    function fails with -ENODATA.</para>
+    function fails with <constant>-ENODATA</constant>.</para>
 
     <para><function>sd_pid_get_slice()</function> may be used to
     determine the slice unit the process is a member of. See
       </varlistentry>
 
       <varlistentry>
-        <term><constant>-BADF</constant></term>
+        <term><constant>-EBADF</constant></term>
 
         <listitem><para>The specified socket file descriptor was
         invalid.</para></listitem>
index c5e6ddab024b00e082b9f16003011c2741dfea0b..3dd461f83fad97f270919d5757f7c91784015489 100644 (file)
     one (<constant>NULL</constant> terminated) with the session
     identifiers of the sessions and one with the user identifiers of
     the Unix users the sessions belong to. An additional parameter may
-    be used to return the number of entries in the latter array. The
-    two arrays and the latter parameter may be passed as
+    be used to return the number of entries in the latter array. This
+    value is the same the return value, if the latter is nonnegative.
+    The two arrays and the last parameter may be passed as
     <constant>NULL</constant> in case these values need not to be
     determined. The arrays and the strings referenced by them need to
     be freed with the libc
index a6076b177abac6815d29733c494a8367bc4b3913..f95e74ead63ee9c47b94617b50c92140355876aa 100644 (file)
     <para><function>sd_session_get_seat()</function> may be used to
     determine the seat identifier of the seat the session identified
     by the specified session identifier belongs to. Note that not all
-    sessions are attached to a seat, this call will fail for them. The
-    returned string needs to be freed with the libc
+    sessions are attached to a seat, this call will fail (returning
+    <constant>-ENODATA</constant>) for them. 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>
 
index 7e1864c4f1a6ce93a996466ca9d90752c59ea8f1..14405141cfcd523370577dfd3cec9429e74e6629 100644 (file)
@@ -907,7 +907,7 @@ Sun 2017-02-26 20:57:49 EST  2h 3min left  Sun 2017-02-26 11:56:36 EST  6h ago
 
               <programlisting>$ systemctl status bluetooth
 ● bluetooth.service - Bluetooth service
-   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
+   Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
    Active: active (running) since Wed 2017-01-04 13:54:04 EST; 1 weeks 0 days ago
      Docs: man:bluetoothd(8)
  Main PID: 930 (bluetoothd)
@@ -1495,11 +1495,26 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
           <term><command>show-environment</command></term>
 
           <listitem>
-            <para>Dump the systemd manager environment block. The
-            environment block will be dumped in straight-forward form
-            suitable for sourcing into a shell script. This environment
-            block will be passed to all processes the manager
-            spawns.</para>
+            <para>Dump the systemd manager environment block. This is the environment
+            block that is passed to all processes the manager spawns. The environment
+            block will be dumped in straight-forward form suitable for sourcing into
+            most shells. If no special characters or whitespace is present in the variable
+            values, no escaping is performed, and the assignments have the form
+            <literal>VARIABLE=value</literal>. If whitespace or characters which have
+            special meaning to the shell are present, dollar-single-quote escaping is
+            used, and assignments have the form <literal>VARIABLE=$'value'</literal>.
+            This syntax is known to be supported by
+            <citerefentry project='die-net'><refentrytitle>bash</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+            <citerefentry project='die-net'><refentrytitle>zsh</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+            <citerefentry project='die-net'><refentrytitle>ksh</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+            and
+            <citerefentry project='die-net'><refentrytitle>busybox</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
+            <citerefentry project='die-net'><refentrytitle>ash</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+            but not
+            <citerefentry project='die-net'><refentrytitle>dash</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+            or
+            <citerefentry project='die-net'><refentrytitle>fish</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+            </para>
           </listitem>
         </varlistentry>
         <varlistentry>
index 51d8ef5d82eb7ca3146853a6295240571c80d420..16ec257014e75489eab57bd19682d6be1866e754 100644 (file)
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-ask-password-console.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd-tty-ask-password</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-tty-ask-password-agent</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry project='die-net'><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry project='die-net'><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='man-pages'><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry>
index 2c285bcb22008ca1e373b063bb975b036b95811b..d71fdc644ff0d512723b39be5c6f28b4b47bbfc8 100644 (file)
 
     <para>In order to by used in the <option>--backtrace</option> mode, an appropriate backtrace
     handler must be installed on the sender side. For example, in case of
-    <citerefentry><refentrytitle>python</refentrytitle><manvolnum>1</manvolnum></citerefentry>, this
+    <citerefentry project='die-net'><refentrytitle>python</refentrytitle><manvolnum>1</manvolnum></citerefentry>, this
     means a <varname>sys.excepthook</varname> must installed, see
     <ulink url="https://github.com/keszybz/systemd-coredump-python">systemd-coredump-python</ulink>.
     </para>
index 6628213209d5fc1220dc200500828da28013e6f9..be241f6950f7b5105adea873f77ba85a4458dc34 100644 (file)
@@ -63,7 +63,7 @@
     compare configuration files that override other configuration
     files. Files in <filename>/etc</filename> have highest priority,
     files in <filename>/run</filename> have the second highest
-    priority, …, files in <filename>/lib</filename> have lowest
+    priority, …, files in <filename>/usr/lib</filename> have lowest
     priority. Files in a directory with higher priority override files
     with the same name in directories of lower priority. In addition,
     certain configuration files can have <literal>.d</literal>
index cc00a5256d6bbff32456476bf26d29010a8e7270..7950aa98a5c431cd44841de961f2e336200e4e38 100644 (file)
@@ -23,7 +23,7 @@
   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="systemd-environment-d-generator">
+<refentry id="systemd-environment-d-generator" conditional='ENABLE_ENVIRONMENT_D'>
 
   <refentryinfo>
     <title>systemd-environment-d-generator</title>
index 50d24d67f06edeae038a5d99469e1956d2cb5a45..b898d719f2213365748353da53cb52475cd4e8a5 100644 (file)
     for more information about special <filename>/etc/fstab</filename>
     mount options this generator understands.</para>
 
+    <para>One special topic is handling of symbolic links.  Historical init
+    implementations supported symlinks in <filename>/etc/fstab</filename>.
+    Because mount units will refuse mounts where the target is a symbolic link,
+    this generator will resolve any symlinks as far as possible when processing
+    <filename>/etc/fstab</filename> in order to enhance backwards compatibility.
+    If a symlink target does not exist at the time that this generator runs, it
+    is assumed that the symlink target is the final target of the mount.</para>
+
     <para><filename>systemd-fstab-generator</filename> implements
     <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
   </refsect1>
index d811b9b551bdeff4428dfc2f1e4b4a7a371788a4..3bbb6ab989426fded92243f311792a0ef4c9323b 100644 (file)
@@ -19,7 +19,7 @@
   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="systemd-hibernate-resume-generator">
+<refentry id="systemd-hibernate-resume-generator" conditional='ENABLE_HIBERNATE'>
 
   <refentryinfo>
     <title>systemd-hibernate-resume-generator</title>
index 7d008274478d868c29199c3ba562047c93261b19..a968adf0a9f7596a4eb6946eb21bef72731e24b5 100644 (file)
@@ -19,7 +19,7 @@
   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="systemd-hibernate-resume@.service">
+<refentry id="systemd-hibernate-resume@.service" conditional='ENABLE_HIBERNATE'>
 
   <refentryinfo>
     <title>systemd-hibernate-resume@.service</title>
index 8bba28678741d17908480aa8bf8372f2a57d4931..63e4fc40f11dc74509161dfd9bcfdfd81d425b6f 100644 (file)
       <arg choice="plain"><option>--list</option></arg>
     </cmdsynopsis>
     <cmdsynopsis>
-      <command>systemd-umount</command>
+      <command>systemd-mount</command>
       <arg choice="opt" rep="repeat"><replaceable>OPTIONS</replaceable></arg>
-      <arg choice="plain" rep="repeat"><replaceable>WHERE</replaceable></arg>
+      <arg choice="plain"><option>--umount</option></arg>
+      <arg choice="plain" rep="repeat"><replaceable>WHAT|WHERE</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
     <replaceable>WHERE</replaceable>.</para>
 
     <para>In many ways, <command>systemd-mount</command> is similar to the lower-level
-    <citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> command, however instead
+    <citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> command, however instead
     of executing the mount operation directly and immediately, <command>systemd-mount</command> schedules it through
     the service manager job queue, so that it may pull in further dependencies (such as parent mounts, or a file system
     checker to execute a priori), and may make use of the auto-mounting logic.</para>
 
     <para>The command takes either one or two arguments. If only one argument is specified it should refer to a block
-    device containing a file system (e.g. <literal>/dev/sdb1</literal>), which is then probed for a label and other
+    device or regular file containing a file system (e.g. <literal>/dev/sdb1</literal> or
+    <literal>/path/to/disk.img</literal>). If it is a block device, which is then probed for a label and other
     metadata, and is mounted to a directory whose name is generated from the label. In this mode the block device must
     exist at the time of invocation of the command, so that it may be probed. If the device is found to be a removable
     block device (e.g. a USB stick) an automount point instead of a regular mount point is created (i.e. the
         <term><option>--umount</option></term>
 
         <listitem><para>Stop the mount and automount units corresponding to the specified mount points
-        <replaceable>WHERE</replaceable>.</para>
-        </listitem>
+        <replaceable>WHERE</replaceable> or the devices <replaceable>WHAT</replaceable>.
+        <command>systemd-mount</command> with this option or <command>systemd-umount</command> can take multiple arguments
+        which can be mount points, devices, <filename>/etc/fstab</filename> style node names, or backing files
+        corresponding to loop devices, like
+        <command>systemd-mount --umount /path/to/umount /dev/sda1 UUID=xxxxxx-xxxx LABEL=xxxxx /path/to/disk.img</command>.
+        Note that when <option>-H</option> or <option>-M</option> is specified, only absolute paths to mount points are
+        supported.</para></listitem>
       </varlistentry>
 
       <xi:include href="user-system-options.xml" xpointer="user" />
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
index a7af8c25db6474f34811ec8d700d2b802a78ebce..5d3212dec7e60243899ffdd1fb871d23619702bc 100644 (file)
       <varlistentry>
         <term><option>--slice=</option></term>
 
-        <listitem><para>Make the container part of the specified
-        slice, instead of the default
-        <filename>machine.slice</filename>. This is only applies if
-        the machine is run in its own scope unit, i.e. if
-        <option>--keep-unit</option> is not used.</para>
+        <listitem><para>Make the container part of the specified slice, instead of the default
+        <filename>machine.slice</filename>. This applies only if the machine is run in its own scope unit, i.e. if
+        <option>--keep-unit</option> isn't used.</para>
         </listitem>
       </varlistentry>
 
       <varlistentry>
         <term><option>--property=</option></term>
 
-        <listitem><para>Set a unit property on the scope unit to
-        register for the machine. This only applies if the machine is
-        run in its own scope unit, i.e. if
-        <option>--keep-unit</option> is not used. Takes unit property
-        assignments in the same format as <command>systemctl
-        set-property</command>. This is useful to set memory limits
-        and similar for machines.</para>
+        <listitem><para>Set a unit property on the scope unit to register for the machine. This applies only if the
+        machine is run in its own scope unit, i.e. if <option>--keep-unit</option> isn't used. Takes unit property
+        assignments in the same format as <command>systemctl set-property</command>. This is useful to set memory
+        limits and similar for container.</para>
         </listitem>
       </varlistentry>
 
         broadcast domain, here called a "zone". Each container may only be part of one zone, but each zone may contain
         any number of containers. Each zone is referenced by its name. Names may be chosen freely (as long as they form
         valid network interface names when prefixed with <literal>vz-</literal>), and it is sufficient to pass the same
-        name to the <option>--network-zones=</option> switch of the various concurrently running containers to join
+        name to the <option>--network-zone=</option> switch of the various concurrently running containers to join
         them in one zone.</para>
 
         <para>Note that
       <varlistentry>
         <term><option>--register=</option></term>
 
-        <listitem><para>Controls whether the container is registered
-        with
-        <citerefentry><refentrytitle>systemd-machined</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
-        Takes a boolean argument, which defaults to <literal>yes</literal>.
-        This option should be enabled when the container runs a full
-        Operating System (more specifically: an init system), and is
-        useful to ensure that the container is accessible via
-        <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-        and shown by tools such as
-        <citerefentry project='man-pages'><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
-        If the container does not run an init system, it is
-        recommended to set this option to <literal>no</literal>.</para></listitem>
+        <listitem><para>Controls whether the container is registered with
+        <citerefentry><refentrytitle>systemd-machined</refentrytitle><manvolnum>8</manvolnum></citerefentry>.  Takes a
+        boolean argument, which defaults to <literal>yes</literal>.  This option should be enabled when the container
+        runs a full Operating System (more specifically: a system and service manager as PID 1), and is useful to
+        ensure that the container is accessible via
+        <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> and shown by
+        tools such as <citerefentry
+        project='man-pages'><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>.  If the container
+        does not run a service manager, it is recommended to set this option to
+        <literal>no</literal>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         service unit, and the service unit's sole purpose is to run a
         single <command>systemd-nspawn</command> container. This
         option is not available if run from a user
-        session.</para></listitem>
+        session.</para>
+        <para>Note that passing <option>--keep-unit</option> disables the effect of <option>--slice=</option> and
+        <option>--property=</option>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
       in a namespace container in it.</para>
     </example>
 
+    <example>
+      <title>Install the OpenSUSE Tumbleweed rolling distribution</title>
+
+      <programlisting># zypper --root=/var/lib/machines/tumbleweed ar -c \
+      https://download.opensuse.org/tumbleweed/repo/oss tumbleweed
+# zypper --root=/var/lib/machines/tumbleweed refresh
+# zypper --root=/var/lib/machines/tumbleweed install --no-recommends \
+      systemd shadow zypper openSUSE-release vim
+# systemd-nspawn -M tumbleweed passwd root
+# systemd-nspawn -M tumbleweed -b</programlisting>
+    </example>
+
     <example>
       <title>Boot into an ephemeral snapshot of the host system</title>
 
       <citerefentry project='mankier'><refentrytitle>dnf</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='die-net'><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='archlinux'><refentrytitle>pacman</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='mankier'><refentrytitle>zypper</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry project='man-pages'><refentrytitle>btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
index 50da971b07958a7dfa596404b3bab3afe4c8df19..e3ef26bb81e174eaa497869406f475b85804123e 100644 (file)
@@ -21,7 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="systemd-resolve"
+<refentry id="systemd-resolve" conditional='ENABLE_RESOLVED'
           xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
index 6ec384313beb672a1f697a4e3a6444a1292db9b1..3edcaf1b4e68995b4fe68f4e703e73b727049855 100644 (file)
     reboots to ensure it monotonically advances even if the system
     lacks a battery-buffered RTC chip.</para>
 
+    <para>The <filename>systemd-timesyncd</filename> service
+    specifically implements only SNTP. This minimalistic
+    service will set the system clock for large offsets or
+    slowly adjust it for smaller deltas. More complex use
+    cases are not covered by <filename>systemd-timesyncd</filename>.</para>
+
     <para>The NTP servers contacted are determined from the global
     settings in
     <citerefentry><refentrytitle>timesyncd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
index f2da2a7b772fe9f701eaebae065c18bb8e47450c..6df82aed32f77f07820689fcca34a4235d8e6b4b 100644 (file)
@@ -59,7 +59,7 @@
 
     <para><filename>systemd-vconsole-setup</filename> is a helper used to prepare either all virtual consoles, or — if
       the optional <replaceable>TTY</replaceable> parameter is provided — a specific one. When the system is booting up
-      it's called by <citerefentry><command>udev</command></citerefentry> during vtconsole subsystem initialization.
+      it's called by <citerefentry><refentrytitle>systemd-udevd</refentrytitle><manvolnum>8</manvolnum></citerefentry> during vtconsole subsystem initialization.
       <productname>Systemd</productname> also calls it internally as needed via
       <filename>systemd-vconsole-setup.service</filename>. The helper calls
       <citerefentry project='mankier'><refentrytitle>loadkeys</refentrytitle><manvolnum>1</manvolnum></citerefentry> and
index fedbd601755cda0966433bae1bad3ac3483566c6..ff8be928337727234165328598178998d5715c8b 100644 (file)
@@ -24,7 +24,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<refentry id="systemd.environment-generator" xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="systemd.environment-generator" conditional='ENABLE_ENVIRONMENT_D'
+    xmlns:xi="http://www.w3.org/2001/XInclude">
   <refentryinfo>
     <title>systemd.environment-generator</title>
     <productname>systemd</productname>
index 5d4986b6bfb508900881b734487be50b1245d2de..d28de2d0f24026f63927284f3e53d320b24ffe1a 100644 (file)
       <varlistentry>
         <term><varname>RootImage=</varname></term>
         <listitem><para>Takes a path to a block device node or regular file as argument. This call is similar to
-        <varname>RootDirectory=</varname> however mounts a file system hierarchy from a block device node or loopack
+        <varname>RootDirectory=</varname> however mounts a file system hierarchy from a block device node or loopback
         file instead of a directory. The device node or file system image file needs to contain a file system without a
         partition table, or a file system within an MBR/MS-DOS or GPT partition table with only a single
         Linux-compatible partition, or a set of file systems within a GPT partition table that follows the <ulink
         <term><varname>Group=</varname></term>
 
         <listitem><para>Set the UNIX user or group that the processes are executed as, respectively. Takes a single
-        user or group name, or numeric ID as argument. For system services (services run by the system service manager,
+        user or group name, or numeric ID as argument. For system services (services run by the system service manager,
         i.e. managed by PID 1) and for user services of the root user (services managed by root's instance of
         <command>systemd --user</command>), the default is <literal>root</literal>, but <varname>User=</varname> may be
         used to specify a different user. For user services of any other user, switching user identity is not
         permitted, hence the only valid setting is the same user the user's service manager is running as. If no group
         is set, the default group of the user is used. This setting does not affect commands whose command line is
-        prefixed with <literal>+</literal>.</para></listitem>
+        prefixed with <literal>+</literal>.</para>
+
+        <para>Note that restrictions on the user/group name syntax are enforced: the specified name must consist only
+        of the characters a-z, A-Z, 0-9, <literal>_</literal> and <literal>-</literal>, except for the first character
+        which must be one of a-z, A-Z or <literal>_</literal> (i.e. numbers and <literal>-</literal> are not permitted
+        as first character). The user/group name must have at least one character, and at most 31. These restrictions
+        are enforced in order to avoid ambiguities and to ensure user/group names and unit files remain portable among
+        Linux systems.</para>
+
+        <para>When used in conjunction with <varname>DynamicUser=</varname> the user/group name specified is
+        dynamically allocated at the time the service is started, and released at the time the service is stopped —
+        unless it is already allocated statically (see below). If <varname>DynamicUser=</varname> is not used the
+        specified user and group must have been created statically in the user database no later than the moment the
+        service is started, for example using the
+        <citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> facility, which
+        is applied at boot or package install time.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         assignments have no effect. Variable expansion is not
         performed inside the strings, however, specifier expansion is
         possible. The $ character has no special meaning. If you need
-        to assign a value containing spaces to a variable, use double
+        to assign a value containing spaces or the equals sign to a variable, use double
         quotes (") for the assignment.</para>
 
         <para>Example:
         <varname>After=</varname> dependencies on all mount units necessary to access <filename>/tmp</filename> and
         <filename>/var/tmp</filename>. Moreover an implicitly <varname>After=</varname> ordering on
         <citerefentry><refentrytitle>systemd-tmpfiles-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        is added.</para></listitem>
+        is added.</para>
+
+        <para>Note that the implementation of this setting might be impossible (for example if mount namespaces
+        are not available), and the unit should be written in a way that does not solely rely on this setting for
+        security.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term><varname>PrivateDevices=</varname></term>
 
-        <listitem><para>Takes a boolean argument. If true, sets up a new /dev namespace for the executed processes and
-        only adds API pseudo devices such as <filename>/dev/null</filename>, <filename>/dev/zero</filename> or
+        <listitem><para>Takes a boolean argument. If true, sets up a new <filename>/dev</filename> mount for the
+        executed processes and only adds API pseudo devices such as <filename>/dev/null</filename>,
+        <filename>/dev/zero</filename> or
         <filename>/dev/random</filename> (as well as the pseudo TTY subsystem) to it, but no physical devices such as
         <filename>/dev/sda</filename>, system memory <filename>/dev/mem</filename>, system ports
         <filename>/dev/port</filename> and others. This is useful to securely turn off physical device access by the
         <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
         for details). Note that using this setting will disconnect propagation of mounts from the service to the host
         (propagation in the opposite direction continues to work).  This means that this setting may not be used for
-        services which shall be able to install mount points in the main mount namespace. The /dev namespace will be
-        mounted read-only and 'noexec'.  The latter may break old programs which try to set up executable memory by
+        services which shall be able to install mount points in the main mount namespace. The new <filename>/dev</filename>
+        will be mounted read-only and 'noexec'. The latter may break old programs which try to set up executable memory by
         using <citerefentry><refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum></citerefentry> of
         <filename>/dev/zero</filename> instead of using <constant>MAP_ANON</constant>. This setting is implied if
         <varname>DynamicUser=</varname> is set. For this setting the same restrictions regarding mount propagation and
         If turned on and if running in user mode, or in system mode, but without the <constant>CAP_SYS_ADMIN</constant>
         capability (e.g. setting <varname>User=</varname>), <varname>NoNewPrivileges=yes</varname>
         is implied.
-        </para></listitem>
+        </para>
+
+        <para>Note that the implementation of this setting might be impossible (for example if mount namespaces
+        are not available), and the unit should be written in a way that does not solely rely on this setting for
+        security.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         configures only the loopback network device
         <literal>lo</literal> inside it. No other network devices will
         be available to the executed process. This is useful to
-        securely turn off network access by the executed process.
+        turn off network access by the executed process.
         Defaults to false. It is possible to run two or more units
         within the same private network namespace by using the
         <varname>JoinsNamespaceOf=</varname> directive, see
         The latter has the effect that AF_UNIX sockets in the abstract
         socket namespace will become unavailable to the processes
         (however, those located in the file system will continue to be
-        accessible).</para></listitem>
+        accessible).</para>
+
+        <para>Note that the implementation of this setting might be impossible (for example if network namespaces
+        are not available), and the unit should be written in a way that does not solely rely on this setting for
+        security.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <para>This setting is particularly useful in conjunction with
         <varname>RootDirectory=</varname>/<varname>RootImage=</varname>, as the need to synchronize the user and group
         databases in the root directory and on the host is reduced, as the only users and groups who need to be matched
-        are <literal>root</literal>, <literal>nobody</literal> and the unit's own user and group.</para></listitem>
+        are <literal>root</literal>, <literal>nobody</literal> and the unit's own user and group.</para>
+
+        <para>Note that the implementation of this setting might be impossible (for example if user namespaces
+        are not available), and the unit should be written in a way that does not solely rely on this setting for
+        security.</para></listitem>
       </varlistentry>
 
       <varlistentry>
 
         <listitem><para>Restricts access to Linux namespace functionality for the processes of this unit. For details
         about Linux namespaces, see
-        <citerefentry><refentrytitle>namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>. Either takes a
+        <citerefentry project='man-pages'><refentrytitle>namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>. Either takes a
         boolean argument, or a space-separated list of namespace type identifiers. If false (the default), no
         restrictions on namespace creation and switching are made. If true, access to any kind of namespacing is
         prohibited. Otherwise, a space-separated list of namespace type identifiers must be specified, consisting of
         the specified flags parameters into account. Note that — if this option is used — in addition to restricting
         creation and switching of the specified types of namespaces (or all of them, if true) access to the
         <function>setns()</function> system call with a zero flags parameter is prohibited.  This setting is only
-        supported on x86, x86-64, s390 and s390x, and enforces no restrictions on other architectures. If running in user
+        supported on x86, x86-64, mips, mips-le, mips64, mips64-le, mips64-n32, mips64-le-n32, ppc64, ppc64-le,
+        s390 and s390x, and enforces no restrictions on other architectures. If running in user
         mode, or in system mode, but without the <constant>CAP_SYS_ADMIN</constant> capability (e.g. setting
         <varname>User=</varname>), <varname>NoNewPrivileges=yes</varname> is implied.  </para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term><varname>RuntimeDirectory=</varname></term>
-        <term><varname>RuntimeDirectoryMode=</varname></term>
 
         <listitem><para>Takes a list of directory names. If set, one
         or more directories by the specified names will be created
         <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>RuntimeDirectoryMode=</varname></term>
+
+        <listitem><para>Specifies the access mode of the directories specified in
+        <varname>RuntimeDirectory=</varname> as an octal number. Defaults to
+        <constant>0755</constant>. See "Permissions" in
+        <citerefentry project='man-pages'><refentrytitle>path_resolution</refentrytitle><manvolnum>7</manvolnum></citerefentry> for a discussion of the meaning of permission bits.
+        </para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>MemoryDenyWriteExecute=</varname></term>
 
         <citerefentry><refentrytitle>mprotect</refentrytitle><manvolnum>2</manvolnum></citerefentry> system calls with
         <constant>PROT_EXEC</constant> set and
         <citerefentry><refentrytitle>shmat</refentrytitle><manvolnum>2</manvolnum></citerefentry> system calls with
-        <constant>SHM_EXEC</constant> set. Note that this option is incompatible with programs that generate program
-        code dynamically at runtime, such as JIT execution engines, or programs compiled making use of the code
+        <constant>SHM_EXEC</constant> set. Note that this option is incompatible with programs and libraries that
+        generate program code dynamically at runtime, including JIT execution engines, executable stacks, and code
         "trampoline" feature of various C compilers. This option improves service security, as it makes harder for
         software exploits to change running code dynamically. Note that this feature is fully available on x86-64, and
         partially on x86. Specifically, the <function>shmat()</function> protection is not available on x86. Note that
index 747d985aa11deb1547818d2849ccc5fd286d6aea..b82c1300ca056e316f36bed7727d9874ede71c62 100644 (file)
@@ -87,7 +87,7 @@
           recommended to be a UUID-compatible ID, but this is not
           enforced, and formatted differently. Developers can generate
           a new ID for this purpose with <command>journalctl
-          <option>--new-id</option></command>.
+          <option>--new-id128</option></command>.
           </para>
         </listitem>
       </varlistentry>
         <listitem>
           <para>The process, user, and group ID of the process the
           journal entry originates from formatted as a decimal
-          string.</para>
+          string. Note that entries obtained via <literal>stdout</literal> or
+          <literal>stderr</literal> of forked processes will contain credentials valid for a parent
+          process (that initiated the connection to <command>systemd-journald</command>).</para>
         </listitem>
       </varlistentry>
 
index 023e24eeb39469772f9f38529b3cf2c46dde31a0..1e4a1528db8988d09b4cae5097943db927289495 100644 (file)
           </variablelist>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Port=</varname></term>
+        <listitem>
+          <para>The port option is used to select the device port. The
+          supported values are:</para>
+
+          <variablelist>
+            <varlistentry>
+              <term><literal>tp</literal></term>
+              <listitem>
+                <para>An Ethernet interface using Twisted-Pair cable as the medium.</para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><literal>aui</literal></term>
+              <listitem>
+                <para>Attachment Unit Interface (AUI). Normally used with hubs.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><literal>bnc</literal></term>
+              <listitem>
+                <para>An Ethernet interface using BNC connectors and co-axial cable.</para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><literal>mii</literal></term>
+              <listitem>
+                <para>An Ethernet interface using a Media Independent Interface (MII).</para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><literal>fibre</literal></term>
+              <listitem>
+                <para>An Ethernet interface using Optical Fibre as the medium.</para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>TCPSegmentationOffload=</varname></term>
         <listitem>
index 4a404fb424f4066c84b21712ac513f067a0b7b3a..1bed7d17f162e0a8b06248b8efbdb6ab09c18af9 100644 (file)
 
     <para>The NFS mount option <option>bg</option> for NFS background mounts
     as documented in <citerefentry project='man-pages'><refentrytitle>nfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>
-    is not supported in <filename>/etc/fstab</filename> entries. The systemd mount option <option>nofail</option>
-    provides similar functionality and should be used instead.</para>
+    is detected by <command>systemd-fstab-generator</command> and the options
+    are transformed so that systemd fulfills the job-control implications of
+    that option.  Specifically <command>systemd-fstab-generator</command> acts
+    as though <literal>x-systemd.mount-timout=infinity,retry=10000</literal> was
+    prepended to the option list, and <literal>fg,nofail</literal> was appended.
+    Depending on specific requirements, it may be appropriate to provide some of
+    these options explicitly, or to make use of the
+    <literal>x-systemd.automount</literal> option described below instead
+    of using <literal>bg</literal>.</para>
 
     <para>When reading <filename>/etc/fstab</filename> a few special
     mount options are understood by systemd which influence how
         <listitem><para>The block device backed file system will be upgraded
         to <varname>BindsTo=</varname> dependency. This option is only useful
         when mounting file systems manually with
-        <citerefentry><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        <citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
         as the default dependency in this case is <varname>Requires=</varname>.
         This option is already implied by entries in <filename>/etc/fstab</filename>
         or by mount units.
 
       <varlistentry>
         <term><varname>Where=</varname></term>
-        <listitem><para>Takes an absolute path of a directory of the
-        mount point. If the mount point does not exist at the time of
+        <listitem><para>Takes an absolute path of a directory for the
+        mount point; in particular, the destination cannot be a symbolic
+        link.  If the mount point does not exist at the time of
         mounting, it is created. This string must be reflected in the
         unit filename. (See above.) This option is
         mandatory.</para></listitem>
index 39e69480ec4548222867ceed9d8131ae53009530..e925b302bf128064caa0aad5367d7310859b9eec 100644 (file)
           <row><entry><varname>vxlan</varname></entry>
           <entry>A virtual extensible LAN (vxlan), for connecting Cloud computing deployments.</entry></row>
 
+          <row><entry><varname>geneve</varname></entry>
+          <entry>A GEneric NEtwork Virtualization Encapsulation (GENEVE) netdev driver.</entry></row>
+
           <row><entry><varname>vrf</varname></entry>
           <entry>A Virtual Routing and Forwarding (<ulink url="https://www.kernel.org/doc/Documentation/networking/vrf.txt">VRF</ulink>) interface to create separate routing and forwarding domains.</entry></row>
 
         <varlistentry>
           <term><varname>DefaultPVID=</varname></term>
           <listitem>
-            <para>This specifies the default port VLAN ID of a newly attached bridge port.</para>
+            <para>This specifies the default port VLAN ID of a newly attached bridge port.
+            Set this to an integer in the range 1–4094 or <literal>none</literal> to disable the PVID.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
             This option is compulsory.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>GVRP=</varname></term>
+          <listitem>
+            <para>The Generic VLAN Registration Protocol (GVRP) is a protocol that
+            allows automatic learning of VLANs on a network. A boolean. When unset,
+            the kernel's default setting applies.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>MVRP=</varname></term>
+          <listitem>
+            <para>Multiple VLAN Registration Protocol (MVRP) formerly known as GARP VLAN
+            Registration Protocol (GVRP) is a standards-based Layer 2 network protocol,
+            for automatic configuration of VLAN information on switches. It was defined
+            in the 802.1ak amendment to 802.1Q-2005. A boolean. When unset, the kernel's
+            default setting applies.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>LooseBinding=</varname></term>
+          <listitem>
+            <para>The VLAN loose binding mode, in which only the operational state is passed
+            from the parent to the associated VLANs, but the VLAN device state is not changed.
+            A boolean. When unset, the kernel's default setting applies.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>ReorderHeader=</varname></term>
+          <listitem>
+            <para>The VLAN reorder header is set VLAN interfaces behave like physical interfaces.
+            A boolean. When unset, the kernel's default setting applies.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
-
   </refsect1>
 
   <refsect1>
       <listitem>
         <para>Configures the default destination UDP port on a per-device basis.
         If destination port is not specified then Linux kernel default will be used.
-        Set destination port 4789 to get the IANA assigned value,
-        and destination port 0 to get default values.</para>
+        Set destination port 4789 to get the IANA assigned value. If not set or if the
+        destination port is assigned the empty string the default port of 4789 is used.</para>
       </listitem>
     </varlistentry>
     <varlistentry>
           ports, and allows overriding via configuration.</para>
         </listitem>
       </varlistentry>
+    <varlistentry>
+      <term><varname>FlowLabel=</varname></term>
+        <listitem>
+          <para>Specifies the flow label to use in outgoing packets.
+          The valid range is 0-1048575.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1>
+    <title>[GENEVE] Section Options</title>
+    <para>The <literal>[GENEVE]</literal> section only applies for
+    netdevs of kind <literal>geneve</literal>, and accepts the
+    following keys:</para>
+
+    <variablelist class='network-directives'>
+      <varlistentry>
+        <term><varname>Id=</varname></term>
+        <listitem>
+          <para>Specifies the Virtual Network Identifer (VNI) to use. Ranges [0-16777215].</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Remote=</varname></term>
+        <listitem>
+          <para>Specifies the unicast destination IP address to use in outgoing packets.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>TOS=</varname></term>
+        <listitem>
+          <para>Specifies the TOS value to use in outgoing packets. Ranges [1-255].</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>TTL=</varname></term>
+        <listitem>
+          <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255].</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>UDPChecksum=</varname></term>
+        <listitem>
+          <para>A boolean. When true, specifies if UDP checksum is calculated for transmitted packets over IPv4.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>UDP6ZeroChecksumTx=</varname></term>
+        <listitem>
+          <para>A boolean. When true, skip UDP checksum calculation for transmitted packets over IPv6.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>UDP6ZeroChecksumRx=</varname></term>
+        <listitem>
+          <para>A boolean. When true, allows incoming UDP packets over IPv6 with zero checksum field.</para>
+        </listitem>
+      </varlistentry>
+    <varlistentry>
+      <term><varname>DestinationPort=</varname></term>
+      <listitem>
+        <para>Specifies destination port. Defaults to 6081. If not set or assigned the empty string, the default
+        port of 6081 is used.</para>
+      </listitem>
+    </varlistentry>
+    <varlistentry>
+      <term><varname>FlowLabel=</varname></term>
+        <listitem>
+          <para>Specifies the flow label to use in outgoing packets.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
index b807ebf29b8040d31a5c7176145c37757023126e..6b83a5b8515062ff7a8b97ef71f8fe5c02d2cf4f 100644 (file)
             <para>This setting is read by
             <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
             "Search domains" correspond to the <varname>domain</varname> and <varname>search</varname> entries in
-            <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+            <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
             Domain name routing has no equivalent in the traditional glibc API, which has no concept of domain
             name servers limited to a specific link.</para>
           </listitem>
         </para></listitem>
         </varlistentry>
         <varlistentry>
-          <term><varname>IPv6ProxyNDPAddress=</varname></term>
-          <listitem><para>An IPv6 address, for which Neighbour Advertisement
-          messages will be proxied.
-          Proxy NDP (Neighbor Discovery Protocol) is a technique for IPv6 to
-          allow routing of addresses to a different destination when peers expect them
-          to be present on a certain physical link.
+          <term><varname>IPv6ProxyNDP=</varname></term>
+          <listitem><para>A boolean. Configures proxy NDP for IPv6. Proxy NDP (Neighbor Discovery
+          Protocol) is a technique for IPv6 to allow routing of addresses to a different
+          destination when peers expect them to be present on a certain physical link.
           In this case a router answers Neighbour Advertisement messages intended for
           another machine by offering its own MAC address as destination.
-          Unlike proxy ARP for IPv4, is not enabled globally, but will only send Neighbour
+          Unlike proxy ARP for IPv4, it is not enabled globally, but will only send Neighbour
           Advertisement messages for addresses in the IPv6 neighbor proxy table,
-          which can also be shown by <command>ip -6 neighbour show proxy</command>
-          This option may be specified more than once. systemd-networkd will control the
-          per-interface `proxy_ndp` switch for each configured interface, depending on whether
-          there are <option>IPv6ProxyNDPAddress=</option> entries configured and add these to
-          the kernels IPv6 neighbor proxy table.
-          Defaults to unset.
+          which can also be shown by <command>ip -6 neighbour show proxy</command>.
+          systemd-networkd will control the per-interface `proxy_ndp` switch for each configured
+          interface depending on this option.
+          Defautls to unset.
+        </para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>IPv6ProxyNDPAddress=</varname></term>
+          <listitem><para>An IPv6 address, for which Neighbour Advertisement messages will be
+          proxied. This option may be specified more than once. systemd-networkd will add the
+          <option>IPv6ProxyNDPAddress=</option> entries to the kernel's IPv6 neighbor proxy table.
+          This option implies <option>IPv6ProxyNDP=true</option> but has no effect if
+          <option>IPv6ProxyNDP</option> has been set to false. Defaults to unset.
         </para></listitem>
         </varlistentry>
         <varlistentry>
       </variablelist>
   </refsect1>
 
+    <refsect1>
+    <title>[IPv6AddressLabel] Section Options</title>
+
+      <para>An <literal>[IPv6AddressLabel]</literal> section accepts the
+      following keys. Specify several <literal>[IPv6AddressLabel]</literal>
+      sections to configure several addresse labels. IPv6 address labels are
+      used for address selection. See <ulink url="https://tools.ietf.org/html/rfc3484">RFC 3484</ulink>.
+      Precedence is managed by userspace, and only the label itself is stored in the kernel</para>
+
+      <variablelist class='network-directives'>
+        <varlistentry>
+          <term><varname>Label=</varname></term>
+          <listitem>
+            <para> The label for the prefix (an unsigned integer) ranges 0 to 4294967294.
+            0xffffffff is reserved. This key is mandatory.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>Prefix=</varname></term>
+          <listitem>
+            <para>IPv6 prefix is an address with a prefix length, separated by a slash <literal>/</literal> character.
+            This key is mandatory. </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+  </refsect1>
+
   <refsect1>
     <title>[Route] Section Options</title>
       <para>The <literal>[Route]</literal> section accepts the
             <para>As in the <literal>[Network]</literal> section.</para>
           </listitem>
         </varlistentry>
+         <varlistentry>
+           <term><varname>GatewayOnlink=</varname></term>
+           <listitem>
+             <para>The <literal>GatewayOnlink</literal> option tells the kernel that it does not have
+             to check if the gateway is reachable directly by the current machine (i.e., the kernel does
+             not need to check if the gateway is attached to the local network), so that we can insert the
+             route in the kernel table without it being complained about. A boolean, defaults to <literal>no</literal>.
+             </para>
+           </listitem>
+         </varlistentry>
         <varlistentry>
           <term><varname>Destination=</varname></term>
           <listitem>
             <para>The metric of the route (an unsigned integer).</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>IPv6Preference=</varname></term>
+          <listitem>
+            <para>Specifies the route preference as defined in <ulink
+            url="https://tools.ietf.org/html/rfc4191">RFC4191</ulink> for Router Discovery messages.
+            Which can be one of <literal>low</literal> the route has a lowest priority,
+            <literal>medium</literal> the route has a default priority or
+            <literal>high</literal> the route has a highest priority.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>Scope=</varname></term>
           <listitem>
           </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>Protocol=</varname></term>
+          <listitem>
+            <para>The Protocol identifier for the route. Takes a number between 0 and 255 or the special values
+            <literal>kernel</literal>, <literal>boot</literal> and <literal>static</literal>. Defaults to
+            <literal>static</literal>.
+            </para>
+          </listitem>
+        </varlistentry>
       </variablelist>
   </refsect1>
 
         <varlistentry>
           <term><varname>UseRoutes=</varname></term>
           <listitem>
-            <para>When true (the default), the static routes will be
-            requested from the DHCP server and added to the routing
-            table with a metric of 1024.</para>
+            <para>When true (the default), the static routes will be requested from the DHCP server and added to the
+              routing table with a metric of 1024, and a scope of "global", "link" or "host", depending on the route's
+              destination and gateway. If the destination is on the local host, e.g., 127.x.x.x, or the same as the
+              link's own address, the scope will be set to "host". Otherwise if the gateway is null (a direct route), a
+              "link" scope will be used. For anything else, scope defaults to "global".</para>
           </listitem>
         </varlistentry>
 
             <para>Sets the "cost" of sending packets of this interface.
             Each port in a bridge may have a different speed and the cost
             is used to decide which link to use. Faster interfaces
-            should have lower costs.</para>
+            should have lower costs. It is an interger value between 1 and
+            65535.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>Priority=</varname></term>
+          <listitem>
+            <para>Sets the "priority" of sending packets on this interface.
+            Each port in a bridge may have a different priority which is used
+            to decide which link to use. Lower value means higher priority.
+            It is an interger value between 0 to 63. Networkd does not set any
+            default, meaning the kernel default value of 32 is used.</para>
           </listitem>
         </varlistentry>
       </variablelist>
@@ -1513,7 +1587,7 @@ VRF=vrf1
       <title>MacVTap</title>
       <para>This brings up a network interface <literal>macvtap-test</literal>
       and attaches it to <literal>enp0s25</literal>.</para>
-      <programlisting># /lib/systemd/network/25-macvtap.network
+      <programlisting># /usr/lib/systemd/network/25-macvtap.network
 [Match]
 Name=enp0s25
 
index 52eb2bb4247d2293fa9d4b3f797e11ddf7faa90a..da35a5205dcaeabfde9bb3edaac4cabcafd4c326 100644 (file)
         process has to exit before systemd starts follow-up units.
         <varname>RemainAfterExit=</varname> is particularly useful for
         this type of service. This is the implied default if neither
-        <varname>Type=</varname> or <varname>ExecStart=</varname> are
+        <varname>Type=</varname> nor <varname>ExecStart=</varname> are
         specified.</para>
 
         <para>Behavior of <option>dbus</option> is similar to
         all <varname>ExecStartPre=</varname> commands that were not prefixed
         with a <literal>-</literal> exit successfully.</para>
 
-        <para><varname>ExecStartPost=</varname> commands are only run after
-        the service has started successfully, as determined by <varname>Type=</varname>
-        (i.e. the process has been started for <varname>Type=simple</varname>
-        or <varname>Type=idle</varname>, the process exits successfully for
-        <varname>Type=oneshot</varname>, the initial process exits successfully
-        for <varname>Type=forking</varname>, <literal>READY=1</literal> is sent
-        for <varname>Type=notify</varname>, or the <varname>BusName=</varname>
-        has been taken for <varname>Type=dbus</varname>).</para>
+        <para><varname>ExecStartPost=</varname> commands are only run after the commands specified in
+        <varname>ExecStart=</varname> have been invoked successfully, as determined by <varname>Type=</varname>
+        (i.e. the process has been started for <varname>Type=simple</varname> or <varname>Type=idle</varname>, the last
+        <varname>ExecStart=</varname> process exited successfully for <varname>Type=oneshot</varname>, the initial
+        process exited successfully for <varname>Type=forking</varname>, <literal>READY=1</literal> is sent for
+        <varname>Type=notify</varname>, or the <varname>BusName=</varname> has been taken for
+        <varname>Type=dbus</varname>).</para>
 
         <para>Note that <varname>ExecStartPre=</varname> may not be
         used to start long-running processes. All processes forked
         multiple command lines, following the same scheme as described
         for <varname>ExecStart=</varname> above. Use of this setting
         is optional. After the commands configured in this option are
-        run, all processes remaining for a service are terminated
+        run, it is implied that the service is stopped, and any processes
+        remaining for it are terminated
         according to the <varname>KillMode=</varname> setting (see
         <citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
         If this option is not specified, the process is terminated by
 
         <para>As exceptions to the setting above, the service will not
         be restarted if the exit code or signal is specified in
-        <varname>RestartPreventExitStatus=</varname> (see below).
-        Also, the services will always be restarted if the exit code
-        or signal is specified in
+        <varname>RestartPreventExitStatus=</varname> (see below) or
+        the service is stopped with <command>systemctl stop</command>
+        or an equivalent operation. Also, the services will always be
+        restarted if the exit code or signal is specified in
         <varname>RestartForceExitStatus=</varname> (see below).</para>
 
         <para>Note that service restart is subject to unit start rate
 
       <varlistentry>
         <term><varname>NonBlocking=</varname></term>
-        <listitem><para>Set the <constant>O_NONBLOCK</constant> flag
-        for all file descriptors passed via socket-based activation.
-        If true, all file descriptors >= 3 (i.e. all except stdin,
-        stdout, and stderr) will have the
-        <constant>O_NONBLOCK</constant> flag set and hence are in
-        non-blocking mode. This option is only useful in conjunction
-        with a socket unit, as described in
-        <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
-        Defaults to false.</para></listitem>
+        <listitem><para>Set the <constant>O_NONBLOCK</constant> flag for all file descriptors passed via socket-based
+        activation. If true, all file descriptors >= 3 (i.e. all except stdin, stdout, stderr), excluding those passed
+        in via the file descriptor storage logic (see <varname>FileDescriptorStoreMax=</varname> for details), will
+        have the <constant>O_NONBLOCK</constant> flag set and hence are in non-blocking mode. This option is only
+        useful in conjunction with a socket unit, as described in
+        <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> and has no
+        effect on file descriptors which were previously saved in the file-descriptor store for example.  Defaults to
+        false.</para></listitem>
       </varlistentry>
 
       <varlistentry>
 
       <varlistentry>
         <term><varname>FileDescriptorStoreMax=</varname></term>
-        <listitem><para>Configure how many file descriptors may be
-        stored in the service manager for the service using
+        <listitem><para>Configure how many file descriptors may be stored in the service manager for the service using
         <citerefentry><refentrytitle>sd_pid_notify_with_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>'s
-        <literal>FDSTORE=1</literal> messages. This is useful for
-        implementing service restart schemes where the state is
-        serialized to <filename>/run</filename> and the file
-        descriptors passed to the service manager, to allow restarts
-        without losing state. Defaults to 0, i.e. no file descriptors
-        may be stored in the service manager. All file
-        descriptors passed to the service manager from a specific
-        service are passed back to the service's main process on the
-        next service restart. Any file descriptors passed to the
-        service manager are automatically closed when POLLHUP or
-        POLLERR is seen on them, or when the service is fully stopped
-        and no job is queued or being executed for it.</para></listitem>
+        <literal>FDSTORE=1</literal> messages. This is useful for implementing services that can restart after an
+        explicit request or a crash without losing state. Any open sockets and other file descriptors which should not
+        be closed during the restart may be stored this way. Application state can either be serialized to a file in
+        <filename>/run</filename>, or better, stored in a
+        <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> memory file
+        descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service manager. All file descriptors
+        passed to the service manager from a specific service are passed back to the service's main process on the next
+        service restart. Any file descriptors passed to the service manager are automatically closed when
+        <constant>POLLHUP</constant> or <constant>POLLERR</constant> is seen on them, or when the service is fully
+        stopped and no job is queued or being executed for it.</para></listitem>
       </varlistentry>
 
       <varlistentry>
 
     <para>Each command line is split on whitespace, with the first item being the command to
     execute, and the subsequent items being the arguments. Double quotes ("…") and single quotes
-    ('…') may be used, in which case everything until the next matching quote becomes part of the
-    same argument. Quotes themselves are removed. C-style escapes are also supported. The table
-    below contains the list of known escape patterns. Only escape patterns which match the syntax in
-    the table are allowed; other patterns may be added in the future and unknown patterns will
-    result in a warning. In particular, any backslashes should be doubled. Finally, a trailing
-    backslash (<literal>\</literal>) may be used to merge lines.</para>
-
-    <para>This syntax is intended to be very similar to shell syntax,
-    but only the meta-characters and expansions described in the
-    following paragraphs are understood. Specifically, redirection
-    using
+    ('…') may be used to wrap a whole item (the opening quote may appear only at the beginning or
+    after whitespace that is not quoted, and the closing quote must be followed by whitespace or the
+    end of line), in which case everything until the next matching quote becomes part of the same
+    argument. Quotes themselves are removed. C-style escapes are also supported. The table below
+    contains the list of known escape patterns. Only escape patterns which match the syntax in the
+    table are allowed; other patterns may be added in the future and unknown patterns will result in
+    a warning. In particular, any backslashes should be doubled. Finally, a trailing backslash
+    (<literal>\</literal>) may be used to merge lines.</para>
+
+    <para>This syntax is inspired by shell syntax, but only the meta-characters and expansions
+    described in the following paragraphs are understood, and the expansion of variables is
+    different. Specifically, redirection using
     <literal>&lt;</literal>,
     <literal>&lt;&lt;</literal>,
     <literal>&gt;</literal>, and
index fa3dc1c5d44f8a952943a0905e3ccd3d30784cad..66c45e39a3cd402fac8f9e40b3cc2ac99a0270e8 100644 (file)
   <refsect1>
     <title>Special Passive User Units</title>
 
-    <refsect2>
-      <title>graphical-session.target</title>
-
-      <para>This target is active whenever any graphical session is running. It
-      is used to stop user services which only apply to a graphical (X,
-      Wayland, etc.) session when the session is terminated. Such services
-      should have <literal>PartOf=graphical-session.target</literal> in their
-      <literal>[Unit]</literal> section. A target for a particular session
-      (e. g.  <filename>gnome-session.target</filename>) starts and stops
-      <literal>graphical-session.target</literal> with
-      <literal>BindsTo=graphical-session.target</literal>.</para>
-
-      <para>Which services are started by a session target is determined by the
-      <literal>Wants=</literal> and <literal>Requires=</literal> dependencies.
-      For services that can be enabled independently, symlinks in
-      <literal>.wants/</literal> and <literal>.requires/</literal> should be
-      used, see
-      <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
-      Those symlinks should either be shipped in packages, or should be added
-      dynamically after installation, for example using <literal>systemctl add-wants</literal>, see
-      <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
-      </para>
+    <variablelist>
+      <varlistentry>
+        <term><filename>graphical-session.target</filename></term>
+        <listitem>
+          <para>This target is active whenever any graphical session is running. It is used to stop user services which
+          only apply to a graphical (X, Wayland, etc.) session when the session is terminated. Such services should
+          have <literal>PartOf=graphical-session.target</literal> in their <literal>[Unit]</literal> section. A target
+          for a particular session (e. g.  <filename>gnome-session.target</filename>) starts and stops
+          <literal>graphical-session.target</literal> with <literal>BindsTo=graphical-session.target</literal>.</para>
+
+          <para>Which services are started by a session target is determined by the <literal>Wants=</literal> and
+          <literal>Requires=</literal> dependencies.  For services that can be enabled independently, symlinks in
+          <literal>.wants/</literal> and <literal>.requires/</literal> should be used, see
+          <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.  Those
+          symlinks should either be shipped in packages, or should be added dynamically after installation, for example
+          using <literal>systemctl add-wants</literal>, see
+          <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+          </para>
 
-      <example>
-        <title>Nautilus as part of a GNOME session</title>
+          <example>
+            <title>Nautilus as part of a GNOME session</title>
 
-        <para><literal>gnome-session.target</literal> pulls in Nautilus as
-        top-level service:</para>
+            <para><literal>gnome-session.target</literal> pulls in Nautilus as top-level service:</para>
 
-        <programlisting>[Unit]
+            <programlisting>[Unit]
 Description=User systemd services for GNOME graphical session
 Wants=nautilus.service
-BindsTo=graphical-session.target
-        </programlisting>
+BindsTo=graphical-session.target</programlisting>
 
-        <para><literal>nautilus.service</literal> gets stopped when the session stops:</para>
+            <para><literal>nautilus.service</literal> gets stopped when the session stops:</para>
 
-        <programlisting>[Unit]
+            <programlisting>[Unit]
 Description=Render the desktop icons with Nautilus
 PartOf=graphical-session.target
 
 [Service]
-…
-        </programlisting>
-      </example>
-    </refsect2>
-
-    <refsect2>
-      <title>graphical-session-pre.target</title>
-
-      <para>This target contains services which set up the environment or
-      global configuration of a graphical session, such as SSH/GPG agents
-      (which need to export an environment variable into all desktop processes)
-      or migration of obsolete d-conf keys after an OS upgrade (which needs to
-      happen before starting any process that might use them). This target must
-      be started before starting a graphical session
-      like <filename>gnome-session.target</filename>.</para>
-    </refsect2>
+…</programlisting>
+          </example>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><filename>graphical-session-pre.target</filename></term>
+        <listitem>
+          <para>This target contains services which set up the environment or global configuration of a graphical
+          session, such as SSH/GPG agents (which need to export an environment variable into all desktop processes) or
+          migration of obsolete d-conf keys after an OS upgrade (which needs to happen before starting any process that
+          might use them). This target must be started before starting a graphical session like
+          <filename>gnome-session.target</filename>.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
 
   </refsect1>
 
index b3cccd4e528a5a20add9ef745ecb055dfa4e7263..dbe7ff014bc91580cc2e561b638f413406daede1 100644 (file)
 
   </refsect1>
 
+  <refsect1>
+    <title>Example</title>
+
+    <example>
+      <title>Simple standalone target</title>
+
+      <programlisting># emergency-net.target
+
+[Unit]
+Description=Emergency Mode with Networking
+Requires=emergency.target systemd-networkd.service
+After=emergency.target systemd-networkd.service
+AllowIsolate=yes</programlisting>
+
+      <para>When adding dependencies to other units, it's important to check if they set
+      <varname>DefaultDependencies=</varname>. Service units, unless they set
+      <varname>DefaultDependencies=no</varname>, automatically get a dependency on
+      <filename>sysinit.target</filename>. In this case, both
+      <filename>emergency.target</filename> and <filename>systemd-networkd.service</filename>
+      have <varname>DefaultDependencies=no</varname>, so they are suitable for use
+      in this target, and do not pull in <filename>sysinit.target</filename>.</para>
+
+      <para>You can now switch into this emergency mode by running <varname>systemctl
+      isolate emergency-net.target</varname> or by passing the option
+      <varname>systemd.unit=emergency-net.target</varname> on the kernel command
+      line.</para>
+
+      <para>Other units can have <varname>WantedBy=emergency-net.target</varname> in the
+      <varname>[Install]</varname> section. After they are enabled using
+      <command>systemctl enable</command>, they will be started before
+      <varname>emergency-net.target</varname> is started. It is also possible to add
+      arbitrary units as dependencies of <filename>emergency.target</filename> without
+      modifying them by using <command>systemctl add-wants</command>.
+      </para>
+    </example>
+  </refsect1>
+
   <refsect1>
       <title>See Also</title>
       <para>
index d30c6cffc97e0f15ba6c739f77852b027331c152..659f14328e79b96a0cce90cb49c9fdb50e77f462 100644 (file)
     the local timezone, similar to the supported syntax of timestamps (see above). Non-local timezones except for UTC
     are not supported.</para>
 
-    <para>The special expressions
-    <literal>minutely</literal>,
-    <literal>hourly</literal>, <literal>daily</literal>,
-    <literal>monthly</literal>, <literal>weekly</literal>,
-    <literal>yearly</literal>,
-    <literal>quarterly</literal>,
-    <literal>semiannually</literal> may be used as
-    calendar events which refer to
-    <literal>*-*-* *:*:00</literal>,
-    <literal>*-*-* *:00:00</literal>,
-    <literal>*-*-* 00:00:00</literal>,
-    <literal>*-*-01 00:00:00</literal>,
-    <literal>Mon *-*-* 00:00:00</literal>,
-    <literal>*-01-01 00:00:00</literal>,
-    <literal>*-01,04,07,10-01 00:00:00</literal> and
-    <literal>*-01,07-01 00:00:00</literal>, respectively.
-    </para>
+  <para>The following special expressions may be used as shorthands for longer normalized forms:</para>
+
+    <programlisting>    minutely → *-*-* *:*:00
+      hourly → *-*-* *:00:00
+       daily → *-*-* 00:00:00
+     monthly → *-*-01 00:00:00
+      weekly → Mon *-*-* 00:00:00
+      yearly → *-01-01 00:00:00
+   quarterly → *-01,04,07,10-01 00:00:00
+semiannually → *-01,07-01 00:00:00
+   </programlisting>
 
     <para>Examples for valid timestamps and their
     normalized form:</para>
index 4fe140e4bc3c0aa7cf2db574ab8880469386ac1e..26a47a1e5ab12d2bc30ff87b2bd951c2c038ec90 100644 (file)
@@ -93,7 +93,7 @@
     on <filename>timers.target</filename>, as well as <varname>Conflicts=</varname> and <varname>Before=</varname> on
     <filename>shutdown.target</filename> to ensure that they are stopped cleanly prior to system shutdown.  Timer units
     with at least one <varname>OnCalendar=</varname> directive will have an additional <varname>After=</varname>
-    dependency on <filename>timer-sync.target</filename> to avoid being started before the system clock has been
+    dependency on <filename>time-sync.target</filename> to avoid being started before the system clock has been
     correctly set. Only timer units involved with early boot or late system shutdown should disable the
     <varname>DefaultDependencies=</varname> option.</para>
   </refsect1>
         <para>Note that timers do not necessarily expire at the
         precise time configured with this setting, as it is subject to
         the <varname>AccuracySec=</varname> setting
-        below.</para></listitem>
+        below.</para>
+
+       <para>May be specified more than once.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 44841ac7dd6c732907d247e13d5c34cb31f2dbb5..dedeb6c6d0128a62206af29d2dab26b51905434f 100644 (file)
         <term><varname>Before=</varname></term>
         <term><varname>After=</varname></term>
 
-        <listitem><para>A space-separated list of unit names.  Configures ordering dependencies between units. If a
-        unit <filename>foo.service</filename> contains a setting <option>Before=bar.service</option> and both units are
-        being started, <filename>bar.service</filename>'s start-up is delayed until <filename>foo.service</filename> is
-        started up.  Note that this setting is independent of and orthogonal to the requirement dependencies as
-        configured by <varname>Requires=</varname>, <varname>Wants=</varname> or <varname>BindsTo=</varname>. It is a
-        common pattern to include a unit name in both the <varname>After=</varname> and <varname>Requires=</varname>
-        option, in which case the unit listed will be started before the unit that is configured with these
-        options. This option may be specified more than once, in which case ordering dependencies for all listed names
-        are created. <varname>After=</varname> is the inverse of <varname>Before=</varname>, i.e. while
-        <varname>After=</varname> ensures that the configured unit is started after the listed unit finished starting
-        up, <varname>Before=</varname> ensures the opposite, i.e. that the configured unit is fully started up before
-        the listed unit is started. Note that when two units with an ordering dependency between them are shut down,
-        the inverse of the start-up order is applied. i.e. if a unit is configured with <varname>After=</varname> on
-        another unit, the former is stopped before the latter if both are shut down. Given two units with any ordering
-        dependency between them, if one unit is shut down and the other is started up, the shutdown is ordered before
-        the start-up. It doesn't matter if the ordering dependency is <varname>After=</varname> or
-        <varname>Before=</varname>, in this case. It also doesn't matter which of the two is shut down, as long as one
-        is shut down and the other is started up. The shutdown is ordered before the start-up in all cases. If two
-        units have no ordering dependencies between them, they are shut down or started up simultaneously, and no
-        ordering takes place.  </para></listitem>
+        <listitem><para>These two settings expect a space-separated list of unit names. They configure ordering
+        dependencies between units. If a unit <filename>foo.service</filename> contains a setting
+        <option>Before=bar.service</option> and both units are being started, <filename>bar.service</filename>'s
+        start-up is delayed until <filename>foo.service</filename> has finished starting up.  Note that this setting is
+        independent of and orthogonal to the requirement dependencies as configured by <varname>Requires=</varname>,
+        <varname>Wants=</varname> or <varname>BindsTo=</varname>. It is a common pattern to include a unit name in both
+        the <varname>After=</varname> and <varname>Requires=</varname> options, in which case the unit listed will be
+        started before the unit that is configured with these options. This option may be specified more than once, in
+        which case ordering dependencies for all listed names are created. <varname>After=</varname> is the inverse of
+        <varname>Before=</varname>, i.e. while <varname>After=</varname> ensures that the configured unit is started
+        after the listed unit finished starting up, <varname>Before=</varname> ensures the opposite, that the
+        configured unit is fully started up before the listed unit is started. Note that when two units with an
+        ordering dependency between them are shut down, the inverse of the start-up order is applied. i.e. if a unit is
+        configured with <varname>After=</varname> on another unit, the former is stopped before the latter if both are
+        shut down. Given two units with any ordering dependency between them, if one unit is shut down and the other is
+        started up, the shutdown is ordered before the start-up. It doesn't matter if the ordering dependency is
+        <varname>After=</varname> or <varname>Before=</varname>, in this case. It also doesn't matter which of the two
+        is shut down, as long as one is shut down and the other is started up. The shutdown is ordered before the
+        start-up in all cases. If two units have no ordering dependencies between them, they are shut down or started
+        up simultaneously, and no ordering takes place. It depends on the unit type when precisely a unit has finished
+        starting up. Most importantly, for service units start-up is considered completed for the purpose of
+        <varname>Before=</varname>/<varname>After=</varname> when all its configured start-up commands have been
+        invoked and they either failed or reported start-up success.</para></listitem>
       </varlistentry>
 
       <varlistentry>
 
       <varlistentry>
         <term><varname>JobTimeoutSec=</varname></term>
+        <term><varname>JobRunningTimeoutSec=</varname></term>
         <term><varname>JobTimeoutAction=</varname></term>
         <term><varname>JobTimeoutRebootArgument=</varname></term>
 
-        <listitem><para>When a job for this unit is queued, a time-out may be configured. If this time limit is
-        reached, the job will be cancelled, the unit however will not change state or even enter the
-        <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts disabled),
-        except for device units. NB: this timeout is independent from any unit-specific timeout (for example, the
-        timeout set with <varname>TimeoutStartSec=</varname> in service units) as the job timeout has no effect on the
-        unit itself, only on the job that might be pending for it. Or in other words: unit-specific timeouts are useful
-        to abort unit state changes, and revert them. The job timeout set with this option however is useful to abort
-        only the job waiting for the unit state to change.</para>
+        <listitem><para>When a job for this unit is queued, a time-out <varname>JobTimeoutSec=</varname> may be
+        configured. Similarly, <varname>JobRunningTimeoutSec=</varname> starts counting when the queued job is actually
+        started. If either time limit is reached, the job will be cancelled, the unit however will not change state or
+        even enter the <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts
+        disabled), except for device units (<varname>JobRunningTimeoutSec=</varname> defaults to
+        <varname>DefaultTimeoutStartSec=</varname>). NB: this timeout is independent from any unit-specific timeout
+        (for example, the timeout set with <varname>TimeoutStartSec=</varname> in service units) as the job timeout has
+        no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific
+        timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however
+        is useful to abort only the job waiting for the unit state to change.</para>
 
         <para><varname>JobTimeoutAction=</varname>
         optionally configures an additional
         <term><varname>ConditionDirectoryNotEmpty=</varname></term>
         <term><varname>ConditionFileNotEmpty=</varname></term>
         <term><varname>ConditionFileIsExecutable=</varname></term>
+        <term><varname>ConditionUser=</varname></term>
+        <term><varname>ConditionGroup=</varname></term>
 
         <!-- We do not document ConditionNull=
              here, as it is not particularly
         <varname>arm64-be</varname>,
         <varname>sh</varname>,
         <varname>sh64</varname>,
-        <varname>m86k</varname>,
+        <varname>m68k</varname>,
         <varname>tilegx</varname>,
-        <varname>cris</varname> to test
+        <varname>cris</varname>,
+        <varname>arc</varname>,
+        <varname>arc-be</varname> to test
         against a specific architecture. The architecture is
         determined from the information returned by
         <citerefentry project='man-pages'><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
         to make sure they run before the stamp file's modification
         time gets reset indicating a completed update.</para>
 
-        <para><varname>ConditionFirstBoot=</varname> takes a boolean
-        argument. This condition may be used to conditionalize units
-        on whether the system is booting up with an unpopulated
-        <filename>/etc</filename> directory. This may be used to
-        populate <filename>/etc</filename> on the first boot after
-        factory reset, or when a new system instances boots up for the
-        first time.</para>
+        <para><varname>ConditionFirstBoot=</varname> takes a boolean argument. This condition may be used to
+        conditionalize units on whether the system is booting up with an unpopulated <filename>/etc</filename>
+        directory (specifically: an <filename>/etc</filename> with no <filename>/etc/machine-id</filename>). This may
+        be used to populate <filename>/etc</filename> on the first boot after factory reset, or when a new system
+        instance boots up for the first time.</para>
 
         <para>With <varname>ConditionPathExists=</varname> a file
         existence condition is checked before a unit is started. If
         whether a certain path exists, is a regular file and marked
         executable.</para>
 
+        <para><varname>ConditionUser=</varname> takes a numeric
+        <literal>UID</literal>, a UNIX user name, or the special value
+        <literal>@system</literal>. This condition may be used to check
+        whether the service manager is running as the given user. The
+        special value <literal>@system</literal> can be used to check
+        if the user id is within the system user range. This option is not
+        useful for system services, as the system manager exclusively
+        runs as the root user, and thus the test result is constant.</para>
+
+        <para><varname>ConditionGroup=</varname> is similar
+        to <varname>ConditionUser=</varname> but verifies that the
+        service manager's real or effective group, or any of its
+        auxiliary groups match the specified group or GID. This setting
+        does not have a special value <literal>@system</literal>.</para>
+
         <para>If multiple conditions are specified, the unit will be
         executed if all of them apply (i.e. a logical AND is applied).
         Condition checks can be prefixed with a pipe symbol (|) in
         <term><varname>AssertDirectoryNotEmpty=</varname></term>
         <term><varname>AssertFileNotEmpty=</varname></term>
         <term><varname>AssertFileIsExecutable=</varname></term>
+        <term><varname>AssertUser=</varname></term>
+        <term><varname>AssertGroup=</varname></term>
 
         <listitem><para>Similar to the <varname>ConditionArchitecture=</varname>,
         <varname>ConditionVirtualization=</varname>, …, condition settings described above, these settings add
@@ -1384,7 +1409,7 @@ WantedBy=multi-user.target</programlisting>
       ordered appropriately (<varname>After=</varname>). Thirdly, in
       order to harden the service a bit more, the administrator would
       like to set the <varname>PrivateTmp=</varname> setting (see
-      <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
       for details). And lastly, the administrator would like to reset
       the niceness of the service to its default value of 0.</para>
 
index 18ee3800d67c4687ee73b755b99351cdb4799596..f232d9906d7b1009d77d13f34793e0c33aa66dbc 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <para><command>systemd-sysusers</command> uses the files from
-    <filename>sysusers.d</filename> directory to create system users
-    and groups at package installation or boot time. This tool may be
-    used to allocate system users and groups only, it is not useful
-    for creating non-system users and groups, as it accesses
-    <filename>/etc/passwd</filename> and
-    <filename>/etc/group</filename> directly, bypassing any more
-    complex user databases, for example any database involving NIS or
-    LDAP.</para>
+    <para><command>systemd-sysusers</command> uses the files from <filename>sysusers.d</filename> directory to create
+    system users and groups at package installation or boot time. This tool may be used to allocate system users and
+    groups only, it is not useful for creating non-system (i.e. regular, "human") users and groups, as it accesses
+    <filename>/etc/passwd</filename> and <filename>/etc/group</filename> directly, bypassing any more complex user
+    databases, for example any database involving NIS or LDAP.</para>
   </refsect1>
 
   <refsect1>
@@ -83,6 +79,9 @@ g input - -
 m authd input
 u root 0 "Superuser" /root</programlisting>
 
+    <para>Empty lines and lines beginning with the <literal>#</literal> character are ignored, and may be used for
+    commenting.</para>
+
     <refsect2>
       <title>Type</title>
 
@@ -134,14 +133,14 @@ u root 0 "Superuser" /root</programlisting>
     <refsect2>
       <title>Name</title>
 
-      <para>The name field specifies the user or group name. It should
-      be shorter than 31 characters and avoid any non-ASCII
-      characters, and not begin with a numeric character. It is
-      strongly recommended to pick user and group names that are
-      unlikely to clash with normal users created by the
-      administrator. A good scheme to guarantee this is by prefixing
-      all system and group names with the underscore, and avoiding too
-      generic names.</para>
+      <para>The name field specifies the user or group name. The specified name must consist only of the characters a-z,
+      A-Z, 0-9, <literal>_</literal> and <literal>-</literal>, except for the first character which must be one of a-z,
+      A-Z or <literal>_</literal> (i.e. numbers and <literal>-</literal> are not permitted as first character). The
+      user/group name must have at least one character, and at most 31.</para>
+
+      <para>It is strongly recommended to pick user and group names that are unlikely to clash with normal users
+      created by the administrator. A good scheme to guarantee this is by prefixing all system and group names with the
+      underscore, and avoiding too generic names.</para>
 
       <para>For <varname>m</varname> lines, this field should contain
       the user name to add to a group.</para>
index 1c7921f5bdd853a0ba6bc78096825dc940bc06a4..8d4fe31ec1c3a3b3060818a07a454c0b7ea81538 100644 (file)
           <term><option>-s</option></term>
           <term><option>--subsystem-match=<replaceable>string[/string]</replaceable></option></term>
           <listitem>
-            <para>Filter events by subsystem[/devtype]. Only udev events with a matching subsystem value will pass.</para>
+            <para>Filter kernel uevents and udev events by subsystem[/devtype]. Only events with a matching subsystem value will pass.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><option>-t</option></term>
           <term><option>--tag-match=<replaceable>string</replaceable></option></term>
           <listitem>
-            <para>Filter events by property. Only udev events with a given tag attached will pass.</para>
+            <para>Filter udev events by tag. Only udev events with a given tag attached will pass.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index fa30ca65696b2feea6de20af064775ae93c980fa..4a6672cbaea84144d301460591975a05fe7f4e41 100644 (file)
     <para>Depending on the operating system other configuration files
     might be checked for configuration of the virtual console as well,
     however only as fallback.</para>
+
+    <para><filename>/etc/vconsole.conf</filename> is usually created and updated
+    using
+    <citerefentry><refentrytitle>systemd-localed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+    <citerefentry><refentrytitle>localectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+    may be used to instruct <command>systemd-localed.service</command> to
+    query or update configuration.</para>
   </refsect1>
 
   <refsect1>
diff --git a/meson.build b/meson.build
new file mode 100644 (file)
index 0000000..20b27c8
--- /dev/null
@@ -0,0 +1,2528 @@
+project('systemd', 'c',
+        version : '234',
+        license : 'LGPLv2+',
+        default_options: [
+                'c_std=gnu99',
+                'prefix=/usr',
+                'sysconfdir=/etc',
+                'localstatedir=/var',
+        ],
+        meson_version : '>= 0.40',
+       )
+
+# We need the same data in three different formats, ugh!
+# Also, for hysterical reasons, we use different variable
+# names, sometimes. Not all variables are included in every
+# set. Ugh, ugh, ugh!
+conf = configuration_data()
+conf.set_quoted('PACKAGE_STRING',  meson.project_name() + ' ' + meson.project_version())
+conf.set_quoted('PACKAGE_VERSION', meson.project_version())
+
+substs = configuration_data()
+substs.set('PACKAGE_URL',          'https://www.freedesktop.org/wiki/Software/systemd')
+substs.set('PACKAGE_VERSION',      meson.project_version())
+
+m4_defines = []
+
+#####################################################################
+
+rootprefixdir = get_option('rootprefix')
+if get_option('split-usr')
+        conf.set('HAVE_SPLIT_USR', true)
+        rootprefixdir = rootprefixdir != '' ? rootprefixdir : '/'
+else
+        rootprefixdir = rootprefixdir != '' ? rootprefixdir : '/usr'
+endif
+
+sysvinit_path = get_option('sysvinit-path')
+sysvrcnd_path = get_option('sysvrcnd-path')
+if sysvinit_path != '' or sysvrcnd_path != ''
+        conf.set('HAVE_SYSV_COMPAT', true,
+                 description : 'SysV init scripts and rcN.d links are supported')
+        m4_defines += ['-DHAVE_SYSV_COMPAT']
+endif
+
+# join_paths ignore the preceding arguments if an absolute component is
+# encountered, so this should canonicalize various paths when they are
+# absolute or relative.
+prefixdir = get_option('prefix')
+if not prefixdir.startswith('/')
+        error('Prefix is not absolute: "@0@"'.format(prefixdir))
+endif
+bindir = join_paths(prefixdir, get_option('bindir'))
+libdir = join_paths(prefixdir, get_option('libdir'))
+sysconfdir = join_paths(prefixdir, get_option('sysconfdir'))
+includedir = join_paths(prefixdir, get_option('includedir'))
+datadir = join_paths(prefixdir, get_option('datadir'))
+localstatedir = join_paths('/', get_option('localstatedir'))
+
+rootbindir = join_paths(rootprefixdir, 'bin')
+rootlibexecdir = join_paths(rootprefixdir, 'lib/systemd')
+
+rootlibdir = get_option('rootlibdir')
+if rootlibdir == ''
+        rootlibdir = join_paths(rootprefixdir, libdir.split('/')[-1])
+endif
+
+# Dirs of external packages
+pkgconfigdatadir = join_paths(datadir, 'pkgconfig')
+pkgconfiglibdir = join_paths(libdir, 'pkgconfig')
+polkitpolicydir = join_paths(datadir, 'polkit-1/actions')
+polkitrulesdir = join_paths(datadir, 'polkit-1/rules.d')
+polkitpkladir = join_paths(localstatedir, 'lib/polkit-1/localauthority/10-vendor.d')
+varlogdir = join_paths(localstatedir, 'log')
+xinitrcdir = join_paths(sysconfdir, 'X11/xinit/xinitrc.d')
+rpmmacrosdir = get_option('rpmmacrosdir')
+
+# Our own paths
+pkgdatadir = join_paths(datadir, 'systemd')
+environmentdir = join_paths(prefixdir, 'lib/environment.d')
+pkgsysconfdir = join_paths(sysconfdir, 'systemd')
+userunitdir = join_paths(prefixdir, 'lib/systemd/user')
+userpresetdir = join_paths(prefixdir, 'lib/systemd/user-preset')
+tmpfilesdir = join_paths(prefixdir, 'lib/tmpfiles.d')
+sysusersdir = join_paths(prefixdir, 'lib/sysusers.d')
+sysctldir = join_paths(prefixdir, 'lib/sysctl.d')
+binfmtdir = join_paths(prefixdir, 'lib/binfmt.d')
+modulesloaddir = join_paths(prefixdir, 'lib/modules-load.d')
+networkdir = join_paths(rootprefixdir, 'lib/systemd/network')
+pkgincludedir = join_paths(includedir, 'systemd')
+systemgeneratordir = join_paths(rootlibexecdir, 'system-generators')
+usergeneratordir = join_paths(prefixdir, 'lib/systemd/user-generators')
+systemenvgeneratordir = join_paths(prefixdir, 'lib/systemd/system-environment-generators')
+userenvgeneratordir = join_paths(prefixdir, 'lib/systemd/user-environment-generators')
+systemshutdowndir = join_paths(rootlibexecdir, 'system-shutdown')
+systemsleepdir = join_paths(rootlibexecdir, 'system-sleep')
+systemunitdir = join_paths(rootprefixdir, 'lib/systemd/system')
+systempresetdir = join_paths(rootprefixdir, 'lib/systemd/system-preset')
+udevlibexecdir = join_paths(rootprefixdir, 'lib/udev')
+udevhomedir = udevlibexecdir
+udevrulesdir = join_paths(udevlibexecdir, 'rules.d')
+udevhwdbdir = join_paths(udevlibexecdir, 'hwdb.d')
+catalogdir = join_paths(prefixdir, 'lib/systemd/catalog')
+kernelinstalldir = join_paths(prefixdir, 'lib/kernel/install.d')
+factorydir = join_paths(datadir, 'factory')
+docdir = join_paths(datadir, 'doc/systemd')
+bootlibdir = join_paths(prefixdir, 'lib/systemd/boot/efi')
+testsdir = join_paths(prefixdir, 'lib/systemd/tests')
+systemdstatedir = join_paths(localstatedir, 'lib/systemd')
+catalogstatedir = join_paths(systemdstatedir, 'catalog')
+randomseeddir = join_paths(localstatedir, 'lib/systemd')
+
+dbuspolicydir = get_option('dbuspolicydir')
+if dbuspolicydir == ''
+        dbuspolicydir = join_paths(datadir, 'dbus-1/system.d')
+endif
+
+dbussessionservicedir = get_option('dbussessionservicedir')
+if dbussessionservicedir == ''
+        dbussessionservicedir = join_paths(datadir, 'dbus-1/services')
+endif
+
+dbussystemservicedir = get_option('dbussystemservicedir')
+if dbussystemservicedir == ''
+        dbussystemservicedir = join_paths(datadir, 'dbus-1/system-services')
+endif
+
+pamlibdir = get_option('pamlibdir')
+if pamlibdir == ''
+        pamlibdir = join_paths(rootlibdir, 'security')
+endif
+
+pamconfdir = get_option('pamconfdir')
+if pamconfdir == ''
+        pamconfdir = join_paths(sysconfdir, 'pam.d')
+endif
+
+conf.set_quoted('PKGSYSCONFDIR',                              pkgsysconfdir)
+conf.set_quoted('SYSTEM_CONFIG_UNIT_PATH',                    join_paths(pkgsysconfdir, 'system'))
+conf.set_quoted('SYSTEM_DATA_UNIT_PATH',                      systemunitdir)
+conf.set_quoted('SYSTEM_SYSVINIT_PATH',                       sysvinit_path)
+conf.set_quoted('SYSTEM_SYSVRCND_PATH',                       sysvrcnd_path)
+conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START',                 get_option('rc-local'))
+conf.set_quoted('RC_LOCAL_SCRIPT_PATH_STOP',                  get_option('halt-local'))
+conf.set_quoted('USER_CONFIG_UNIT_PATH',                      join_paths(pkgsysconfdir, 'user'))
+conf.set_quoted('USER_DATA_UNIT_PATH',                        userunitdir)
+conf.set_quoted('CERTIFICATE_ROOT',                           get_option('certificate-root'))
+conf.set_quoted('CATALOG_DATABASE',                           join_paths(catalogstatedir, 'database'))
+conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH',                  join_paths(rootlibexecdir, 'systemd-cgroups-agent'))
+conf.set_quoted('SYSTEMD_BINARY_PATH',                        join_paths(rootlibexecdir, 'systemd'))
+conf.set_quoted('SYSTEMD_FSCK_PATH',                          join_paths(rootlibexecdir, 'systemd-fsck'))
+conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               join_paths(rootlibexecdir, 'systemd-shutdown'))
+conf.set_quoted('SYSTEMD_SLEEP_BINARY_PATH',                  join_paths(rootlibexecdir, 'systemd-sleep'))
+conf.set_quoted('SYSTEMCTL_BINARY_PATH',                      join_paths(rootbindir, 'systemctl'))
+conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent'))
+conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH',           join_paths(bindir, 'systemd-stdio-bridge'))
+conf.set_quoted('ROOTPREFIX',                                 rootprefixdir)
+conf.set_quoted('RANDOM_SEED_DIR',                            randomseeddir)
+conf.set_quoted('RANDOM_SEED',                                join_paths(randomseeddir, 'random-seed'))
+conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH',                    join_paths(rootlibexecdir, 'systemd-cryptsetup'))
+conf.set_quoted('SYSTEM_GENERATOR_PATH',                      systemgeneratordir)
+conf.set_quoted('USER_GENERATOR_PATH',                        usergeneratordir)
+conf.set_quoted('SYSTEM_ENV_GENERATOR_PATH',                  systemenvgeneratordir)
+conf.set_quoted('USER_ENV_GENERATOR_PATH',                    userenvgeneratordir)
+conf.set_quoted('SYSTEM_SHUTDOWN_PATH',                       systemshutdowndir)
+conf.set_quoted('SYSTEM_SLEEP_PATH',                          systemsleepdir)
+conf.set_quoted('SYSTEMD_KBD_MODEL_MAP',                      join_paths(pkgdatadir, 'kbd-model-map'))
+conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP',              join_paths(pkgdatadir, 'language-fallback-map'))
+conf.set_quoted('UDEVLIBEXECDIR',                             udevlibexecdir)
+conf.set_quoted('POLKIT_AGENT_BINARY_PATH',                   join_paths(bindir, 'pkttyagent'))
+conf.set_quoted('LIBDIR',                                     libdir)
+conf.set_quoted('ROOTLIBDIR',                                 rootlibdir)
+conf.set_quoted('ROOTLIBEXECDIR',                             rootlibexecdir)
+conf.set_quoted('BOOTLIBDIR',                                 bootlibdir)
+conf.set_quoted('SYSTEMD_PULL_PATH',                          join_paths(rootlibexecdir, 'systemd-pull'))
+conf.set_quoted('SYSTEMD_IMPORT_PATH',                        join_paths(rootlibexecdir, 'systemd-import'))
+conf.set_quoted('SYSTEMD_EXPORT_PATH',                        join_paths(rootlibexecdir, 'systemd-export'))
+conf.set_quoted('VENDOR_KEYRING_PATH',                        join_paths(rootlibexecdir, 'import-pubring.gpg'))
+conf.set_quoted('USER_KEYRING_PATH',                          join_paths(pkgsysconfdir, 'import-pubring.gpg'))
+conf.set_quoted('DOCUMENT_ROOT',                              join_paths(pkgdatadir, 'gatewayd'))
+
+conf.set_quoted('ABS_BUILD_DIR',                              meson.build_root())
+conf.set_quoted('ABS_SRC_DIR',                                meson.source_root())
+
+substs.set('prefix',                                          prefixdir)
+substs.set('exec_prefix',                                     prefixdir)
+substs.set('libdir',                                          libdir)
+substs.set('rootlibdir',                                      rootlibdir)
+substs.set('includedir',                                      includedir)
+substs.set('pkgsysconfdir',                                   pkgsysconfdir)
+substs.set('bindir',                                          bindir)
+substs.set('rootbindir',                                      rootbindir)
+substs.set('rootlibexecdir',                                  rootlibexecdir)
+substs.set('systemunitdir',                                   systemunitdir)
+substs.set('userunitdir',                                     userunitdir)
+substs.set('systempresetdir',                                 systempresetdir)
+substs.set('userpresetdir',                                   userpresetdir)
+substs.set('udevhwdbdir',                                     udevhwdbdir)
+substs.set('udevrulesdir',                                    udevrulesdir)
+substs.set('udevlibexecdir',                                  udevlibexecdir)
+substs.set('catalogdir',                                      catalogdir)
+substs.set('tmpfilesdir',                                     tmpfilesdir)
+substs.set('sysusersdir',                                     sysusersdir)
+substs.set('sysctldir',                                       sysctldir)
+substs.set('binfmtdir',                                       binfmtdir)
+substs.set('modulesloaddir',                                  modulesloaddir)
+substs.set('systemgeneratordir',                              systemgeneratordir)
+substs.set('usergeneratordir',                                usergeneratordir)
+substs.set('systemenvgeneratordir',                           systemenvgeneratordir)
+substs.set('userenvgeneratordir',                             userenvgeneratordir)
+substs.set('systemshutdowndir',                               systemshutdowndir)
+substs.set('systemsleepdir',                                  systemsleepdir)
+substs.set('VARLOGDIR',                                       varlogdir)
+substs.set('CERTIFICATEROOT',                                 get_option('certificate-root'))
+substs.set('SYSTEMCTL',                                       join_paths(rootbindir, 'systemctl'))
+substs.set('RANDOM_SEED',                                     join_paths(randomseeddir, 'random-seed'))
+substs.set('SYSTEM_SYSVINIT_PATH',                            sysvinit_path)
+substs.set('SYSTEM_SYSVRCND_PATH',                            sysvrcnd_path)
+substs.set('RC_LOCAL_SCRIPT_PATH_START',                      get_option('rc-local'))
+substs.set('RC_LOCAL_SCRIPT_PATH_STOP',                       get_option('halt-local'))
+
+#####################################################################
+
+cc = meson.get_compiler('c')
+pkgconfig = import('pkgconfig')
+check_compilation_sh = find_program('tools/meson-check-compilation.sh')
+
+cxx = find_program('c++', required : false)
+if cxx.found()
+        #  Used only for tests
+        add_languages('cpp')
+endif
+
+foreach arg : ['-Wextra',
+               '-Wundef',
+               '-Wlogical-op',
+               '-Wmissing-include-dirs',
+               '-Wold-style-definition',
+               '-Wpointer-arith',
+               '-Winit-self',
+               '-Wdeclaration-after-statement',
+               '-Wfloat-equal',
+               '-Wsuggest-attribute=noreturn',
+               '-Werror=missing-prototypes',
+               '-Werror=implicit-function-declaration',
+               '-Werror=missing-declarations',
+               '-Werror=return-type',
+               '-Werror=incompatible-pointer-types',
+               '-Werror=format=2',
+               '-Wstrict-prototypes',
+               '-Wredundant-decls',
+               '-Wmissing-noreturn',
+               '-Wshadow',
+               '-Wendif-labels',
+               '-Wstrict-aliasing=2',
+               '-Wwrite-strings',
+               '-Werror=overflow',
+               '-Wdate-time',
+               '-Wnested-externs',
+               '-ffast-math',
+               '-fno-common',
+               '-fdiagnostics-show-option',
+               '-fno-strict-aliasing',
+               '-fvisibility=hidden',
+               '-fstack-protector',
+               '-fstack-protector-strong',
+               '-fPIE',
+               '--param=ssp-buffer-size=4',
+              ]
+        if cc.has_argument(arg)
+                add_project_arguments(arg, language : 'c')
+        endif
+endforeach
+
+# "negative" arguments: gcc on purpose does not return an error for "-Wno-"
+# arguments, just emits a warnings. So test for the "positive" version instead.
+foreach arg : ['unused-parameter',
+               'missing-field-initializers',
+               'unused-result',
+               'format-signedness']
+        if cc.has_argument('-W' + arg)
+                add_project_arguments('-Wno-' + arg, language : 'c')
+        endif
+endforeach
+
+if cc.compiles('
+   #include <time.h>
+   #include <inttypes.h>
+   typedef uint64_t usec_t;
+   usec_t now(clockid_t clock);
+   int main(void) {
+           struct timespec now;
+           return 0;
+   }
+', name : '-Werror=shadow with local shadowing')
+        add_project_arguments('-Werror=shadow', language : 'c')
+endif
+
+if cc.get_id() == 'clang'
+        foreach arg : ['-Wno-typedef-redefinition',
+                       '-Wno-gnu-variable-sized-type-not-at-end',
+                      ]
+                if cc.has_argument(arg,
+                                   name : '@0@ is supported'.format(arg))
+                        add_project_arguments(arg, language : 'c')
+                endif
+        endforeach
+endif
+
+link_test_c = files('tools/meson-link-test.c')
+
+# --as-needed and --no-undefined are provided by meson by default,
+# run mesonconf to see what is enabled
+foreach arg : ['-Wl,-z,relro',
+               '-Wl,-z,now',
+               '-pie',
+              ]
+
+        have = run_command(check_compilation_sh,
+                           cc.cmd_array(), '-x', 'c', arg,
+                           '-include', link_test_c).returncode() == 0
+        message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
+        if have
+                add_project_link_arguments(arg, language : 'c')
+        endif
+endforeach
+
+if get_option('buildtype') != 'debug'
+        foreach arg : ['-ffunction-sections',
+                       '-fdata-sections']
+                if cc.has_argument(arg,
+                                   name : '@0@ is supported'.format(arg))
+                        add_project_arguments(arg, language : 'c')
+                endif
+        endforeach
+
+        foreach arg : ['-Wl,--gc-sections']
+                have = run_command(check_compilation_sh,
+                                   cc.cmd_array(), '-x', 'c', arg,
+                                   '-include', link_test_c).returncode() == 0
+                message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
+                if have
+                        add_project_link_arguments(arg, language : 'c')
+                endif
+        endforeach
+endif
+
+cpp = ' '.join(cc.cmd_array()) + ' -E'
+
+#####################################################################
+# compilation result tests
+
+conf.set('_GNU_SOURCE', true)
+conf.set('__SANE_USERSPACE_TYPES__', true)
+
+conf.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_GID_T', cc.sizeof('gid_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
+conf.set('SIZEOF_TIME_T', cc.sizeof('time_t', prefix : '#include <sys/time.h>'))
+conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
+
+decl_headers = '''
+#include <uchar.h>
+#include <linux/ethtool.h>
+'''
+# FIXME: key_serial_t is only defined in keyutils.h, this is bound to fail
+
+foreach decl : ['char16_t',
+                'char32_t',
+                'key_serial_t',
+                'struct ethtool_link_settings',
+               ]
+
+        # We get -1 if the size cannot be determined
+        have = cc.sizeof(decl, prefix : decl_headers) > 0
+        conf.set('HAVE_' + decl.underscorify().to_upper(), have)
+endforeach
+
+foreach decl : [['IFLA_INET6_ADDR_GEN_MODE',         'linux/if_link.h'],
+                ['IN6_ADDR_GEN_MODE_STABLE_PRIVACY', 'linux/if_link.h'],
+                ['IFLA_VRF_TABLE',                   'linux/if_link.h'],
+                ['IFLA_MACVLAN_FLAGS',               'linux/if_link.h'],
+                ['IFLA_IPVLAN_MODE',                 'linux/if_link.h'],
+                ['IFLA_PHYS_PORT_ID',                'linux/if_link.h'],
+                ['IFLA_BOND_AD_INFO',                'linux/if_link.h'],
+                ['IFLA_VLAN_PROTOCOL',               'linux/if_link.h'],
+                ['IFLA_VXLAN_REMCSUM_NOPARTIAL',     'linux/if_link.h'],
+                ['IFLA_VXLAN_GPE',                   'linux/if_link.h'],
+                ['IFLA_GENEVE_LABEL',                'linux/if_link.h'],
+                # if_tunnel.h is buggy and cannot be included on its own
+                ['IFLA_VTI_REMOTE',                  'linux/if_tunnel.h', '#include <net/if.h>'],
+                ['IFLA_IPTUN_ENCAP_DPORT',           'linux/if_tunnel.h', '#include <net/if.h>'],
+                ['IFLA_GRE_ENCAP_DPORT',             'linux/if_tunnel.h', '#include <net/if.h>'],
+                ['IFLA_BRIDGE_VLAN_INFO',            'linux/if_bridge.h'],
+                ['IFLA_BRPORT_PROXYARP',             'linux/if_link.h'],
+                ['IFLA_BRPORT_LEARNING_SYNC',        'linux/if_link.h'],
+                ['IFLA_BR_VLAN_DEFAULT_PVID',        'linux/if_link.h'],
+                ['NDA_IFINDEX',                      'linux/neighbour.h'],
+                ['IFA_FLAGS',                        'linux/if_addr.h'],
+                ['LO_FLAGS_PARTSCAN',                'linux/loop.h'],
+               ]
+        prefix = decl.length() > 2 ? decl[2] : ''
+        have = cc.has_header_symbol(decl[1], decl[0], prefix : prefix)
+        conf.set10('HAVE_DECL_' + decl[0], have)
+endforeach
+
+skip = false
+foreach ident : ['secure_getenv', '__secure_getenv']
+        if not skip and cc.has_function(ident)
+                conf.set('HAVE_' + ident.to_upper(), true)
+                skip = true
+        endif
+endforeach
+
+foreach ident : [
+        ['memfd_create',      '''#include <sys/memfd.h>'''],
+        ['gettid',            '''#include <sys/types.h>'''],
+        ['pivot_root',        '''#include <stdlib.h>'''],     # no known header declares pivot_root
+        ['name_to_handle_at', '''#define _GNU_SOURCE
+                                 #include <sys/types.h>
+                                 #include <sys/stat.h>
+                                 #include <fcntl.h>'''],
+        ['setns',             '''#define _GNU_SOURCE
+                                 #include <sched.h>'''],
+        ['renameat2',         '''#include <stdio.h>'''],
+        ['kcmp',              '''#include <linux/kcmp.h>'''],
+        ['keyctl',            '''#include <sys/types.h>
+                                 #include <keyutils.h>'''],
+        ['copy_file_range',   '''#include <sys/syscall.h>
+                                 #include <unistd.h>'''],
+        ['explicit_bzero' ,   '''#include <string.h>'''],
+]
+
+        have = cc.has_function(ident[0], prefix : ident[1])
+        conf.set10('HAVE_DECL_' + ident[0].to_upper(), have)
+endforeach
+
+if cc.has_function('getrandom', prefix : '''#include <sys/random.h>''')
+        conf.set('USE_SYS_RANDOM_H', true)
+        conf.set10('HAVE_DECL_GETRANDOM', true)
+else
+        have = cc.has_function('getrandom', prefix : '''#include <linux/random.h>''')
+        conf.set10('HAVE_DECL_GETRANDOM', have)
+endif
+
+#####################################################################
+
+sed = find_program('sed')
+grep = find_program('grep')
+awk = find_program('awk')
+m4 = find_program('m4')
+stat = find_program('stat')
+git = find_program('git', required : false)
+
+meson_make_symlink = meson.source_root() + '/tools/meson-make-symlink.sh'
+mkdir_p = 'mkdir -p $DESTDIR/@0@'
+test_efi_create_disk_sh = find_program('test/test-efi-create-disk.sh')
+splash_bmp = files('test/splash.bmp')
+
+# if -Dxxx-path option is found, use that. Otherwise, check in $PATH,
+# /usr/sbin, /sbin, and fall back to the default from middle column.
+progs = [['telinit',    '/lib/sysvinit/telinit'],
+         ['quotaon',    '/usr/sbin/quotaon'    ],
+         ['quotacheck', '/usr/sbin/quotacheck' ],
+         ['kill',       '/usr/bin/kill'        ],
+         ['kmod',       '/usr/bin/kmod'        ],
+         ['kexec',      '/usr/sbin/kexec'      ],
+         ['sulogin',    '/usr/sbin/sulogin'    ],
+         ['mount',      '/usr/bin/mount',      'MOUNT_PATH'],
+         ['umount',     '/usr/bin/umount',     'UMOUNT_PATH'],
+         ['loadkeys',   '/usr/bin/loadkeys',   'KBD_LOADKEYS'],
+         ['setfont',    '/usr/bin/setfont',    'KBD_SETFONT'],
+        ]
+foreach prog : progs
+        path = get_option(prog[0] + '-path')
+        if path != ''
+                message('Using @1@ for @0@'.format(prog[0], path))
+        else
+                exe = find_program(prog[0],
+                                   '/usr/sbin/' + prog[0],
+                                   '/sbin/' + prog[0],
+                                   required: false)
+                path = exe.found() ? exe.path() : prog[1]
+        endif
+        name = prog.length() > 2 ? prog[2] : prog[0].to_upper()
+        conf.set_quoted(name, path)
+        substs.set(name, path)
+endforeach
+
+if run_command('ln', '--relative', '--help').returncode() != 0
+        error('ln does not support --relative')
+endif
+
+############################################################
+
+gperf = find_program('gperf')
+
+gperf_test_format = '''
+#include <string.h>
+const char * in_word_set(const char *, @0@);
+@1@
+'''
+gperf_snippet_format = 'echo foo,bar | @0@ -L ANSI-C'
+gperf_snippet = run_command('sh', '-c', gperf_snippet_format.format(gperf.path()))
+gperf_test = gperf_test_format.format('size_t', gperf_snippet.stdout())
+if cc.compiles(gperf_test)
+        gperf_len_type = 'size_t'
+else
+        gperf_test = gperf_test_format.format('unsigned', gperf_snippet.stdout())
+        if cc.compiles(gperf_test)
+                gperf_len_type = 'unsigned'
+        else
+                error('unable to determine gperf len type')
+        endif
+endif
+message('gperf len type is @0@'.format(gperf_len_type))
+conf.set('GPERF_LEN_TYPE', gperf_len_type,
+         description : 'The type of gperf "len" parameter')
+
+############################################################
+
+if not cc.has_header('sys/capability.h')
+        error('POSIX caps headers not found')
+endif
+foreach header : ['linux/btrfs.h',
+                  'linux/memfd.h',
+                  'linux/vm_sockets.h',
+                  'valgrind/memcheck.h',
+                  'valgrind/valgrind.h',
+                 ]
+
+        conf.set('HAVE_' + header.underscorify().to_upper(),
+                 cc.has_header(header))
+endforeach
+
+############################################################
+
+conf.set_quoted('FALLBACK_HOSTNAME', get_option('fallback-hostname'))
+
+default_hierarchy = get_option('default-hierarchy')
+conf.set_quoted('DEFAULT_HIERARCHY_NAME', default_hierarchy,
+                description : 'default cgroup hierarchy as string')
+if default_hierarchy == 'legacy'
+        conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_NONE')
+elif default_hierarchy == 'hybrid'
+        conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_SYSTEMD')
+else
+        conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_ALL')
+endif
+
+time_epoch = get_option('time-epoch')
+if time_epoch == ''
+        NEWS = files('NEWS')
+        time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout()
+endif
+time_epoch = time_epoch.to_int()
+conf.set('TIME_EPOCH', time_epoch)
+
+system_uid_max = get_option('system-uid-max')
+if system_uid_max == ''
+        system_uid_max = run_command(
+                awk,
+                'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }',
+                '/etc/login.defs').stdout()
+endif
+system_uid_max = system_uid_max.to_int()
+conf.set('SYSTEM_UID_MAX', system_uid_max)
+substs.set('systemuidmax', system_uid_max)
+message('maximum system UID is @0@'.format(system_uid_max))
+
+conf.set_quoted('NOBODY_USER_NAME', get_option('nobody-user'))
+conf.set_quoted('NOBODY_GROUP_NAME', get_option('nobody-group'))
+
+system_gid_max = get_option('system-gid-max')
+if system_gid_max == ''
+        system_gid_max = run_command(
+                awk,
+                'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }',
+                '/etc/login.defs').stdout()
+endif
+system_gid_max = system_gid_max.to_int()
+conf.set('SYSTEM_GID_MAX', system_gid_max)
+substs.set('systemgidmax', system_gid_max)
+message('maximum system GID is @0@'.format(system_gid_max))
+
+tty_gid = get_option('tty-gid')
+conf.set('TTY_GID', tty_gid)
+substs.set('TTY_GID', tty_gid)
+
+if get_option('adm-group')
+        m4_defines += ['-DENABLE_ADM_GROUP']
+endif
+
+if get_option('wheel-group')
+        m4_defines += ['-DENABLE_WHEEL_GROUP']
+endif
+
+substs.set('DEV_KVM_MODE', get_option('dev-kvm-mode'))
+
+kill_user_processes = get_option('default-kill-user-processes')
+conf.set10('KILL_USER_PROCESSES', kill_user_processes)
+substs.set('KILL_USER_PROCESSES', kill_user_processes ? 'yes' : 'no')
+
+dns_servers = get_option('dns-servers')
+conf.set_quoted('DNS_SERVERS', dns_servers)
+substs.set('DNS_SERVERS', dns_servers)
+
+ntp_servers = get_option('ntp-servers')
+conf.set_quoted('NTP_SERVERS', ntp_servers)
+substs.set('NTP_SERVERS', ntp_servers)
+
+conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
+
+substs.set('SUSHELL', get_option('debug-shell'))
+substs.set('DEBUGTTY', get_option('debug-tty'))
+
+debug = get_option('debug')
+if debug != ''
+        foreach name : debug.split(',')
+                if name == 'hashmap'
+                        conf.set('ENABLE_DEBUG_HASHMAP', true)
+                elif name == 'mmap-cache'
+                        conf.set('ENABLE_DEBUG_MMAP_CACHE', true)
+                else
+                        message('unknown debug option "@0@", ignoring'.format(name))
+                endif
+        endforeach
+endif
+
+#####################################################################
+
+threads = dependency('threads')
+librt = cc.find_library('rt')
+libm = cc.find_library('m')
+libdl = cc.find_library('dl')
+libcrypt = cc.find_library('crypt')
+
+libcap = dependency('libcap', required : false)
+if not libcap.found()
+        # Compat with Ubuntu 14.04 which ships libcap w/o .pc file
+        libcap = cc.find_library('cap')
+endif
+
+libmount = dependency('mount',
+                      version : '>= 2.27')
+
+want_seccomp = get_option('seccomp')
+if want_seccomp != 'false'
+        libseccomp = dependency('libseccomp',
+                                version : '>= 2.3.1',
+                                required : want_seccomp == 'true')
+        if libseccomp.found()
+                conf.set('HAVE_SECCOMP', true)
+                m4_defines += ['-DHAVE_SECCOMP']
+        endif
+else
+        libseccomp = []
+endif
+
+want_selinux = get_option('selinux')
+if want_selinux != 'false'
+        libselinux = dependency('libselinux',
+                                version : '>= 2.1.9',
+                                required : want_selinux == 'true')
+        if libselinux.found()
+                conf.set('HAVE_SELINUX', true)
+                m4_defines += ['-DHAVE_SELINUX']
+        endif
+else
+        libselinux = []
+endif
+
+want_apparmor = get_option('apparmor')
+if want_apparmor != 'false'
+        libapparmor = dependency('libapparmor',
+                                 required : want_apparmor == 'true')
+        if libapparmor.found()
+                conf.set('HAVE_APPARMOR', true)
+                m4_defines += ['-DHAVE_APPARMOR']
+        endif
+else
+        libapparmor = []
+endif
+
+smack_run_label = get_option('smack-run-label')
+if smack_run_label != ''
+        conf.set_quoted('SMACK_RUN_LABEL', smack_run_label)
+        m4_defines += ['-DHAVE_SMACK_RUN_LABEL']
+endif
+
+want_polkit = get_option('polkit')
+install_polkit = false
+install_polkit_pkla = false
+if want_polkit != 'false'
+        conf.set('ENABLE_POLKIT', true)
+        install_polkit = true
+
+        libpolkit = dependency('polkit-gobject-1',
+                               required : false)
+        if libpolkit.found() and libpolkit.version().version_compare('< 0.106')
+                message('Old polkit detected, will install pkla files')
+                install_polkit_pkla = true
+        endif
+endif
+
+want_acl = get_option('acl')
+if want_acl != 'false'
+        libacl = cc.find_library('acl', required : want_acl == 'true')
+        if libacl.found()
+                conf.set('HAVE_ACL', true)
+                m4_defines += ['-DHAVE_ACL']
+        endif
+else
+        libacl = []
+endif
+
+want_audit = get_option('audit')
+if want_audit != 'false'
+        libaudit = dependency('audit', required : want_audit == 'true')
+        conf.set('HAVE_AUDIT', libaudit.found())
+else
+        libaudit = []
+endif
+
+want_blkid = get_option('blkid')
+if want_blkid != 'false'
+        libblkid = dependency('blkid', required : want_blkid == 'true')
+        conf.set('HAVE_BLKID', libblkid.found())
+else
+        libblkid = []
+endif
+
+want_kmod = get_option('kmod')
+if want_kmod != 'false'
+        libkmod = dependency('libkmod',
+                             version : '>= 15',
+                             required : want_kmod == 'true')
+        conf.set('HAVE_KMOD', libkmod.found())
+else
+        libkmod = []
+endif
+
+want_pam = get_option('pam')
+if want_pam != 'false'
+        libpam = cc.find_library('pam', required : want_pam == 'true')
+        libpam_misc = cc.find_library('pam_misc', required : want_pam == 'true')
+        if libpam.found() and libpam_misc.found()
+                conf.set('HAVE_PAM', true)
+                m4_defines += ['-DHAVE_PAM']
+        endif
+else
+        libpam = []
+        libpam_misc = []
+endif
+
+want_microhttpd = get_option('microhttpd')
+if want_microhttpd != 'false'
+        libmicrohttpd = dependency('libmicrohttpd',
+                                   version : '>= 0.9.33',
+                                   required : want_microhttpd == 'true')
+        if libmicrohttpd.found()
+                conf.set('HAVE_MICROHTTPD', true)
+                m4_defines += ['-DHAVE_MICROHTTPD']
+        endif
+else
+        libmicrohttpd = []
+endif
+
+want_libcryptsetup = get_option('libcryptsetup')
+if want_libcryptsetup != 'false'
+        libcryptsetup = dependency('libcryptsetup',
+                                   version : '>= 1.6.0',
+                                   required : want_libcryptsetup == 'true')
+        conf.set('HAVE_LIBCRYPTSETUP', libcryptsetup.found())
+else
+        libcryptsetup = []
+endif
+
+want_libcurl = get_option('libcurl')
+if want_libcurl != 'false'
+        libcurl = dependency('libcurl',
+                             version : '>= 7.32.0',
+                             required : want_libcurl == 'true')
+        if libcurl.found()
+                conf.set('HAVE_LIBCURL', true)
+                m4_defines += ['-DHAVE_LIBCURL']
+        endif
+else
+        libcurl = []
+endif
+
+want_libidn = get_option('libidn')
+want_libidn2 = get_option('libidn2')
+if want_libidn == 'true' and want_libidn2 == 'true'
+        error('libidn and libidn2 cannot be requested simultaneously')
+endif
+
+if want_libidn != 'false' and want_libidn2 != 'true'
+        libidn = dependency('libidn',
+                            required : want_libidn == 'true')
+        if libidn.found()
+                conf.set('HAVE_LIBIDN', true)
+                m4_defines += ['-DHAVE_LIBIDN']
+        endif
+else
+        libidn = []
+endif
+if not conf.get('HAVE_LIBIDN', false) and want_libidn2 != 'false'
+        # libidn is used for both libidn and libidn2 objects
+        libidn = dependency('libidn2',
+                            required : want_libidn2 == 'true')
+        if libidn.found()
+                conf.set('HAVE_LIBIDN2', true)
+                m4_defines += ['-DHAVE_LIBIDN2']
+        endif
+endif
+
+want_libiptc = get_option('libiptc')
+if want_libiptc != 'false'
+        libiptc = dependency('libiptc',
+                             required : want_libiptc == 'true')
+        if libiptc.found()
+                conf.set('HAVE_LIBIPTC', true)
+                m4_defines += ['-DHAVE_LIBIPTC']
+        endif
+else
+        libiptc = []
+endif
+
+want_qrencode = get_option('qrencode')
+if want_qrencode != 'false'
+        libqrencode = dependency('libqrencode',
+                                 required : want_qrencode == 'true')
+        conf.set('HAVE_QRENCODE', libqrencode.found())
+else
+        libqrencode = []
+endif
+
+want_gnutls = get_option('gnutls')
+if want_gnutls != 'false'
+        libgnutls = dependency('gnutls',
+                               version : '>= 3.1.4',
+                               required : want_gnutls == 'true')
+        conf.set('HAVE_GNUTLS', libgnutls.found())
+else
+        libgnutls = []
+endif
+
+want_elfutils = get_option('elfutils')
+if want_elfutils != 'false'
+        libdw = dependency('libdw',
+                           required : want_elfutils == 'true')
+        conf.set('HAVE_ELFUTILS', libdw.found())
+else
+        libdw = []
+endif
+
+want_zlib = get_option('zlib')
+if want_zlib != 'false'
+        libz = dependency('zlib',
+                          required : want_zlib == 'true')
+        conf.set('HAVE_ZLIB', libz.found())
+else
+        libz = []
+endif
+
+want_bzip2 = get_option('bzip2')
+if want_bzip2 != 'false'
+        libbzip2 = cc.find_library('bz2',
+                                   required : want_bzip2 == 'true')
+        conf.set('HAVE_BZIP2', libbzip2.found())
+else
+        libbzip2 = []
+endif
+
+want_xz = get_option('xz')
+if want_xz != 'false'
+        libxz = dependency('liblzma',
+                           required : want_xz == 'true')
+        conf.set('HAVE_XZ', libxz.found())
+else
+        libxz = []
+endif
+
+want_lz4 = get_option('lz4')
+if want_lz4 != 'false'
+        liblz4 = dependency('liblz4',
+                            required : want_lz4 == 'true')
+        conf.set('HAVE_LZ4', liblz4.found())
+else
+        liblz4 = []
+endif
+
+want_glib = get_option('glib')
+if want_glib != 'false'
+        libglib =    dependency('glib-2.0',
+                                version : '>= 2.22.0',
+                                required : want_glib == 'true')
+        libgobject = dependency('gobject-2.0',
+                                version : '>= 2.22.0',
+                                required : want_glib == 'true')
+        libgio =     dependency('gio-2.0',
+                                required : want_glib == 'true')
+        have = libglib.found() and libgobject.found() and libgio.found()
+        conf.set('HAVE_GLIB', have)
+else
+        libglib = []
+        libgobject = []
+        libgio = []
+endif
+
+want_xkbcommon = get_option('xkbcommon')
+if want_xkbcommon != 'false'
+        libxkbcommon = dependency('xkbcommon',
+                                  version : '>= 0.3.0',
+                                  required : want_xkbcommon == 'true')
+        conf.set('HAVE_XKBCOMMON', libxkbcommon.found())
+else
+        libxkbcommon = []
+endif
+
+want_dbus = get_option('dbus')
+if want_dbus != 'false'
+        libdbus = dependency('dbus-1',
+                             version : '>= 1.3.2',
+                             required : want_dbus == 'true')
+        conf.set('HAVE_DBUS', libdbus.found())
+else
+        libdbus = []
+endif
+
+want_gcrypt = get_option('gcrypt')
+if want_gcrypt != 'false'
+        libgcrypt = cc.find_library('gcrypt', required : want_gcrypt == 'true')
+        libgpg_error = cc.find_library('gpg-error', required : want_gcrypt == 'true')
+
+        have_deps = libgcrypt.found() and libgpg_error.found()
+        conf.set('HAVE_GCRYPT', have_deps)
+        if not have_deps
+                # link to neither of the libs if one is not found
+                libgcrypt = []
+                libgpg_error = []
+        endif
+else
+        libgcrypt = []
+        libgpg_error = []
+endif
+
+default_dnssec = get_option('default-dnssec')
+if default_dnssec != 'no' and not conf.get('HAVE_GCRYPT', false)
+        message('default-dnssec cannot be set to yes or allow-downgrade when gcrypt is disabled. Setting default-dnssec to no.')
+        default_dnssec = 'no'
+endif
+conf.set('DEFAULT_DNSSEC_MODE',
+         'DNSSEC_' + default_dnssec.underscorify().to_upper())
+substs.set('DEFAULT_DNSSEC_MODE', default_dnssec)
+
+want_importd = get_option('importd')
+if want_importd != 'false'
+        have_deps = (conf.get('HAVE_LIBCURL', false) and
+                     conf.get('HAVE_ZLIB', false) and
+                     conf.get('HAVE_BZIP2', false) and
+                     conf.get('HAVE_XZ', false) and
+                     conf.get('HAVE_GCRYPT', false))
+        conf.set('ENABLE_IMPORTD', have_deps)
+        if want_importd == 'true' and not have_deps
+                error('importd support was requested, but dependencies are not available')
+        endif
+endif
+
+want_remote = get_option('remote')
+if want_remote != 'false'
+        have_deps = [conf.get('HAVE_MICROHTTPD', false),
+                     conf.get('HAVE_LIBCURL', false)]
+        # sd-j-remote requires µhttpd, and sd-j-upload requires libcurl, so
+        # it's possible to build one without the other. Complain only if
+        # support was explictly requested. The auxiliary files like sysusers
+        # config should be installed when any of the programs are built.
+        if want_remote == 'true' and not (have_deps[0] and have_deps[1])
+                error('remote support was requested, but dependencies are not available')
+        endif
+        conf.set('ENABLE_REMOTE', have_deps[0] or have_deps[1])
+endif
+
+foreach pair : [['utmp',          'HAVE_UTMP'],
+                ['hibernate',     'ENABLE_HIBERNATE'],
+                ['environment-d', 'ENABLE_ENVIRONMENT_D'],
+                ['binfmt',        'ENABLE_BINFMT'],
+                ['coredump',      'ENABLE_COREDUMP'],
+                ['resolve',       'ENABLE_RESOLVED'],
+                ['logind',        'ENABLE_LOGIND'],
+                ['hostnamed',     'ENABLE_HOSTNAMED'],
+                ['localed',       'ENABLE_LOCALED'],
+                ['machined',      'ENABLE_MACHINED'],
+                ['networkd',      'ENABLE_NETWORKD'],
+                ['timedated',     'ENABLE_TIMEDATED'],
+                ['timesyncd',     'ENABLE_TIMESYNCD'],
+                ['myhostname',    'HAVE_MYHOSTNAME'],
+                ['firstboot',     'ENABLE_FIRSTBOOT'],
+                ['randomseed',    'ENABLE_RANDOMSEED'],
+                ['backlight',     'ENABLE_BACKLIGHT'],
+                ['vconsole',      'ENABLE_VCONSOLE'],
+                ['quotacheck',    'ENABLE_QUOTACHECK'],
+                ['sysusers',      'ENABLE_SYSUSERS'],
+                ['tmpfiles',      'ENABLE_TMPFILES'],
+                ['hwdb',          'ENABLE_HWDB'],
+                ['rfkill',        'ENABLE_RFKILL'],
+                ['ldconfig',      'ENABLE_LDCONFIG'],
+                ['efi',           'ENABLE_EFI'],
+                ['tpm',           'SD_BOOT_LOG_TPM'],
+                ['ima',           'HAVE_IMA'],
+                ['smack',         'HAVE_SMACK'],
+                ['gshadow',       'ENABLE_GSHADOW'],
+                ['idn',           'ENABLE_IDN'],
+                ['nss-systemd',   'ENABLE_NSS_SYSTEMD'],
+               ]
+
+        if get_option(pair[0])
+                conf.set(pair[1], true)
+                m4_defines += ['-D' + pair[1]]
+        endif
+endforeach
+
+want_tests = get_option('tests')
+install_tests = get_option('install-tests')
+tests = []
+
+#####################################################################
+
+if get_option('efi')
+        efi_arch = host_machine.cpu_family()
+
+        if efi_arch == 'x86'
+                EFI_MACHINE_TYPE_NAME = 'ia32'
+                gnu_efi_arch = 'ia32'
+        elif efi_arch == 'x86_64'
+                EFI_MACHINE_TYPE_NAME = 'x64'
+                gnu_efi_arch = 'x86_64'
+        elif efi_arch == 'arm'
+                EFI_MACHINE_TYPE_NAME = 'arm'
+                gnu_efi_arch = 'arm'
+        elif efi_arch == 'aarch64'
+                EFI_MACHINE_TYPE_NAME = 'aa64'
+                gnu_efi_arch = 'aarch64'
+        else
+                EFI_MACHINE_TYPE_NAME = ''
+                gnu_efi_arch = ''
+        endif
+
+        conf.set('ENABLE_EFI', true)
+        conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME)
+
+        conf.set('SD_TPM_PCR', get_option('tpm-pcrindex').to_int())
+endif
+
+#####################################################################
+
+config_h = configure_file(
+        output : 'config.h',
+        configuration : conf)
+
+includes = include_directories('src/basic',
+                               'src/shared',
+                               'src/systemd',
+                               'src/journal',
+                               'src/resolve',
+                               'src/timesync',
+                               'src/login',
+                               'src/udev',
+                               'src/libudev',
+                               'src/core',
+                               'src/libsystemd/sd-bus',
+                               'src/libsystemd/sd-device',
+                               'src/libsystemd/sd-hwdb',
+                               'src/libsystemd/sd-id128',
+                               'src/libsystemd/sd-netlink',
+                               'src/libsystemd/sd-network',
+                               'src/libsystemd-network',
+                              )
+
+add_project_arguments('-include', 'config.h', language : 'c')
+
+gcrypt_util_sources = files('src/shared/gcrypt-util.h',
+                            'src/shared/gcrypt-util.c')
+
+subdir('po')
+subdir('catalog')
+subdir('src/systemd')
+subdir('src/basic')
+subdir('src/libsystemd')
+subdir('src/libsystemd-network')
+subdir('src/journal')
+subdir('src/login')
+
+libjournal_core = static_library(
+        'journal-core',
+        libjournal_core_sources,
+        journald_gperf_c,
+        include_directories : includes,
+        install : false)
+
+libsystemd_sym_path = '@0@/@1@'.format(meson.current_source_dir(), libsystemd_sym)
+libsystemd = shared_library(
+        'systemd',
+        libsystemd_internal_sources,
+        journal_internal_sources,
+        version : '0.19.0',
+        include_directories : includes,
+        link_args : ['-shared',
+                     '-Wl,--version-script=' + libsystemd_sym_path],
+        link_with : [libbasic],
+        dependencies : [threads,
+                        libgcrypt,
+                        librt,
+                        libxz,
+                        liblz4],
+        link_depends : libsystemd_sym,
+        install : true,
+        install_dir : rootlibdir)
+
+############################################################
+
+# binaries that have --help and are intended for use by humans,
+# usually, but not always, installed in /bin.
+public_programs = []
+
+subdir('src/libudev')
+subdir('src/shared')
+subdir('src/core')
+subdir('src/udev')
+subdir('src/network')
+
+subdir('src/analyze')
+subdir('src/journal-remote')
+subdir('src/coredump')
+subdir('src/hostname')
+subdir('src/import')
+subdir('src/kernel-install')
+subdir('src/locale')
+subdir('src/machine')
+subdir('src/nspawn')
+subdir('src/resolve')
+subdir('src/timedate')
+subdir('src/timesync')
+subdir('src/vconsole')
+subdir('src/sulogin-shell')
+subdir('src/boot/efi')
+
+subdir('src/test')
+subdir('test')
+
+############################################################
+
+# only static linking apart from libdl, to make sure that the
+# module is linked to all libraries that it uses.
+test_dlopen = executable(
+        'test-dlopen',
+        test_dlopen_c,
+        include_directories : includes,
+        link_with : [libbasic],
+        dependencies : [libdl])
+
+foreach tuple : [['myhostname', 'HAVE_MYHOSTNAME'],
+                 ['systemd',    'ENABLE_NSS_SYSTEMD'],
+                 ['mymachines', 'ENABLE_MACHINED'],
+                 ['resolve',    'ENABLE_RESOLVED']]
+
+        condition = tuple[1] == '' or conf.get(tuple[1], false)
+        if condition
+                module = tuple[0]
+
+                sym = 'src/nss-@0@/nss-@0@.sym'.format(module)
+                version_script_arg = join_paths(meson.current_source_dir(), sym)
+
+                nss = shared_library(
+                        'nss_' + module,
+                        'src/nss-@0@/nss-@0@.c'.format(module),
+                        version : '2',
+                        include_directories : includes,
+                        link_args : ['-shared',
+                                     '-Wl,--version-script=' + version_script_arg,
+                                     '-Wl,--undefined'],
+                        link_with : [libsystemd_internal,
+                                     libbasic],
+                        dependencies : [threads,
+                                        librt],
+                        link_depends : sym,
+                        install : true,
+                        install_dir : rootlibdir)
+
+                # We cannot use shared_module because it does not support version suffix.
+                # Unfortunately shared_library insists on creating the symlink…
+                meson.add_install_script('sh', '-c',
+                                         'rm $DESTDIR@0@/libnss_@1@.so'
+                                         .format(rootlibdir, module))
+
+                test('dlopen-nss_' + module,
+                     test_dlopen,
+                     args : [nss.full_path()]) # path to dlopen must include a slash
+        endif
+endforeach
+
+############################################################
+
+executable('systemd',
+           systemd_sources,
+           include_directories : includes,
+           link_with : [libcore,
+                        libshared],
+           dependencies : [threads,
+                           librt,
+                           libseccomp,
+                           libselinux,
+                           libmount,
+                           libblkid],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-analyze',
+                 systemd_analyze_sources,
+                 include_directories : includes,
+                 link_with : [libcore,
+                              libshared],
+                 dependencies : [threads,
+                                 librt,
+                                 libseccomp,
+                                 libselinux,
+                                 libmount,
+                                 libblkid],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+executable('systemd-journald',
+           systemd_journald_sources,
+           include_directories : includes,
+           link_with : [libjournal_core,
+                        libshared],
+           dependencies : [threads,
+                           libxz,
+                           liblz4,
+                           libselinux],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-cat',
+                 systemd_cat_sources,
+                 include_directories : includes,
+                 link_with : [libjournal_core,
+                              libshared],
+                 dependencies : [threads],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('journalctl',
+                 journalctl_sources,
+                 include_directories : includes,
+                 link_with : [libshared],
+                 dependencies : [threads,
+                                 libqrencode,
+                                 libxz,
+                                 liblz4],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+executable('systemd-getty-generator',
+           'src/getty-generator/getty-generator.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : systemgeneratordir)
+
+executable('systemd-debug-generator',
+           'src/debug-generator/debug-generator.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : systemgeneratordir)
+
+executable('systemd-fstab-generator',
+           'src/fstab-generator/fstab-generator.c',
+           'src/core/mount-setup.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : systemgeneratordir)
+
+if conf.get('ENABLE_ENVIRONMENT_D', false)
+        executable('30-systemd-environment-d-generator',
+                   'src/environment-d-generator/environment-d-generator.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : userenvgeneratordir)
+
+        meson.add_install_script(meson_make_symlink,
+                                 join_paths(sysconfdir, 'environment'),
+                                 join_paths(environmentdir, '99-environment.conf'))
+endif
+
+if conf.get('ENABLE_HIBERNATE', false)
+        executable('systemd-hibernate-resume-generator',
+                   'src/hibernate-resume/hibernate-resume-generator.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : systemgeneratordir)
+
+        executable('systemd-hibernate-resume',
+                   'src/hibernate-resume/hibernate-resume.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+if conf.get('HAVE_BLKID', false)
+        executable('systemd-gpt-auto-generator',
+                   'src/gpt-auto-generator/gpt-auto-generator.c',
+                   'src/basic/blkid-util.h',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : libblkid,
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : systemgeneratordir)
+
+        exe = executable('systemd-dissect',
+                         'src/dissect/dissect.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootlibexecdir)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_RESOLVED', false)
+        executable('systemd-resolved',
+                   systemd_resolved_sources,
+                   gcrypt_util_sources,
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [threads,
+                                   libgcrypt,
+                                   libgpg_error,
+                                   libm,
+                                   libidn],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('systemd-resolve',
+                         systemd_resolve_sources,
+                         gcrypt_util_sources,
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [threads,
+                                         libgcrypt,
+                                         libgpg_error,
+                                         libm,
+                                         libidn],
+                         install_rpath : rootlibexecdir,
+                         install : true)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_LOGIND', false)
+        executable('systemd-logind',
+                   systemd_logind_sources,
+                   include_directories : includes,
+                   link_with : [liblogind_core,
+                                libshared],
+                   dependencies : [threads,
+                                   libacl],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('loginctl',
+                         loginctl_sources,
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [threads,
+                                         liblz4,
+                                         libxz],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootbindir)
+        public_programs += [exe]
+
+        exe = executable('systemd-inhibit',
+                         'src/login/inhibit.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootbindir)
+        public_programs += [exe]
+
+        if conf.get('HAVE_PAM', false)
+                version_script_arg = join_paths(meson.current_source_dir(), pam_systemd_sym)
+                pam_systemd = shared_library(
+                        'pam_systemd',
+                        pam_systemd_c,
+                        name_prefix : '',
+                        include_directories : includes,
+                        link_args : ['-shared',
+                                     '-Wl,--version-script=' + version_script_arg],
+                        link_with : [libsystemd_internal,
+                                     libshared_static],
+                        dependencies : [threads,
+                                        libpam,
+                                        libpam_misc],
+                        link_depends : pam_systemd_sym,
+                        install : true,
+                        install_dir : pamlibdir)
+
+                test('dlopen-pam_systemd',
+                     test_dlopen,
+                     args : [pam_systemd.full_path()]) # path to dlopen must include a slash
+        endif
+endif
+
+if conf.get('HAVE_PAM', false)
+        executable('systemd-user-sessions',
+                   'src/user-sessions/user-sessions.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+if conf.get('ENABLE_EFI', false) and conf.get('HAVE_BLKID', false)
+        exe = executable('bootctl',
+                         'src/boot/bootctl.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [libblkid],
+                         install_rpath : rootlibexecdir,
+                         install : true)
+        public_programs += [exe]
+endif
+
+exe = executable('systemd-socket-activate', 'src/activate/activate.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 dependencies : [threads],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('systemctl', 'src/systemctl/systemctl.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 dependencies : [threads,
+                                 libcap,
+                                 libselinux,
+                                 libxz,
+                                 liblz4],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+if conf.get('ENABLE_BACKLIGHT', false)
+        executable('systemd-backlight',
+                   'src/backlight/backlight.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+if conf.get('ENABLE_RFKILL', false)
+        executable('systemd-rfkill',
+                   'src/rfkill/rfkill.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+executable('systemd-system-update-generator',
+           'src/system-update-generator/system-update-generator.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : systemgeneratordir)
+
+if conf.get('HAVE_LIBCRYPTSETUP', false)
+        executable('systemd-cryptsetup',
+                   'src/cryptsetup/cryptsetup.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [libcryptsetup],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        executable('systemd-cryptsetup-generator',
+                   'src/cryptsetup/cryptsetup-generator.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [libcryptsetup],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : systemgeneratordir)
+
+        executable('systemd-veritysetup',
+                   'src/veritysetup/veritysetup.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [libcryptsetup],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        executable('systemd-veritysetup-generator',
+                   'src/veritysetup/veritysetup-generator.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [libcryptsetup],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : systemgeneratordir)
+endif
+
+if conf.get('HAVE_SYSV_COMPAT', false)
+        executable('systemd-sysv-generator',
+                   'src/sysv-generator/sysv-generator.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : systemgeneratordir)
+
+        executable('systemd-rc-local-generator',
+                   'src/rc-local-generator/rc-local-generator.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : systemgeneratordir)
+endif
+
+if conf.get('ENABLE_HOSTNAMED', false)
+        executable('systemd-hostnamed',
+                   'src/hostname/hostnamed.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('hostnamectl',
+                         'src/hostname/hostnamectl.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         install_rpath : rootlibexecdir,
+                         install : true)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_LOCALED', false)
+        if conf.get('HAVE_XKBCOMMON', false)
+                # logind will load libxkbcommon.so dynamically on its own
+                deps = [libdl]
+        else
+                deps = []
+        endif
+
+        executable('systemd-localed',
+                   systemd_localed_sources,
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : deps,
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('localectl',
+                         localectl_sources,
+                         include_directories : includes,
+                         link_with : [libshared],
+                         install_rpath : rootlibexecdir,
+                         install : true)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_TIMEDATED', false)
+        executable('systemd-timedated',
+                   'src/timedate/timedated.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('timedatectl',
+                         'src/timedate/timedatectl.c',
+                         include_directories : includes,
+                         install_rpath : rootlibexecdir,
+                         link_with : [libshared],
+                         install : true)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_TIMESYNCD', false)
+        executable('systemd-timesyncd',
+                   systemd_timesyncd_sources,
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [threads,
+                                   libm],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+if conf.get('ENABLE_MACHINED', false)
+        executable('systemd-machined',
+                   systemd_machined_sources,
+                   include_directories : includes,
+                   link_with : [libmachine_core,
+                                libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('machinectl',
+                         'src/machine/machinectl.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [threads,
+                                         libxz,
+                                         liblz4],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootbindir)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_IMPORTD', false)
+        executable('systemd-importd',
+                   systemd_importd_sources,
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [threads],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        systemd_pull = executable('systemd-pull',
+                                  systemd_pull_sources,
+                                  include_directories : includes,
+                                  link_with : [libshared],
+                                  dependencies : [libcurl,
+                                                  libz,
+                                                  libbzip2,
+                                                  libxz,
+                                                  libgcrypt],
+                                  install_rpath : rootlibexecdir,
+                                  install : true,
+                                  install_dir : rootlibexecdir)
+
+        systemd_import = executable('systemd-import',
+                                    systemd_import_sources,
+                                    include_directories : includes,
+                                    link_with : [libshared],
+                                    dependencies : [libcurl,
+                                                    libz,
+                                                    libbzip2,
+                                                    libxz],
+                                    install_rpath : rootlibexecdir,
+                                    install : true,
+                                    install_dir : rootlibexecdir)
+
+        systemd_export = executable('systemd-export',
+                                    systemd_export_sources,
+                                    include_directories : includes,
+                                    link_with : [libshared],
+                                    dependencies : [libcurl,
+                                                    libz,
+                                                    libbzip2,
+                                                    libxz],
+                                    install_rpath : rootlibexecdir,
+                                    install : true,
+                                    install_dir : rootlibexecdir)
+        public_programs += [systemd_pull, systemd_import, systemd_export]
+endif
+
+if conf.get('ENABLE_REMOTE', false) and conf.get('HAVE_LIBCURL', false)
+        exe = executable('systemd-journal-upload',
+                         systemd_journal_upload_sources,
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [threads,
+                                         libcurl,
+                                         libgnutls,
+                                         libxz,
+                                         liblz4],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootlibexecdir)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_REMOTE', false) and conf.get('HAVE_MICROHTTPD', false)
+        s_j_remote = executable('systemd-journal-remote',
+                                systemd_journal_remote_sources,
+                                include_directories : includes,
+                                link_with : [libshared],
+                                dependencies : [threads,
+                                                libmicrohttpd,
+                                                libgnutls,
+                                                libxz,
+                                                liblz4],
+                                install_rpath : rootlibexecdir,
+                                install : true,
+                                install_dir : rootlibexecdir)
+
+        s_j_gatewayd = executable('systemd-journal-gatewayd',
+                                  systemd_journal_gatewayd_sources,
+                                  include_directories : includes,
+                                  link_with : [libshared],
+                                  dependencies : [threads,
+                                                  libmicrohttpd,
+                                                  libgnutls,
+                                                  libxz,
+                                                  liblz4],
+                                  install_rpath : rootlibexecdir,
+                                  install : true,
+                                  install_dir : rootlibexecdir)
+        public_programs += [s_j_remote, s_j_gatewayd]
+endif
+
+if conf.get('ENABLE_COREDUMP', false)
+        executable('systemd-coredump',
+                   systemd_coredump_sources,
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [threads,
+                                   libacl,
+                                   libdw,
+                                   libxz,
+                                   liblz4],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        exe = executable('coredumpctl',
+                         coredumpctl_sources,
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [threads,
+                                         libxz,
+                                         liblz4],
+                         install_rpath : rootlibexecdir,
+                         install : true)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_BINFMT', false)
+        exe = executable('systemd-binfmt',
+                         'src/binfmt/binfmt.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootlibexecdir)
+        public_programs += [exe]
+
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format(binfmtdir))
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format(join_paths(sysconfdir, 'binfmt.d')))
+endif
+
+if conf.get('ENABLE_VCONSOLE', false)
+        executable('systemd-vconsole-setup',
+                   'src/vconsole/vconsole-setup.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+if conf.get('ENABLE_RANDOMSEED', false)
+        executable('systemd-random-seed',
+                   'src/random-seed/random-seed.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+if conf.get('ENABLE_FIRSTBOOT', false)
+        executable('systemd-firstboot',
+                   'src/firstboot/firstboot.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [libcrypt],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootbindir)
+endif
+
+executable('systemd-remount-fs',
+           'src/remount-fs/remount-fs.c',
+           'src/core/mount-setup.c',
+           'src/core/mount-setup.h',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+executable('systemd-machine-id-setup',
+           'src/machine-id-setup/machine-id-setup-main.c',
+           'src/core/machine-id-setup.c',
+           'src/core/machine-id-setup.h',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootbindir)
+
+executable('systemd-fsck',
+           'src/fsck/fsck.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+executable('systemd-sleep',
+           'src/sleep/sleep.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-sysctl',
+                 'src/sysctl/sysctl.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootlibexecdir)
+public_programs += [exe]
+
+executable('systemd-ac-power',
+           'src/ac-power/ac-power.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-detect-virt',
+                 'src/detect-virt/detect-virt.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('systemd-delta',
+                 'src/delta/delta.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('systemd-escape',
+                 'src/escape/escape.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+exe = executable('systemd-notify',
+                 'src/notify/notify.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+executable('systemd-volatile-root',
+           'src/volatile-root/volatile-root.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+executable('systemd-cgroups-agent',
+           'src/cgroups-agent/cgroups-agent.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-path',
+                 'src/path/path.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('systemd-ask-password',
+                 'src/ask-password/ask-password.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+executable('systemd-reply-password',
+           'src/reply-password/reply-password.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-tty-ask-password-agent',
+                 'src/tty-ask-password-agent/tty-ask-password-agent.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+exe = executable('systemd-cgls',
+                 'src/cgls/cgls.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('systemd-cgtop',
+                 'src/cgtop/cgtop.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+executable('systemd-initctl',
+           'src/initctl/initctl.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+exe = executable('systemd-mount',
+                 'src/mount/mount-tool.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+meson.add_install_script(meson_make_symlink,
+                         'systemd-mount', join_paths(bindir, 'systemd-umount'))
+
+exe = executable('systemd-run',
+                 'src/run/run.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('systemd-stdio-bridge',
+                 'src/stdio-bridge/stdio-bridge.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+exe = executable('busctl',
+                 'src/busctl/busctl.c',
+                 'src/busctl/busctl-introspect.c',
+                 'src/busctl/busctl-introspect.h',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+if conf.get('ENABLE_SYSUSERS', false)
+        exe = executable('systemd-sysusers',
+                         'src/sysusers/sysusers.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootbindir)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_TMPFILES', false)
+        exe = executable('systemd-tmpfiles',
+                         'src/tmpfiles/tmpfiles.c',
+                         include_directories : includes,
+                         link_with : [libshared],
+                         dependencies : [libacl],
+                         install_rpath : rootlibexecdir,
+                         install : true,
+                         install_dir : rootbindir)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_HWDB', false)
+        exe = executable('systemd-hwdb',
+                         'src/hwdb/hwdb.c',
+                         'src/libsystemd/sd-hwdb/hwdb-internal.h',
+                         include_directories : includes,
+                         link_with : [libudev_internal],
+                         install_rpath : udev_rpath,
+                         install : true,
+                         install_dir : rootbindir)
+        public_programs += [exe]
+endif
+
+if conf.get('ENABLE_QUOTACHECK', false)
+        executable('systemd-quotacheck',
+                   'src/quotacheck/quotacheck.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+exe = executable('systemd-socket-proxyd',
+                 'src/socket-proxy/socket-proxyd.c',
+                 include_directories : includes,
+                 link_with : [libshared],
+                 dependencies : [threads],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootlibexecdir)
+public_programs += [exe]
+
+exe = executable('systemd-udevd',
+                 systemd_udevd_sources,
+                 include_directories : includes,
+                 c_args : ['-DLOG_REALM=LOG_REALM_UDEV'],
+                 link_with : [libudev_core,
+                              libsystemd_network,
+                              libudev_internal],
+                 dependencies : [threads,
+                                 libkmod,
+                                 libidn,
+                                 libacl,
+                                 libblkid],
+                 install_rpath : udev_rpath,
+                 install : true,
+                 install_dir : rootlibexecdir)
+public_programs += [exe]
+
+exe = executable('udevadm',
+                 udevadm_sources,
+                 include_directories : includes,
+                 link_with : [libudev_core,
+                              libsystemd_network,
+                              libudev_internal],
+                 dependencies : [threads,
+                                 libkmod,
+                                 libidn,
+                                 libacl,
+                                 libblkid],
+                 install_rpath : udev_rpath,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+executable('systemd-shutdown',
+           systemd_shutdown_sources,
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+executable('systemd-update-done',
+           'src/update-done/update-done.c',
+           include_directories : includes,
+           link_with : [libshared],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+executable('systemd-update-utmp',
+           'src/update-utmp/update-utmp.c',
+           include_directories : includes,
+           link_with : [libshared],
+           dependencies : [libaudit],
+           install_rpath : rootlibexecdir,
+           install : true,
+           install_dir : rootlibexecdir)
+
+if conf.get('HAVE_KMOD', false)
+        executable('systemd-modules-load',
+                   'src/modules-load/modules-load.c',
+                   include_directories : includes,
+                   link_with : [libshared],
+                   dependencies : [libkmod],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format(modulesloaddir))
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format(join_paths(sysconfdir, 'modules-load.d')))
+endif
+
+exe = executable('systemd-nspawn',
+                 systemd_nspawn_sources,
+                 'src/core/mount-setup.c', # FIXME: use a variable?
+                 'src/core/mount-setup.h',
+                 'src/core/loopback-setup.c',
+                 'src/core/loopback-setup.h',
+                 include_directories : [includes, include_directories('src/nspawn')],
+                 link_with : [libshared],
+                 dependencies : [libacl,
+                                 libblkid,
+                                 libseccomp,
+                                 libselinux],
+                 install_rpath : rootlibexecdir,
+                 install : true)
+public_programs += [exe]
+
+if conf.get('ENABLE_NETWORKD', false)
+        executable('systemd-networkd',
+                   systemd_networkd_sources,
+                   include_directories : includes,
+                   link_with : [libnetworkd_core,
+                                libsystemd_network,
+                                libudev_internal,
+                                libshared],
+                   dependencies : [threads],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+
+        executable('systemd-networkd-wait-online',
+                   systemd_networkd_wait_online_sources,
+                   include_directories : includes,
+                   link_with : [libnetworkd_core,
+                                libshared],
+                   install_rpath : rootlibexecdir,
+                   install : true,
+                   install_dir : rootlibexecdir)
+endif
+
+exe = executable('networkctl',
+                 networkctl_sources,
+                 include_directories : includes,
+                 link_with : [libsystemd_network,
+                              libshared],
+                 install_rpath : rootlibexecdir,
+                 install : true,
+                 install_dir : rootbindir)
+public_programs += [exe]
+
+############################################################
+
+foreach tuple : tests
+        sources = tuple[0]
+        link_with = tuple[1].length() > 0 ? tuple[1] : [libshared]
+        dependencies = tuple[2]
+        condition = tuple.length() >= 4 ? tuple[3] : ''
+        type = tuple.length() >= 5 ? tuple[4] : ''
+        defs = tuple.length() >= 6 ? tuple[5] : []
+        incs = tuple.length() >= 7 ? tuple[6] : includes
+        timeout = 30
+
+        name = sources[0].split('/')[-1].split('.')[0]
+        if type.startswith('timeout=')
+                timeout = type.split('=')[1].to_int()
+                type = ''
+        endif
+
+        if condition == '' or conf.get(condition, false)
+                exe = executable(
+                        name,
+                        sources,
+                        include_directories : incs,
+                        link_with : link_with,
+                        dependencies : dependencies,
+                        c_args : defs,
+                        install_rpath : rootlibexecdir,
+                        install : install_tests,
+                        install_dir : join_paths(testsdir, type))
+
+                if type == 'manual'
+                        message('@0@ is a manual test'.format(name))
+                elif type == 'unsafe' and want_tests != 'unsafe'
+                        message('@0@ is an unsafe test'.format(name))
+                else
+                        test(name, exe,
+                             env : test_env,
+                             timeout : timeout)
+                endif
+        else
+                message('Not compiling @0@ because @1@ is not true'.format(name, condition))
+        endif
+endforeach
+
+test_libsystemd_sym = executable(
+        'test-libsystemd-sym',
+        test_libsystemd_sym_c,
+        include_directories : includes,
+        link_with : [libsystemd],
+        install : install_tests,
+        install_dir : testsdir)
+test('test-libsystemd-sym',
+     test_libsystemd_sym)
+
+test_libudev_sym = executable(
+        'test-libudev-sym',
+        test_libudev_sym_c,
+        include_directories : includes,
+        c_args : ['-Wno-deprecated-declarations'],
+        link_with : [libudev],
+        install : install_tests,
+        install_dir : testsdir)
+test('test-libudev-sym',
+     test_libudev_sym)
+
+############################################################
+
+make_directive_index_py = find_program('tools/make-directive-index.py')
+make_man_index_py = find_program('tools/make-man-index.py')
+xml_helper_py = find_program('tools/xml_helper.py')
+hwdb_update_sh = find_program('tools/meson-hwdb-update.sh')
+
+subdir('units')
+subdir('sysctl.d')
+subdir('sysusers.d')
+subdir('tmpfiles.d')
+subdir('rules')
+subdir('hwdb')
+subdir('network')
+subdir('man')
+subdir('shell-completion/bash')
+subdir('shell-completion/zsh')
+subdir('docs/sysvinit')
+subdir('docs/var-log')
+
+# FIXME: figure out if the warning is true:
+# https://github.com/mesonbuild/meson/wiki/Reference-manual#install_subdir
+install_subdir('factory/etc',
+               install_dir : factorydir)
+
+
+install_data('xorg/50-systemd-user.sh',
+             install_dir : xinitrcdir)
+install_data('system-preset/90-systemd.preset',
+             install_dir : systempresetdir)
+install_data('README',
+             'NEWS',
+             'CODING_STYLE',
+             'DISTRO_PORTING',
+             'ENVIRONMENT.md',
+             'LICENSE.GPL2',
+             'LICENSE.LGPL2.1',
+             'src/libsystemd/sd-bus/GVARIANT-SERIALIZATION',
+             install_dir : docdir)
+
+meson.add_install_script('sh', '-c', mkdir_p.format(systemdstatedir))
+meson.add_install_script('sh', '-c', 'touch $DESTDIR@0@'.format(prefixdir))
+
+############################################################
+
+meson_check_help = find_program('tools/meson-check-help.sh')
+
+foreach exec : public_programs
+        name = exec.full_path().split('/')[-1]
+        test('check-help-' + name,
+             meson_check_help,
+             args : [exec.full_path()])
+endforeach
+
+############################################################
+
+if git.found()
+        all_files = run_command(
+                git,
+                ['--git-dir=@0@/.git'.format(meson.source_root()),
+                 'ls-files',
+                 ':/*.[ch]'])
+        all_files = files(all_files.stdout().split())
+
+        run_target(
+                'tags',
+                input : all_files,
+                command : ['env', 'etags', '-o', '@0@/TAGS'.format(meson.source_root())] + all_files)
+        run_target(
+                'ctags',
+                input : all_files,
+                command : ['env', 'ctags', '-o', '@0@/tags'.format(meson.source_root())] + all_files)
+endif
+
+if git.found()
+        meson_git_contrib_sh = find_program('tools/meson-git-contrib.sh')
+        run_target(
+                'git-contrib',
+                command : [meson_git_contrib_sh])
+endif
+
+if git.found()
+        git_head = run_command(
+                git,
+                ['--git-dir=@0@/.git'.format(meson.source_root()),
+                 'rev-parse', 'HEAD']).stdout().strip()
+        git_head_short = run_command(
+                git,
+                ['--git-dir=@0@/.git'.format(meson.source_root()),
+                 'rev-parse', '--short=7', 'HEAD']).stdout().strip()
+
+        run_target(
+                'git-snapshot',
+                command : ['git', 'archive',
+                           '-o', '@0@/systemd-@1@.tar.gz'.format(meson.source_root(),
+                                                                 git_head_short),
+                           '--prefix', 'systemd-@0@/'.format(git_head),
+                           'HEAD'])
+endif
+
+############################################################
+
+status = [
+        '@0@ @1@'.format(meson.project_name(), meson.project_version()),
+
+        'prefix:                            @0@'.format(prefixdir),
+        'rootprefix:                        @0@'.format(rootprefixdir),
+        'sysconf dir:                       @0@'.format(sysconfdir),
+        'includedir:                        @0@'.format(includedir),
+        'lib dir:                           @0@'.format(libdir),
+        'rootlib dir:                       @0@'.format(rootlibdir),
+        'SysV init scripts:                 @0@'.format(sysvinit_path),
+        'SysV rc?.d directories:            @0@'.format(sysvrcnd_path),
+        'PAM modules dir:                   @0@'.format(pamlibdir),
+        'PAM configuration dir:             @0@'.format(pamconfdir),
+        'RPM macros dir:                    @0@'.format(rpmmacrosdir),
+        'D-Bus policy dir:                  @0@'.format(dbuspolicydir),
+        'D-Bus session dir:                 @0@'.format(dbussessionservicedir),
+        'D-Bus system dir:                  @0@'.format(dbussystemservicedir),
+        'bash completions dir:              @0@'.format(bashcompletiondir),
+        'zsh completions dir:               @0@'.format(zshcompletiondir),
+        'extra start script:                @0@'.format(get_option('rc-local')),
+        'extra stop script:                 @0@'.format(get_option('halt-local')),
+        'debug shell:                       @0@ @ @1@'.format(get_option('debug-shell'),
+                                                              get_option('debug-tty')),
+        'TTY GID:                           @0@'.format(tty_gid),
+        'maximum system UID:                @0@'.format(system_uid_max),
+        'maximum system GID:                @0@'.format(system_gid_max),
+        '/dev/kvm access mode:              @0@'.format(get_option('dev-kvm-mode')),
+        'certificate root:                  @0@'.format(get_option('certificate-root')),
+        'support URL:                       @0@'.format(support_url),
+        'nobody user name:                  @0@'.format(get_option('nobody-user')),
+        'nobody group name:                 @0@'.format(get_option('nobody-group')),
+        'fallback hostname:                 @0@'.format(get_option('fallback-hostname')),
+
+        'default DNSSEC mode:               @0@'.format(default_dnssec),
+        'default cgroup hierarchy:          @0@'.format(default_hierarchy),
+        'default KillUserProcesses setting: @0@'.format(kill_user_processes)]
+
+alt_dns_servers = '\n                                            '.join(dns_servers.split(' '))
+alt_ntp_servers = '\n                                            '.join(ntp_servers.split(' '))
+status += [
+        'default DNS servers:               @0@'.format(alt_dns_servers),
+        'default NTP servers:               @0@'.format(alt_ntp_servers)]
+
+alt_time_epoch = run_command('date', '-Is', '-u', '-d',
+                             '@@0@'.format(time_epoch)).stdout().strip()
+status += [
+        'time epoch:                        @0@ (@1@)'.format(time_epoch, alt_time_epoch)]
+
+# TODO:
+# CFLAGS:   ${OUR_CFLAGS} ${CFLAGS}
+# CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
+# LDFLAGS:  ${OUR_LDFLAGS} ${LDFLAGS}
+
+if conf.get('ENABLE_EFI', false)
+        status += [
+                'efi arch:                          @0@'.format(efi_arch)]
+
+        if have_gnu_efi
+                status += [
+                        'EFI machine type:                  @0@'.format(EFI_MACHINE_TYPE_NAME),
+                        'EFI CC                             @0@'.format(efi_cc),
+                        'EFI libdir:                        @0@'.format(efi_libdir),
+                        'EFI ldsdir:                        @0@'.format(efi_ldsdir),
+                        'EFI includedir:                    @0@'.format(efi_incdir)]
+        endif
+endif
+
+found = []
+missing = []
+
+foreach tuple : [
+        ['libcryptsetup'],
+        ['PAM'],
+        ['AUDIT'],
+        ['IMA'],
+        ['AppArmor'],
+        ['SELinux'],
+        ['SECCOMP'],
+        ['SMACK'],
+        ['zlib'],
+        ['xz'],
+        ['lz4'],
+        ['bzip2'],
+        ['ACL'],
+        ['gcrypt'],
+        ['qrencode'],
+        ['microhttpd'],
+        ['gnutls'],
+        ['libcurl'],
+        ['idn'],
+        ['libidn2'],
+        ['libidn'],
+        ['nss-systemd'],
+        ['libiptc'],
+        ['elfutils'],
+        ['binfmt'],
+        ['vconsole'],
+        ['quotacheck'],
+        ['tmpfiles'],
+        ['environment.d'],
+        ['sysusers'],
+        ['firstboot'],
+        ['randomseed'],
+        ['backlight'],
+        ['rfkill'],
+        ['logind'],
+        ['machined'],
+        ['importd'],
+        ['hostnamed'],
+        ['timedated'],
+        ['timesyncd'],
+        ['localed'],
+        ['networkd'],
+        ['resolved'],
+        ['coredump'],
+        ['polkit'],
+        ['legacy pkla',      install_polkit_pkla],
+        ['efi'],
+        ['gnu-efi',          have_gnu_efi],
+        ['kmod'],
+        ['xkbcommon'],
+        ['blkid'],
+        ['dbus'],
+        ['glib'],
+        ['nss-myhostname',   conf.get('HAVE_MYHOSTNAME', false)],
+        ['hwdb'],
+        ['tpm'],
+        ['man pages',        want_man],
+        ['html pages',       want_html],
+        ['man page indices', want_man and have_lxml],
+        ['split /usr',       conf.get('HAVE_SPLIT_USR', false)],
+        ['SysV compat'],
+        ['utmp'],
+        ['ldconfig'],
+        ['hibernate'],
+        ['adm group',        get_option('adm-group')],
+        ['wheel group',      get_option('wheel-group')],
+        ['gshadow'],
+        ['debug hashmap'],
+        ['debug mmap cache'],
+]
+
+        cond = tuple.get(1, '')
+        if cond == ''
+                ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
+                ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
+                cond = conf.get(ident1, false) or conf.get(ident2, false)
+        endif
+        if cond
+                found += [tuple[0]]
+        else
+                missing += [tuple[0]]
+        endif
+endforeach
+
+status += [
+        'enabled features: @0@'.format(', '.join(found)),
+        'disabled features: @0@'.format(', '.join(missing))]
+message('\n         '.join(status))
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644 (file)
index 0000000..1594fec
--- /dev/null
@@ -0,0 +1,256 @@
+# -*- mode: meson -*-
+
+option('split-usr', type : 'boolean', value : false,
+       description : '''assume that /bin, /sbin aren't symlinks into /usr''')
+option('rootlibdir', type : 'string',
+       description : '''[/usr]/lib/x86_64-linux-gnu or such''')
+option('rootprefix', type : 'string',
+       description : '''override the root prefix''')
+option('link-udev-shared', type : 'boolean',
+       description : 'link systemd-udev and its helpers to libsystemd-shared.so')
+
+option('sysvinit-path', type : 'string', value : '/etc/init.d',
+       description : 'the directory where the SysV init scripts are located')
+option('sysvrcnd-path', type : 'string', value : '/etc/rc.d',
+       description : 'the base directory for SysV rcN.d directories')
+option('telinit-path', type : 'string', description : 'path to telinit')
+option('rc-local', type : 'string',
+       value : '/etc/rc.local')
+option('halt-local', type : 'string',
+       value : '/usr/sbin/halt.local')
+
+option('quotaon-path', type : 'string', description : 'path to quotaon')
+option('quotacheck-path', type : 'string', description : 'path to quotacheck')
+option('kill-path', type : 'string', description : 'path to kill')
+option('kmod-path', type : 'string', description : 'path to kmod')
+option('kexec-path', type : 'string', description : 'path to kexec')
+option('sulogin-path', type : 'string', description : 'path to sulogin')
+option('mount-path', type : 'string', description : 'path to mount')
+option('umount-path', type : 'string', description : 'path to umount')
+option('loadkeys-path', type : 'string', description : 'path to loadkeys')
+option('setfont-path', type : 'string', description : 'path to setfont')
+
+option('debug-shell', type : 'string', value : '/bin/sh',
+       description : 'path to debug shell binary')
+option('debug-tty', type : 'string', value : '/dev/tty9',
+       description : 'specify the tty device for debug shell')
+option('debug', type : 'string',
+       description : 'enable extra debugging (hashmap,mmap-cache)')
+
+option('utmp', type : 'boolean',
+       description : 'support for utmp/wtmp log handling')
+option('hibernate', type : 'boolean',
+       description : 'support for hibernation')
+option('ldconfig', type : 'boolean',
+       description : 'support for dynamic linker cache creation')
+option('resolve', type : 'boolean',
+       description : 'systemd-resolved stack')
+option('efi', type : 'boolean',
+       description : 'enable systemd-boot and bootctl')
+option('tpm', type : 'boolean', value : false,
+       description : 'TPM should be used to log events and extend the registers')
+option('environment-d', type : 'boolean',
+       description : 'support for environment.d')
+option('binfmt', type : 'boolean',
+       description : 'support for custom binary formats')
+option('coredump', type : 'boolean',
+       description : 'install the coredump handler')
+option('logind', type : 'boolean',
+       description : 'install the systemd-logind stack')
+option('hostnamed', type : 'boolean',
+       description : 'install the systemd-hostnamed stack')
+option('localed', type : 'boolean',
+       description : 'install the systemd-localed stack')
+option('machined', type : 'boolean',
+       description : 'install the systemd-machined stack')
+option('networkd', type : 'boolean',
+       description : 'install the systemd-networkd stack')
+option('timedated', type : 'boolean',
+       description : 'install the systemd-timedated daemon')
+option('timesyncd', type : 'boolean',
+       description : 'install the systemd-timesyncd daemon')
+option('remote', type : 'boolean',
+       description : 'support for "journal over the network"')
+option('myhostname', type : 'boolean',
+       description : 'nss-myhostname support')
+option('firstboot', type : 'boolean',
+       description : 'support for firstboot mechanism')
+option('randomseed', type : 'boolean',
+       description : 'support for restoring random seed')
+option('backlight', type : 'boolean',
+       description : 'support for restoring backlight state')
+option('vconsole', type : 'boolean',
+       description : 'support for vconsole configuration')
+option('quotacheck', type : 'boolean',
+       description : 'support for the quotacheck tools')
+option('sysusers', type : 'boolean',
+       description : 'support for the sysusers configuration')
+option('tmpfiles', type : 'boolean',
+       description : 'support for tmpfiles.d')
+option('importd', type : 'boolean',
+       description : 'install the systemd-importd daemon')
+option('hwdb', type : 'boolean',
+       description : 'support for the hardware database')
+option('rfkill', type : 'boolean',
+       description : 'support for the rfkill tools')
+option('man', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'build and install man pages')
+option('html', type : 'combo', choices : ['auto', 'true', 'false'],
+       value : 'false',
+       description : 'build and install html pages')
+
+option('certificate-root', type : 'string', value : '/etc/ssl',
+       description : 'the prefix for TLS certificates')
+option('dbuspolicydir', type : 'string',
+       description : 'D-Bus policy directory')
+option('dbussessionservicedir', type : 'string',
+       description : 'D-Bus session service directory')
+option('dbussystemservicedir', type : 'string',
+       description : 'D-Bus system service directory')
+option('pkgconfigdatadir', type : 'string', value : 'share/pkgconfig',
+       description : 'directory for ')
+option('pkgconfiglibdir', type : 'string', value : '',
+       description : 'directory for ')
+option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d',
+       description : 'directory for rpm macros ["no" disables]')
+option('pamlibdir', type : 'string',
+       description : 'directory for PAM modules')
+option('pamconfdir', type : 'string',
+       description : 'directory for PAM configuration ["no" disables]')
+
+option('fallback-hostname', type : 'string', value : 'localhost',
+       description : 'the hostname used if none configured')
+option('default-hierarchy', type : 'combo',
+       choices : ['legacy', 'hybrid', 'unified'], value : 'hybrid',
+       description : 'default cgroup hierarchy')
+option('time-epoch', type : 'string',
+       description : 'time epoch for time clients')
+option('system-uid-max', type : 'string',
+       description : 'maximum system UID')
+option('system-gid-max', type : 'string',
+       description : 'maximum system GID')
+option('tty-gid', type : 'string',
+       description : 'the numeric GID of the "tty" group',
+       value : '5')
+option('adm-group', type : 'boolean',
+       description : 'the ACL for adm group should be added')
+option('wheel-group', type : 'boolean',
+       description : 'the ACL for wheel group should be added')
+option('nobody-user', type : 'string',
+       description : 'The name of the nobody user (the one with UID 65534)',
+       value : 'nobody')
+option('nobody-group', type : 'string',
+       description : 'The name of the nobody group (the one with GID 65534)',
+       value : 'nobody')
+option('dev-kvm-mode', type : 'string', value : '0660',
+       description : '/dev/kvm access mode')
+option('default-kill-user-processes', type : 'boolean',
+       description : 'the default value for KillUserProcesses= setting')
+option('gshadow', type : 'boolean',
+       description : 'support for shadow group')
+
+option('default-dnssec', type : 'combo',
+       description : 'default DNSSEC mode',
+       choices : ['yes', 'allow-downgrade', 'no'],
+       value : 'allow-downgrade')
+option('dns-servers', type : 'string',
+       description : 'space-separated list of default DNS servers',
+       value : '8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844')
+option('ntp-servers', type : 'string',
+       description : 'space-separated list of default NTP servers',
+       value : 'time1.google.com time2.google.com time3.google.com time4.google.com')
+option('support-url', type : 'string',
+       description : 'the support URL to show in catalog entries included in systemd',
+       value : 'https://lists.freedesktop.org/mailman/listinfo/systemd-devel')
+option('www-target', type : 'string',
+       description : 'the address and dir to upload docs too',
+       value : 'www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd')
+
+option('seccomp', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'SECCOMP support')
+option('selinux', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'SELinux support')
+option('apparmor', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'AppArmor support')
+option('smack', type : 'boolean',
+       description : 'SMACK support')
+option('smack-run-label', type : 'string',
+       description : 'run systemd --system itself with a specific SMACK label')
+option('polkit', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'PolicyKit support')
+option('ima', type : 'boolean',
+       description : 'IMA support')
+
+option('acl', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libacl support')
+option('audit', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libaudit support')
+option('blkid', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libblkid support')
+option('kmod', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'support for loadable modules')
+option('pam', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'PAM support')
+option('microhttpd', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libµhttpd support')
+option('libcryptsetup', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libcryptsetup support')
+option('libcurl', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libcurl support')
+option('idn', type : 'boolean',
+       description : 'use IDN when printing host names')
+option('libidn2', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libidn2 support')
+option('libidn', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libidn support')
+option('nss-systemd', type : 'boolean',
+       description : 'enable nss-systemd')
+option('libiptc', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libiptc support')
+option('qrencode', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libqrencode support')
+option('gcrypt', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'gcrypt support')
+option('gnutls', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'gnutls support')
+option('elfutils', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'elfutils support')
+option('zlib', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'zlib compression support')
+option('bzip2', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'bzip2 compression support')
+option('xz', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'xz compression support')
+option('lz4', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'lz4 compression support')
+option('xkbcommon', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'xkbcommon keymap support')
+option('glib', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libglib support (for tests only)')
+option('dbus', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'libdbus support (for tests only)')
+
+option('gnu-efi', type : 'combo', choices : ['auto', 'true', 'false'],
+       description : 'gnu-efi support for sd-boot')
+option('efi-cc', type : 'string', value : 'gcc',
+       description : 'the compiler to use for EFI modules')
+option('efi-ld', type : 'string', value : 'ld',
+       description : 'the linker to use for EFI modules')
+option('efi-libdir', type : 'string',
+       description : 'path to the EFI lib directory')
+option('efi-ldsdir', type : 'string',
+       description : 'path to the EFI lds directory')
+option('efi-includedir', type : 'string', value : '/usr/include/efi',
+       description : 'path to the EFI header directory')
+option('tpm-pcrindex', type : 'string', value : '8',
+       description : 'TPM PCR register number to use')
+
+option('bashcompletiondir', type : 'string',
+       description : 'directory for bash completion scripts ["no" disables]')
+option('zshcompletiondir', type : 'string',
+       description : 'directory for zsh completion scripts ["no" disables]')
+
+option('tests', type : 'combo', choices : ['true', 'unsafe'],
+       description : 'enable extra tests with =unsafe')
+option('install-tests', type : 'boolean', value : 'false',
+       description : 'install test executables')
index 872841eb63e39e0b2386c46c9c22558646666713..2231118da5f489b80a0de59ef58c7b226b70db6a 100755 (executable)
 # This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi).
 # Simply invoke "mkosi" in the project directory to build an OS image.
 
-./autogen.sh c
-make -j `nproc`
-
-make check
-make install
+export LC_CTYPE=C.UTF-8
+meson build
+ninja -C build all
+ninja -C build test
+ninja -C build install
 
 mkdir -p $DESTDIR/etc
 
diff --git a/network/meson.build b/network/meson.build
new file mode 100644 (file)
index 0000000..e9f9bba
--- /dev/null
@@ -0,0 +1,12 @@
+if conf.get('ENABLE_NETWORKD', false)
+        install_data('80-container-host0.network',
+                     '80-container-ve.network',
+                     '80-container-vz.network',
+                     install_dir : networkdir)
+
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format(join_paths(sysconfdir, 'systemd/network')))
+endif
+
+install_data('99-default.link',
+             install_dir : networkdir)
index bd283b61303269d987080511c7d25b393cbbdfe2..cc64eab997ac1bafb7424f9aa97539b34ca419f9 100644 (file)
@@ -17,6 +17,7 @@ ko
 pl
 pt_BR
 ru
+sk
 sr
 sv
 tr
index 014ed4266ce82015e6b976d52185d8e34dcdd91e..9622c7105409e39af347e6a4337ff72d4caf8885 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -1,15 +1,15 @@
 # Czech translation for systemd.
-# Copyright (C) 2016 systemd's author and translators.
+# Copyright (C) 2016-2017 systemd's author and translators.
 # This file is distributed under the same license as the systemd package.
-# Daniel Maixner <xskipy@gmail.com>, 2016
-# Daniel Rusek <mail@asciiwolf.com>, 2016
+# Daniel Maixner <xskipy@gmail.com>, 2016.
+# Daniel Rusek <mail@asciiwolf.com>, 2016, 2017.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
-"Report-Msgid-Bugs-To: \n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
 "POT-Creation-Date: 2016-04-23 14:24+0200\n"
-"PO-Revision-Date: 2017-02-07 18:38+0100\n"
+"PO-Revision-Date: 2017-04-20 23:00+0200\n"
 "Last-Translator: Daniel Rusek <mail@asciiwolf.com>\n"
 "Language: cs\n"
 "MIME-Version: 1.0\n"
@@ -26,36 +26,35 @@ msgstr "Odeslat heslo zpět do systému"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
 msgid "Authentication is required to send the entered passphrase back to the system."
-msgstr "Autentizace je vyžadována pro odeslání zadaného hesla do systému."
+msgstr "Pro odeslání zadaného hesla do systému je vyžadováno ověření."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
 msgid "Manage system services or other units"
-msgstr "Správa systémových služeb nebo dalších jednotek"
+msgstr "Spravovat systémové služby nebo další jednotky"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
 msgid "Authentication is required to manage system services or other units."
-msgstr ""
-"Autentizace je vyžadována pro správu systémových služeb nebo dalších jednotek."
+msgstr "Pro správu systémových služeb nebo dalších jednotek je vyžadováno ověření."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
 msgid "Manage system service or unit files"
-msgstr "Správa systémové služby nebo souborů jednotky"
+msgstr "Spravovat systémové služby nebo soubory jednotek"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
 msgid "Authentication is required to manage system service or unit files."
-msgstr "Autentizace je vyžadována pro správu systémové služby nebo souborů jednotky."
+msgstr "Pro správu systémových služeb nebo souborů jednotek je vyžadováno ověření."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
 msgid "Set or unset system and service manager environment variables"
-msgstr "Nastavení nebo rušení proměnných správce systému a služeb"
+msgstr "Nastavit nebo rušit proměnné správce systému a služeb"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
 msgid ""
 "Authentication is required to set or unset system and service manager environment "
 "variables."
 msgstr ""
-"Autentizace je vyžadována pro nastavení nebo rušení proměnných správce systému a "
-"služeb."
+"Pro nastavení nebo rušení proměnných správce systému a služeb je vyžadováno "
+"ověření."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
 msgid "Reload the systemd state"
@@ -63,53 +62,51 @@ msgstr "Znovu načíst stav systemd"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
 msgid "Authentication is required to reload the systemd state."
-msgstr "Autentizace je vyžadována pro znovu načtení stavu systemd."
+msgstr "Pro znovu načtení stavu systemd je vyžadováno ověření."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
 msgid "Set host name"
-msgstr "Nastavení názvu stroje"
+msgstr "Nastavit název stroje"
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
 msgid "Authentication is required to set the local host name."
-msgstr "Autentizace je vyžadována pro nastavení lokálního názvu stroje."
+msgstr "Pro nastavení lokálního názvu stroje je vyžadováno ověření."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
 msgid "Set static host name"
-msgstr "Nastavení statického názvu stoje"
+msgstr "Nastavit statický název stoje"
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
 msgid ""
 "Authentication is required to set the statically configured local host name, as "
 "well as the pretty host name."
 msgstr ""
-"Autentizace je vyžadována pro nastavení staticky konfigurovaného názvu lokálního "
-"stroje, stejně tak pro změnu uživatelsky přívětivého jména."
+"Pro nastavení staticky konfigurovaného názvu lokálního stroje, stejně tak pro "
+"změnu uživatelsky přívětivého jména je vyžadováno ověření."
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
 msgid "Set machine information"
-msgstr "Nastavení informací o stroji"
+msgstr "Nastavit informace o stroji"
 
 #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
 msgid "Authentication is required to set local machine information."
-msgstr "Autentizace je vyžadována pro nastavení informací o stroji."
+msgstr "Pro nastavení informací o stroji je vyžadováno ověření."
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:1
 msgid "Import a VM or container image"
-msgstr "Import obrazu virtuální stroje nebo kontejneru"
+msgstr "Importovat obraz virtuální stroje nebo kontejneru"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:2
 msgid "Authentication is required to import a VM or container image"
-msgstr ""
-"Autentizace je vyžadována pro import obrazu virtuálního stroje nebo kontejneru"
+msgstr "Pro import obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:3
 msgid "Export a VM or container image"
-msgstr "Export obrazu virtuálního stroje nebo kontejneru"
+msgstr "Exportovat obraz virtuálního stroje nebo kontejneru"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:4
 msgid "Authentication is required to export a VM or container image"
-msgstr ""
-"Autentizace je vyžadována pro export obrazu virtuálního stroje nebo kontejneru"
+msgstr "Pro export obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:5
 msgid "Download a VM or container image"
@@ -117,24 +114,23 @@ msgstr "Stáhnout obraz virtuálního stroje nebo kontejneru"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:6
 msgid "Authentication is required to download a VM or container image"
-msgstr ""
-"Autentizace je vyžadována pro stažení obrazu virtuálního stroje nebo kontejneru"
+msgstr "Pro stažení obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
 msgid "Set system locale"
-msgstr "Nastavení lokalizace systému"
+msgstr "Nastavit lokalizaci systému"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:2
 msgid "Authentication is required to set the system locale."
-msgstr "Autentizace je vyžadována pro nastavení lokalizace systému."
+msgstr "Pro nastavení lokalizace systému je vyžadováno ověření."
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:3
 msgid "Set system keyboard settings"
-msgstr "Nastavení systémové konfigurace klávesnice"
+msgstr "Nastavit systémovou konfiguraci klávesnice"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
 msgid "Authentication is required to set the system keyboard settings."
-msgstr "Autentizace je vyžadována pro nastavení systémové konfigurace klávesnice."
+msgstr "Pro nastavení systémové konfigurace klávesnice je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:1
 msgid "Allow applications to inhibit system shutdown"
@@ -142,7 +138,7 @@ msgstr "Povolit aplikacím zakázat vypnutí systému"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:2
 msgid "Authentication is required for an application to inhibit system shutdown."
-msgstr "Autentizace je vyžadována pro povolení aplikacím zakázat vypnutí systému."
+msgstr "Pro povolení aplikacím zakázat vypnutí systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:3
 msgid "Allow applications to delay system shutdown"
@@ -150,7 +146,7 @@ msgstr "Povolit aplikacím odložit vypnutí systému"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:4
 msgid "Authentication is required for an application to delay system shutdown."
-msgstr "Autentizace je vyžadována pro povolení aplikacím odložit vypnutí systému."
+msgstr "Pro povolení aplikacím odložit vypnutí systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:5
 msgid "Allow applications to inhibit system sleep"
@@ -158,7 +154,7 @@ msgstr "Povolit aplikacím zakázat uspání systému"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:6
 msgid "Authentication is required for an application to inhibit system sleep."
-msgstr "Autentizace je vyžadována pro povolení aplikacím zakázat uspání systému."
+msgstr "Pro povolení aplikacím zakázat uspání systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:7
 msgid "Allow applications to delay system sleep"
@@ -166,7 +162,7 @@ msgstr "Povolit aplikacím odložit uspání systému"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:8
 msgid "Authentication is required for an application to delay system sleep."
-msgstr "Autentizace je vyžadována pro povolení aplikacím odložit uspání systému."
+msgstr "Pro povolení aplikacím odložit uspání systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:9
 msgid "Allow applications to inhibit automatic system suspend"
@@ -176,8 +172,7 @@ msgstr "Povolit aplikacím zakázat automatické vypnutí systému"
 msgid ""
 "Authentication is required for an application to inhibit automatic system suspend."
 msgstr ""
-"Autentizace je vyžadována pro povolení aplikacím zakázat automatické vypnutí "
-"systému."
+"Pro povolení aplikacím zakázat automatické vypnutí systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:11
 msgid "Allow applications to inhibit system handling of the power key"
@@ -188,8 +183,8 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of the "
 "power key."
 msgstr ""
-"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na "
-"stisknutí vypínacího tlačítka."
+"Pro povolení aplikacím zakázat chovaní systému na stisknutí vypínacího tlačítka je "
+"vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:13
 msgid "Allow applications to inhibit system handling of the suspend key"
@@ -200,8 +195,8 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of the "
 "suspend key."
 msgstr ""
-"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na "
-"stisknutí uspávacího tlačítka."
+"Pro povolení aplikacím zakázat chovaní systému na stisknutí uspávacího tlačítka je "
+"vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:15
 msgid "Allow applications to inhibit system handling of the hibernate key"
@@ -212,8 +207,8 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of the "
 "hibernate key."
 msgstr ""
-"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na "
-"stisknutí tlačítka hibernace."
+"Pro povolení aplikacím zakázat chovaní systému na stisknutí tlačítka hibernace je "
+"vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:17
 msgid "Allow applications to inhibit system handling of the lid switch"
@@ -224,8 +219,8 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of the "
 "lid switch."
 msgstr ""
-"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na "
-"zavření víka."
+"Pro povolení aplikacím zakázat chovaní systému na zavření víka je vyžadováno "
+"ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
 msgid "Allow non-logged-in user to run programs"
@@ -234,7 +229,7 @@ msgstr "Povolit nepřihlášenému uživateli spouštět programy"
 #: ../src/login/org.freedesktop.login1.policy.in.h:20
 msgid "Explicit request is required to run programs as a non-logged-in user."
 msgstr ""
-"Speciální požadavek je třeba ke spuštění programů jako nepřihlášený uživatel."
+"Ke spuštění programů jako nepřihlášený uživatel je třeba speciální požadavek."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
@@ -242,33 +237,33 @@ msgstr "Povolit nepřihlášeným uživatelům spouštět programy"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
-msgstr "Autentizace je vyžadována ke spuštění programů jako nepřihlášený uživatel."
+msgstr "Ke spuštění programů jako nepřihlášený uživatel je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
-msgstr "Povolit připojování zařízení ke stanovišti"
+msgstr "Povolit připojování zařízení ke stanovištím"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
-msgstr "Autentizace je vyžadována pro připojování zařízení ke stanovišti."
+msgstr "Pro připojování zařízení ke stanovišti je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
-msgstr "Odstranění přiřazení zařízení ke stanovištím"
+msgstr "Odstranit přiřazení zařízení ke stanovištím"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
-"Autentizace je vyžadována pro reset způsobu jak jsou zařízení přiřazována ke "
-"stanovištím."
+"Pro reset způsobu jak jsou zařízení přiřazována ke stanovištím je vyžadováno "
+"ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
-msgstr "Vypnutí systému"
+msgstr "Vypnout systém"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
-msgstr "Autentizace je vyžadována pro vypnutí systému."
+msgstr "Pro vypnutí systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
@@ -279,8 +274,7 @@ msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
 msgstr ""
-"Autentizace je vyžadována pro vypnutí systému, když jsou přihlášeni další "
-"uživatelé."
+"Pro vypnutí systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
@@ -291,8 +285,7 @@ msgid ""
 "Authentication is required for powering off the system while an application asked "
 "to inhibit it."
 msgstr ""
-"Autentizace je vyžadována pro vypnutí systému, když aplikace požádala o zákaz "
-"vypnutí."
+"Pro vypnutí systému, když aplikace požádala o zákaz vypnutí je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
@@ -300,7 +293,7 @@ msgstr "Restartovat systém"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
-msgstr "Autentizace je vyžadována pro restartovaní systému."
+msgstr "Pro restartování systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
@@ -311,8 +304,8 @@ msgid ""
 "Authentication is required for rebooting the system while other users are logged "
 "in."
 msgstr ""
-"Autentizace je vyžadována pro restart systému, když jsou přihlášeni další "
-"uživatelé."
+"Pro restartování systému, když jsou přihlášeni další uživatelé je vyžadováno "
+"ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
@@ -323,16 +316,16 @@ msgid ""
 "Authentication is required for rebooting the system while an application asked to "
 "inhibit it."
 msgstr ""
-"Autentizace je vyžadována pro restart systému, když aplikace požádala o zákaz "
-"restartu."
+"Pro restartování systému, když aplikace požádala o zákaz restartu je vyžadováno "
+"ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
-msgstr "Uspání systému"
+msgstr "Uspat systém"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
-msgstr "Autentizace je vyžadována pro uspání systému."
+msgstr "Pro uspání systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
@@ -343,7 +336,7 @@ msgid ""
 "Authentication is required for suspending the system while other users are logged "
 "in."
 msgstr ""
-"Autentizace je vyžadována pro uspání systému, když jsou přihlášeni další uživatelé."
+"Pro uspání systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
@@ -354,16 +347,15 @@ msgid ""
 "Authentication is required for suspending the system while an application asked to "
 "inhibit it."
 msgstr ""
-"Autentizace je vyžadována pro uspání systému, když aplikace požádala o zákaz "
-"uspání."
+"Pro uspání systému, když aplikace požádala o zákaz uspání je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
-msgstr "Hibernace systému"
+msgstr "Hibernovat systém"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
-msgstr "Autentizace je vyžadována k hibernaci systému."
+msgstr "Pro hibernaci systému je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
@@ -374,37 +366,35 @@ msgid ""
 "Authentication is required for hibernating the system while other users are logged "
 "in."
 msgstr ""
-"Autentizace je vyžadována pro hibernaci systému, když jsou přihlášeni další "
-"uživatelé."
+"Pro hibernaci systému, když jsou přihlášeni další uživatelé je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
-msgstr "Hibernace systému, i když aplikace požádala o zákaz hibernace"
+msgstr "Hibernovat systém, i když aplikace požádala o zákaz hibernace"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application asked "
 "to inhibit it."
 msgstr ""
-"Autentizace je vyžadována pro hibernaci systému, když aplikace požádala o zákaz "
-"hibernace."
+"Pro hibernaci systému, když aplikace požádala o zákaz hibernace je vyžadováno "
+"ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
-msgstr "Správa aktivních sezení, uživatelů a stanovišť"
+msgstr "Spravovat aktivní sezení, uživatele a stanoviště"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid "Authentication is required for managing active sessions, users and seats."
-msgstr ""
-"Autentizace je vyžadována pro správu aktivních sezení, uživatelů a stanovišť."
+msgstr "Pro správu aktivních sezení, uživatelů a stanovišť je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
-msgstr "Zamčení nebo odemčení aktivních sezení"
+msgstr "Zamknout nebo odemknout aktivní sezení"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Autentizace je vyžadována pro zamčení nebo odemčení aktivních sezení."
+msgstr "Pro zamčení nebo odemčení aktivních sezení je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
@@ -414,8 +404,7 @@ msgstr "Povolit indikaci firmwaru bootovat instalační prostředí"
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup interface."
 msgstr ""
-"Autentizace je vyžadována k povolení indikace firmwaru bootovat instalační "
-"prostředí."
+"K povolení indikace firmwaru bootovat instalační prostředí je vyžadováno ověření."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
@@ -423,7 +412,7 @@ msgstr "Nastavit zprávu všem uživatelům"
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
-msgstr "Autentizace je vyžadována k nastavení zprávy všem uživatelům"
+msgstr "K nastavení zprávy všem uživatelům je vyžadováno ověření"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
@@ -431,7 +420,7 @@ msgstr "Přihlásit se do lokálního kontejneru"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
 msgid "Authentication is required to log into a local container."
-msgstr "Autentizace je vyžadována pro přihlášení do lokálního kontejneru."
+msgstr "Pro přihlášení do lokálního kontejneru je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
 msgid "Log into the local host"
@@ -439,39 +428,39 @@ msgstr "Přihlásit se na lokální stroj"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
 msgid "Authentication is required to log into the local host."
-msgstr "Autentizace je vyžadována pro přihlášení k lokálnímu stroji."
+msgstr "Pro přihlášení k lokálnímu stroji je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
 msgid "Acquire a shell in a local container"
-msgstr "Získání shellu v lokálním kontejneru"
+msgstr "Získat shell v lokálním kontejneru"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
 msgid "Authentication is required to acquire a shell in a local container."
-msgstr "Autentizace je vyžadována pro získání shellu v lokálním kontejneru."
+msgstr "Pro získání shellu v lokálním kontejneru je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
 msgid "Acquire a shell on the local host"
-msgstr "Získání shellu na lokálním stroji"
+msgstr "Získat shell na lokálním stroji"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
 msgid "Authentication is required to acquire a shell on the local host."
-msgstr "Autentizace je vyžadována pro získání shellu na lokálním stroji."
+msgstr "Pro získání shellu na lokálním stroji je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
 msgid "Acquire a pseudo TTY in a local container"
-msgstr "Získání Pseudo TTY v lokálním kontejneru"
+msgstr "Získat pseudo TTY v lokálním kontejneru"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
 msgid "Authentication is required to acquire a pseudo TTY in a local container."
-msgstr "Autentizace je vyžadována pro získání pseudo TTY v lokálním kontejneru."
+msgstr "Pro získání pseudo TTY v lokálním kontejneru je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
 msgid "Acquire a pseudo TTY on the local host"
-msgstr "Získání pseudo TTY na lokálním stroji"
+msgstr "Získat pseudo TTY na lokálním stroji"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
 msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "Autentizace je vyžadována pro získání pseudo TTY na lokálním stroji."
+msgstr "Pro získání pseudo TTY na lokálním stroji je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
@@ -479,8 +468,7 @@ msgstr "Spravovat lokální virtuální stroje a kontejnery"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
 msgid "Authentication is required to manage local virtual machines and containers."
-msgstr ""
-"Autentizace je vyžadována pro správu lokálních virtuálních strojů a kontejnerů."
+msgstr "Pro správu lokálních virtuálních strojů a kontejnerů je vyžadováno ověření."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
@@ -489,7 +477,8 @@ msgstr "Spravovat lokální obrazy virtuálních strojů a kontejnerů"
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
 msgid ""
 "Authentication is required to manage local virtual machine and container images."
-msgstr "Autentizace je vyžadována ke správě obrazů virtuálních strojů a kontejnerů."
+msgstr ""
+"Pro správu obrazů lokálních virtuálních strojů a kontejnerů je vyžadováno ověření."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -497,7 +486,7 @@ msgstr "Nastavit systémový čas"
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
 msgid "Authentication is required to set the system time."
-msgstr "Autentizace je vyžadována pro nastavení systémového času."
+msgstr "Pro nastavení systémového času je vyžadováno ověření."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
 msgid "Set system timezone"
@@ -505,7 +494,7 @@ msgstr "Nastavit systémovou časovou zónu"
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
 msgid "Authentication is required to set the system timezone."
-msgstr "Autentizace je vyžadována pro nastavení systémové časové zóny."
+msgstr "Pro nastavení systémové časové zóny je vyžadováno ověření."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
 msgid "Set RTC to local timezone or UTC"
@@ -515,8 +504,8 @@ msgstr "Nastavit RTC na lokální časovou zónu nebo UTC"
 msgid ""
 "Authentication is required to control whether the RTC stores the local or UTC time."
 msgstr ""
-"Autentizace je vyžadována pro kontrolu jestli RTC ukládá lokální časovou zónu nebo "
-"UTC čas."
+"Pro kontrolu jestli RTC ukládá lokální časovou zónu nebo UTC čas je vyžadováno "
+"ověření."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
 msgid "Turn network time synchronization on or off"
@@ -526,32 +515,32 @@ msgstr "Zapnout nebo vypnout synchronizaci s časem ze sítě"
 msgid ""
 "Authentication is required to control whether network time synchronization shall "
 "be enabled."
-msgstr "Autentizace je vyžadována pro kontrolu synchronizace času ze sítě."
+msgstr "Pro kontrolu synchronizace času ze sítě je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:459
 msgid "Authentication is required to start '$(unit)'."
-msgstr "Autentizace je vyžadována pro spuštění „$(unit)”."
+msgstr "Pro spuštění „$(unit)” je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:460
 msgid "Authentication is required to stop '$(unit)'."
-msgstr "Autentizace je vyžadována pro vypnutí „$(unit)”."
+msgstr "Pro vypnutí „$(unit)” je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:461
 msgid "Authentication is required to reload '$(unit)'."
-msgstr "Autentizace je vyžadována pro znovu načtení „$(unit)”."
+msgstr "Pro znovu načtení „$(unit)” je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:462 ../src/core/dbus-unit.c:463
 msgid "Authentication is required to restart '$(unit)'."
-msgstr "Autentizace je vyžadována pro restart „$(unit)”."
+msgstr "Pro restart „$(unit)” je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:570
 msgid "Authentication is required to kill '$(unit)'."
-msgstr "Autentizace je vyžadována pro ukončení „$(unit)”."
+msgstr "Pro ukončení „$(unit)” je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:601
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "Autentizace je vyžadována pro resetování chybného stavu „$(unit)”."
+msgstr "Pro resetování chybného stavu „$(unit)” je vyžadováno ověření."
 
 #: ../src/core/dbus-unit.c:634
 msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "Autentizace je vyžadována pro nastavení vlastností na „$(unit)”."
+msgstr "Pro nastavení vlastností na „$(unit)” je vyžadováno ověření."
diff --git a/po/meson.build b/po/meson.build
new file mode 100644 (file)
index 0000000..f89291b
--- /dev/null
@@ -0,0 +1,12 @@
+i18n = import('i18n')
+i18n.gettext(meson.project_name())
+
+#####################################################################
+
+intltool_merge = find_program('intltool-merge')
+po_dir = meson.current_source_dir()
+
+intltool_cache = join_paths(meson.current_build_dir(), 'intltool-merge-cache')
+intltool_command = [intltool_merge, '-x', '-u',
+                    '-c', intltool_cache,
+                    po_dir, '@INPUT@', '@OUTPUT@']
index 2a11371f97924d3a2ffeecac714c2f8a7b9fb105..a087a4786b649028480d4e3afdbaadef7dc45e5b 100644 (file)
@@ -1,23 +1,22 @@
 # Brazilian Portuguese translation for systemd.
-# Copyright (C) 2015 systemd's COPYRIGHT HOLDER
+# Copyright (C) 2017 systemd's COPYRIGHT HOLDER
 # This file is distributed under the same license as the systemd package.
-# Rafael Ferreira <rafael.f.f1@gmail.com>, 2014.
 # Enrico Nicoletto <liverig@gmail.com>, 2014.
-#
+# Rafael Fontenelle <rafaelff@gnome.org>, 2015, 2017.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-11-22 16:37+0100\n"
-"PO-Revision-Date: 2015-01-10 12:23-0300\n"
-"Last-Translator: Rafael Ferreira <rafael.f.f1@gmail.com>\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2016-11-17 03:29+0000\n"
+"PO-Revision-Date: 2017-04-03 14:25-0200\n"
+"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
 "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
 "Language: pt_BR\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 1.7.1\n"
+"X-Generator: Virtaal 1.0.0-beta1\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
 msgid "Send passphrase back to system"
@@ -31,15 +30,14 @@ msgstr ""
 "sistema."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-#, fuzzy
 msgid "Manage system services or other units"
-msgstr "Gerenciar unidades e serviços do sistema"
+msgstr "Gerenciar serviços do sistema e outras unidades"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-#, fuzzy
 msgid "Authentication is required to manage system services or other units."
 msgstr ""
-"É necessária autenticação para gerenciar unidades e serviços do sistema."
+"É necessária autenticação para gerenciar serviços do sistema ou outras "
+"unidades."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
 msgid "Manage system service or unit files"
@@ -52,18 +50,18 @@ msgstr ""
 "sistema."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
-#, fuzzy
 msgid "Set or unset system and service manager environment variables"
-msgstr "Acesso privilegiado ao gerenciador de serviço e de sistema"
+msgstr ""
+"Definir ou retirar definição de variáveis de ambiente de gerenciador de "
+"serviço e sistema"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
-#, fuzzy
 msgid ""
 "Authentication is required to set or unset system and service manager "
 "environment variables."
 msgstr ""
-"É necessária autenticação para gerenciar arquivos \"unit\" e \"service\" do "
-"sistema."
+"É necessária autenticação para definir ou retirar definição de variáveis de "
+"ambiente de gerenciador de serviço e sistema."
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
 msgid "Reload the systemd state"
@@ -103,30 +101,27 @@ msgstr "É necessária autenticação para definir informações de máquina loc
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:1
 msgid "Import a VM or container image"
-msgstr ""
+msgstr "Importar uma VM ou imagem contêiner"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to import a VM or container image"
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr "É necessária autenticação para importar uma VM ou imagem contêiner"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:3
 msgid "Export a VM or container image"
-msgstr ""
+msgstr "Exportar uma VM ou imagem contêiner"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to export a VM or container image"
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr "É necessária autenticação para exportar uma VM ou imagem contêiner"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:5
 msgid "Download a VM or container image"
-msgstr ""
+msgstr "Baixar uma VM ou imagem contêiner"
 
 #: ../src/import/org.freedesktop.import1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to download a VM or container image"
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr "É necessária autenticação para baixar uma VM ou imagem contêiner"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:1
 msgid "Set system locale"
@@ -254,48 +249,61 @@ msgstr ""
 "sistema sobre o interruptor da tela."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+#| msgid "Allow non-logged-in users to run programs"
+msgid "Allow non-logged-in user to run programs"
+msgstr ""
+"Permitir que programas sejam executados por usuário que não possui sessão"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#| msgid "Authentication is required to run programs as a non-logged-in user."
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"É necessária requisição explícita para executar programas como usuário sem "
+"sessão aberta."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr ""
 "Permitir que programas sejam executados por usuários que não possuem sessão"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "É necessária autenticação para executar programas como usuário sem sessão "
 "aberta."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Permitir conectar dispositivos em estações"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr "É necessária autenticação para conectar um dispositivo em uma estação."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Liberar dispositivo para conexões da estação"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "É necessária autenticação para redefinir a quantidade de dispositivos "
 "conectados na estação."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Desligar o sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "É necessária autenticação para desligar o sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Desligar o sistema enquanto outros usuários estão conectados"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -303,11 +311,11 @@ msgstr ""
 "É necessária autenticação para desligar o sistema enquanto outros usuários "
 "estão conectados."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Desligar o sistema enquanto um aplicativo solicitou inibição"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -315,19 +323,19 @@ msgstr ""
 "É necessária autenticação para desligar o sistema enquanto um aplicativo "
 "solicitou inibição."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Reiniciar o sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "É necessária autenticação para reiniciar o sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Reiniciar o sistema enquanto outros usuários estiverem conectados"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -335,11 +343,11 @@ msgstr ""
 "É necessária autenticação para reiniciar o sistema enquanto outros usuários "
 "estiverem conectados."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Reiniciar o sistema enquanto um aplicativo solicitou inibição"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -347,19 +355,19 @@ msgstr ""
 "É necessária autenticação para reiniciar o sistema enquanto um aplicativo "
 "solicitou inibição."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Suspender o sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "É necessária autenticação para suspender o sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr "Suspender o sistema enquanto outros usuários estiverem conectados"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -367,11 +375,11 @@ msgstr ""
 "É necessária autenticação para suspender o sistema enquanto outros usuários "
 "estiverem conectados."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "Suspender o sistema enquanto um aplicativo solicitou inibição"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -379,19 +387,19 @@ msgstr ""
 "É necessária autenticação para suspender o sistema enquanto um aplicativo "
 "solicitou inibição."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Hibernar o sistema"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "É necessária autenticação para hibernar o sistema."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr "Hibernar o sistema enquanto outros usuários estiverem conectados"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -399,11 +407,11 @@ msgstr ""
 "É necessária autenticação para hibernar o sistema enquanto outros usuários "
 "estiverem conectados."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "Hibernar o sistema enquanto um aplicativo solicitou inibição"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -411,123 +419,121 @@ msgstr ""
 "É necessária autenticação para hibernar o sistema enquanto um aplicativo "
 "solicitou inibição."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
-msgstr ""
+msgstr "Gerenciar estações, usuários e sessões ativas"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
-#, fuzzy
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
-msgstr "É necessária autenticação para conectar um dispositivo em uma estação."
+msgstr ""
+"É necessária autenticação para gerenciar estações, usuários e sessões ativas."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
-msgstr ""
+msgstr "Travar ou destravar sessões ativas"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
-#, fuzzy
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr "É necessária autenticação para travar ou destravar sessões ativas."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr ""
+"Permitir indicação para o firmware inicializar para a interface de "
+"configuração"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
-#, fuzzy
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
-msgstr "É necessária autenticação para definir nome de máquina local."
+msgstr ""
+"É necessária autenticação para indicar para o firmware inicializar para a "
+"interface de configuração."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
-msgstr ""
+msgstr "Definir uma mensagem de parede"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
-#, fuzzy
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
-msgstr "É necessária autenticação para definir nome de máquina local."
+msgstr "É necessária autenticação para definir uma mensagem de parede"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:1
 msgid "Log into a local container"
 msgstr "Conectar a um contêiner local"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-#, fuzzy
 msgid "Authentication is required to log into a local container."
 msgstr "É necessária autenticação para se conectar a um contêiner local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-#, fuzzy
 msgid "Log into the local host"
-msgstr "Conectar a um contêiner local"
+msgstr "Conectar a uma máquina local"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-#, fuzzy
 msgid "Authentication is required to log into the local host."
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr "É necessária autenticação para se conectar a uma máquina local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:5
-#, fuzzy
 msgid "Acquire a shell in a local container"
-msgstr "Conectar a um contêiner local"
+msgstr "Adquirir uma shell em um contêiner local"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-#, fuzzy
 msgid "Authentication is required to acquire a shell in a local container."
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr ""
+"É necessária autenticação para adquirir uma shell em um contêiner local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:7
 msgid "Acquire a shell on the local host"
-msgstr ""
+msgstr "Adquirir uma shell na máquina local"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:8
-#, fuzzy
 msgid "Authentication is required to acquire a shell on the local host."
-msgstr "É necessária autenticação para definir nome de máquina local."
+msgstr ""
+"É necessária autenticação para adquirir uma shell em uma máquina local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:9
-#, fuzzy
 msgid "Acquire a pseudo TTY in a local container"
-msgstr "Conectar a um contêiner local"
+msgstr "Adquirir um pseudo TTY em um contêiner local"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:10
-#, fuzzy
 msgid ""
 "Authentication is required to acquire a pseudo TTY in a local container."
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr ""
+"É necessária autenticação para adquirir um pseudo TTY em um contêiner local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:11
 msgid "Acquire a pseudo TTY on the local host"
-msgstr ""
+msgstr "Adquiri um pseudo TTY na máquina local"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:12
-#, fuzzy
 msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "É necessária autenticação para definir nome de máquina local."
+msgstr ""
+"É necessária autenticação para adquirir um pseudo TTY em um máquina local."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:13
 msgid "Manage local virtual machines and containers"
-msgstr ""
+msgstr "Gerenciar máquinas virtuais locais e contêineres"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:14
-#, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machines and containers."
-msgstr "É necessária autenticação para definir informações de máquina local."
+msgstr ""
+"É necessária autenticação para gerenciar máquinas virtuais locais e "
+"contêineres."
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:15
 msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Gerenciar máquinas virtuais locais e imagens contêineres"
 
 #: ../src/machine/org.freedesktop.machine1.policy.in.h:16
-#, fuzzy
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
-msgstr "É necessária autenticação para definir informações de máquina local."
+msgstr ""
+"É necessária autenticação para gerenciar máquinas virtuais locais e imagens "
+"contêineres."
 
 #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
 msgid "Set system time"
@@ -569,37 +575,31 @@ msgstr ""
 "É necessária autenticação para controlar se deve ser habilitada, ou não, a "
 "sincronização de horário através de rede."
 
-#: ../src/core/dbus-unit.c:428
-#, fuzzy
+#: ../src/core/dbus-unit.c:457
 msgid "Authentication is required to start '$(unit)'."
-msgstr "É necessária autenticação para definir o horário do sistema."
+msgstr "É necessária autenticação para iniciar '$(unit)'."
 
-#: ../src/core/dbus-unit.c:429
-#, fuzzy
+#: ../src/core/dbus-unit.c:458
 msgid "Authentication is required to stop '$(unit)'."
-msgstr "É necessária autenticação para definir o horário do sistema."
+msgstr "É necessária autenticação para parar '$(unit)'."
 
-#: ../src/core/dbus-unit.c:430
-#, fuzzy
+#: ../src/core/dbus-unit.c:459
 msgid "Authentication is required to reload '$(unit)'."
-msgstr "É necessária autenticação para recarregar o estado do sistema."
+msgstr "É necessária autenticação para recarregar '$(unit)'."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
-#, fuzzy
+#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
 msgid "Authentication is required to restart '$(unit)'."
-msgstr "É necessária autenticação para definir o horário do sistema."
+msgstr "É necessária autenticação para reiniciar '$(unit)'."
 
-#: ../src/core/dbus-unit.c:535
-#, fuzzy
+#: ../src/core/dbus-unit.c:568
 msgid "Authentication is required to kill '$(unit)'."
-msgstr "É necessária autenticação para se conectar a um contêiner local."
+msgstr "É necessária autenticação para matar '$(unit)'."
 
-#: ../src/core/dbus-unit.c:565
-#, fuzzy
+#: ../src/core/dbus-unit.c:599
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "É necessária autenticação para definir nome de máquina local."
+msgstr ""
+"É necessária autenticação para reiniciar o estado \"failed\" de '$(unit)'."
 
-#: ../src/core/dbus-unit.c:597
-#, fuzzy
+#: ../src/core/dbus-unit.c:632
 msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "É necessária autenticação para definir o horário do sistema."
+msgstr "É necessária autenticação para definir propriedades em '$(unit)'."
diff --git a/po/sk.po b/po/sk.po
new file mode 100644 (file)
index 0000000..84dd732
--- /dev/null
+++ b/po/sk.po
@@ -0,0 +1,556 @@
+# Slovak translation for systemd.
+# Copyright (C) 2017 systemd's COPYRIGHT HOLDER
+# This file is distributed under the same license as the systemd package.
+# Dušan Kazik <prescott66@gmail.com>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2017-06-24 03:26+0000\n"
+"PO-Revision-Date: 2017-06-25 11:03+0200\n"
+"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
+"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
+"X-Generator: Poedit 2.0.2\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "Odoslanie hesla späť do systému"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na odoslanie zadaného hesla späť do systému."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "Správa systémových služieb alebo iných jednotiek"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na správu systémových služieb alebo iných "
+"jednotiek."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "Správa systémovej služby alebo súborov jednotky"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na správu systémovej služby alebo súborov "
+"jednotky."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr ""
+"Nastavenie alebo zrušenie nastavenia premenných prostredia systému a správcu "
+"služieb"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na nastavenie alebo zrušenie nastavenia "
+"premenných prostredia systému a správcu služieb."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "Znovu načítanie stavu systému systemd"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "Nastavenie názvu hostiteľa"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "Nastavenie nemenného názvu hostiteľa"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na nastavenie pevne určeného názvu miestneho "
+"hostiteľa, známeho ako zrozumiteľný názov hostiteľa."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "Nastavenie informácií o počítači"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na nastavenie informácií o miestnom počítači."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr ""
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr ""
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr ""
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr ""
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr ""
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr ""
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "Nastavenie miestnych nastavení"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "Nastavenie nastavení systémovej klávesnice"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej "
+"klávesnice."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Umožnenie aplikáciám odložiť spánok systému"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na odloženie spánku systému aplikáciou."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr "Umožnenie neprihlásenému používateľovi spúšťanie programov"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Vyžaduje sa explicitná požiadavka na spúšťanie programov ako neprihlásený "
+"používateľ."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow non-logged-in users to run programs"
+msgstr "Umožnenie neprihláseným používateľom spúšťanie programov"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na spúšťanie programov ako neprihlásený "
+"používateľ."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Allow attaching devices to seats"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid "Authentication is required for attaching a device to a seat."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Flush device to seat attachments"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system"
+msgstr "Vypnutie systému"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid "Authentication is required for powering off the system."
+msgstr "Vyžaduje sa overenie totožnosti na vypnutie systému."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while other users are logged in"
+msgstr "Vypnutie systému, pokiaľ sú prihlásení iní používatelia"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na vypnutie systému, pokiaľ sú prihlásení "
+"iní používatelia."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Power off the system while an application asked to inhibit it"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system"
+msgstr "Reštart systému"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid "Authentication is required for rebooting the system."
+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while other users are logged in"
+msgstr "Reštart systému, pokiaľ sú prihlásení iní používatelia"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na reštartovanie systému, pokiaľ sú "
+"prihlásení iní používatelia."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system"
+msgstr "Uspanie systému"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid "Authentication is required for suspending the system."
+msgstr "Vyžaduje sa overenie totožnosti na uspanie systému."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while other users are logged in"
+msgstr "Uspanie systému, pokiaľ sú prihlásení iní používatelia"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na uspanie systému, pokiaľ sú prihlásení iní "
+"používatelia."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid "Authentication is required for hibernating the system."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while other users are logged in"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Manage active sessions, users and seats"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Lock or unlock active sessions"
+msgstr "Zamknutie alebo odomknutie aktívnych relácií"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na uzamknutie alebo odomknutie aktívnych "
+"relácií."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr "Umožnenie indikácie spustenia inštalačného rozhrania pre firmvér"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na indikáciu spustenia inštalačného "
+"rozhrania pre firmvér."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
+msgid "Set a wall message"
+msgstr ""
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
+msgid "Authentication is required to set a wall message"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "Prihlásenie do miestneho kontajneru"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na prihlásenie do miestneho kontajneru."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr ""
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr ""
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "Zapnutie alebo vypnutie sieťovej synchronizácie času"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr ""
+"Vyžaduje sa overenie totožnosti na ovládanie, či má byť povolená "
+"synchronizácia času cez sieť."
+
+#: ../src/core/dbus-unit.c:457
+msgid "Authentication is required to start '$(unit)'."
+msgstr ""
+
+#: ../src/core/dbus-unit.c:458
+msgid "Authentication is required to stop '$(unit)'."
+msgstr ""
+
+#: ../src/core/dbus-unit.c:459
+msgid "Authentication is required to reload '$(unit)'."
+msgstr ""
+
+#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
+msgid "Authentication is required to restart '$(unit)'."
+msgstr ""
+
+#: ../src/core/dbus-unit.c:568
+msgid "Authentication is required to kill '$(unit)'."
+msgstr ""
+
+#: ../src/core/dbus-unit.c:599
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+
+#: ../src/core/dbus-unit.c:632
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr ""
index 6ecf5479a474918d14fc56f020064c4f8e4feb0e..1de9b4650de6d5b8b7f06c04ce2d2ce54790e046 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -1,24 +1,23 @@
 # Swedish translation for systemd.
 # Copyright © 2015 systemd's COPYRIGHT HOLDER
 # This file is distributed under the same license as the systemd package.
-# Josef Andersson <josef.andersson@fripost.org>, 2015.
 # Sebastian Rasmussen <sebras@gmail.com>, 2015.
 # Andreas Henriksson <andreas@fatal.se>, 2016.
-#
+# Josef Andersson <l10nl18nsweja@gmail.com>, 2015, 2017.
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd master\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-11-22 16:37+0100\n"
-"PO-Revision-Date: 2016-09-29 11:58+0200\n"
-"Last-Translator: Andreas Henriksson <andreas@fatal.se>\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2017-03-01 15:50+0000\n"
+"PO-Revision-Date: 2017-03-19 21:18+0100\n"
+"Last-Translator: Josef Andersson <l10nl18nsweja@gmail.com>\n"
 "Language-Team: Swedish\n"
 "Language: sv\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Gtranslator 2.91.7\n"
+"X-Generator: Poedit 1.8.9\n"
 
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
 msgid "Send passphrase back to system"
@@ -134,7 +133,8 @@ msgstr "Ange systeminställningar för tangentbord"
 
 #: ../src/locale/org.freedesktop.locale1.policy.in.h:4
 msgid "Authentication is required to set the system keyboard settings."
-msgstr "Autentisering krävs för att ställa in systeminställningar för tangentbord."
+msgstr ""
+"Autentisering krävs för att ställa in systeminställningar för tangentbord."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:1
 msgid "Allow applications to inhibit system shutdown"
@@ -237,45 +237,54 @@ msgstr ""
 "av brytaren för datorhöljet."
 
 #: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in user to run programs"
+msgstr "Tillåt ej inloggad användare att köra program"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Uttrycklig begäran krävs för att köra program som en icke inloggad användare."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
 msgid "Allow non-logged-in users to run programs"
 msgstr "Tillåt ej inloggade användare att köra program"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
 msgid "Authentication is required to run programs as a non-logged-in user."
 msgstr ""
 "Autentisering krävs för att köra program som en icke inloggad användare."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
 msgid "Allow attaching devices to seats"
 msgstr "Tillåt att binda enheter till platser"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
 msgid "Authentication is required for attaching a device to a seat."
 msgstr "Autentisering krävs för att binda en enhet till en plats."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
 msgid "Flush device to seat attachments"
 msgstr "Töm bindningar för enhet-till-plats"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
 msgid ""
 "Authentication is required for resetting how devices are attached to seats."
 msgstr ""
 "Autentisering krävs för att återställa hur enheter är bundna till platser."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
 msgid "Power off the system"
 msgstr "Stäng av systemet"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
 msgid "Authentication is required for powering off the system."
 msgstr "Autentisering krävs för att stänga av systemet."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
 msgid "Power off the system while other users are logged in"
 msgstr "Stäng av systemet medan andra användare är inloggade"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
 msgid ""
 "Authentication is required for powering off the system while other users are "
 "logged in."
@@ -283,11 +292,11 @@ msgstr ""
 "Autentisering krävs för att stänga av systemet medan andra användare är "
 "inloggade."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
 msgid "Power off the system while an application asked to inhibit it"
 msgstr "Stäng av systemet även då ett program hindrar det"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
 msgid ""
 "Authentication is required for powering off the system while an application "
 "asked to inhibit it."
@@ -295,19 +304,19 @@ msgstr ""
 "Autentisering krävs för att stänga av systemet även då ett program hindrar "
 "det."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
 msgid "Reboot the system"
 msgstr "Starta om systemet"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
 msgid "Authentication is required for rebooting the system."
 msgstr "Autentisering krävs för att starta om systemet."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
 msgid "Reboot the system while other users are logged in"
 msgstr "Starta om systemet medan andra användare är inloggade"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
 msgid ""
 "Authentication is required for rebooting the system while other users are "
 "logged in."
@@ -315,11 +324,11 @@ msgstr ""
 "Autentisering krävs för att starta om systemet medan andra användare är "
 "inloggade."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
 msgid "Reboot the system while an application asked to inhibit it"
 msgstr "Starta om systemet även då ett program hindrar det"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
 msgid ""
 "Authentication is required for rebooting the system while an application "
 "asked to inhibit it."
@@ -327,19 +336,19 @@ msgstr ""
 "Autentisering krävs för att starta om systemet även då ett program hindrar "
 "det."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
 msgid "Suspend the system"
 msgstr "Försätt system i vänteläge"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
 msgid "Authentication is required for suspending the system."
 msgstr "Autentisering krävs för att försätta system i vänteläge."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
 msgid "Suspend the system while other users are logged in"
 msgstr "Försätt systemet i vänteläge medan andra användare är inloggade"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
 msgid ""
 "Authentication is required for suspending the system while other users are "
 "logged in."
@@ -347,11 +356,11 @@ msgstr ""
 "Autentisering krävs för att försätta systemet i vänteläge medan andra "
 "användare är inloggade."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
 msgid "Suspend the system while an application asked to inhibit it"
 msgstr "Försätt systemet i vänteläge även då ett program hindrar det"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
 msgid ""
 "Authentication is required for suspending the system while an application "
 "asked to inhibit it."
@@ -359,19 +368,19 @@ msgstr ""
 "Autentisering krävs för att försätta ett program i vänteläge även då ett "
 "program hindrar det."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
 msgid "Hibernate the system"
 msgstr "Försätt systemet i viloläge"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
 msgid "Authentication is required for hibernating the system."
 msgstr "Autentisering krävs för att försätta systemet i viloläge."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
 msgid "Hibernate the system while other users are logged in"
 msgstr "Försätt systemet i viloläge medan andra användare är inloggade"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
 msgid ""
 "Authentication is required for hibernating the system while other users are "
 "logged in."
@@ -379,11 +388,11 @@ msgstr ""
 "Autentisering krävs för att försätta systemet i viloläge medan andra "
 "användare är inloggade."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
 msgid "Hibernate the system while an application asked to inhibit it"
 msgstr "Försätt systemet i viloläge även då ett program hindrar det"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
 msgid ""
 "Authentication is required for hibernating the system while an application "
 "asked to inhibit it."
@@ -391,30 +400,30 @@ msgstr ""
 "Autentisering krävs för att försätta ett program i viloläge även då ett "
 "program hindrar det."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
 msgid "Manage active sessions, users and seats"
 msgstr "Hantera aktiva sessioner, användare och platser"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
 msgid ""
 "Authentication is required for managing active sessions, users and seats."
 msgstr ""
 "Autentisering krävs för att hantera aktiva sessioner, användare och platser."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
 msgid "Lock or unlock active sessions"
 msgstr "Lås eller lås upp aktiva sessioner"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
 msgid "Authentication is required to lock or unlock active sessions."
 msgstr "Autentisering krävs för att låsa eller låsa upp aktiva sessioner."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
 msgid "Allow indication to the firmware to boot to setup interface"
 msgstr ""
 "Tillåt indikering till firmware att starta upp i inställningsgränssnitt"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
 msgid ""
 "Authentication is required to indicate to the firmware to boot to setup "
 "interface."
@@ -422,11 +431,11 @@ msgstr ""
 "Autentisering krävs för att indikera till firmware att starta upp till "
 "inställningsgränssnitt."
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: ../src/login/org.freedesktop.login1.policy.in.h:57
 msgid "Set a wall message"
 msgstr "Ange ett väggmeddelande"
 
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: ../src/login/org.freedesktop.login1.policy.in.h:58
 msgid "Authentication is required to set a wall message"
 msgstr "Autentisering krävs för att ställa in ett väggmeddelande"
 
@@ -547,33 +556,33 @@ msgstr ""
 "Autentisering krävs för att kontrollera huruvida synkronisering av "
 "nätverkstid ska vara aktiverat."
 
-#: ../src/core/dbus-unit.c:428
+#: ../src/core/dbus-unit.c:457
 msgid "Authentication is required to start '$(unit)'."
 msgstr "Autentisering krävs för att starta \"$(unit)\"."
 
-#: ../src/core/dbus-unit.c:429
+#: ../src/core/dbus-unit.c:458
 msgid "Authentication is required to stop '$(unit)'."
 msgstr "Autentisering krävs för att stoppa \"$(unit)\"."
 
-#: ../src/core/dbus-unit.c:430
+#: ../src/core/dbus-unit.c:459
 msgid "Authentication is required to reload '$(unit)'."
 msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"."
 
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461
 msgid "Authentication is required to restart '$(unit)'."
 msgstr "Autentisering krävs för att starta om \"$(unit)\"."
 
-#: ../src/core/dbus-unit.c:535
+#: ../src/core/dbus-unit.c:568
 msgid "Authentication is required to kill '$(unit)'."
 msgstr "Autentisering krävs för att döda \"$(unit)\"."
 
-#: ../src/core/dbus-unit.c:565
+#: ../src/core/dbus-unit.c:599
 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
 msgstr ""
 "Autentisering krävs för att återställa det \"fallerade\" tillståndet för "
 "\"$(unit)\"."
 
-#: ../src/core/dbus-unit.c:597
+#: ../src/core/dbus-unit.c:632
 msgid "Authentication is required to set properties on '$(unit)'."
 msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"."
 
index 93a50ddd804218fc41aaa7ca21156daa5f6bc3ec..ea6e216bad2d7f4ce966fab460ced4b8da160a31 100644 (file)
@@ -1 +1,2 @@
+/50-udev-default.rules
 /99-systemd.rules
diff --git a/rules/50-udev-default.rules b/rules/50-udev-default.rules
deleted file mode 100644 (file)
index 3347c8c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-# do not edit this file, it will be overwritten on update
-
-# run a command on remove events
-ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}"
-ACTION=="remove", GOTO="default_end"
-
-SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}"
-
-# select "system RTC" or just use the first one
-SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc"
-SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
-
-SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
-SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
-ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"
-
-ACTION!="add", GOTO="default_end"
-
-SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666"
-SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666"
-SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620"
-SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620"
-SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620"
-SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620"
-SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty"
-KERNEL=="tty[A-Z]*[0-9]|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout"
-
-SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640"
-
-SUBSYSTEM=="input", GROUP="input"
-SUBSYSTEM=="input", KERNEL=="js[0-9]*", MODE="0664"
-
-SUBSYSTEM=="video4linux", GROUP="video"
-SUBSYSTEM=="graphics", GROUP="video"
-SUBSYSTEM=="drm", GROUP="video"
-SUBSYSTEM=="dvb", GROUP="video"
-
-SUBSYSTEM=="sound", GROUP="audio", \
-  OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer"
-
-SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664"
-
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", GROUP="video"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", GROUP="video"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", GROUP="video"
-SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", GROUP="video"
-
-KERNEL=="parport[0-9]*", GROUP="lp"
-SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp"
-SUBSYSTEM=="ppdev", GROUP="lp"
-KERNEL=="lp[0-9]*", GROUP="lp"
-KERNEL=="irlpt[0-9]*", GROUP="lp"
-SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", GROUP="lp"
-
-SUBSYSTEM=="block", GROUP="disk"
-SUBSYSTEM=="block", KERNEL=="sr[0-9]*", GROUP="cdrom"
-SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", GROUP="cdrom"
-KERNEL=="sch[0-9]*", GROUP="cdrom"
-KERNEL=="pktcdvd[0-9]*", GROUP="cdrom"
-KERNEL=="pktcdvd", GROUP="cdrom"
-
-SUBSYSTEM=="scsi_generic|scsi_tape", SUBSYSTEMS=="scsi", ATTRS{type}=="1|8", GROUP="tape"
-SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="0", GROUP="disk"
-KERNEL=="qft[0-9]*|nqft[0-9]*|zqft[0-9]*|nzqft[0-9]*|rawqft[0-9]*|nrawqft[0-9]*", GROUP="disk"
-KERNEL=="loop-control", GROUP="disk", OPTIONS+="static_node=loop-control"
-KERNEL=="btrfs-control", GROUP="disk"
-KERNEL=="rawctl", GROUP="disk"
-SUBSYSTEM=="raw", KERNEL=="raw[0-9]*", GROUP="disk"
-SUBSYSTEM=="aoe", GROUP="disk", MODE="0220"
-SUBSYSTEM=="aoe", KERNEL=="err", MODE="0440"
-
-KERNEL=="rfkill", MODE="0664"
-KERNEL=="tun", MODE="0666", OPTIONS+="static_node=net/tun"
-
-KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse"
-
-SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm"
-
-LABEL="default_end"
diff --git a/rules/50-udev-default.rules.in b/rules/50-udev-default.rules.in
new file mode 100644 (file)
index 0000000..898148c
--- /dev/null
@@ -0,0 +1,82 @@
+# do not edit this file, it will be overwritten on update
+
+# run a command on remove events
+ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}"
+ACTION=="remove", GOTO="default_end"
+
+SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}"
+
+# select "system RTC" or just use the first one
+SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc"
+SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
+
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"
+
+ACTION!="add", GOTO="default_end"
+
+SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666"
+SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666"
+SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty"
+KERNEL=="tty[A-Z]*[0-9]|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout"
+
+SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640"
+
+SUBSYSTEM=="input", GROUP="input"
+SUBSYSTEM=="input", KERNEL=="js[0-9]*", MODE="0664"
+
+SUBSYSTEM=="video4linux", GROUP="video"
+SUBSYSTEM=="graphics", GROUP="video"
+SUBSYSTEM=="drm", GROUP="video"
+SUBSYSTEM=="dvb", GROUP="video"
+SUBSYSTEM=="media", GROUP="video"
+SUBSYSTEM=="cec", GROUP="video"
+
+SUBSYSTEM=="sound", GROUP="audio", \
+  OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer"
+
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664"
+
+SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", GROUP="video"
+SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", GROUP="video"
+SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", GROUP="video"
+SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", GROUP="video"
+
+KERNEL=="parport[0-9]*", GROUP="lp"
+SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp"
+SUBSYSTEM=="ppdev", GROUP="lp"
+KERNEL=="lp[0-9]*", GROUP="lp"
+KERNEL=="irlpt[0-9]*", GROUP="lp"
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", GROUP="lp"
+
+SUBSYSTEM=="block", GROUP="disk"
+SUBSYSTEM=="block", KERNEL=="sr[0-9]*", GROUP="cdrom"
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", GROUP="cdrom"
+KERNEL=="sch[0-9]*", GROUP="cdrom"
+KERNEL=="pktcdvd[0-9]*", GROUP="cdrom"
+KERNEL=="pktcdvd", GROUP="cdrom"
+
+SUBSYSTEM=="scsi_generic|scsi_tape", SUBSYSTEMS=="scsi", ATTRS{type}=="1|8", GROUP="tape"
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="0", GROUP="disk"
+KERNEL=="qft[0-9]*|nqft[0-9]*|zqft[0-9]*|nzqft[0-9]*|rawqft[0-9]*|nrawqft[0-9]*", GROUP="disk"
+KERNEL=="loop-control", GROUP="disk", OPTIONS+="static_node=loop-control"
+KERNEL=="btrfs-control", GROUP="disk"
+KERNEL=="rawctl", GROUP="disk"
+SUBSYSTEM=="raw", KERNEL=="raw[0-9]*", GROUP="disk"
+SUBSYSTEM=="aoe", GROUP="disk", MODE="0220"
+SUBSYSTEM=="aoe", KERNEL=="err", MODE="0440"
+
+KERNEL=="rfkill", MODE="0664"
+KERNEL=="tun", MODE="0666", OPTIONS+="static_node=net/tun"
+
+KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse"
+
+KERNEL=="kvm", GROUP="kvm", MODE="@DEV_KVM_MODE@"
+
+SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm"
+
+LABEL="default_end"
index 42c75974a571acb6a10a3eaec58308de0fcd982d..343fc06f852abbebb92028147e1767680fb20f70 100644 (file)
@@ -8,4 +8,4 @@ ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_
 ACTION=="change", SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST=="block", ATTR{block/*/uevent}="change"
 
 # watch metadata changes, caused by tools closing the device node which was opened for writing
-ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*|nvme*|sd*|vd*|xvd*|pmem*", OPTIONS+="watch"
+ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*|nvme*|sd*|vd*|xvd*|pmem*|mmcblk*", OPTIONS+="watch"
index f91d8cb456f323b869264efe471fbd57850fbeef..288f8ce2f9621a726b2c444719810d4e2013ead3 100644 (file)
@@ -2,7 +2,7 @@
 
 ACTION=="remove", GOTO="cdrom_end"
 SUBSYSTEM!="block", GOTO="cdrom_end"
-KERNEL!="sr[0-9]*|xvd*", GOTO="cdrom_end"
+KERNEL!="sr[0-9]*|vdisk*|xvd*", GOTO="cdrom_end"
 ENV{DEVTYPE}!="disk", GOTO="cdrom_end"
 
 # unconditionally tag device as CDROM
index f5d5ba6a5f8393fbbc501d43af76b0bac72937ea..e5e608acd3daa4a73990a1ce8e17aa8842f46ffd 100644 (file)
@@ -8,7 +8,7 @@ IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \
   RUN{builtin}+="keyboard", GOTO="evdev_end"
 
 # AT keyboard matching by the machine's DMI data
-ENV{ID_INPUT_KEY}=="?*", DRIVERS=="atkbd", \
+DRIVERS=="atkbd", \
   IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \
   RUN{builtin}+="keyboard", GOTO="evdev_end"
 
diff --git a/rules/60-input-id.rules b/rules/60-input-id.rules
new file mode 100644 (file)
index 0000000..dee4219
--- /dev/null
@@ -0,0 +1,7 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="id_input_end"
+
+SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
+
+LABEL="id_input_end"
index 607144bf8af8204f64a03fbf5602e606c597be50..91efbe7294318c7018c7c369bceef406ec857039 100644 (file)
@@ -3,6 +3,8 @@
 ACTION=="remove", GOTO="persistent_input_end"
 SUBSYSTEM!="input", GOTO="persistent_input_end"
 SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
+# Bluetooth devices don't always have the bluetooth subsystem
+ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
 SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi", GOTO="persistent_input_end"
 SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042", GOTO="persistent_input_end"
 
index 9817e9c64bb72d0baab12c1fb88b2cee3526b301..d2745f65f4e0f2927f13fc8562ce454d7568dd02 100644 (file)
@@ -64,7 +64,8 @@ KERNEL=="msblk[0-9]p[0-9]|mspblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}
 
 # by-path
 ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id"
-ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
+KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-boot%n"
+KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
 ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
 
 # legacy virtio-pci by-path links (deprecated)
index 82e44f8843cb83aabd334db8597df1bd8fc4be28..7ad2c36be3d405b3725bf8990daded4ce65645b6 100644 (file)
@@ -7,4 +7,12 @@ SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="usb|i2c", \
   IMPORT{builtin}="hwdb 'sensor:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \
   GOTO="sensor_end"
 
+SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="acpi", \
+  IMPORT{builtin}="hwdb 'sensor:modalias:acpi:$attr{hid}:$attr{[dmi/id]modalias}'", \
+  GOTO="sensor_end"
+
+SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="platform", \
+  IMPORT{builtin}="hwdb 'sensor:modalias:platform:$id:$attr{[dmi/id]modalias}'", \
+  GOTO="sensor_end"
+
 LABEL="sensor_end"
diff --git a/rules/70-joystick.rules b/rules/70-joystick.rules
new file mode 100644 (file)
index 0000000..b80d203
--- /dev/null
@@ -0,0 +1,12 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="joystick_end"
+ENV{ID_INPUT_JOYSTICK}=="", GOTO="joystick_end"
+KERNEL!="event*", GOTO="joystick_end"
+
+# joystick:<bustype>:v<vid>p<pid>:name:<name>:*
+KERNELS=="input*", ENV{ID_BUS}!="", \
+        IMPORT{builtin}="hwdb 'joystick:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
+        GOTO="joystick_end"
+
+LABEL="joystick_end"
diff --git a/rules/meson.build b/rules/meson.build
new file mode 100644 (file)
index 0000000..0f818a5
--- /dev/null
@@ -0,0 +1,39 @@
+rules = files('''
+        60-block.rules
+        60-cdrom_id.rules
+        60-drm.rules
+        60-evdev.rules
+        60-input-id.rules
+        60-persistent-alsa.rules
+        60-persistent-input.rules
+        60-persistent-storage.rules
+        60-persistent-storage-tape.rules
+        60-persistent-v4l.rules
+        60-sensor.rules
+        60-serial.rules
+        64-btrfs.rules
+        70-mouse.rules
+        70-touchpad.rules
+        75-net-description.rules
+        75-probe_mtd.rules
+        78-sound-card.rules
+        80-drivers.rules
+        80-net-setup-link.rules
+'''.split())
+
+install_data(rules,
+             install_dir : udevrulesdir)
+
+rules_in = '''
+        50-udev-default.rules
+        99-systemd.rules
+'''.split()
+
+foreach file : rules_in
+        gen = configure_file(
+                input : file + '.in',
+                output : file,
+                configuration : substs)
+        install_data(gen,
+                     install_dir : udevrulesdir)
+endforeach
diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build
new file mode 100644 (file)
index 0000000..9399661
--- /dev/null
@@ -0,0 +1,50 @@
+bashcompletiondir = get_option('bashcompletiondir')
+if bashcompletiondir == ''
+        bash_completion = dependency('bash-completion', required : false)
+        if bash_completion.found()
+                bashcompletiondir = bash_completion.get_pkgconfig_variable('completionsdir')
+        else
+                bashcompletiondir = join_paths(datadir, 'bash-completion/completions')
+        endif
+
+        message('bash completions: @0@'.format(bashcompletiondir))
+endif
+
+if bashcompletiondir != 'no'
+        bash_systemctl = configure_file(
+                input : 'systemctl.in',
+                output : 'systemctl',
+                configuration : substs)
+
+        items = [['busctl',              ''],
+                 ['journalctl',          ''],
+                 ['systemd-analyze',     ''],
+                 ['systemd-cat',         ''],
+                 ['systemd-cgls',        ''],
+                 ['systemd-cgtop',       ''],
+                 ['systemd-delta',       ''],
+                 ['systemd-detect-virt', ''],
+                 ['systemd-nspawn',      ''],
+                 ['systemd-path',        ''],
+                 ['systemd-run',         ''],
+                 ['udevadm',             ''],
+                 ['kernel-install',      ''],
+                 [bash_systemctl,        ''],
+                 ['bootctl',             'ENABLE_EFI'],
+                 ['coredumpctl',         'ENABLE_COREDUMP'],
+                 ['hostnamectl',         'ENABLE_HOSTNAMED'],
+                 ['localectl',           'ENABLE_LOCALED'],
+                 ['loginctl',            'ENABLE_LOGIND'],
+                 ['machinectl',          'ENABLE_MACHINED'],
+                 ['networkctl',          'ENABLE_NETWORKD'],
+                 ['systemd-resolve',     'ENABLE_RESOLVED'],
+                 ['timedatectl',         'ENABLE_TIMEDATED'],
+                ]
+
+        foreach item : items
+                if item[1] == '' or conf.get(item[1], false)
+                        install_data(item[0],
+                                     install_dir : bashcompletiondir)
+                endif
+        endforeach
+endif
index 942c7e1c009b786a307444cabc0272bcab54e9e6..68e33384717f966f0848b422e253ee476edfb97d 100644 (file)
@@ -36,7 +36,7 @@ _networkctl() {
         )
 
         local -A VERBS=(
-                [STANDALONE]='list lldp'
+                [STANDALONE]='list lldp label'
                 [LINKS]='status'
         )
 
index e4ccad879961a3bbeb3aafc4c2b9fd270b30a504..0398d09d18d14f1c717872a95113d9970a4b2e65 100644 (file)
@@ -172,7 +172,7 @@ _systemctl () {
                                 comps='full enable-only disable-only'
                         ;;
                         --output|-o)
-                                comps='short short-full short-iso short-precise short-monotonic short-unix verbose export json
+                                comps='short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json
                                        json-pretty json-sse cat'
                         ;;
                         --machine|-M)
@@ -189,7 +189,7 @@ _systemctl () {
         fi
 
         local -A VERBS=(
-                [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies edit set-property'
+                [ALL_UNITS]='is-active is-failed is-enabled status show cat mask preset help list-dependencies edit set-property revert'
             [ENABLED_UNITS]='disable'
            [DISABLED_UNITS]='enable'
         [REENABLABLE_UNITS]='reenable'
index 61f173b78e9630dae87a24623451022db642a325..acf7463edb5533a11d9da94eb45565ea4be26ae2 100644 (file)
@@ -6,6 +6,7 @@ _networkctl_command(){
             'list:List existing links'
            'status:Show information about the specified links'
            'lldp:Show Link Layer Discovery Protocol status'
+           'label:Show address labels'
     )
     if (( CURRENT == 1 )); then
         _describe -t commands 'networkctl command' _networkctl_cmds
index 52617c6b7aaef8e83a270c19fbc5008b119caa72..2948f40130be08ddff5828b15dd4e0d29370cf5e 100644 (file)
@@ -1,5 +1,5 @@
 #autoload
 
 local -a _output_opts
-_output_opts=(short short-full short-iso short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat)
+_output_opts=(short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat)
 _describe -t output 'output mode' _output_opts || compadd "$@"
index 92a56ba99a0959317947d52d2bab41850e9864a1..aad700b739ce829667be0110a3169c567a718725 100644 (file)
@@ -29,6 +29,8 @@
     "list-unit-files:List installed unit files"
     "enable:Enable one or more unit files"
     "disable:Disable one or more unit files"
+    "add-wants:Add Wants= dependencies to a unit"
+    "add-requires:Add Requires= dependencies to a unit"
     "reenable:Reenable one or more unit files"
     "preset:Enable/disable one or more unit files based on preset configuration"
     "set-default:Set the default target"
@@ -58,6 +60,7 @@
     "kexec:Shut down and reboot the system with kexec"
     "exit:Ask for user instance termination"
     "switch-root:Change root directory"
+    "revert:Revert unit files to their vendor versions"
   )
 
   if (( CURRENT == 1 )); then
@@ -157,7 +160,7 @@ _systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__sys
 
 local fun
 # Completion functions for ALL_UNITS
-for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies edit ; do
+for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies edit revert add-wants add-requires ; do
   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
   {
     _systemctl_really_all_units
diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build
new file mode 100644 (file)
index 0000000..34408ce
--- /dev/null
@@ -0,0 +1,47 @@
+zshcompletiondir = get_option('zshcompletiondir')
+if zshcompletiondir == ''
+        zshcompletiondir = join_paths(datadir, 'zsh/site-functions')
+
+        message('zsh completions: @0@'.format(zshcompletiondir))
+endif
+
+if zshcompletiondir != 'no'
+        zsh_systemctl = configure_file(
+                input : '_systemctl.in',
+                output : '_systemctl',
+                configuration : substs)
+
+        items = [['_busctl',                   ''],
+                 ['_journalctl',               ''],
+                 ['_systemd-analyze',          ''],
+                 ['_systemd-delta',            ''],
+                 ['_systemd-nspawn',           ''],
+                 ['_systemd',                  ''],
+                 ['_systemd-run',              ''],
+                 ['_udevadm',                  ''],
+                 ['_kernel-install',           ''],
+                 ['_sd_hosts_or_user_at_host', ''],
+                 ['_sd_outputmodes',           ''],
+                 ['_sd_unit_files',            ''],
+                 ['_sd_machines',              ''],
+                 [zsh_systemctl,               ''],
+                 ['_bootctl',                  'ENABLE_EFI'],
+                 ['_coredumpctl',              'ENABLE_COREDUMP'],
+                 ['_hostnamectl',              'ENABLE_HOSTNAMED'],
+                 ['_localectl',                'ENABLE_LOCALED'],
+                 ['_loginctl',                 'ENABLE_LOGIND'],
+                 ['_machinectl',               'ENABLE_MACHINED'],
+                 ['_networkctl',               'ENABLE_NETWORKD'],
+                 ['_systemd-inhibit',          'ENABLE_LOGIND'],
+                 ['_systemd-resolve',          'ENABLE_RESOLVED'],
+                 ['_systemd-tmpfiles',         'ENABLE_TMPFILES'],
+                 ['_timedatectl',              'ENABLE_TIMEDATED'],
+                ]
+
+        foreach item : items
+                if item[1] == '' or conf.get(item[1], false)
+                        install_data(item[0],
+                                     install_dir : zshcompletiondir)
+                endif
+        endforeach
+endif
index ac0470b20d931fae3e323823c659529b4c75092d..1eb2ca0ccf63a2418a1e4e6a9f9cdc8465fd7bde 100644 (file)
@@ -627,7 +627,7 @@ static int analyze_plot(sd_bus *bus) {
             "<!-- that render these files properly but much slower are ImageMagick,   -->\n"
             "<!-- gimp, inkscape, etc. To display the files on your system, just      -->\n"
             "<!-- point your browser to this file.                                    -->\n\n"
-            "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", VERSION);
+            "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", PACKAGE_VERSION);
 
         /* style sheet */
         svg("<defs>\n  <style type=\"text/css\">\n    <![CDATA[\n"
diff --git a/src/analyze/meson.build b/src/analyze/meson.build
new file mode 100644 (file)
index 0000000..fcbd814
--- /dev/null
@@ -0,0 +1,5 @@
+systemd_analyze_sources = files('''
+        analyze.c
+        analyze-verify.c
+        analyze-verify.h
+'''.split())
diff --git a/src/basic/af-to-name.awk b/src/basic/af-to-name.awk
new file mode 100644 (file)
index 0000000..18d0a89
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN{
+        print "static const char* const af_names[] = { "
+}
+!/AF_FILE/ && !/AF_ROUTE/ && !/AF_LOCAL/ {
+        printf "        [%s] = \"%s\",\n", $1, $1
+}
+END{
+        print "};"
+}
index 5a3dc08a4a7bb637f5079e481fa689e696f88ac9..2518dd81125d2f030805eaea93e7bf0460e57914 100644 (file)
@@ -132,6 +132,9 @@ int uname_architecture(void) {
 #  elif __SIZEOF_POINTER__ == 8
                 { "riscv",      ARCHITECTURE_RISCV64  },
 #  endif
+#elif defined(__arc__)
+                { "arc",        ARCHITECTURE_ARC      },
+                { "arceb",      ARCHITECTURE_ARC_BE   },
 #else
 #error "Please register your architecture here!"
 #endif
@@ -185,6 +188,8 @@ static const char *const architecture_table[_ARCHITECTURE_MAX] = {
         [ARCHITECTURE_NIOS2] = "nios2",
         [ARCHITECTURE_RISCV32] = "riscv32",
         [ARCHITECTURE_RISCV64] = "riscv64",
+        [ARCHITECTURE_ARC] = "arc",
+        [ARCHITECTURE_ARC_BE] = "arc-be",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(architecture, int);
index 46883719d16c3314ccb6e4e508a8d25467637951..40a2ce6448d58b100bbfff2eb14ef29ea922ed16 100644 (file)
@@ -60,6 +60,8 @@ enum {
         ARCHITECTURE_NIOS2,
         ARCHITECTURE_RISCV32,
         ARCHITECTURE_RISCV64,
+        ARCHITECTURE_ARC,
+        ARCHITECTURE_ARC_BE,
         _ARCHITECTURE_MAX,
         _ARCHITECTURE_INVALID = -1
 };
@@ -79,7 +81,11 @@ int uname_architecture(void);
 
 #if defined(__x86_64__)
 #  define native_architecture() ARCHITECTURE_X86_64
-#  define LIB_ARCH_TUPLE "x86_64-linux-gnu"
+#  if defined(__ILP32__)
+#    define LIB_ARCH_TUPLE "x86_64-linux-gnux32"
+#  else
+#    define LIB_ARCH_TUPLE "x86_64-linux-gnu"
+#  endif
 #  define SECONDARY_ARCHITECTURE ARCHITECTURE_X86
 #elif defined(__i386__)
 #  define native_architecture() ARCHITECTURE_X86
@@ -97,7 +103,11 @@ int uname_architecture(void);
 #elif defined(__powerpc__)
 #  if __BYTE_ORDER == __BIG_ENDIAN
 #    define native_architecture() ARCHITECTURE_PPC
-#    define LIB_ARCH_TUPLE "powerpc-linux-gnu"
+#    if defined(__NO_FPRS__)
+#      define LIB_ARCH_TUPLE "powerpc-linux-gnuspe"
+#    else
+#      define LIB_ARCH_TUPLE "powerpc-linux-gnu"
+#    endif
 #  else
 #    define native_architecture() ARCHITECTURE_PPC_LE
 #    error "Missing LIB_ARCH_TUPLE for PPCLE"
@@ -189,7 +199,23 @@ int uname_architecture(void);
 #  error "Missing LIB_ARCH_TUPLE for SH64"
 #elif defined(__sh__)
 #  define native_architecture() ARCHITECTURE_SH
-#  define LIB_ARCH_TUPLE "sh4-linux-gnu"
+#  if defined(__SH1__)
+#    define LIB_ARCH_TUPLE "sh1-linux-gnu"
+#  elif defined(__SH2__)
+#    define LIB_ARCH_TUPLE "sh2-linux-gnu"
+#  elif defined(__SH2A__)
+#    define LIB_ARCH_TUPLE "sh2a-linux-gnu"
+#  elif defined(__SH2E__)
+#    define LIB_ARCH_TUPLE "sh2e-linux-gnu"
+#  elif defined(__SH3__)
+#    define LIB_ARCH_TUPLE "sh3-linux-gnu"
+#  elif defined(__SH3E__)
+#    define LIB_ARCH_TUPLE "sh3e-linux-gnu"
+#  elif defined(__SH4__) && !defined(__SH4A__)
+#    define LIB_ARCH_TUPLE "sh4-linux-gnu"
+#  elif defined(__SH4A__)
+#    define LIB_ARCH_TUPLE "sh4a-linux-gnu"
+#  endif
 #elif defined(__m68k__)
 #  define native_architecture() ARCHITECTURE_M68K
 #  define LIB_ARCH_TUPLE "m68k-linux-gnu"
@@ -213,6 +239,14 @@ int uname_architecture(void);
 #  else
 #    error "Unrecognized riscv architecture variant"
 #  endif
+#elif defined(__arc__)
+#  if __BYTE_ORDER == __BIG_ENDIAN
+#    define native_architecture() ARCHITECTURE_ARC_BE
+#    define LIB_ARCH_TUPLE "arceb-linux"
+#  else
+#    define native_architecture() ARCHITECTURE_ARC
+#    define LIB_ARCH_TUPLE "arc-linux"
+#  endif
 #else
 #  error "Please register your architecture here!"
 #endif
diff --git a/src/basic/arphrd-to-name.awk b/src/basic/arphrd-to-name.awk
new file mode 100644 (file)
index 0000000..5a35673
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN{
+        print "static const char* const arphrd_names[] = { "
+}
+!/CISCO/ {
+        printf "        [ARPHRD_%s] = \"%s\",\n", $1, $1
+}
+END{
+        print "};"
+}
index 7aa75eb091242e3d17b137440a18ad7efa6d266b..1b9cace0407257d05aca29b3faf686642c125cdc 100644 (file)
@@ -20,7 +20,7 @@
 ***/
 
 #ifdef HAVE_BLKID
-#include <blkid/blkid.h>
+#include <blkid.h>
 #endif
 
 #include "util.h"
index 91312bd2a3cb89692b781314b6799f22253c3134..3223915da617be3855f891c2168bc91fef4ae97a 100644 (file)
 #define _KMOD_FEATURE_ "-KMOD"
 #endif
 
+#ifdef HAVE_LIBIDN2
+#define _IDN2_FEATURE_ "+IDN2"
+#else
+#define _IDN2_FEATURE_ "-IDN2"
+#endif
+
 #ifdef HAVE_LIBIDN
 #define _IDN_FEATURE_ "+IDN"
 #else
         _BLKID_FEATURE_ " "                                             \
         _ELFUTILS_FEATURE_ " "                                          \
         _KMOD_FEATURE_ " "                                              \
+        _IDN2_FEATURE_ " "                                              \
         _IDN_FEATURE_ " "                                               \
         _CGROUP_HIEARCHY_
index 2323eb85556b24df4adc1a87a7337eb9e20ad5cb..204120ee0e939bcf11716c11b88631860d55cdfc 100644 (file)
@@ -487,22 +487,33 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
         }
 }
 
+static int parse_one_number(const char *p, const char **e, unsigned long *ret) {
+        char *ee = NULL;
+        unsigned long value;
+
+        errno = 0;
+        value = strtoul(p, &ee, 10);
+        if (errno > 0)
+                return -errno;
+        if (ee == p)
+                return -EINVAL;
+
+        *ret = value;
+        *e = ee;
+        return 0;
+}
+
 static int parse_component_decimal(const char **p, bool usec, int *res) {
         unsigned long value;
         const char *e = NULL;
-        char *ee = NULL;
         int r;
 
         if (!isdigit(**p))
                 return -EINVAL;
 
-        errno = 0;
-        value = strtoul(*p, &ee, 10);
-        if (errno > 0)
-                return -errno;
-        if (ee == *p)
-                return -EINVAL;
-        e = ee;
+        r = parse_one_number(*p, &e, &value);
+        if (r < 0)
+                return r;
 
         if (usec) {
                 if (value * USEC_PER_SEC / USEC_PER_SEC != value)
@@ -553,6 +564,47 @@ static int const_chain(int value, CalendarComponent **c) {
         return 0;
 }
 
+static int calendarspec_from_time_t(CalendarSpec *c, time_t time) {
+        struct tm tm;
+        CalendarComponent *year = NULL, *month = NULL, *day = NULL, *hour = NULL, *minute = NULL, *us = NULL;
+        int r;
+
+        assert_se(gmtime_r(&time, &tm));
+
+        r = const_chain(tm.tm_year + 1900, &year);
+        if (r < 0)
+                return r;
+
+        r = const_chain(tm.tm_mon + 1, &month);
+        if (r < 0)
+                return r;
+
+        r = const_chain(tm.tm_mday, &day);
+        if (r < 0)
+                return r;
+
+        r = const_chain(tm.tm_hour, &hour);
+        if (r < 0)
+                return r;
+
+        r = const_chain(tm.tm_min, &minute);
+        if (r < 0)
+                return r;
+
+        r = const_chain(tm.tm_sec * USEC_PER_SEC, &us);
+        if (r < 0)
+                return r;
+
+        c->utc = true;
+        c->year = year;
+        c->month = month;
+        c->day = day;
+        c->hour = hour;
+        c->minute = minute;
+        c->microsecond = us;
+        return 0;
+}
+
 static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
         int r, start, stop = -1, repeat = 0;
         CalendarComponent *cc;
@@ -657,6 +709,27 @@ static int parse_date(const char **p, CalendarSpec *c) {
         if (*t == 0)
                 return 0;
 
+        /* @TIMESTAMP — UNIX time in seconds since the epoch */
+        if (*t == '@') {
+                unsigned long value;
+                time_t time;
+
+                r = parse_one_number(t + 1, &t, &value);
+                if (r < 0)
+                        return r;
+
+                time = value;
+                if ((unsigned long) time != value)
+                        return -ERANGE;
+
+                r = calendarspec_from_time_t(c, time);
+                if (r < 0)
+                        return r;
+
+                *p = t;
+                return 1; /* finito, don't parse H:M:S after that */
+        }
+
         r = parse_chain(&t, false, &first);
         if (r < 0)
                 return r;
@@ -832,7 +905,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                                 continue;
 
                         e = endswith_no_case(p, tzname[j]);
-                        if(!e)
+                        if (!e)
                                 continue;
                         if (e == p)
                                 continue;
@@ -986,9 +1059,11 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
-                r = parse_calendar_time(&p, c);
-                if (r < 0)
-                        goto fail;
+                if (r == 0) {
+                        r = parse_calendar_time(&p, c);
+                        if (r < 0)
+                                goto fail;
+                }
 
                 if (*p != 0) {
                         r = -EINVAL;
diff --git a/src/basic/cap-to-name.awk b/src/basic/cap-to-name.awk
new file mode 100644 (file)
index 0000000..402a782
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN{
+        print "static const char* const capability_names[] = { "
+}
+{
+        printf "        [%s] = \"%s\",\n", $1, tolower($1)
+}
+END{
+        print "};"
+}
index bda5c555ad38fe6e2e069e4b23670a7508c29753..6344372610b70508d46132f27eb2c439249ac3f9 100644 (file)
@@ -55,6 +55,7 @@
 #include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strv.h"
 #include "unit-name.h"
 #include "user-util.h"
 
@@ -839,7 +840,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid) {
         if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
                 r = cg_attach(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, pid);
                 if (r < 0)
-                        log_warning_errno(r, "Failed to attach %d to compat systemd cgroup %s: %m", pid, path);
+                        log_warning_errno(r, "Failed to attach "PID_FMT" to compat systemd cgroup %s: %m", pid, path);
         }
 
         return 0;
@@ -2211,6 +2212,60 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root)
         return 0;
 }
 
+int cg_mask_to_string(CGroupMask mask, char **ret) {
+        const char *controllers[_CGROUP_CONTROLLER_MAX + 1];
+        CGroupController c;
+        int i = 0;
+        char *s;
+
+        assert(ret);
+
+        if (mask == 0) {
+                *ret = NULL;
+                return 0;
+        }
+
+        for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
+
+                if (!(mask & CGROUP_CONTROLLER_TO_MASK(c)))
+                        continue;
+
+                controllers[i++] = cgroup_controller_to_string(c);
+                controllers[i] = NULL;
+        }
+
+        s = strv_join((char **)controllers, NULL);
+        if (!s)
+                return -ENOMEM;
+
+        *ret = s;
+        return 0;
+}
+
+int cg_mask_from_string(const char *value, CGroupMask *mask) {
+        assert(mask);
+        assert(value);
+
+        for (;;) {
+                _cleanup_free_ char *n = NULL;
+                CGroupController v;
+                int r;
+
+                r = extract_first_word(&value, &n, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                v = cgroup_controller_from_string(n);
+                if (v < 0)
+                        continue;
+
+                *mask |= CGROUP_CONTROLLER_TO_MASK(v);
+        }
+        return 0;
+}
+
 int cg_mask_supported(CGroupMask *ret) {
         CGroupMask mask = 0;
         int r;
@@ -2224,7 +2279,6 @@ int cg_mask_supported(CGroupMask *ret) {
                 return r;
         if (r > 0) {
                 _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL;
-                const char *c;
 
                 /* In the unified hierarchy we can read the supported
                  * and accessible controllers from a the top-level
@@ -2242,23 +2296,9 @@ int cg_mask_supported(CGroupMask *ret) {
                 if (r < 0)
                         return r;
 
-                c = controllers;
-                for (;;) {
-                        _cleanup_free_ char *n = NULL;
-                        CGroupController v;
-
-                        r = extract_first_word(&c, &n, NULL, 0);
-                        if (r < 0)
-                                return r;
-                        if (r == 0)
-                                break;
-
-                        v = cgroup_controller_from_string(n);
-                        if (v < 0)
-                                continue;
-
-                        mask |= CGROUP_CONTROLLER_TO_MASK(v);
-                }
+                r = cg_mask_from_string(controllers, &mask);
+                if (r < 0)
+                        return r;
 
                 /* Currently, we support the cpu, memory, io and pids
                  * controller in the unified hierarchy, mask
index a522095d9574ccb6e0ef24f8862f87a305a16579..c16a33723cc4eafe6d1d34cc898ca7c1f395e713 100644 (file)
@@ -235,6 +235,8 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root)
 int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p);
 
 int cg_mask_supported(CGroupMask *ret);
+int cg_mask_from_string(const char *s, CGroupMask *ret);
+int cg_mask_to_string(CGroupMask mask, char **ret);
 
 int cg_kernel_controllers(Set *controllers);
 
index 200ea973c19041d4dbe2b9b33beb16b6a7c583b6..b1a3bc190bd0e39cd713f7ccca6550ce7ca19114 100644 (file)
                 .un.sun_path = "\0/org/freedesktop/plymouthd",  \
         }
 
-#ifndef TTY_GID
-#define TTY_GID 5
-#endif
-
 #define NOTIFY_FD_MAX 768
 #define NOTIFY_BUFFER_MAX PIPE_BUF
 
index 6b9d26773ea78868a50fdb662bb6ba8ea559bd64..5bf58bcdc36d442022e1ef6a82965e06aecfcdf2 100644 (file)
@@ -75,3 +75,14 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
 
         return endswith(de->d_name, suffix);
 }
+
+struct dirent* readdir_no_dot(DIR *dirp) {
+        struct dirent* d;
+
+        for (;;) {
+                d = readdir(dirp);
+                if (d && dot_or_dot_dot(d->d_name))
+                        continue;
+                return d;
+        }
+}
index b91d04908f9a01545ed7f68e4f32fbc91323288d..18b9db9b28c6c3d80bd3a5d422149f5b4c3b6cee 100644 (file)
@@ -31,6 +31,8 @@ int dirent_ensure_type(DIR *d, struct dirent *de);
 bool dirent_is_file(const struct dirent *de) _pure_;
 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
 
+struct dirent* readdir_no_dot(DIR *dirp);
+
 #define FOREACH_DIRENT(de, d, on_error)                                 \
         for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d))   \
                 if (!de) {                                              \
index 1ec574e8a0e3d77a96bef77fb9cb2d29b2f4b974..56e7b6fd8c1d92b33032179bc91d6ed114c0da80 100644 (file)
@@ -779,7 +779,7 @@ int serialize_environment(FILE *f, char **environment) {
                 if (!ce)
                         return -ENOMEM;
 
-                fprintf(f, "env=%s\n", *e);
+                fprintf(f, "env=%s\n", ce);
         }
 
         /* caller should call ferror() */
@@ -788,7 +788,7 @@ int serialize_environment(FILE *f, char **environment) {
 }
 
 int deserialize_environment(char ***environment, const char *line) {
-        char *uce = NULL;
+        char *uce;
         int r;
 
         assert(line);
@@ -799,8 +799,10 @@ int deserialize_environment(char ***environment, const char *line) {
         if (r < 0)
                 return r;
 
-        if (!env_assignment_is_valid(uce))
+        if (!env_assignment_is_valid(uce)) {
+                free(uce);
                 return -EINVAL;
+        }
 
         return strv_env_replace(environment, uce);
 }
diff --git a/src/basic/errno-to-name.awk b/src/basic/errno-to-name.awk
new file mode 100644 (file)
index 0000000..0878aba
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN{
+        print "static const char* const errno_names[] = { "
+}
+!/EDEADLOCK/ && !/EWOULDBLOCK/ && !/ENOTSUP/ {
+        printf "        [%s] = \"%s\",\n", $1, $1
+}
+END{
+        print "};"
+}
index 4a1ec4505ed3b12d508327be60905247570b2e57..85e4b5282ed758a914ad0109176f3a6601ee8815 100644 (file)
@@ -441,10 +441,16 @@ char *octescape(const char *s, size_t len) {
 
 }
 
-static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
+static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) {
         assert(bad);
 
         for (; *s; s++) {
+                if (escape_tab_nl && IN_SET(*s, '\n', '\t')) {
+                        *(t++) = '\\';
+                        *(t++) = *s == '\n' ? 'n' : 't';
+                        continue;
+                }
+
                 if (*s == '\\' || strchr(bad, *s))
                         *(t++) = '\\';
 
@@ -461,20 +467,21 @@ char *shell_escape(const char *s, const char *bad) {
         if (!r)
                 return NULL;
 
-        t = strcpy_backslash_escaped(r, s, bad);
+        t = strcpy_backslash_escaped(r, s, bad, false);
         *t = 0;
 
         return r;
 }
 
-char *shell_maybe_quote(const char *s) {
+char* shell_maybe_quote(const char *s, EscapeStyle style) {
         const char *p;
         char *r, *t;
 
         assert(s);
 
-        /* Encloses a string in double quotes if necessary to make it
-         * OK as shell string. */
+        /* Encloses a string in quotes if necessary to make it OK as a shell
+         * string. Note that we treat benign UTF-8 characters as needing
+         * escaping too, but that should be OK. */
 
         for (p = s; *p; p++)
                 if (*p <= ' ' ||
@@ -485,17 +492,30 @@ char *shell_maybe_quote(const char *s) {
         if (!*p)
                 return strdup(s);
 
-        r = new(char, 1+strlen(s)*2+1+1);
+        r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1);
         if (!r)
                 return NULL;
 
         t = r;
-        *(t++) = '"';
+        if (style == ESCAPE_BACKSLASH)
+                *(t++) = '"';
+        else if (style == ESCAPE_POSIX) {
+                *(t++) = '$';
+                *(t++) = '\'';
+        } else
+                assert_not_reached("Bad EscapeStyle");
+
         t = mempcpy(t, s, p - s);
 
-        t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
+        if (style == ESCAPE_BACKSLASH)
+                t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false);
+        else
+                t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
 
-        *(t++)= '"';
+        if (style == ESCAPE_BACKSLASH)
+                *(t++) = '"';
+        else
+                *(t++) = '\'';
         *t = 0;
 
         return r;
index deaa4def2828e27776b95a4062b92238e4a4d269..6f5cc60bc80d7bc58538d4058775028451c061a2 100644 (file)
 /* What characters are special in the shell? */
 /* must be escaped outside and inside double-quotes */
 #define SHELL_NEED_ESCAPE "\"\\`$"
-/* can be escaped or double-quoted */
-#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;"
+
+/* Those that can be escaped or double-quoted.
+ *
+ * Stricly speaking, ! does not need to be escaped, except in interactive
+ * mode, but let's be extra nice to the user and quote ! in case this
+ * output is ever used in interactive mode. */
+#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;!"
+
+/* Note that we assume control characters would need to be escaped too in
+ * addition to the "special" characters listed here, if they appear in the
+ * string. Current users disallow control characters. Also '"' shall not
+ * be escaped.
+ */
+#define SHELL_NEED_ESCAPE_POSIX "\\\'"
 
 typedef enum UnescapeFlags {
         UNESCAPE_RELAX = 1,
 } UnescapeFlags;
 
+typedef enum EscapeStyle {
+        ESCAPE_BACKSLASH = 1,
+        ESCAPE_POSIX = 2,
+} EscapeStyle;
+
 char *cescape(const char *s);
 char *cescape_length(const char *s, size_t n);
 size_t cescape_char(char c, char *buf);
@@ -51,4 +68,4 @@ char *xescape(const char *s, const char *bad);
 char *octescape(const char *s, size_t len);
 
 char *shell_escape(const char *s, const char *bad);
-char *shell_maybe_quote(const char *s);
+char* shell_maybe_quote(const char *s, EscapeStyle style);
index f8cac3e911fddef4630ff78eb731077b508089bd..804f14c44c48ac02525086ceb289d1aa41177a80 100644 (file)
@@ -241,7 +241,12 @@ int extract_first_word_and_warn(
         return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
 }
 
-int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
+/* We pass ExtractFlags as unsigned int (to avoid undefined behaviour when passing
+ * an object that undergoes default argument promotion as an argument to va_start).
+ * Let's make sure that ExtractFlags fits into an unsigned int. */
+assert_cc(sizeof(enum ExtractFlags) <= sizeof(unsigned));
+
+int extract_many_words(const char **p, const char *separators, unsigned flags, ...) {
         va_list ap;
         char **l;
         int n = 0, i, c, r;
index 21db5ef33fb550bb3e34644a9f510dcf7958079a..04746c6d085ed3db60902ebaf923a81e1fdde6b5 100644 (file)
@@ -32,4 +32,4 @@ typedef enum ExtractFlags {
 
 int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
 int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
-int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
+int extract_many_words(const char **p, const char *separators, unsigned flags, ...) _sentinel_;
index 66dbc0fe1e6286cede6359f21948591078116191..ef51c493955c4e1eda771b39f2e45f197b8d1603 100644 (file)
 #include "fileio.h"
 #include "selinux-util.h"
 
-int write_string_file_atomic_label(const char *fn, const char *line) {
+int write_string_file_atomic_label_ts(const char *fn, const char *line, struct timespec *ts) {
         int r;
 
         r = mac_selinux_create_file_prepare(fn, S_IFREG);
         if (r < 0)
                 return r;
 
-        r = write_string_file(fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+        r = write_string_file_ts(fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC, ts);
 
         mac_selinux_create_file_clear();
 
index fe7543013d143441ec492c98e2b8c1a1b33614d9..9854ea50b9d4ba3246b21e36f4ff7c5529780d05 100644 (file)
 
 #include "fileio.h"
 
-int write_string_file_atomic_label(const char *fn, const char *line);
+int write_string_file_atomic_label_ts(const char *fn, const char *line, struct timespec *ts);
+static inline int write_string_file_atomic_label(const char *fn, const char *line) {
+        return write_string_file_atomic_label_ts(fn, line, NULL);
+}
 int write_env_file_label(const char *fname, char **l);
 int fopen_temporary_label(const char *target,
                           const char *path, FILE **f, char **temp_path);
index 7c2c2b38f5112ce143387258de55bd15c4dd923a..9a185e3e6098097746c4c2258dd9d3162212e6de 100644 (file)
@@ -51,7 +51,7 @@
 
 #define READ_FULL_BYTES_MAX (4U*1024U*1024U)
 
-int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
+int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts) {
 
         assert(f);
         assert(line);
@@ -60,6 +60,13 @@ int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
         if (enforce_newline && !endswith(line, "\n"))
                 fputc('\n', f);
 
+        if (ts) {
+                struct timespec twice[2] = {*ts, *ts};
+
+                if (futimens(fileno(f), twice) < 0)
+                        return -errno;
+        }
+
         return fflush_and_check(f);
 }
 
@@ -89,7 +96,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
         return r;
 }
 
-int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
+int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) {
         _cleanup_fclose_ FILE *f = NULL;
         int q, r;
 
@@ -104,7 +111,8 @@ int write_string_file(const char *fn, const char *line, WriteStringFileFlags fla
                         goto fail;
 
                 return r;
-        }
+        } else
+                assert(ts == NULL);
 
         if (flags & WRITE_STRING_FILE_CREATE) {
                 f = fopen(fn, "we");
@@ -131,7 +139,7 @@ int write_string_file(const char *fn, const char *line, WriteStringFileFlags fla
                 }
         }
 
-        r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+        r = write_string_stream_ts(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE), ts);
         if (r < 0)
                 goto fail;
 
index e547614cc489398360f408dcabef5f2a42614b73..60985622650b8010ac6148f00d26b1bdce513e76 100644 (file)
@@ -35,8 +35,14 @@ typedef enum {
         WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
 } 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 write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts);
+static inline int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
+        return write_string_stream_ts(f, line, enforce_newline, NULL);
+}
+int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts);
+static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
+        return write_string_file_ts(fn, line, flags, NULL);
+}
 
 int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
index 39a185f59b4affffedc8044b556a4ab019edcd95..ae42a8f89e8ca87d32898c3c7bb05af1616b01dc 100644 (file)
 #  error Unknown time_t size
 #endif
 
+#if defined __x86_64__ && defined __ILP32__
+#  define PRI_TIMEX PRIi64
+#else
+#  define PRI_TIMEX "li"
+#endif
+
 #if SIZEOF_RLIM_T == 8
 #  define RLIM_FMT "%" PRIu64
 #elif SIZEOF_RLIM_T == 4
diff --git a/src/basic/generate-af-list.sh b/src/basic/generate-af-list.sh
new file mode 100755 (executable)
index 0000000..8d9cdd1
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh -eu
+
+$1 -E -dM -include sys/socket.h - </dev/null | \
+        grep -Ev 'AF_UNSPEC|AF_MAX' | \
+        awk '/^#define[ \t]+AF_[^ \t]+[ \t]+PF_[^ \t]/ { print $2; }'
diff --git a/src/basic/generate-arphrd-list.sh b/src/basic/generate-arphrd-list.sh
new file mode 100755 (executable)
index 0000000..ee207fb
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh -eu
+
+$1 -dM -include net/if_arp.h - </dev/null | \
+        awk '/^#define[ \t]+ARPHRD_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
+        sed -e 's/ARPHRD_//'
diff --git a/src/basic/generate-cap-list.sh b/src/basic/generate-cap-list.sh
new file mode 100755 (executable)
index 0000000..1d4a562
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh -eu
+
+$1 -dM -include linux/capability.h -include "$2" -include "$3" - </dev/null | \
+        awk '/^#define[ \t]+CAP_[A-Z_]+[ \t]+/ { print $2; }' | \
+        grep -v CAP_LAST_CAP
diff --git a/src/basic/generate-errno-list.sh b/src/basic/generate-errno-list.sh
new file mode 100755 (executable)
index 0000000..e2bab8b
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh -eu
+
+$1 -dM -include errno.h - </dev/null | \
+        awk '/^#define[ \t]+E[^ _]+[ \t]+/ { print $2; }'
diff --git a/src/basic/generate-gperfs.py b/src/basic/generate-gperfs.py
new file mode 100755 (executable)
index 0000000..d4cc9aa
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+
+"""Generate %-from-name.gperf from %-list.txt
+"""
+
+import sys
+
+name, prefix, input = sys.argv[1:]
+
+print("""\
+struct {}_name {{ const char* name; int id; }};
+%null-strings
+%%""".format(name))
+
+for line in open(input):
+    print("{0}, {1}{0}".format(line.rstrip(), prefix))
index 007198c269863a9f69ee4bfc8b75d3e66107770a..f611c42e4c3fc0f437cc088f5621c5bb264708a8 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
 #include <errno.h>
 #include <glob.h>
+#include <sys/types.h>
 
+#include "dirent-util.h"
 #include "glob-util.h"
 #include "macro.h"
+#include "path-util.h"
 #include "strv.h"
 
-int glob_exists(const char *path) {
-        _cleanup_globfree_ glob_t g = {};
+int safe_glob(const char *path, int flags, glob_t *pglob) {
         int k;
 
-        assert(path);
+        /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */
+        assert(!(flags & GLOB_ALTDIRFUNC));
+
+        if (!pglob->gl_closedir)
+                pglob->gl_closedir = (void (*)(void *)) closedir;
+        if (!pglob->gl_readdir)
+                pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot;
+        if (!pglob->gl_opendir)
+                pglob->gl_opendir = (void *(*)(const char *)) opendir;
+        if (!pglob->gl_lstat)
+                pglob->gl_lstat = lstat;
+        if (!pglob->gl_stat)
+                pglob->gl_stat = stat;
 
         errno = 0;
-        k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+        k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob);
 
         if (k == GLOB_NOMATCH)
-                return 0;
+                return -ENOENT;
         if (k == GLOB_NOSPACE)
                 return -ENOMEM;
         if (k != 0)
                 return errno > 0 ? -errno : -EIO;
+        if (strv_isempty(pglob->gl_pathv))
+                return -ENOENT;
 
-        return !strv_isempty(g.gl_pathv);
+        return 0;
 }
 
-int glob_extend(char ***strv, const char *path) {
+int glob_exists(const char *path) {
         _cleanup_globfree_ glob_t g = {};
         int k;
-        char **p;
 
-        errno = 0;
-        k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+        assert(path);
 
-        if (k == GLOB_NOMATCH)
-                return -ENOENT;
-        if (k == GLOB_NOSPACE)
-                return -ENOMEM;
-        if (k != 0)
-                return errno > 0 ? -errno : -EIO;
-        if (strv_isempty(g.gl_pathv))
-                return -ENOENT;
+        k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
+        if (k == -ENOENT)
+                return false;
+        if (k < 0)
+                return k;
+        return true;
+}
+
+int glob_extend(char ***strv, const char *path) {
+        _cleanup_globfree_ glob_t g = {};
+        int k;
 
-        STRV_FOREACH(p, g.gl_pathv) {
-                k = strv_extend(strv, *p);
-                if (k < 0)
-                        return k;
-        }
+        k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
+        if (k < 0)
+                return k;
 
-        return 0;
+        return strv_extend_strv(strv, g.gl_pathv, false);
 }
index 5d8fb47a268c3a265aa8290051273aa2f9d4b6bc..e1f6083afaf911f05e01f5d18c62d009dca79f6d 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <glob.h>
 #include <stdbool.h>
 #include <string.h>
 
 #include "macro.h"
 #include "string-util.h"
 
+/* Note: this function modifies pglob to set various functions. */
+int safe_glob(const char *path, int flags, glob_t *pglob);
+
 int glob_exists(const char *path);
 int glob_extend(char ***strv, const char *path);
 
index 3927df2955862436349fdee73e48487cd3eba5f1..d52fdad3ac974c670783a8c8bd4ef00bd040b2ae 100644 (file)
@@ -464,3 +464,45 @@ int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen)
 
         return -EAFNOSUPPORT;
 }
+
+int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, uint8_t *ret_prefixlen) {
+        union in_addr_union buffer;
+        const char *e, *l;
+        uint8_t k;
+        int r;
+
+        assert(p);
+
+        if (!IN_SET(family, AF_INET, AF_INET6))
+                return -EAFNOSUPPORT;
+
+        e = strchr(p, '/');
+        if (e)
+                l = strndupa(p, e - p);
+        else
+                l = p;
+
+        r = in_addr_from_string(family, l, &buffer);
+        if (r < 0)
+                return r;
+
+        k = FAMILY_ADDRESS_SIZE(family) * 8;
+
+        if (e) {
+                uint8_t n;
+
+                r = safe_atou8(e + 1, &n);
+                if (r < 0)
+                        return r;
+
+                if (n > k)
+                        return -ERANGE;
+
+                k = n;
+        }
+
+        *ret_prefix = buffer;
+        *ret_prefixlen = k;
+
+        return 0;
+}
index 51a5aa67e4101b6ec1934748dd5475e81a10a492..14e27246b59684d6f7594afaef7d423902a83311 100644 (file)
@@ -60,6 +60,7 @@ struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char
 int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen);
 int in_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask);
 int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen);
+int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, uint8_t *ret_prefixlen);
 
 static inline size_t FAMILY_ADDRESS_SIZE(int family) {
         assert(family == AF_INET || family == AF_INET6);
index 4c13e46a49e986d5d93b79b9b6750e9218b295a0..7d72effdea9f30c57e8d4ca9b284f3359e3fbd64 100644 (file)
@@ -24,6 +24,7 @@
 #include "fd-util.h"
 #include "parse-util.h"
 #include "string-util.h"
+#include "unaligned.h"
 
 enum {
         IMPORTER_STATE_LINE = 0,    /* waiting to read, or reading line */
@@ -68,6 +69,7 @@ void journal_importer_cleanup(JournalImporter *imp) {
                 safe_close(imp->fd);
         }
 
+        free(imp->name);
         free(imp->buf);
         iovw_free_contents(&imp->iovw);
 }
@@ -203,7 +205,7 @@ static int get_data_size(JournalImporter *imp) {
         if (r <= 0)
                 return r;
 
-        imp->data_size = le64toh( *(uint64_t *) data );
+        imp->data_size = unaligned_read_le64(data);
         if (imp->data_size > DATA_SIZE_MAX) {
                 log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u",
                           imp->data_size, DATA_SIZE_MAX);
@@ -314,7 +316,7 @@ int journal_importer_process_data(JournalImporter *imp) {
                         return r;
                 if (r == 0) {
                         imp->state = IMPORTER_STATE_EOF;
-                        return r;
+                        return 0;
                 }
                 assert(n > 0);
                 assert(line[n-1] == '\n');
index 36efc9ac7d8eaf598f776ba831c605d0f78f8070..3fd53800a090e6d82037e1fa2a9c51beaa20afb4 100644 (file)
@@ -58,7 +58,8 @@
 #define SNDBUF_SIZE (8*1024*1024)
 
 static LogTarget log_target = LOG_TARGET_CONSOLE;
-static int log_max_level = LOG_INFO;
+static int log_max_level[] = {LOG_INFO, LOG_INFO};
+assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX);
 static int log_facility = LOG_DAEMON;
 
 static int console_fd = STDERR_FILENO;
@@ -231,6 +232,8 @@ fail:
 int log_open(void) {
         int r;
 
+        /* Do not call from library code. */
+
         /* If we don't use the console we close it here, to not get
          * killed by SAK. If we don't use syslog we close it here so
          * that we are not confused by somebody deleting the socket in
@@ -305,6 +308,8 @@ void log_set_target(LogTarget target) {
 }
 
 void log_close(void) {
+        /* Do not call from library code. */
+
         log_close_journal();
         log_close_syslog();
         log_close_kmsg();
@@ -312,13 +317,16 @@ void log_close(void) {
 }
 
 void log_forget_fds(void) {
+        /* Do not call from library code. */
+
         console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
 }
 
-void log_set_max_level(int level) {
+void log_set_max_level_realm(LogRealm realm, int level) {
         assert((level & LOG_PRIMASK) == level);
+        assert(realm < ELEMENTSOF(log_max_level));
 
-        log_max_level = level;
+        log_max_level[realm] = level;
 }
 
 void log_set_facility(int facility) {
@@ -553,7 +561,7 @@ static int write_to_journal(
         return 1;
 }
 
-static int log_dispatch(
+int log_dispatch_internal(
                 int level,
                 int error,
                 const char *file,
@@ -636,13 +644,14 @@ static int log_dispatch(
 }
 
 int log_dump_internal(
-        int level,
-        int error,
-        const char *file,
-        int line,
-        const char *func,
-        char *buffer) {
+                int level,
+                int error,
+                const char *file,
+                int line,
+                const char *func,
+                char *buffer) {
 
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
         PROTECT_ERRNO;
 
         /* This modifies the buffer... */
@@ -650,13 +659,13 @@ int log_dump_internal(
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return -error;
 
-        return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
+        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
 }
 
-int log_internalv(
+int log_internalv_realm(
                 int level,
                 int error,
                 const char *file,
@@ -665,13 +674,14 @@ int log_internalv(
                 const char *format,
                 va_list ap) {
 
-        PROTECT_ERRNO;
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
         char buffer[LINE_MAX];
+        PROTECT_ERRNO;
 
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return -error;
 
         /* Make sure that %m maps to the specified error */
@@ -680,10 +690,10 @@ int log_internalv(
 
         vsnprintf(buffer, sizeof(buffer), format, ap);
 
-        return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
+        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
 }
 
-int log_internal(
+int log_internal_realm(
                 int level,
                 int error,
                 const char *file,
@@ -695,7 +705,7 @@ int log_internal(
         int r;
 
         va_start(ap, format);
-        r = log_internalv(level, error, file, line, func, format, ap);
+        r = log_internalv_realm(level, error, file, line, func, format, ap);
         va_end(ap);
 
         return r;
@@ -716,12 +726,11 @@ int log_object_internalv(
 
         PROTECT_ERRNO;
         char *buffer, *b;
-        size_t l;
 
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
                 return -error;
 
         /* Make sure that %m maps to the specified error */
@@ -733,18 +742,15 @@ int log_object_internalv(
                 size_t n;
 
                 n = strlen(object);
-                l = n + 2 + LINE_MAX;
-
-                buffer = newa(char, l);
+                buffer = newa(char, n + 2 + LINE_MAX);
                 b = stpcpy(stpcpy(buffer, object), ": ");
-        } else {
-                l = LINE_MAX;
-                b = buffer = newa(char, l);
-        }
+        } else
+                b = buffer = newa(char, LINE_MAX);
 
-        vsnprintf(b, l, format, ap);
+        vsnprintf(b, LINE_MAX, format, ap);
 
-        return log_dispatch(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
+        return log_dispatch_internal(level, error, file, line, func,
+                                     object_field, object, extra_field, extra, buffer);
 }
 
 int log_object_internal(
@@ -778,8 +784,9 @@ static void log_assert(
                 const char *format) {
 
         static char buffer[LINE_MAX];
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return;
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
@@ -788,26 +795,45 @@ static void log_assert(
 
         log_abort_msg = buffer;
 
-        log_dispatch(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
+        log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
 }
 
-noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
-        log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
+noreturn void log_assert_failed_realm(
+                LogRealm realm,
+                const char *text,
+                const char *file,
+                int line,
+                const char *func) {
+        log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
+                   "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
         abort();
 }
 
-noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
-        log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
+noreturn void log_assert_failed_unreachable_realm(
+                LogRealm realm,
+                const char *text,
+                const char *file,
+                int line,
+                const char *func) {
+        log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
+                   "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
         abort();
 }
 
-void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
+void log_assert_failed_return_realm(
+                LogRealm realm,
+                const char *text,
+                const char *file,
+                int line,
+                const char *func) {
         PROTECT_ERRNO;
-        log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
+        log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
+                   "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
 }
 
-int log_oom_internal(const char *file, int line, const char *func) {
-        log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
+int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
+        log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
+                           ENOMEM, file, line, func, "Out of memory.");
         return -ENOMEM;
 }
 
@@ -867,13 +893,14 @@ int log_struct_internal(
 
         char buf[LINE_MAX];
         bool found = false;
+        LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
         PROTECT_ERRNO;
         va_list ap;
 
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[realm]))
                 return -error;
 
         if (log_target == LOG_TARGET_NULL)
@@ -943,7 +970,7 @@ int log_struct_internal(
         if (!found)
                 return -error;
 
-        return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
+        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
 }
 
 int log_set_target_from_string(const char *e) {
@@ -957,14 +984,14 @@ int log_set_target_from_string(const char *e) {
         return 0;
 }
 
-int log_set_max_level_from_string(const char *e) {
+int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
         int t;
 
         t = log_level_from_string(e);
         if (t < 0)
                 return -EINVAL;
 
-        log_set_max_level(t);
+        log_set_max_level_realm(realm, t);
         return 0;
 }
 
@@ -1012,7 +1039,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
         return 0;
 }
 
-void log_parse_environment(void) {
+void log_parse_environment_realm(LogRealm realm) {
+        /* Do not call from library code. */
+
         const char *e;
 
         if (get_ctty_devnr(0, NULL) < 0)
@@ -1020,19 +1049,19 @@ void log_parse_environment(void) {
                    user stuff. */
                 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
 
-        e = secure_getenv("SYSTEMD_LOG_TARGET");
+        e = getenv("SYSTEMD_LOG_TARGET");
         if (e && log_set_target_from_string(e) < 0)
                 log_warning("Failed to parse log target '%s'. Ignoring.", e);
 
-        e = secure_getenv("SYSTEMD_LOG_LEVEL");
-        if (e && log_set_max_level_from_string(e) < 0)
+        e = getenv("SYSTEMD_LOG_LEVEL");
+        if (e && log_set_max_level_from_string_realm(realm, e) < 0)
                 log_warning("Failed to parse log level '%s'. Ignoring.", e);
 
-        e = secure_getenv("SYSTEMD_LOG_COLOR");
+        e = getenv("SYSTEMD_LOG_COLOR");
         if (e && log_show_color_from_string(e) < 0)
                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
 
-        e = secure_getenv("SYSTEMD_LOG_LOCATION");
+        e = getenv("SYSTEMD_LOG_LOCATION");
         if (e && log_show_location_from_string(e) < 0)
                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
 }
@@ -1041,8 +1070,8 @@ LogTarget log_get_target(void) {
         return log_target;
 }
 
-int log_get_max_level(void) {
-        return log_max_level;
+int log_get_max_level_realm(LogRealm realm) {
+        return log_max_level[realm];
 }
 
 void log_show_color(bool b) {
@@ -1146,7 +1175,7 @@ int log_syntax_internal(
         if (error < 0)
                 error = -error;
 
-        if (_likely_(LOG_PRI(level) > log_max_level))
+        if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
                 return -error;
 
         if (log_target == LOG_TARGET_NULL)
@@ -1163,7 +1192,8 @@ int log_syntax_internal(
                 unit_fmt = getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
 
         return log_struct_internal(
-                        level, error,
+                        LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
+                        error,
                         file, line, func,
                         "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
                         "CONFIG_FILE=%s", config_file,
index 72714e02e5625992241e271537dd9041af0c909a..ff5d776b1d7054f2acd7c3e73eca8b2cf737782e 100644 (file)
 
 #include "macro.h"
 
+typedef enum LogRealm {
+        LOG_REALM_SYSTEMD,
+        LOG_REALM_UDEV,
+        _LOG_REALM_MAX,
+} LogRealm;
+
+#ifndef LOG_REALM
+#  define LOG_REALM LOG_REALM_SYSTEMD
+#endif
+
 typedef enum LogTarget{
         LOG_TARGET_CONSOLE,
         LOG_TARGET_CONSOLE_PREFIXED,
@@ -44,14 +54,24 @@ typedef enum LogTarget{
         LOG_TARGET_NULL,
         _LOG_TARGET_MAX,
         _LOG_TARGET_INVALID = -1
-}  LogTarget;
+} LogTarget;
+
+#define LOG_REALM_PLUS_LEVEL(realm, level)      \
+        ((realm) << 10 | (level))
+#define LOG_REALM_REMOVE_LEVEL(realm_level)     \
+        ((realm_level >> 10))
 
 void log_set_target(LogTarget target);
-void log_set_max_level(int level);
+void log_set_max_level_realm(LogRealm realm, int level);
+#define log_set_max_level(level)                \
+        log_set_max_level_realm(LOG_REALM, (level))
+
 void log_set_facility(int facility);
 
 int log_set_target_from_string(const char *e);
-int log_set_max_level_from_string(const char *e);
+int log_set_max_level_from_string_realm(LogRealm realm, const char *e);
+#define log_set_max_level_from_string(e)        \
+        log_set_max_level_from_string_realm(LOG_REALM, (e))
 
 void log_show_color(bool b);
 bool log_get_show_color(void) _pure_;
@@ -62,7 +82,14 @@ int log_show_color_from_string(const char *e);
 int log_show_location_from_string(const char *e);
 
 LogTarget log_get_target(void) _pure_;
-int log_get_max_level(void) _pure_;
+int log_get_max_level_realm(LogRealm realm) _pure_;
+#define log_get_max_level()                     \
+        log_get_max_level_realm(LOG_REALM)
+
+/* Functions below that open and close logs or configure logging based on the
+ * environment should not be called from library code — this is always a job
+ * for the application itself.
+ */
 
 int log_open(void);
 void log_close(void);
@@ -73,17 +100,33 @@ void log_close_journal(void);
 void log_close_kmsg(void);
 void log_close_console(void);
 
-void log_parse_environment(void);
+void log_parse_environment_realm(LogRealm realm);
+#define log_parse_environment() \
+        log_parse_environment_realm(LOG_REALM)
 
-int log_internal(
+int log_dispatch_internal(
+                int level,
+                int error,
+                const char *file,
+                int line,
+                const char *func,
+                const char *object_field,
+                const char *object,
+                const char *extra,
+                const char *extra_field,
+                char *buffer);
+
+int log_internal_realm(
                 int level,
                 int error,
                 const char *file,
                 int line,
                 const char *func,
                 const char *format, ...) _printf_(6,7);
+#define log_internal(level, ...) \
+        log_internal_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__)
 
-int log_internalv(
+int log_internalv_realm(
                 int level,
                 int error,
                 const char *file,
@@ -91,7 +134,10 @@ int log_internalv(
                 const char *func,
                 const char *format,
                 va_list ap) _printf_(6,0);
+#define log_internalv(level, ...) \
+        log_internalv_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__)
 
+/* Realm is fixed to LOG_REALM_SYSTEMD for those */
 int log_object_internal(
                 int level,
                 int error,
@@ -115,7 +161,7 @@ int log_object_internalv(
                 const char *extra_field,
                 const char *extra,
                 const char *format,
-                va_list ap) _printf_(9,0);
+                va_list ap) _printf_(10,0);
 
 int log_struct_internal(
                 int level,
@@ -126,6 +172,7 @@ int log_struct_internal(
                 const char *format, ...) _printf_(6,0) _sentinel_;
 
 int log_oom_internal(
+                LogRealm realm,
                 const char *file,
                 int line,
                 const char *func);
@@ -137,7 +184,7 @@ int log_format_iovec(
                 bool newline_separator,
                 int error,
                 const char *format,
-                va_list ap);
+                va_list ap) _printf_(6, 0);
 
 /* This modifies the buffer passed! */
 int log_dump_internal(
@@ -149,34 +196,50 @@ int log_dump_internal(
                 char *buffer);
 
 /* Logging for various assertions */
-noreturn void log_assert_failed(
+noreturn void log_assert_failed_realm(
+                LogRealm realm,
                 const char *text,
                 const char *file,
                 int line,
                 const char *func);
+#define log_assert_failed(text, ...) \
+        log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__)
 
-noreturn void log_assert_failed_unreachable(
+noreturn void log_assert_failed_unreachable_realm(
+                LogRealm realm,
                 const char *text,
                 const char *file,
                 int line,
                 const char *func);
+#define log_assert_failed_unreachable(text, ...) \
+        log_assert_failed_unreachable_realm(LOG_REALM, (text), __VA_ARGS__)
 
-void log_assert_failed_return(
+void log_assert_failed_return_realm(
+                LogRealm realm,
                 const char *text,
                 const char *file,
                 int line,
                 const char *func);
+#define log_assert_failed_return(text, ...) \
+        log_assert_failed_return_realm(LOG_REALM, (text), __VA_ARGS__)
+
+#define log_dispatch(level, error, buffer)                              \
+        log_dispatch_internal(level, error, __FILE__, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer)
 
 /* Logging with level */
-#define log_full_errno(level, error, ...)                               \
+#define log_full_errno_realm(realm, level, error, ...)                  \
         ({                                                              \
                 int _level = (level), _e = (error);                     \
-                (log_get_max_level() >= LOG_PRI(_level))                \
-                        ? log_internal(_level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \
+                (log_get_max_level_realm((realm)) >= LOG_PRI(_level))   \
+                        ? log_internal_realm(LOG_REALM_PLUS_LEVEL((realm), _level), _e, \
+                                             __FILE__, __LINE__, __func__, __VA_ARGS__) \
                         : -abs(_e);                                     \
         })
 
-#define log_full(level, ...) log_full_errno(level, 0, __VA_ARGS__)
+#define log_full_errno(level, error, ...)                               \
+        log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__)
+
+#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__)
 
 /* Normal logging */
 #define log_debug(...)     log_full(LOG_DEBUG,   __VA_ARGS__)
@@ -201,13 +264,17 @@ void log_assert_failed_return(
 #endif
 
 /* Structured logging */
-#define log_struct(level, ...) log_struct_internal(level, 0, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_struct_errno(level, error, ...) log_struct_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+#define log_struct_errno(level, error, ...) \
+        log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
+                            error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__)
 
 /* This modifies the buffer passed! */
-#define log_dump(level, buffer) log_dump_internal(level, 0, __FILE__, __LINE__, __func__, buffer)
+#define log_dump(level, buffer) \
+        log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
+                          0, __FILE__, __LINE__, __func__, buffer)
 
-#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
+#define log_oom() log_oom_internal(LOG_REALM, __FILE__, __LINE__, __func__)
 
 bool log_on_console(void) _pure_;
 
index 6b2aeb933fdd36bcbcc02cefea06bcc2324322ff..a51562db35aa461599367fcfed11886455fefe97 100644 (file)
@@ -19,7 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <sys/param.h>
diff --git a/src/basic/meson.build b/src/basic/meson.build
new file mode 100644 (file)
index 0000000..065f0ac
--- /dev/null
@@ -0,0 +1,281 @@
+basic_sources_plain = files('''
+        af-list.c
+        af-list.h
+        alloc-util.c
+        alloc-util.h
+        architecture.c
+        architecture.h
+        arphrd-list.c
+        arphrd-list.h
+        async.c
+        async.h
+        audit-util.c
+        audit-util.h
+        barrier.c
+        barrier.h
+        bitmap.c
+        bitmap.h
+        blkid-util.h
+        btrfs-ctree.h
+        btrfs-util.c
+        btrfs-util.h
+        build.h
+        bus-label.c
+        bus-label.h
+        calendarspec.c
+        calendarspec.h
+        capability-util.c
+        capability-util.h
+        cap-list.c
+        cap-list.h
+        cgroup-util.c
+        cgroup-util.h
+        chattr-util.c
+        chattr-util.h
+        clock-util.c
+        clock-util.h
+        conf-files.c
+        conf-files.h
+        copy.c
+        copy.h
+        cpu-set-util.c
+        cpu-set-util.h
+        def.h
+        device-nodes.c
+        device-nodes.h
+        dirent-util.c
+        dirent-util.h
+        env-util.c
+        env-util.h
+        errno-list.c
+        errno-list.h
+        escape.c
+        escape.h
+        ether-addr-util.c
+        ether-addr-util.h
+        exec-util.c
+        exec-util.h
+        exit-status.c
+        exit-status.h
+        extract-word.c
+        extract-word.h
+        fd-util.c
+        fd-util.h
+        fileio.c
+        fileio.h
+        fileio-label.c
+        fileio-label.h
+        format-util.h
+        fs-util.c
+        fs-util.h
+        glob-util.c
+        glob-util.h
+        gunicode.c
+        gunicode.h
+        hash-funcs.c
+        hash-funcs.h
+        hashmap.c
+        hashmap.h
+        hexdecoct.c
+        hexdecoct.h
+        hostname-util.c
+        hostname-util.h
+        in-addr-util.c
+        in-addr-util.h
+        ioprio.h
+        io-util.c
+        io-util.h
+        journal-importer.c
+        journal-importer.h
+        khash.c
+        khash.h
+        label.c
+        label.h
+        list.h
+        locale-util.c
+        locale-util.h
+        lockfile-util.c
+        lockfile-util.h
+        log.c
+        log.h
+        login-util.c
+        login-util.h
+        macro.h
+        memfd-util.c
+        memfd-util.h
+        mempool.c
+        mempool.h
+        missing_syscall.h
+        mkdir.c
+        mkdir.h
+        mkdir-label.c
+        mount-util.c
+        mount-util.h
+        MurmurHash2.c
+        MurmurHash2.h
+        nss-util.h
+        ordered-set.c
+        ordered-set.h
+        parse-util.c
+        parse-util.h
+        path-util.c
+        path-util.h
+        prioq.c
+        prioq.h
+        proc-cmdline.c
+        proc-cmdline.h
+        process-util.c
+        process-util.h
+        random-util.c
+        random-util.h
+        ratelimit.c
+        ratelimit.h
+        raw-clone.h
+        refcnt.h
+        replace-var.c
+        replace-var.h
+        rlimit-util.c
+        rlimit-util.h
+        rm-rf.c
+        rm-rf.h
+        securebits.h
+        selinux-util.c
+        selinux-util.h
+        set.h
+        sigbus.c
+        sigbus.h
+        signal-util.c
+        signal-util.h
+        siphash24.c
+        siphash24.h
+        smack-util.c
+        smack-util.h
+        socket-label.c
+        socket-util.c
+        socket-util.h
+        sparse-endian.h
+        special.h
+        stat-util.c
+        stat-util.h
+        stdio-util.h
+        strbuf.c
+        strbuf.h
+        string-table.c
+        string-table.h
+        string-util.c
+        string-util.h
+        strv.c
+        strv.h
+        strxcpyx.c
+        strxcpyx.h
+        syslog-util.c
+        syslog-util.h
+        terminal-util.c
+        terminal-util.h
+        time-util.c
+        time-util.h
+        umask-util.h
+        unaligned.h
+        unit-name.c
+        unit-name.h
+        user-util.c
+        user-util.h
+        utf8.c
+        utf8.h
+        util.c
+        util.h
+        verbs.c
+        verbs.h
+        virt.c
+        virt.h
+        web-util.c
+        web-util.h
+        xattr-util.c
+        xattr-util.h
+        xml.c
+        xml.h
+'''.split())
+
+missing_h = files('missing.h')
+
+generate_gperfs = find_program('generate-gperfs.py')
+
+generate_af_list = find_program('generate-af-list.sh')
+af_list_txt = custom_target(
+        'af-list.txt',
+        output : 'af-list.txt',
+        command : [generate_af_list, cpp],
+        capture : true)
+
+generate_arphrd_list = find_program('generate-arphrd-list.sh')
+arphrd_list_txt = custom_target(
+        'arphrd-list.txt',
+        output : 'arphrd-list.txt',
+        command : [generate_arphrd_list, cpp],
+        capture : true)
+
+generate_cap_list = find_program('generate-cap-list.sh')
+cap_list_txt = custom_target(
+        'cap-list.txt',
+        output : 'cap-list.txt',
+        command : [generate_cap_list, cpp, config_h, missing_h],
+        capture : true)
+
+generate_errno_list = find_program('generate-errno-list.sh')
+errno_list_txt = custom_target(
+        'errno-list.txt',
+        output : 'errno-list.txt',
+        command : [generate_errno_list, cpp],
+        capture : true)
+
+generated_gperf_headers = []
+foreach item : [['af',     af_list_txt,     'af',         ''],
+                ['arphrd', arphrd_list_txt, 'arphrd',     'ARPHRD_'],
+                ['cap',    cap_list_txt,    'capability', ''],
+                ['errno',  errno_list_txt,  'errno',      '']]
+
+        fname = '@0@-from-name.gperf'.format(item[0])
+        gperf_file = custom_target(
+                fname,
+                input : item[1],
+                output : fname,
+                command : [generate_gperfs, item[2], item[3], '@INPUT@'],
+                capture : true)
+
+        fname = '@0@-from-name.h'.format(item[0])
+        target1 = custom_target(
+                fname,
+                input : gperf_file,
+                output : fname,
+                command : [gperf,
+                           '-L', 'ANSI-C', '-t', '--ignore-case',
+                           '-N', 'lookup_@0@'.format(item[2]),
+                           '-H', 'hash_@0@_name'.format(item[2]),
+                           '-p', '-C',
+                           '@INPUT@'],
+                capture : true)
+
+        fname = '@0@-to-name.h'.format(item[0])
+        awkscript = '@0@-to-name.awk'.format(item[0])
+        target2 = custom_target(
+                fname,
+                input : [awkscript, item[1]],
+                output : fname,
+                command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+                capture : true)
+
+        generated_gperf_headers += [target1, target2]
+endforeach
+
+basic_sources = basic_sources_plain + [missing_h] + generated_gperf_headers
+
+libbasic = static_library(
+        'basic',
+        basic_sources,
+        include_directories : includes,
+        dependencies : [threads,
+                        libcap,
+                        libblkid,
+                        libselinux,
+                       ],
+        install : false)
index 480462357de9e0f04ba7b54ceb1e4c7f12a106eb..7830a4f415b927e7217d6b03d93c382bd2507556 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <linux/audit.h>
 #include <linux/capability.h>
 #include <linux/if_link.h>
@@ -68,8 +69,6 @@ struct sockaddr_vm {
 };
 #endif /* !HAVE_LINUX_VM_SOCKETS_H */
 
-#include "macro.h"
-
 #ifndef RLIMIT_RTTIME
 #define RLIMIT_RTTIME 15
 #endif
@@ -571,6 +570,17 @@ struct btrfs_ioctl_quota_ctl_args {
 #  define EVIOCREVOKE _IOW('E', 0x91, int)
 #endif
 
+#ifndef EVIOCSMASK
+
+struct input_mask {
+        uint32_t type;
+        uint32_t codes_size;
+        uint64_t codes_ptr;
+};
+
+#define EVIOCSMASK _IOW('E', 0x93, struct input_mask)
+#endif
+
 #ifndef DRM_IOCTL_SET_MASTER
 #  define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
 #endif
@@ -726,7 +736,7 @@ struct btrfs_ioctl_quota_ctl_args {
 #define IFLA_VLAN_MAX   (__IFLA_VLAN_MAX - 1)
 #endif
 
-#if !HAVE_DECL_IFLA_VXLAN_REMCSUM_NOPARTIAL
+#if !HAVE_DECL_IFLA_VXLAN_GPE
 #define IFLA_VXLAN_UNSPEC 0
 #define IFLA_VXLAN_ID 1
 #define IFLA_VXLAN_GROUP 2
@@ -752,11 +762,34 @@ struct btrfs_ioctl_quota_ctl_args {
 #define IFLA_VXLAN_REMCSUM_RX 22
 #define IFLA_VXLAN_GBP 23
 #define IFLA_VXLAN_REMCSUM_NOPARTIAL 24
-#define __IFLA_VXLAN_MAX 25
+#define IFLA_VXLAN_COLLECT_METADATA 25
+#define IFLA_VXLAN_LABEL 26
+#define IFLA_VXLAN_GPE 27
+
+#define __IFLA_VXLAN_MAX 28
 
 #define IFLA_VXLAN_MAX  (__IFLA_VXLAN_MAX - 1)
 #endif
 
+#if !HAVE_DECL_IFLA_GENEVE_LABEL
+#define IFLA_GENEVE_UNSPEC 0
+#define IFLA_GENEVE_ID 1
+#define IFLA_GENEVE_REMOTE 2
+#define IFLA_GENEVE_TTL 3
+#define IFLA_GENEVE_TOS 4
+#define IFLA_GENEVE_PORT 5
+#define IFLA_GENEVE_COLLECT_METADATA 6
+#define IFLA_GENEVE_REMOTE6 7
+#define IFLA_GENEVE_UDP_CSUM 8
+#define IFLA_GENEVE_UDP_ZERO_CSUM6_TX 9
+#define IFLA_GENEVE_UDP_ZERO_CSUM6_RX 10
+#define IFLA_GENEVE_LABEL 11
+
+#define __IFLA_GENEVE_MAX 12
+
+#define IFLA_GENEVE_MAX  (__IFLA_GENEVE_MAX - 1)
+#endif
+
 #if !HAVE_DECL_IFLA_IPTUN_ENCAP_DPORT
 #define IFLA_IPTUN_UNSPEC 0
 #define IFLA_IPTUN_LINK 1
@@ -1040,6 +1073,15 @@ struct btrfs_ioctl_quota_ctl_args {
 #define INPUT_PROP_ACCELEROMETER  0x06
 #endif
 
+#ifndef BTN_DPAD_UP
+#define BTN_DPAD_UP 0x220
+#define BTN_DPAD_RIGHT 0x223
+#endif
+
+#ifndef KEY_ALS_TOGGLE
+#define KEY_ALS_TOGGLE 0x230
+#endif
+
 #ifndef HAVE_KEY_SERIAL_T
 typedef int32_t key_serial_t;
 #endif
index 9fc415656456e960b93b5c134784fbb22973854d..898116c7b31040909f79d7bb04ceb3fc3435a03c 100644 (file)
@@ -52,6 +52,8 @@ static inline int pivot_root(const char *new_root, const char *put_old) {
 #      endif
 #    elif defined __i386__
 #      define __NR_memfd_create 356
+#    elif defined __arc__
+#      define __NR_memfd_create 279
 #    else
 #      warning "__NR_memfd_create unknown for your architecture"
 #    endif
@@ -97,6 +99,8 @@ static inline int memfd_create(const char *name, unsigned int flags) {
 #      if _MIPS_SIM == _MIPS_SIM_ABI64
 #        define __NR_getrandom 5313
 #      endif
+#    elif defined(__arc__)
+#      define __NR_getrandom 278
 #    else
 #      warning "__NR_getrandom unknown for your architecture"
 #    endif
@@ -132,6 +136,8 @@ static inline pid_t gettid(void) {
 #      define __NR_name_to_handle_at 370
 #    elif defined(__powerpc__)
 #      define __NR_name_to_handle_at 345
+#    elif defined(__arc__)
+#      define __NR_name_to_handle_at 264
 #    else
 #      error "__NR_name_to_handle_at is not defined"
 #    endif
@@ -161,6 +167,8 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
 #      define __NR_setns 308
 #    elif defined(__i386__)
 #      define __NR_setns 346
+#    elif defined(__arc__)
+#      define __NR_setns 268
 #    else
 #      error "__NR_setns is not defined"
 #    endif
@@ -208,6 +216,12 @@ static inline pid_t raw_getpid(void) {
 #      endif
 #    elif defined __i386__
 #      define __NR_renameat2 353
+#    elif defined __powerpc64__
+#      define __NR_renameat2 357
+#    elif defined __s390__ || defined __s390x__
+#      define __NR_renameat2 347
+#    elif defined __arc__
+#      define __NR_renameat2 276
 #    else
 #      warning "__NR_renameat2 unknown for your architecture"
 #    endif
@@ -283,6 +297,8 @@ static inline key_serial_t request_key(const char *type, const char *description
 #      define __NR_copy_file_range 285
 #    elif defined __powerpc__
 #      define __NR_copy_file_range 379
+#    elif defined __arc__
+#      define __NR_copy_file_range 285
 #    else
 #      warning "__NR_copy_file_range not defined for your architecture"
 #    endif
index a8fd63fb45807ddc582227ab341a57f380ecee0b..7b9400b47cad450c347e0fb4c6ab0d58c287ea8d 100644 (file)
@@ -317,11 +317,16 @@ static int get_mount_flags(const char *path, unsigned long *flags) {
         return 0;
 }
 
-int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
+/* Use this function only if do you have direct access to /proc/self/mountinfo
+ * and need the caller to open it for you. This is the case when /proc is
+ * masked or not mounted. Otherwise, use bind_remount_recursive. */
+int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **blacklist, FILE *proc_self_mountinfo) {
         _cleanup_set_free_free_ Set *done = NULL;
         _cleanup_free_ char *cleaned = NULL;
         int r;
 
+        assert(proc_self_mountinfo);
+
         /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already
          * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
          * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to
@@ -344,7 +349,6 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
                 return -ENOMEM;
 
         for (;;) {
-                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
                 _cleanup_set_free_free_ Set *todo = NULL;
                 bool top_autofs = false;
                 char *x;
@@ -354,9 +358,7 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
                 if (!todo)
                         return -ENOMEM;
 
-                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
-                if (!proc_self_mountinfo)
-                        return -errno;
+                rewind(proc_self_mountinfo);
 
                 for (;;) {
                         _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
@@ -495,6 +497,16 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
         }
 }
 
+int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
+        _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+
+        proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+        if (!proc_self_mountinfo)
+                return -errno;
+
+        return bind_remount_recursive_with_mountinfo(prefix, ro, blacklist, proc_self_mountinfo);
+}
+
 int mount_move_root(const char *path) {
         assert(path);
 
index 1615c94e9abe73c3cd4a65055df1cba2a586fafd..2e24a184c5351fed13408eac725243a4893be365 100644 (file)
@@ -36,6 +36,7 @@ int repeat_unmount(const char *path, int flags);
 
 int umount_recursive(const char *target, int flags);
 int bind_remount_recursive(const char *prefix, bool ro, char **blacklist);
+int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **blacklist, FILE *proc_self_mountinfo);
 
 int mount_move_root(const char *path);
 
index 6e58ced6f5291758ae7acab9f9c5d0531aad73ee..4532f222c8ab0bb09790ea5176815e19233b0049 100644 (file)
@@ -23,7 +23,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <xlocale.h>
 
 #include "alloc-util.h"
 #include "extract-word.h"
@@ -590,3 +589,18 @@ int parse_ip_port(const char *s, uint16_t *ret) {
 
         return 0;
 }
+
+int parse_dev(const char *s, dev_t *ret) {
+        unsigned x, y;
+        dev_t d;
+
+        if (sscanf(s, "%u:%u", &x, &y) != 2)
+                return -EINVAL;
+
+        d = makedev(x, y);
+        if ((unsigned) major(d) != x || (unsigned) minor(d) != y)
+                return -EINVAL;
+
+        *ret = d;
+        return 0;
+}
index 4d132f0de5a265429f631a6eae366d1b731159d1..dc09782ca8997618e04ecafbf4d5576b551cee61 100644 (file)
@@ -30,6 +30,7 @@
 #define MODE_INVALID ((mode_t) -1)
 
 int parse_boolean(const char *v) _pure_;
+int parse_dev(const char *s, dev_t *ret);
 int parse_pid(const char *s, pid_t* ret_pid);
 int parse_mode(const char *s, mode_t *ret);
 int parse_ifindex(const char *s, int *ret);
index 1313a52c9cab551b682a3977f566b32405f0d7a4..80fdda170f10c42472ca2ea98bc821f0b681b509 100644 (file)
@@ -442,8 +442,8 @@ bool path_equal(const char *a, const char *b) {
         return path_compare(a, b) == 0;
 }
 
-bool path_equal_or_files_same(const char *a, const char *b) {
-        return path_equal(a, b) || files_same(a, b) > 0;
+bool path_equal_or_files_same(const char *a, const char *b, int flags) {
+        return path_equal(a, b) || files_same(a, b, flags) > 0;
 }
 
 char* path_join(const char *root, const char *path, const char *rest) {
index 35aef3adc83b5ff13364be969c067cf279ddd169..26f165fc386791cebfa6a4f60932c63e8852e559 100644 (file)
@@ -46,7 +46,7 @@ char* path_kill_slashes(char *path);
 char* path_startswith(const char *path, const char *prefix) _pure_;
 int path_compare(const char *a, const char *b) _pure_;
 bool path_equal(const char *a, const char *b) _pure_;
-bool path_equal_or_files_same(const char *a, const char *b);
+bool path_equal_or_files_same(const char *a, const char *b, int flags);
 char* path_join(const char *root, const char *path, const char *rest);
 
 static inline bool path_equal_ptr(const char *a, const char *b) {
index 0df3fed64064e0f9b171e4ed38fc2bd268dd944c..b80cacaa42ec646dac66b90adf6f80095f993732 100644 (file)
@@ -807,7 +807,7 @@ int pid_from_same_root_fs(pid_t pid) {
 
         root = procfs_file_alloca(pid, "root");
 
-        return files_same(root, "/proc/1/root");
+        return files_same(root, "/proc/1/root", 0);
 }
 
 bool is_main_thread(void) {
@@ -905,6 +905,23 @@ int pid_compare_func(const void *a, const void *b) {
         return 0;
 }
 
+int ioprio_parse_priority(const char *s, int *ret) {
+        int i, r;
+
+        assert(s);
+        assert(ret);
+
+        r = safe_atoi(s, &i);
+        if (r < 0)
+                return r;
+
+        if (!ioprio_priority_is_valid(i))
+                return -EINVAL;
+
+        *ret = i;
+        return 0;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
index d37890139922480af5561aae64d3e66d152ec48b..28d8d7499a5060fde2126ab50cbac1937a142dcb 100644 (file)
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/resource.h>
+#include <sys/types.h>
 
 #include "format-util.h"
+#include "ioprio.h"
 #include "macro.h"
 
 #define procfs_file_alloca(pid, field)                                  \
@@ -108,3 +109,13 @@ int pid_compare_func(const void *a, const void *b);
 static inline bool nice_is_valid(int n) {
         return n >= PRIO_MIN && n < PRIO_MAX;
 }
+
+static inline bool ioprio_class_is_valid(int i) {
+        return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE);
+}
+
+static inline bool ioprio_priority_is_valid(int i) {
+        return i >= 0 && i < IOPRIO_BE_NR;
+}
+
+int ioprio_parse_priority(const char *s, int *ret);
index ad7b3eedf2c1d5ffb7ca92662bff43e070878872..810eeab4d551b395fe1833aa804ad23121737762 100644 (file)
 #include <stdint.h>
 
 #ifdef HAVE_SYS_AUXV_H
-#include <sys/auxv.h>
+#  include <sys/auxv.h>
+#endif
+
+#ifdef USE_SYS_RANDOM_H
+#  include <sys/random.h>
+#else
+#  include <linux/random.h>
 #endif
 
 #include "fd-util.h"
 #include "random-util.h"
 #include "time-util.h"
 
-int dev_urandom(void *p, size_t n) {
+int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
         static int have_syscall = -1;
 
         _cleanup_close_ int fd = -1;
+        unsigned already_done = 0;
         int r;
 
-        /* Gathers some randomness from the kernel. This call will
-         * never block, and will always return some data from the
-         * kernel, regardless if the random pool is fully initialized
-         * or not. It thus makes no guarantee for the quality of the
-         * returned entropy, but is good enough for our usual usecases
-         * of seeding the hash functions for hashtable */
+        /* Gathers some randomness from the kernel. This call will never block. If
+         * high_quality_required, it will always return some data from the kernel,
+         * regardless of whether the random pool is fully initialized or not.
+         * Otherwise, it will return success if at least some random bytes were
+         * successfully acquired, and an error if the kernel has no entropy whatsover
+         * for us. */
 
-        /* Use the getrandom() syscall unless we know we don't have
-         * it, or when the requested size is too large for it. */
-        if (have_syscall != 0 || (size_t) (int) n != n) {
+        /* Use the getrandom() syscall unless we know we don't have it. */
+        if (have_syscall != 0) {
                 r = getrandom(p, n, GRND_NONBLOCK);
-                if (r == (int) n) {
+                if (r > 0) {
+                        have_syscall = true;
+                        if ((size_t) r == n)
+                                return 0;
+                        if (!high_quality_required) {
+                                /* Fill in the remaing bytes using pseudorandom values */
+                                pseudorandom_bytes((uint8_t*) p + r, n - r);
+                                return 0;
+                        }
+
+                        already_done = r;
+                } else if (errno == ENOSYS)
+                          /* We lack the syscall, continue with reading from /dev/urandom. */
+                          have_syscall = false;
+                else if (errno == EAGAIN) {
+                        /* The kernel has no entropy whatsoever. Let's remember to
+                         * use the syscall the next time again though.
+                         *
+                         * If high_quality_required is false, return an error so that
+                         * random_bytes() can produce some pseudorandom
+                         * bytes. Otherwise, fall back to /dev/urandom, which we know
+                         * is empty, but the kernel will produce some bytes for us on
+                         * a best-effort basis. */
                         have_syscall = true;
-                        return 0;
-                }
-
-                if (r < 0) {
-                        if (errno == ENOSYS)
-                                /* we lack the syscall, continue with
-                                 * reading from /dev/urandom */
-                                have_syscall = false;
-                        else if (errno == EAGAIN)
-                                /* not enough entropy for now. Let's
-                                 * remember to use the syscall the
-                                 * next time, again, but also read
-                                 * from /dev/urandom for now, which
-                                 * doesn't care about the current
-                                 * amount of entropy.  */
-                                have_syscall = true;
-                        else
-                                return -errno;
+
+                        if (!high_quality_required)
+                                return -ENODATA;
                 } else
-                        /* too short read? */
-                        return -ENODATA;
+                        return -errno;
         }
 
         fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
         if (fd < 0)
                 return errno == ENOENT ? -ENOSYS : -errno;
 
-        return loop_read_exact(fd, p, n, true);
+        return loop_read_exact(fd, (uint8_t*) p + already_done, n - already_done, true);
 }
 
 void initialize_srand(void) {
@@ -96,12 +108,13 @@ void initialize_srand(void) {
                 return;
 
 #ifdef HAVE_SYS_AUXV_H
-        /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the
-         * pseudo-random generator. It's better than nothing... */
+        /* The kernel provides us with 16 bytes of entropy in auxv, so let's
+         * try to make use of that to seed the pseudo-random generator. It's
+         * better than nothing... */
 
         auxv = (void*) getauxval(AT_RANDOM);
         if (auxv) {
-                assert_cc(sizeof(x) < 16);
+                assert_cc(sizeof(x) <= 16);
                 memcpy(&x, auxv, sizeof(x));
         } else
 #endif
@@ -115,19 +128,44 @@ void initialize_srand(void) {
         srand_called = true;
 }
 
-void random_bytes(void *p, size_t n) {
+/* INT_MAX gives us only 31 bits, so use 24 out of that. */
+#if RAND_MAX >= INT_MAX
+#  define RAND_STEP 3
+#else
+/* SHORT_INT_MAX or lower gives at most 15 bits, we just just 8 out of that. */
+#  define RAND_STEP 1
+#endif
+
+void pseudorandom_bytes(void *p, size_t n) {
         uint8_t *q;
+
+        initialize_srand();
+
+        for (q = p; q < (uint8_t*) p + n; q += RAND_STEP) {
+                unsigned rr;
+
+                rr = (unsigned) rand();
+
+#if RAND_STEP >= 3
+                if ((size_t) (q - (uint8_t*) p + 2) < n)
+                        q[2] = rr >> 16;
+#endif
+#if RAND_STEP >= 2
+                if ((size_t) (q - (uint8_t*) p + 1) < n)
+                        q[1] = rr >> 8;
+#endif
+                q[0] = rr;
+        }
+}
+
+void random_bytes(void *p, size_t n) {
         int r;
 
-        r = dev_urandom(p, n);
+        r = acquire_random_bytes(p, n, false);
         if (r >= 0)
                 return;
 
-        /* If some idiot made /dev/urandom unavailable to us, he'll
-         * get a PRNG instead. */
-
-        initialize_srand();
-
-        for (q = p; q < (uint8_t*) p + n; q ++)
-                *q = rand();
+        /* If some idiot made /dev/urandom unavailable to us, or the
+         * kernel has no entropy, use a PRNG instead. */
+        return pseudorandom_bytes(p, n);
 }
index 3cee4c501408e5143a485f4c095497d6a3e3b0b0..804e225fc1ecee76c7c071c493dfd9db371f27bb 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 
-int dev_urandom(void *p, size_t n);
+int acquire_random_bytes(void *p, size_t n, bool high_quality_required);
+void pseudorandom_bytes(void *p, size_t n);
 void random_bytes(void *p, size_t n);
 void initialize_srand(void);
 
index 08497af729c13aa600e04c0f3755a4725e38d7b9..3f80ed263aa81e32020c7d143cd6176b71d539bd 100644 (file)
@@ -182,7 +182,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
         /* We refuse to clean the root file system with this
          * call. This is extra paranoia to never cause a really
          * seriously broken system. */
-        if (path_equal(path, "/")) {
+        if (path_equal_or_files_same(path, "/", AT_SYMLINK_NOFOLLOW)) {
                 log_error("Attempted to remove entire root file system, and we can't allow that.");
                 return -EPERM;
         }
index bc07654668e80da867d068f707c6baa7d2ff9f50..139e6e21e3e5f4012658cd2080db6b5df1732bbc 100644 (file)
@@ -50,10 +50,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
 static int cached_use = -1;
 static struct selabel_handle *label_hnd = NULL;
 
-#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
+#define log_enforcing(...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, errno, __VA_ARGS__)
 #endif
 
-bool mac_selinux_have(void) {
+bool mac_selinux_use(void) {
 #ifdef HAVE_SELINUX
         if (cached_use < 0)
                 cached_use = is_selinux_enabled() > 0;
@@ -64,16 +64,6 @@ bool mac_selinux_have(void) {
 #endif
 }
 
-bool mac_selinux_use(void) {
-        if (!mac_selinux_have())
-                return false;
-
-        /* Never try to configure SELinux features if we aren't
-         * root */
-
-        return getuid() == 0;
-}
-
 void mac_selinux_retest(void) {
 #ifdef HAVE_SELINUX
         cached_use = -1;
@@ -205,7 +195,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
         assert(exe);
         assert(label);
 
-        if (!mac_selinux_have())
+        if (!mac_selinux_use())
                 return -EOPNOTSUPP;
 
         r = getcon_raw(&mycon);
@@ -231,7 +221,7 @@ int mac_selinux_get_our_label(char **label) {
         assert(label);
 
 #ifdef HAVE_SELINUX
-        if (!mac_selinux_have())
+        if (!mac_selinux_use())
                 return -EOPNOTSUPP;
 
         r = getcon_raw(label);
@@ -255,7 +245,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
         assert(exe);
         assert(label);
 
-        if (!mac_selinux_have())
+        if (!mac_selinux_use())
                 return -EOPNOTSUPP;
 
         r = getcon_raw(&mycon);
@@ -310,7 +300,7 @@ char* mac_selinux_free(char *label) {
         if (!label)
                 return NULL;
 
-        if (!mac_selinux_have())
+        if (!mac_selinux_use())
                 return NULL;
 
 
index ce6bc8e44c1eb49d13c75aabf7dc2abdb43420c4..5bf72364b440a8346bff222e5374263a56af4bb9 100644 (file)
@@ -26,7 +26,6 @@
 #include "macro.h"
 
 bool mac_selinux_use(void);
-bool mac_selinux_have(void);
 void mac_selinux_retest(void);
 
 int mac_selinux_init(void);
index e5847dce00ac6a98330bd83e355bc723d7f44c40..016e64aa03442d4aca97cc862e292cee28cbf5d4 100644 (file)
 #include "utf8.h"
 #include "util.h"
 
+#ifdef ENABLE_IDN
+#  define IDN_FLAGS (NI_IDN|NI_IDN_USE_STD3_ASCII_RULES)
+#else
+#  define IDN_FLAGS 0
+#endif
+
 int socket_address_parse(SocketAddress *a, const char *s) {
         char *e, *n;
         unsigned u;
@@ -406,7 +412,7 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
                         return false;
 
                 if (a->sockaddr.un.sun_path[0]) {
-                        if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
+                        if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, 0))
                                 return false;
                 } else {
                         if (a->size != b->size)
@@ -723,8 +729,7 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
 
         assert(_ret);
 
-        r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
-                        NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
+        r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0, IDN_FLAGS);
         if (r != 0) {
                 int saved_errno = errno;
 
index 7e1914aa140fae46a0c8c85078586b33befabccd..d87370e672985a53f7f91278aa3b96920534c803 100644 (file)
@@ -169,16 +169,16 @@ int path_is_os_tree(const char *path) {
         return 1;
 }
 
-int files_same(const char *filea, const char *fileb) {
+int files_same(const char *filea, const char *fileb, int flags) {
         struct stat a, b;
 
         assert(filea);
         assert(fileb);
 
-        if (stat(filea, &a) < 0)
+        if (fstatat(AT_FDCWD, filea, &a, flags) < 0)
                 return -errno;
 
-        if (stat(fileb, &b) < 0)
+        if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
                 return -errno;
 
         return a.st_dev == b.st_dev &&
index 5d571efe186fb43f394282f72018522776e23404..cd204ac6cbda9368c5725d986a4f3876598ffd64 100644 (file)
@@ -49,7 +49,7 @@ int null_or_empty_fd(int fd);
 int path_is_read_only_fs(const char *path);
 int path_is_os_tree(const char *path);
 
-int files_same(const char *filea, const char *fileb);
+int files_same(const char *filea, const char *fileb, int flags);
 
 /* The .f_type field of struct statfs is really weird defined on
  * different archs. Let's give its type a name. */
index 0eec868eed1f5e0dc46288eadf16b89830d49b7c..c63f11c6ade9627a6fa3af6a2eeb863a82dd71d0 100644 (file)
@@ -770,11 +770,7 @@ static int str_compare(const void *_a, const void *_b) {
 }
 
 char **strv_sort(char **l) {
-
-        if (strv_isempty(l))
-                return l;
-
-        qsort(l, strv_length(l), sizeof(char*), str_compare);
+        qsort_safe(l, strv_length(l), sizeof(char*), str_compare);
         return l;
 }
 
index aaf11d21f6b94afeb2dbb785c89f556fd9bea463..c6fbe79647c3611f6411b5e8492bec30867168f3 100644 (file)
 
 /*
  * Concatenates/copies strings. In any case, terminates in all cases
- * with '\0' * and moves the @dest pointer forward to the added '\0'.
- * Returns the * remaining size, and 0 if the string was truncated.
+ * with '\0' and moves the @dest pointer forward to the added '\0'.
+ * Returns the remaining size, and 0 if the string was truncated.
+ *
+ * Due to the intended usage, these helpers silently noop invocations
+ * having zero size.  This is technically an exception to the above
+ * statement "terminates in all cases".  It's unexpected for such calls to
+ * occur outside of a loop where this is the preferred behavior.
  */
 
 #include <stdarg.h>
 size_t strpcpy(char **dest, size_t size, const char *src) {
         size_t len;
 
+        assert(dest);
+        assert(src);
+
+        if (size == 0)
+                return 0;
+
         len = strlen(src);
         if (len >= size) {
                 if (size > 1)
@@ -51,23 +62,30 @@ size_t strpcpyf(char **dest, size_t size, const char *src, ...) {
         va_list va;
         int i;
 
+        assert(dest);
+        assert(src);
+
+        if (size == 0)
+                return 0;
+
         va_start(va, src);
         i = vsnprintf(*dest, size, src, va);
         if (i < (int)size) {
                 *dest += i;
                 size -= i;
         } else {
-                *dest += size;
                 size = 0;
         }
         va_end(va);
-        *dest[0] = '\0';
         return size;
 }
 
 size_t strpcpyl(char **dest, size_t size, const char *src, ...) {
         va_list va;
 
+        assert(dest);
+        assert(src);
+
         va_start(va, src);
         do {
                 size = strpcpy(dest, size, src);
@@ -80,6 +98,9 @@ size_t strpcpyl(char **dest, size_t size, const char *src, ...) {
 size_t strscpy(char *dest, size_t size, const char *src) {
         char *s;
 
+        assert(dest);
+        assert(src);
+
         s = dest;
         return strpcpy(&s, size, src);
 }
@@ -88,6 +109,9 @@ size_t strscpyl(char *dest, size_t size, const char *src, ...) {
         va_list va;
         char *s;
 
+        assert(dest);
+        assert(src);
+
         va_start(va, src);
         s = dest;
         do {
index a0db97c41a73fdaaeff815df9d49debf0278b11a..68ba86f6a55902ced6484646a325c03fc54fc84d 100644 (file)
@@ -107,7 +107,7 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
         ts->realtime = u;
 
         delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
-        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
+        ts->monotonic = usec_sub_signed(now(CLOCK_MONOTONIC), delta);
 
         return ts;
 }
@@ -124,8 +124,8 @@ triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u)
 
         ts->realtime = u;
         delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
-        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
-        ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
+        ts->monotonic = usec_sub_signed(now(CLOCK_MONOTONIC), delta);
+        ts->boottime = clock_boottime_supported() ? usec_sub_signed(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
 
         return ts;
 }
@@ -141,7 +141,7 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
 
         ts->monotonic = u;
         delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u;
-        ts->realtime = usec_sub(now(CLOCK_REALTIME), delta);
+        ts->realtime = usec_sub_signed(now(CLOCK_REALTIME), delta);
 
         return ts;
 }
@@ -156,8 +156,8 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
 
         dual_timestamp_get(ts);
         delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
-        ts->realtime = usec_sub(ts->realtime, delta);
-        ts->monotonic = usec_sub(ts->monotonic, delta);
+        ts->realtime = usec_sub_signed(ts->realtime, delta);
+        ts->monotonic = usec_sub_signed(ts->monotonic, delta);
 
         return ts;
 }
@@ -241,7 +241,7 @@ usec_t timeval_load(const struct timeval *tv) {
 struct timeval *timeval_store(struct timeval *tv, usec_t u) {
         assert(tv);
 
-        if (u == USEC_INFINITY||
+        if (u == USEC_INFINITY ||
             u / USEC_PER_SEC > TIME_T_MAX) {
                 tv->tv_sec = (time_t) -1;
                 tv->tv_usec = (suseconds_t) -1;
@@ -555,15 +555,29 @@ void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
 
 int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
         uint64_t a, b;
+        int r, pos;
 
         assert(value);
         assert(t);
 
-        if (sscanf(value, "%" PRIu64 "%" PRIu64, &a, &b) != 2) {
-                log_debug("Failed to parse dual timestamp value \"%s\": %m", value);
+        pos = strspn(value, WHITESPACE);
+        if (value[pos] == '-')
+                return -EINVAL;
+        pos += strspn(value + pos, DIGITS);
+        pos += strspn(value + pos, WHITESPACE);
+        if (value[pos] == '-')
+                return -EINVAL;
+
+        r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
+        if (r != 2) {
+                log_debug("Failed to parse dual timestamp value \"%s\".", value);
                 return -EINVAL;
         }
 
+        if (value[pos] != '\0')
+                /* trailing garbage */
+                return -EINVAL;
+
         t->realtime = a;
         t->monotonic = b;
 
@@ -850,10 +864,10 @@ finish:
         if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX)
                 return -EINVAL;
 
-        if (ret > minus)
+        if (ret >= minus)
                 ret -= minus;
         else
-                ret = 0;
+                return -EINVAL;
 
         *usec = ret;
 
@@ -995,6 +1009,16 @@ int parse_sec(const char *t, usec_t *usec) {
         return parse_time(t, usec, USEC_PER_SEC);
 }
 
+int parse_sec_fix_0(const char *t, usec_t *usec) {
+        t += strspn(t, WHITESPACE);
+        if (streq(t, "0")) {
+                *usec = USEC_INFINITY;
+                return 0;
+        }
+
+        return parse_sec(t, usec);
+}
+
 int parse_nsec(const char *t, nsec_t *nsec) {
         static const struct {
                 const char *suffix;
@@ -1337,3 +1361,22 @@ unsigned long usec_to_jiffies(usec_t u) {
 
         return DIV_ROUND_UP(u , USEC_PER_SEC / hz);
 }
+
+usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) {
+        usec_t a, b;
+
+        if (x == USEC_INFINITY)
+                return USEC_INFINITY;
+        if (map_clock_id(from) == map_clock_id(to))
+                return x;
+
+        a = now(from);
+        b = now(to);
+
+        if (x > a)
+                /* x lies in the future */
+                return usec_add(b, usec_sub_unsigned(x, a));
+        else
+                /* x lies in the past */
+                return usec_sub_unsigned(b, usec_sub_unsigned(a, x));
+}
index 7463507f51ab3380322cd1bf737ccda36040f9fc..3b7f0e99c03617a5c7231884cba9a92bdabeee02 100644 (file)
@@ -133,6 +133,7 @@ int timestamp_deserialize(const char *value, usec_t *timestamp);
 int parse_timestamp(const char *t, usec_t *usec);
 
 int parse_sec(const char *t, usec_t *usec);
+int parse_sec_fix_0(const char *t, usec_t *usec);
 int parse_time(const char *t, usec_t *usec, usec_t default_unit);
 int parse_nsec(const char *t, nsec_t *nsec);
 
@@ -145,6 +146,8 @@ bool clock_boottime_supported(void);
 bool clock_supported(clockid_t clock);
 clockid_t clock_boottime_or_monotonic(void);
 
+usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to);
+
 #define xstrftime(buf, fmt, tm) \
         assert_message_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0, \
                           "xstrftime: " #buf "[] must be big enough")
@@ -169,19 +172,23 @@ static inline usec_t usec_add(usec_t a, usec_t b) {
         return c;
 }
 
-static inline usec_t usec_sub(usec_t timestamp, int64_t delta) {
-        if (delta < 0)
-                return usec_add(timestamp, (usec_t) (-delta));
+static inline usec_t usec_sub_unsigned(usec_t timestamp, usec_t delta) {
 
         if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */
                 return USEC_INFINITY;
-
-        if (timestamp < (usec_t) delta)
+        if (timestamp < delta)
                 return 0;
 
         return timestamp - delta;
 }
 
+static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
+        if (delta < 0)
+                return usec_add(timestamp, (usec_t) (-delta));
+        else
+                return usec_sub_unsigned(timestamp, (usec_t) delta);
+}
+
 #if SIZEOF_TIME_T == 8
 /* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit year
  * territory. However, since we want to stay away from this in all timezones we take one day off. */
index 0a6efa449a0d261e309249887070d0c4a734b768..920ca0d9f511fb8cc3c1aad4a23fce66e816cb14 100644 (file)
@@ -1047,3 +1047,12 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
+
+static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
+        [NOTIFY_NONE] = "none",
+        [NOTIFY_MAIN] = "main",
+        [NOTIFY_EXEC] = "exec",
+        [NOTIFY_ALL] = "all"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
index 44eadf034756a4c429db22cb141530ae6f8e8235..0f164a6aa96f11f4e1b731f9789f4479fb37530e 100644 (file)
@@ -257,6 +257,15 @@ typedef enum UnitDependency {
         _UNIT_DEPENDENCY_INVALID = -1
 } UnitDependency;
 
+typedef enum NotifyAccess {
+        NOTIFY_NONE,
+        NOTIFY_ALL,
+        NOTIFY_MAIN,
+        NOTIFY_EXEC,
+        _NOTIFY_ACCESS_MAX,
+        _NOTIFY_ACCESS_INVALID = -1
+} NotifyAccess;
+
 typedef enum UnitNameFlags {
         UNIT_NAME_PLAIN = 1,      /* Allow foo.service */
         UNIT_NAME_INSTANCE = 2,   /* Allow foo@bar.service */
@@ -365,3 +374,6 @@ TimerState timer_state_from_string(const char *s) _pure_;
 
 const char *unit_dependency_to_string(UnitDependency i) _const_;
 UnitDependency unit_dependency_from_string(const char *s) _pure_;
+
+const char* notify_access_to_string(NotifyAccess i) _const_;
+NotifyAccess notify_access_from_string(const char *s) _pure_;
index 3dce0ea92eb79044a7b3ee39f88ccd0e9ee1c67c..b52a5db31b9e8f997a2a3d4992e779b8110001dd 100644 (file)
@@ -541,7 +541,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
                 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
                         return -ENOMEM;
 
-                r = files_same(userns_fd_path, "/proc/self/ns/user");
+                r = files_same(userns_fd_path, "/proc/self/ns/user", 0);
                 if (r < 0)
                         return r;
                 if (r)
index ff4491d6d61f64c04b0885a21e4811b0e3d405de..60117445238f395b8015dcb73b0ac5a17933d1ed 100644 (file)
@@ -574,7 +574,7 @@ int running_in_chroot(void) {
         if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
                 return 0;
 
-        ret = files_same("/proc/1/root", "/");
+        ret = files_same("/proc/1/root", "/", 0);
         if (ret < 0)
                 return ret;
 
index 155bf278b2e444072e05d60916070f9d3036e3fd..233bc802929c8c0142cd428885f3ca49a0aa5531 100644 (file)
@@ -18,8 +18,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
-#include <blkid/blkid.h>
+#include <blkid.h>
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
@@ -74,17 +73,23 @@ static int verify_esp(
         struct statfs sfs;
         sd_id128_t uuid = SD_ID128_NULL;
         uint32_t part = 0;
+        bool quiet;
         int r;
 
         assert(p);
 
+        /* Non-root user can run only `bootctl status`, then if error occured in the following, it does not cause any issues.
+         * So, let's silence the error messages. */
+        quiet = (geteuid() != 0);
+
         if (statfs(p, &sfs) < 0) {
 
                 /* If we are searching for the mount point, don't generate a log message if we can't find the path */
                 if (errno == ENOENT && searching)
                         return -ENOENT;
 
-                return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p);
+                return log_full_errno(quiet && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+                                      "Failed to check file system type of \"%s\": %m", p);
         }
 
         if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) {
@@ -97,7 +102,8 @@ static int verify_esp(
         }
 
         if (stat(p, &st) < 0)
-                return log_error_errno(errno, "Failed to determine block device node of \"%s\": %m", p);
+                return log_full_errno(quiet && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+                                      "Failed to determine block device node of \"%s\": %m", p);
 
         if (major(st.st_dev) == 0) {
                 log_error("Block device node of %p is invalid.", p);
@@ -107,7 +113,8 @@ static int verify_esp(
         t2 = strjoina(p, "/..");
         r = stat(t2, &st2);
         if (r < 0)
-                return log_error_errno(errno, "Failed to determine block device node of parent of \"%s\": %m", p);
+                return log_full_errno(quiet && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+                                      "Failed to determine block device node of parent of \"%s\": %m", p);
 
         if (st.st_dev == st2.st_dev) {
                 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p);
@@ -115,8 +122,8 @@ static int verify_esp(
         }
 
         /* In a container we don't have access to block devices, skip this part of the verification, we trust the
-         * container manager set everything up correctly on its own. */
-        if (detect_container() > 0)
+         * container manager set everything up correctly on its own. Also skip the following verification for non-root user. */
+        if (detect_container() > 0 || geteuid() != 0)
                 goto finish;
 
         r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
@@ -340,7 +347,15 @@ static int status_binaries(const char *esp_path, sd_id128_t partition) {
 
         printf("Boot Loader Binaries:\n");
 
-        printf("          ESP: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(partition));
+        if (!esp_path) {
+                printf("          ESP: Cannot find or access mount point of ESP.\n\n");
+                return -ENOENT;
+        }
+
+        printf("          ESP: %s", esp_path);
+        if (!sd_id128_is_null(partition))
+                printf(" (/dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)", SD_ID128_FORMAT_VAL(partition));
+        printf("\n");
 
         r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
         if (r == 0)
@@ -391,11 +406,6 @@ static int status_variables(void) {
         _cleanup_free_ uint16_t *options = NULL, *order = NULL;
         int i;
 
-        if (!is_efi_boot()) {
-                log_notice("Not booted with EFI, not showing EFI variables.");
-                return 0;
-        }
-
         n_options = efi_get_boot_options(&options);
         if (n_options == -ENOENT)
                 return log_error_errno(n_options,
@@ -1027,15 +1037,9 @@ static int must_be_root(void) {
 static int verb_status(int argc, char *argv[], void *userdata) {
 
         sd_id128_t uuid = SD_ID128_NULL;
-        int r;
+        int r, r2;
 
-        r = must_be_root();
-        if (r < 0)
-                return r;
-
-        r = find_esp(NULL, NULL, NULL, &uuid);
-        if (r < 0)
-                return r;
+        r2 = find_esp(NULL, NULL, NULL, &uuid);
 
         if (is_efi_boot()) {
                 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
@@ -1051,44 +1055,47 @@ static int verb_status(int argc, char *argv[], void *userdata) {
 
                 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
                 if (r < 0 && r != -ENOENT)
-                        log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
+                        r2 = log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
 
                 printf("System:\n");
                 printf("     Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
 
                 r = is_efi_secure_boot();
                 if (r < 0)
-                        log_warning_errno(r, "Failed to query secure boot status: %m");
+                        r2 = log_warning_errno(r, "Failed to query secure boot status: %m");
                 else
                         printf("  Secure Boot: %sd\n", enable_disable(r));
 
                 r = is_efi_secure_boot_setup_mode();
                 if (r < 0)
-                        log_warning_errno(r, "Failed to query secure boot mode: %m");
+                        r2 = log_warning_errno(r, "Failed to query secure boot mode: %m");
                 else
                         printf("   Setup Mode: %s\n", r ? "setup" : "user");
                 printf("\n");
 
-                printf("Loader:\n");
+                printf("Current Loader:\n");
                 printf("      Product: %s\n", strna(loader));
                 if (!sd_id128_is_null(loader_part_uuid))
-                        printf("    Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+                        printf("          ESP: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
                                SD_ID128_FORMAT_VAL(loader_part_uuid));
                 else
-                        printf("    Partition: n/a\n");
+                        printf("          ESP: n/a\n");
                 printf("         File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
                 printf("\n");
         } else
-                printf("System:\n    Not booted with EFI\n");
+                printf("System:\n    Not booted with EFI\n\n");
 
         r = status_binaries(arg_path, uuid);
         if (r < 0)
-                return r;
+                r2 = r;
 
-        if (arg_touch_variables)
+        if (is_efi_boot()) {
                 r = status_variables();
+                if (r < 0)
+                        r2 = r;
+        }
 
-        return r;
+        return r2;
 }
 
 static int verb_install(int argc, char *argv[], void *userdata) {
index 681e783f2e2ee423a0dc1d2fd394f7f7d081ea26..1e990b38251261dc5bedb5540f1bde16c6d30541 100644 (file)
 #include "disk.h"
 #include "graphics.h"
 #include "linux.h"
-#include "pefile.h"
-#include "util.h"
 #include "measure.h"
+#include "pe.h"
+#include "shim.h"
+#include "util.h"
 
 #ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI
 #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL
 #endif
 
 /* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " VERSION " ####";
+static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " PACKAGE_VERSION " ####";
 
 static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
 
@@ -363,7 +364,7 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
         uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
         uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
 
-        Print(L"systemd-boot version:   " VERSION "\n");
+        Print(L"systemd-boot version:   " PACKAGE_VERSION "\n");
         Print(L"architecture:           " EFI_MACHINE_TYPE_NAME "\n");
         Print(L"loaded image:           %s\n", loaded_image_path);
         Print(L"UEFI specification:     %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
@@ -383,6 +384,9 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
                 FreePool(b);
         }
 
+        if (shim_loaded())
+                Print(L"Shim:                   present\n");
+
         if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
                 Print(L"OsIndicationsSupported: %d\n", (UINT64)*b);
                 FreePool(b);
@@ -781,7 +785,7 @@ static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, CHAR16 *load
                         break;
 
                 case KEYPRESS(0, 0, 'v'):
-                        status = PoolPrint(L"systemd-boot " VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
+                        status = PoolPrint(L"systemd-boot " PACKAGE_VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
                                            ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff,
                                            ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
                         break;
@@ -1539,7 +1543,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
                                 continue;
 
                         /* look for .osrel and .cmdline sections in the .efi binary */
-                        err = pefile_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
+                        err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
                         if (EFI_ERROR(err))
                                 continue;
 
@@ -1718,7 +1722,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         InitializeLib(image, sys_table);
         init_usec = time_usec();
         efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
-        efivar_set(L"LoaderInfo", L"systemd-boot " VERSION, FALSE);
+        efivar_set(L"LoaderInfo", L"systemd-boot " PACKAGE_VERSION, FALSE);
         s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
         efivar_set(L"LoaderFirmwareInfo", s, FALSE);
         FreePool(s);
@@ -1745,6 +1749,14 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 return EFI_LOAD_ERROR;
         }
 
+        if (secure_boot_enabled() && shim_loaded()) {
+                err = security_policy_install();
+                if (EFI_ERROR(err)) {
+                        Print(L"Error installing security policy: %r ", err);
+                        uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+                        return err;
+                }
+        }
 
         /* the filesystem path to this image, to prevent adding ourselves to the menu */
         loaded_image_path = DevicePathToStr(loaded_image->FilePath);
index 4ac11a9bb05fe7a932b696c7aef40a9d0333825f..b22d37b62d391eda42108e99f7c226d606a660af 100644 (file)
@@ -199,7 +199,7 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p
 
         event_number = 1;
         status = uefi_call_wrapper(tcg->HashLogExtendEvent, 7,
-                                   tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last);
+                                   (EFI_TCG *) tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last);
 
         if (EFI_ERROR(status))
                 return status;
@@ -219,7 +219,7 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p
  */
 static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg)
 {
-        return uefi_call_wrapper(tcg->GetEventLog, 5, tcg,
+        return uefi_call_wrapper(tcg->GetEventLog, 5, (EFI_TCG2 *) tcg,
                                  EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL,
                                  NULL, NULL);
 }
@@ -254,7 +254,7 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32
 
         CopyMem((VOID *) tcg_event->Event, (VOID *) description, desc_len);
 
-        status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, tcg, 0, buffer, buffer_size, tcg_event);
+        status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, (EFI_TCG2 *) tcg, 0, buffer, buffer_size, tcg_event);
 
         uefi_call_wrapper(BS->FreePool, 1, tcg_event);
 
index a2cfe817d0e04f3466052aef66d6f16acbae6f6a..43aa8a0058534bdaadd525c770cf73306451b15b 100644 (file)
@@ -13,9 +13,6 @@
 #ifndef __SDBOOT_MEASURE_H
 #define __SDBOOT_MEASURE_H
 
-#ifndef SD_TPM_PCR
-#define SD_TPM_PCR 8
-#endif
-
 EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description);
+
 #endif
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
new file mode 100644 (file)
index 0000000..5ef5b2d
--- /dev/null
@@ -0,0 +1,205 @@
+efi_headers = files('''
+        console.h
+        disk.h
+        graphics.h
+        linux.h
+        measure.h
+        pe.h
+        splash.h
+        util.h
+        shim.h
+'''.split())
+
+common_sources = '''
+        disk.c
+        graphics.c
+        measure.c
+        pe.c
+        util.c
+'''.split()
+
+systemd_boot_sources = '''
+        boot.c
+        console.c
+        shim.c
+'''.split()
+
+stub_sources = '''
+        linux.c
+        splash.c
+        stub.c
+'''.split()
+
+if conf.get('ENABLE_EFI', false) and get_option('gnu-efi') != 'false'
+        efi_cc = get_option('efi-cc')
+        efi_ld = get_option('efi-ld')
+
+        efi_incdir = get_option('efi-includedir')
+        have_header = (gnu_efi_arch != '' and
+                       cc.has_header('@0@/@1@/efibind.h'.format(efi_incdir, gnu_efi_arch)))
+
+        if have_header and EFI_MACHINE_TYPE_NAME == ''
+                error('gnu-efi is available, but EFI_MACHINE_TYPE_NAME is unknown')
+        endif
+
+        efi_libdir = get_option('efi-libdir')
+        if efi_libdir == ''
+                cmd = 'cd /usr/lib/$(@0@ -print-multi-os-directory) && pwd'.format(efi_cc)
+                ret = run_command('sh', '-c', cmd)
+                if ret.returncode() == 0
+                        efi_libdir = ret.stdout().strip()
+                endif
+        endif
+
+        have_gnu_efi = have_header and efi_libdir != ''
+else
+        have_gnu_efi = false
+endif
+
+if get_option('gnu-efi') == 'true' and not have_gnu_efi
+        error('gnu-efi support requested, but headers were not found')
+endif
+
+if have_gnu_efi
+        efi_conf = configuration_data()
+        efi_conf.set_quoted('PACKAGE_VERSION', meson.project_version())
+        efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME)
+        efi_conf.set('SD_BOOT_LOG_TPM', get_option('tpm'))
+        efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex'))
+
+        efi_config_h = configure_file(
+                output : 'efi_config.h',
+                configuration : efi_conf)
+
+        objcopy = find_program('objcopy')
+
+        efi_ldsdir = get_option('efi-ldsdir')
+        arch_lds = 'elf_@0@_efi.lds'.format(gnu_efi_arch)
+        if efi_ldsdir == ''
+                efi_ldsdir = join_paths(efi_libdir, 'gnuefi')
+                cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds))
+                if cmd.returncode() != 0
+                        efi_ldsdir = efi_libdir
+                        cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds))
+                        if cmd.returncode() != 0
+                               error('Cannot find @0@'.format(arch_lds))
+                        endif
+                endif
+        endif
+
+        message('efi-libdir: "@0@"'.format(efi_libdir))
+        message('efi-ldsdir: "@0@"'.format(efi_ldsdir))
+        message('efi-includedir: "@0@"'.format(efi_incdir))
+
+        compile_args = ['-Wall',
+                        '-Wextra',
+                        '-std=gnu90',
+                        '-nostdinc',
+                        '-ggdb', '-O0',
+                        '-fpic',
+                        '-fshort-wchar',
+                        '-ffreestanding',
+                        '-fno-strict-aliasing',
+                        '-fno-stack-protector',
+                        '-Wsign-compare',
+                        '-Wno-missing-field-initializers',
+                        '-isystem', efi_incdir,
+                        '-isystem', join_paths(efi_incdir, gnu_efi_arch),
+                        '-include', efi_config_h]
+        if efi_arch == 'x86_64'
+                compile_args += ['-mno-red-zone',
+                                 '-mno-sse',
+                                 '-mno-mmx',
+                                 '-DEFI_FUNCTION_WRAPPER',
+                                 '-DGNU_EFI_USE_MS_ABI']
+        elif efi_arch == 'ia32'
+                compile_args += ['-mno-sse',
+                                 '-mno-mmx']
+        endif
+
+        efi_ldflags = ['-T',
+                       join_paths(efi_ldsdir, arch_lds),
+                       '-shared',
+                       '-Bsymbolic',
+                       '-nostdlib',
+                       '-znocombreloc',
+                       '-L', efi_libdir,
+                       join_paths(efi_ldsdir, 'crt0-efi-@0@.o'.format(gnu_efi_arch))]
+        if efi_arch == 'aarch64' or efi_arch == 'arm'
+                # Aarch64 and ARM32 don't have an EFI capable objcopy. Use 'binary'
+                # instead, and add required symbols manually.
+                efi_ldflags += ['--defsym=EFI_SUBSYSTEM=0xa']
+                efi_format = ['-O', 'binary']
+        else
+                efi_format = ['--target=efi-app-@0@'.format(gnu_efi_arch)]
+        endif
+
+        systemd_boot_objects = []
+        stub_objects = []
+        foreach file : common_sources + systemd_boot_sources + stub_sources
+                o_file = custom_target(file + '.o',
+                                       input : file,
+                                       output : file + '.o',
+                                       command : [efi_cc, '-c', '@INPUT@', '-o', '@OUTPUT@']
+                                                 + compile_args,
+                                       depend_files : efi_headers)
+                if (common_sources + systemd_boot_sources).contains(file)
+                        systemd_boot_objects += [o_file]
+                endif
+                if (common_sources + stub_sources).contains(file)
+                        stub_objects += [o_file]
+                endif
+        endforeach
+
+        libgcc_file_name = run_command(efi_cc, '-print-libgcc-file-name').stdout().strip()
+        systemd_boot_efi_name = 'systemd-boot@0@.efi'.format(EFI_MACHINE_TYPE_NAME)
+        stub_efi_name = 'linux@0@.efi.stub'.format(EFI_MACHINE_TYPE_NAME)
+        no_undefined_symbols = find_program('no-undefined-symbols.sh')
+
+        foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects],
+                         ['stub.so', stub_efi_name, stub_objects]]
+                so = custom_target(
+                        tuple[0],
+                        input : tuple[2],
+                        output : tuple[0],
+                        command : [efi_ld, '-o', '@OUTPUT@'] +
+                                  efi_ldflags + tuple[2] +
+                                  ['-lefi', '-lgnuefi', libgcc_file_name])
+
+                test('no-undefined-symbols-' + tuple[0],
+                     no_undefined_symbols,
+                     args : [so])
+
+                stub = custom_target(
+                        tuple[1],
+                        input : so,
+                        output : tuple[1],
+                        command : [objcopy,
+                                   '-j', '.text',
+                                   '-j', '.sdata',
+                                   '-j', '.data',
+                                   '-j', '.dynamic',
+                                   '-j', '.dynsym',
+                                   '-j', '.rel',
+                                   '-j', '.rela',
+                                   '-j', '.reloc']
+                                  + efi_format +
+                                  ['@INPUT@', '@OUTPUT@'],
+                        install : true,
+                        install_dir : bootlibdir)
+
+                set_variable(tuple[0].underscorify(), so)
+                set_variable(tuple[0].underscorify() + '_stub', stub)
+        endforeach
+endif
+
+############################################################
+
+if have_gnu_efi
+        test_efi_disk_img = custom_target(
+                'test-efi-disk.img',
+                input : [systemd_boot_so, stub_so_stub],
+                output : 'test-efi-disk.img',
+                command : [test_efi_create_disk_sh, '@OUTPUT@',
+                           '@INPUT0@', '@INPUT1@', splash_bmp])
+endif
diff --git a/src/boot/efi/no-undefined-symbols.sh b/src/boot/efi/no-undefined-symbols.sh
new file mode 100755 (executable)
index 0000000..08b266c
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh -eu
+
+if nm -D -u "$1" | grep ' U '; then
+        echo "Undefined symbols detected!"
+        exit 1
+fi
diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c
new file mode 100644 (file)
index 0000000..054e8ed
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "pe.h"
+#include "util.h"
+
+struct DosFileHeader {
+        UINT8   Magic[2];
+        UINT16  LastSize;
+        UINT16  nBlocks;
+        UINT16  nReloc;
+        UINT16  HdrSize;
+        UINT16  MinAlloc;
+        UINT16  MaxAlloc;
+        UINT16  ss;
+        UINT16  sp;
+        UINT16  Checksum;
+        UINT16  ip;
+        UINT16  cs;
+        UINT16  RelocPos;
+        UINT16  nOverlay;
+        UINT16  reserved[4];
+        UINT16  OEMId;
+        UINT16  OEMInfo;
+        UINT16  reserved2[10];
+        UINT32  ExeHeader;
+} __attribute__((packed));
+
+#define PE_HEADER_MACHINE_I386          0x014c
+#define PE_HEADER_MACHINE_X64           0x8664
+struct PeFileHeader {
+        UINT16  Machine;
+        UINT16  NumberOfSections;
+        UINT32  TimeDateStamp;
+        UINT32  PointerToSymbolTable;
+        UINT32  NumberOfSymbols;
+        UINT16  SizeOfOptionalHeader;
+        UINT16  Characteristics;
+} __attribute__((packed));
+
+struct PeHeader {
+        UINT8   Magic[4];
+        struct PeFileHeader FileHeader;
+} __attribute__((packed));
+
+struct PeSectionHeader {
+        UINT8   Name[8];
+        UINT32  VirtualSize;
+        UINT32  VirtualAddress;
+        UINT32  SizeOfRawData;
+        UINT32  PointerToRawData;
+        UINT32  PointerToRelocations;
+        UINT32  PointerToLinenumbers;
+        UINT16  NumberOfRelocations;
+        UINT16  NumberOfLinenumbers;
+        UINT32  Characteristics;
+} __attribute__((packed));
+
+EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
+        struct DosFileHeader *dos;
+        struct PeHeader *pe;
+        UINTN i;
+        UINTN offset;
+
+        dos = (struct DosFileHeader *)base;
+
+        if (CompareMem(dos->Magic, "MZ", 2) != 0)
+                return EFI_LOAD_ERROR;
+
+        pe = (struct PeHeader *)&base[dos->ExeHeader];
+        if (CompareMem(pe->Magic, "PE\0\0", 4) != 0)
+                return EFI_LOAD_ERROR;
+
+        /* PE32+ Subsystem type */
+        if (pe->FileHeader.Machine != PE_HEADER_MACHINE_X64 &&
+            pe->FileHeader.Machine != PE_HEADER_MACHINE_I386)
+                return EFI_LOAD_ERROR;
+
+        if (pe->FileHeader.NumberOfSections > 96)
+                return EFI_LOAD_ERROR;
+
+        offset = dos->ExeHeader + sizeof(*pe) + pe->FileHeader.SizeOfOptionalHeader;
+
+        for (i = 0; i < pe->FileHeader.NumberOfSections; i++) {
+                struct PeSectionHeader *sect;
+                UINTN j;
+
+                sect = (struct PeSectionHeader *)&base[offset];
+                for (j = 0; sections[j]; j++) {
+                        if (CompareMem(sect->Name, sections[j], strlena(sections[j])) != 0)
+                                continue;
+
+                        if (addrs)
+                                addrs[j] = (UINTN)sect->VirtualAddress;
+                        if (offsets)
+                                offsets[j] = (UINTN)sect->PointerToRawData;
+                        if (sizes)
+                                sizes[j] = (UINTN)sect->VirtualSize;
+                }
+                offset += sizeof(*sect);
+        }
+
+        return EFI_SUCCESS;
+}
+
+EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
+        EFI_FILE_HANDLE handle;
+        struct DosFileHeader dos;
+        struct PeHeader pe;
+        UINTN len;
+        UINTN headerlen;
+        EFI_STATUS err;
+        CHAR8 *header = NULL;
+
+        err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
+        if (EFI_ERROR(err))
+                return err;
+
+        /* MS-DOS stub */
+        len = sizeof(dos);
+        err = uefi_call_wrapper(handle->Read, 3, handle, &len, &dos);
+        if (EFI_ERROR(err))
+                goto out;
+        if (len != sizeof(dos)) {
+                err = EFI_LOAD_ERROR;
+                goto out;
+        }
+
+        err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader);
+        if (EFI_ERROR(err))
+                goto out;
+
+        len = sizeof(pe);
+        err = uefi_call_wrapper(handle->Read, 3, handle, &len, &pe);
+        if (EFI_ERROR(err))
+                goto out;
+        if (len != sizeof(pe)) {
+                err = EFI_LOAD_ERROR;
+                goto out;
+        }
+
+        headerlen = sizeof(dos) + sizeof(pe) + pe.FileHeader.SizeOfOptionalHeader + pe.FileHeader.NumberOfSections * sizeof(struct PeSectionHeader);
+        header = AllocatePool(headerlen);
+        if (!header) {
+                err = EFI_OUT_OF_RESOURCES;
+                goto out;
+        }
+        len = headerlen;
+        err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0);
+        if (EFI_ERROR(err))
+                goto out;
+
+        err = uefi_call_wrapper(handle->Read, 3, handle, &len, header);
+        if (EFI_ERROR(err)) {
+                goto out;
+        }
+        if (len != headerlen) {
+                err = EFI_LOAD_ERROR;
+                goto out;
+        }
+
+        err = pe_memory_locate_sections(header, sections, addrs, offsets, sizes);
+out:
+        if (header)
+                FreePool(header);
+        uefi_call_wrapper(handle->Close, 1, handle);
+        return err;
+}
diff --git a/src/boot/efi/pe.h b/src/boot/efi/pe.h
new file mode 100644 (file)
index 0000000..fa8feea
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
+ */
+
+#ifndef __SDBOOT_PEFILE_H
+#define __SDBOOT_PEFILE_H
+
+EFI_STATUS pe_memory_locate_sections(CHAR8 *base,
+                                     CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes);
+EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path,
+                                   CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes);
+#endif
diff --git a/src/boot/efi/pefile.c b/src/boot/efi/pefile.c
deleted file mode 100644 (file)
index 77fff77..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "pefile.h"
-#include "util.h"
-
-struct DosFileHeader {
-        UINT8   Magic[2];
-        UINT16  LastSize;
-        UINT16  nBlocks;
-        UINT16  nReloc;
-        UINT16  HdrSize;
-        UINT16  MinAlloc;
-        UINT16  MaxAlloc;
-        UINT16  ss;
-        UINT16  sp;
-        UINT16  Checksum;
-        UINT16  ip;
-        UINT16  cs;
-        UINT16  RelocPos;
-        UINT16  nOverlay;
-        UINT16  reserved[4];
-        UINT16  OEMId;
-        UINT16  OEMInfo;
-        UINT16  reserved2[10];
-        UINT32  ExeHeader;
-} __attribute__((packed));
-
-#define PE_HEADER_MACHINE_I386          0x014c
-#define PE_HEADER_MACHINE_X64           0x8664
-struct PeFileHeader {
-        UINT16  Machine;
-        UINT16  NumberOfSections;
-        UINT32  TimeDateStamp;
-        UINT32  PointerToSymbolTable;
-        UINT32  NumberOfSymbols;
-        UINT16  SizeOfOptionalHeader;
-        UINT16  Characteristics;
-} __attribute__((packed));
-
-struct PeSectionHeader {
-        UINT8   Name[8];
-        UINT32  VirtualSize;
-        UINT32  VirtualAddress;
-        UINT32  SizeOfRawData;
-        UINT32  PointerToRawData;
-        UINT32  PointerToRelocations;
-        UINT32  PointerToLinenumbers;
-        UINT16  NumberOfRelocations;
-        UINT16  NumberOfLinenumbers;
-        UINT32  Characteristics;
-} __attribute__((packed));
-
-
-EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
-        EFI_FILE_HANDLE handle;
-        struct DosFileHeader dos;
-        uint8_t magic[4];
-        struct PeFileHeader pe;
-        UINTN len;
-        UINTN i;
-        EFI_STATUS err;
-
-        err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
-        if (EFI_ERROR(err))
-                return err;
-
-        /* MS-DOS stub */
-        len = sizeof(dos);
-        err = uefi_call_wrapper(handle->Read, 3, handle, &len, &dos);
-        if (EFI_ERROR(err))
-                goto out;
-        if (len != sizeof(dos)) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        if (CompareMem(dos.Magic, "MZ", 2) != 0) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader);
-        if (EFI_ERROR(err))
-                goto out;
-
-        /* PE header */
-        len = sizeof(magic);
-        err = uefi_call_wrapper(handle->Read, 3, handle, &len, &magic);
-        if (EFI_ERROR(err))
-                goto out;
-        if (len != sizeof(magic)) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        if (CompareMem(magic, "PE\0\0", 2) != 0) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        len = sizeof(pe);
-        err = uefi_call_wrapper(handle->Read, 3, handle, &len, &pe);
-        if (EFI_ERROR(err))
-                goto out;
-        if (len != sizeof(pe)) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        /* PE32+ Subsystem type */
-        if (pe.Machine != PE_HEADER_MACHINE_X64 &&
-            pe.Machine != PE_HEADER_MACHINE_I386) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        if (pe.NumberOfSections > 96) {
-                err = EFI_LOAD_ERROR;
-                goto out;
-        }
-
-        /* the sections start directly after the headers */
-        err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader + sizeof(magic) + sizeof(pe) + pe.SizeOfOptionalHeader);
-        if (EFI_ERROR(err))
-                goto out;
-
-        for (i = 0; i < pe.NumberOfSections; i++) {
-                struct PeSectionHeader sect;
-                UINTN j;
-
-                len = sizeof(sect);
-                err = uefi_call_wrapper(handle->Read, 3, handle, &len, &sect);
-                if (EFI_ERROR(err))
-                        goto out;
-                if (len != sizeof(sect)) {
-                        err = EFI_LOAD_ERROR;
-                        goto out;
-                }
-                for (j = 0; sections[j]; j++) {
-                        if (CompareMem(sect.Name, sections[j], strlena(sections[j])) != 0)
-                                continue;
-
-                        if (addrs)
-                                addrs[j] = (UINTN)sect.VirtualAddress;
-                        if (offsets)
-                                offsets[j] = (UINTN)sect.PointerToRawData;
-                        if (sizes)
-                                sizes[j] = (UINTN)sect.VirtualSize;
-                }
-        }
-
-out:
-        uefi_call_wrapper(handle->Close, 1, handle);
-        return err;
-}
diff --git a/src/boot/efi/pefile.h b/src/boot/efi/pefile.h
deleted file mode 100644 (file)
index 2e445ed..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This 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
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#ifndef __SDBOOT_PEFILE_H
-#define __SDBOOT_PEFILE_H
-
-EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path,
-                                  CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes);
-#endif
diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c
new file mode 100644 (file)
index 0000000..0f73be9
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * Port to systemd-boot
+ * Copyright 2017 Max Resch <resch.max@gmail.com>
+ *
+ * Security Policy Handling
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ * https://github.com/mjg59/efitools
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "util.h"
+#include "shim.h"
+
+/* well known shim lock guid */
+#define SHIM_LOCK_GUID
+
+struct ShimLock {
+        EFI_STATUS __attribute__((sysv_abi)) (*shim_verify) (VOID *buffer, UINT32 size);
+
+        /* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
+         * see shim.c/shim.h and PeHeader.h in the github shim repo */
+        EFI_STATUS __attribute__((sysv_abi)) (*generate_hash) (VOID *data, UINT32 datasize, VOID *context, UINT8 *sha256hash, UINT8 *sha1hash);
+
+        EFI_STATUS __attribute__((sysv_abi)) (*read_header) (VOID *data, UINT32 datasize, VOID *context);
+};
+
+static const EFI_GUID simple_fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
+static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
+
+static const EFI_GUID security_protocol_guid = { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } };
+static const EFI_GUID security2_protocol_guid = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
+static const EFI_GUID shim_lock_guid = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
+
+BOOLEAN shim_loaded(void) {
+        struct ShimLock *shim_lock;
+
+        return uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS;
+}
+
+static BOOLEAN shim_validate(VOID *data, UINT32 size) {
+        struct ShimLock *shim_lock;
+
+        if (!data)
+                return FALSE;
+
+        if (uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) != EFI_SUCCESS)
+                return FALSE;
+
+        if (!shim_lock)
+                return FALSE;
+
+        if (shim_lock->shim_verify(data, size) == EFI_SUCCESS)
+                return TRUE;
+
+        return FALSE;
+}
+
+BOOLEAN secure_boot_enabled(void) {
+        CHAR8 *b;
+        UINTN size;
+        BOOLEAN result;
+
+        if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
+                result = *b > 0;
+                FreePool(b);
+                return result;
+        }
+
+        return FALSE;
+}
+
+/*
+ * See the UEFI Platform Initialization manual (Vol2: DXE) for this
+ */
+struct _EFI_SECURITY2_PROTOCOL;
+struct _EFI_SECURITY_PROTOCOL;
+struct _EFI_DEVICE_PATH_PROTOCOL;
+
+typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL;
+typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL;
+typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) (
+        const EFI_SECURITY_PROTOCOL *This,
+        UINT32 AuthenticationStatus,
+        const EFI_DEVICE_PATH_PROTOCOL *File
+);
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) (
+        const EFI_SECURITY2_PROTOCOL *This,
+        const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+        VOID *FileBuffer,
+        UINTN FileSize,
+        BOOLEAN  BootPolicy
+);
+
+struct _EFI_SECURITY2_PROTOCOL {
+        EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
+};
+
+struct _EFI_SECURITY_PROTOCOL {
+        EFI_SECURITY_FILE_AUTHENTICATION_STATE  FileAuthenticationState;
+};
+
+/* Handle to the original authenticator for security1 protocol */
+static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL;
+
+/* Handle to the original authenticator for security2 protocol */
+static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL;
+
+/*
+ * Perform shim/MOK and Secure Boot authentication on a binary that's already been
+ * loaded into memory. This function does the platform SB authentication first
+ * but preserves its return value in case of its failure, so that it can be
+ * returned in case of a shim/MOK authentication failure. This is done because
+ * the SB failure code seems to vary from one implementation to another, and I
+ * don't want to interfere with that at this time.
+ */
+static EFIAPI EFI_STATUS security2_policy_authentication (const EFI_SECURITY2_PROTOCOL *this,
+                                                          const EFI_DEVICE_PATH_PROTOCOL *device_path,
+                                                          VOID *file_buffer, UINTN file_size, BOOLEAN boot_policy) {
+        EFI_STATUS status;
+
+        /* Chain original security policy */
+        status = uefi_call_wrapper(es2fa, 5, this, device_path, file_buffer, file_size, boot_policy);
+
+        /* if OK, don't bother with MOK check */
+        if (status == EFI_SUCCESS)
+                return status;
+
+        if (shim_validate(file_buffer, file_size))
+                return EFI_SUCCESS;
+
+        return status;
+}
+
+/*
+ * Perform both shim/MOK and platform Secure Boot authentication. This function loads
+ * the file and performs shim/MOK authentication first simply to avoid double loads
+ * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
+ * since kernels are big and can take several seconds to load on some computers and
+ * filesystems. This also has the effect of returning whatever the platform code is for
+ * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
+ * else. (This seems to vary between implementations.)
+ */
+static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROTOCOL *this, UINT32 authentication_status,
+                                                         const EFI_DEVICE_PATH_PROTOCOL *device_path_const) {
+        EFI_STATUS status;
+        EFI_DEVICE_PATH *dev_path;
+        EFI_HANDLE h;
+        EFI_FILE *root;
+        VOID *file_buffer = NULL;
+        UINTN file_size;
+        CHAR16 *dev_path_str;
+
+        if (!device_path_const)
+                return EFI_INVALID_PARAMETER;
+
+        dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const);
+
+        status = uefi_call_wrapper(BS->LocateDevicePath, 3, (EFI_GUID*) &simple_fs_guid, &dev_path, &h);
+        if (status != EFI_SUCCESS) {
+                FreePool(dev_path);
+                return status;
+        }
+
+        /* No need to check return value, this already happend in efi_main() */
+        root = LibOpenRoot(h);
+        dev_path_str = DevicePathToStr(dev_path);
+        FreePool(dev_path);
+
+        file_size = file_read(root, dev_path_str, 0, 0, file_buffer);
+        FreePool(dev_path_str);
+        uefi_call_wrapper(root->Close, 1, root);
+
+        if (shim_validate(file_buffer, file_size))
+                status = EFI_SUCCESS;
+
+        FreePool(file_buffer);
+
+        /* Try using the platform's native policy.... */
+        if (status != EFI_SUCCESS)
+                status = uefi_call_wrapper(esfas, 3, this, authentication_status, device_path_const);
+
+        return status;
+}
+
+EFI_STATUS security_policy_install(void) {
+        EFI_SECURITY_PROTOCOL *security_protocol;
+        EFI_SECURITY2_PROTOCOL *security2_protocol = NULL;
+        EFI_STATUS status;
+
+        /* Already Installed */
+        if (esfas)
+                return EFI_ALREADY_STARTED;
+
+        /*
+         * Don't bother with status here.  The call is allowed
+         * to fail, since SECURITY2 was introduced in PI 1.2.1
+         * If it fails, use security2_protocol == NULL as indicator
+         */
+        uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security2_protocol_guid, NULL, (VOID**) &security2_protocol);
+
+        status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security_protocol_guid, NULL, (VOID**) &security_protocol);
+         /* This one is mandatory, so there's a serious problem */
+        if (status != EFI_SUCCESS)
+                return status;
+
+        if (!security2_protocol) {
+                es2fa = security2_protocol->FileAuthentication;
+                security2_protocol->FileAuthentication = security2_policy_authentication;
+        }
+
+        esfas = security_protocol->FileAuthenticationState;
+        security_protocol->FileAuthenticationState = security_policy_authentication;
+
+        return EFI_SUCCESS;
+}
+
+EFI_STATUS security_policy_uninstall(void) {
+        EFI_STATUS status;
+
+        if (esfas) {
+                EFI_SECURITY_PROTOCOL *security_protocol;
+
+                status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security_protocol_guid, NULL, (VOID**) &security_protocol);
+
+                if (status != EFI_SUCCESS)
+                        return status;
+
+                security_protocol->FileAuthenticationState = esfas;
+                esfas = NULL;
+        } else
+                /* nothing installed */
+                return EFI_NOT_STARTED;
+
+        if (es2fa) {
+                EFI_SECURITY2_PROTOCOL *security2_protocol;
+
+                status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security2_protocol_guid, NULL, (VOID**) &security2_protocol);
+
+                if (status != EFI_SUCCESS)
+                        return status;
+
+                security2_protocol->FileAuthentication = es2fa;
+                es2fa = NULL;
+        }
+
+        return EFI_SUCCESS;
+}
diff --git a/src/boot/efi/shim.h b/src/boot/efi/shim.h
new file mode 100644 (file)
index 0000000..2dcf48d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * Port to systemd-boot
+ * Copyright 2017 Max Resch <resch.max@gmail.com>
+ *
+ * Security Policy Handling
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ * https://github.com/mjg59/efitools
+ */
+
+#ifndef __SDBOOT_SHIM_H
+#define __SDBOOT_SHIM_H
+
+BOOLEAN shim_loaded(void);
+
+BOOLEAN secure_boot_enabled(void);
+
+EFI_STATUS security_policy_install(void);
+
+EFI_STATUS security_policy_uninstall(void);
+
+#endif
index b7d5d3cdae369febeb9585bb08f7ef8afa5a89d4..bab5d46de9a6bc882ebbda3f27bc2076e307e3ea 100644 (file)
 #include "disk.h"
 #include "graphics.h"
 #include "linux.h"
-#include "pefile.h"
+#include "measure.h"
+#include "pe.h"
 #include "splash.h"
 #include "util.h"
-#include "measure.h"
 
 /* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " VERSION " ####";
+static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " PACKAGE_VERSION " ####";
 
 static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
 
 EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         EFI_LOADED_IMAGE *loaded_image;
-        EFI_FILE *root_dir;
-        CHAR16 *loaded_image_path;
         CHAR8 *b;
         UINTN size;
         BOOLEAN secure = FALSE;
@@ -59,22 +57,12 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                 return err;
         }
 
-        root_dir = LibOpenRoot(loaded_image->DeviceHandle);
-        if (!root_dir) {
-                Print(L"Unable to open root directory: %r ", err);
-                uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
-                return EFI_LOAD_ERROR;
-        }
-
-        loaded_image_path = DevicePathToStr(loaded_image->FilePath);
-
         if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
                 if (*b > 0)
                         secure = TRUE;
                 FreePool(b);
         }
-
-        err = pefile_locate_sections(root_dir, loaded_image_path, sections, addrs, offs, szs);
+        err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
         if (EFI_ERROR(err)) {
                 Print(L"Unable to locate embedded .linux section: %r ", err);
                 uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
diff --git a/src/busctl/busctl-introspect.c b/src/busctl/busctl-introspect.c
new file mode 100644 (file)
index 0000000..a057949
--- /dev/null
@@ -0,0 +1,782 @@
+/***
+  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 "sd-bus.h"
+
+#include "alloc-util.h"
+#include "busctl-introspect.h"
+#include "string-util.h"
+#include "util.h"
+#include "xml.h"
+
+#define NODE_DEPTH_MAX 16
+
+typedef struct Context {
+        const XMLIntrospectOps *ops;
+        void *userdata;
+
+        char *interface_name;
+        uint64_t interface_flags;
+
+        char *member_name;
+        char *member_signature;
+        char *member_result;
+        uint64_t member_flags;
+        bool member_writable;
+
+        const char *current;
+        void *xml_state;
+} Context;
+
+static void context_reset_member(Context *c) {
+        free(c->member_name);
+        free(c->member_signature);
+        free(c->member_result);
+
+        c->member_name = c->member_signature = c->member_result = NULL;
+        c->member_flags = 0;
+        c->member_writable = false;
+}
+
+static void context_reset_interface(Context *c) {
+        c->interface_name = mfree(c->interface_name);
+        c->interface_flags = 0;
+
+        context_reset_member(c);
+}
+
+static int parse_xml_annotation(Context *context, uint64_t *flags) {
+
+        enum {
+                STATE_ANNOTATION,
+                STATE_NAME,
+                STATE_VALUE
+        } state = STATE_ANNOTATION;
+
+        _cleanup_free_ char *field = NULL, *value = NULL;
+
+        assert(context);
+
+        for (;;) {
+                _cleanup_free_ char *name = NULL;
+
+                int t;
+
+                t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
+                if (t < 0) {
+                        log_error("XML parse error.");
+                        return t;
+                }
+
+                if (t == XML_END) {
+                        log_error("Premature end of XML data.");
+                        return -EBADMSG;
+                }
+
+                switch (state) {
+
+                case STATE_ANNOTATION:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_NAME;
+
+                                else if (streq_ptr(name, "value"))
+                                        state = STATE_VALUE;
+
+                                else {
+                                        log_error("Unexpected <annotation> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) {
+
+                                if (flags) {
+                                        if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) {
+
+                                                if (streq_ptr(value, "true"))
+                                                        *flags |= SD_BUS_VTABLE_DEPRECATED;
+
+                                        } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) {
+
+                                                if (streq_ptr(value, "true"))
+                                                        *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY;
+
+                                        } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) {
+
+                                                if (streq_ptr(value, "const"))
+                                                        *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST;
+                                                else if (streq_ptr(value, "invalidates"))
+                                                        *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION;
+                                                else if (streq_ptr(value, "false"))
+                                                        *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION);
+                                        }
+                                }
+
+                                return 0;
+
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in <annotation>. (1)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                free_and_replace(field, name);
+
+                                state = STATE_ANNOTATION;
+                        } else {
+                                log_error("Unexpected token in <annotation>. (2)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_VALUE:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                free_and_replace(value, name);
+
+                                state = STATE_ANNOTATION;
+                        } else {
+                                log_error("Unexpected token in <annotation>. (3)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                default:
+                        assert_not_reached("Bad state");
+                }
+        }
+}
+
+static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) {
+
+        enum {
+                STATE_NODE,
+                STATE_NODE_NAME,
+                STATE_INTERFACE,
+                STATE_INTERFACE_NAME,
+                STATE_METHOD,
+                STATE_METHOD_NAME,
+                STATE_METHOD_ARG,
+                STATE_METHOD_ARG_NAME,
+                STATE_METHOD_ARG_TYPE,
+                STATE_METHOD_ARG_DIRECTION,
+                STATE_SIGNAL,
+                STATE_SIGNAL_NAME,
+                STATE_SIGNAL_ARG,
+                STATE_SIGNAL_ARG_NAME,
+                STATE_SIGNAL_ARG_TYPE,
+                STATE_SIGNAL_ARG_DIRECTION,
+                STATE_PROPERTY,
+                STATE_PROPERTY_NAME,
+                STATE_PROPERTY_TYPE,
+                STATE_PROPERTY_ACCESS,
+        } state = STATE_NODE;
+
+        _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL;
+        const char *np = prefix;
+        int r;
+
+        assert(context);
+        assert(prefix);
+
+        if (n_depth > NODE_DEPTH_MAX) {
+                log_error("<node> depth too high.");
+                return -EINVAL;
+        }
+
+        for (;;) {
+                _cleanup_free_ char *name = NULL;
+                int t;
+
+                t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
+                if (t < 0) {
+                        log_error("XML parse error.");
+                        return t;
+                }
+
+                if (t == XML_END) {
+                        log_error("Premature end of XML data.");
+                        return -EBADMSG;
+                }
+
+                switch (state) {
+
+                case STATE_NODE:
+                        if (t == XML_ATTRIBUTE_NAME) {
+
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_NODE_NAME;
+                                else {
+                                        log_error("Unexpected <node> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+
+                        } else if (t == XML_TAG_OPEN) {
+
+                                if (streq_ptr(name, "interface"))
+                                        state = STATE_INTERFACE;
+                                else if (streq_ptr(name, "node")) {
+
+                                        r = parse_xml_node(context, np, n_depth+1);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected <node> tag %s.", name);
+                                        return -EBADMSG;
+                                }
+
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) {
+
+                                if (context->ops->on_path) {
+                                        r = context->ops->on_path(node_path ? node_path : np, context->userdata);
+                                        if (r < 0)
+                                                return r;
+                                }
+
+                                return 0;
+
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in <node>. (1)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_NODE_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+
+                                free(node_path);
+
+                                if (name[0] == '/') {
+                                        node_path = name;
+                                        name = NULL;
+                                } else {
+
+                                        if (endswith(prefix, "/"))
+                                                node_path = strappend(prefix, name);
+                                        else
+                                                node_path = strjoin(prefix, "/", name);
+                                        if (!node_path)
+                                                return log_oom();
+                                }
+
+                                np = node_path;
+                                state = STATE_NODE;
+                        } else {
+                                log_error("Unexpected token in <node>. (2)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_INTERFACE:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_INTERFACE_NAME;
+                                else {
+                                        log_error("Unexpected <interface> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+
+                        } else if (t == XML_TAG_OPEN) {
+                                if (streq_ptr(name, "method"))
+                                        state = STATE_METHOD;
+                                else if (streq_ptr(name, "signal"))
+                                        state = STATE_SIGNAL;
+                                else if (streq_ptr(name, "property")) {
+                                        context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE;
+                                        state = STATE_PROPERTY;
+                                } else if (streq_ptr(name, "annotation")) {
+                                        r = parse_xml_annotation(context, &context->interface_flags);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected <interface> tag %s.", name);
+                                        return -EINVAL;
+                                }
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) {
+
+                                if (n_depth == 0) {
+                                        if (context->ops->on_interface) {
+                                                r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata);
+                                                if (r < 0)
+                                                        return r;
+                                        }
+
+                                        context_reset_interface(context);
+                                }
+
+                                state = STATE_NODE;
+
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in <interface>. (1)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_INTERFACE_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                if (n_depth == 0)
+                                        free_and_replace(context->interface_name, name);
+
+                                state = STATE_INTERFACE;
+                        } else {
+                                log_error("Unexpected token in <interface>. (2)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_METHOD:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_METHOD_NAME;
+                                else {
+                                        log_error("Unexpected <method> attribute %s", name);
+                                        return -EBADMSG;
+                                }
+                        } else if (t == XML_TAG_OPEN) {
+                                if (streq_ptr(name, "arg"))
+                                        state = STATE_METHOD_ARG;
+                                else if (streq_ptr(name, "annotation")) {
+                                        r = parse_xml_annotation(context, &context->member_flags);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected <method> tag %s.", name);
+                                        return -EINVAL;
+                                }
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) {
+
+                                if (n_depth == 0) {
+                                        if (context->ops->on_method) {
+                                                r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata);
+                                                if (r < 0)
+                                                        return r;
+                                        }
+
+                                        context_reset_member(context);
+                                }
+
+                                state = STATE_INTERFACE;
+
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in <method> (1).");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_METHOD_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                if (n_depth == 0)
+                                        free_and_replace(context->member_name, name);
+
+                                state = STATE_METHOD;
+                        } else {
+                                log_error("Unexpected token in <method> (2).");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_METHOD_ARG:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_METHOD_ARG_NAME;
+                                else if (streq_ptr(name, "type"))
+                                        state = STATE_METHOD_ARG_TYPE;
+                                else if (streq_ptr(name, "direction"))
+                                        state = STATE_METHOD_ARG_DIRECTION;
+                                else {
+                                        log_error("Unexpected method <arg> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+                        } else if (t == XML_TAG_OPEN) {
+                                if (streq_ptr(name, "annotation")) {
+                                        r = parse_xml_annotation(context, NULL);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected method <arg> tag %s.", name);
+                                        return -EINVAL;
+                                }
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
+
+                                if (n_depth == 0) {
+
+                                        if (argument_type) {
+                                                if (!argument_direction || streq(argument_direction, "in")) {
+                                                        if (!strextend(&context->member_signature, argument_type, NULL))
+                                                                return log_oom();
+                                                } else if (streq(argument_direction, "out")) {
+                                                        if (!strextend(&context->member_result, argument_type, NULL))
+                                                                return log_oom();
+                                                } else
+                                                        log_error("Unexpected method <arg> direction value '%s'.", argument_direction);
+                                        }
+
+                                        argument_type = mfree(argument_type);
+                                        argument_direction = mfree(argument_direction);
+                                }
+
+                                state = STATE_METHOD;
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in method <arg>. (1)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_METHOD_ARG_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE)
+                                state = STATE_METHOD_ARG;
+                        else {
+                                log_error("Unexpected token in method <arg>. (2)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_METHOD_ARG_TYPE:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                free_and_replace(argument_type, name);
+
+                                state = STATE_METHOD_ARG;
+                        } else {
+                                log_error("Unexpected token in method <arg>. (3)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_METHOD_ARG_DIRECTION:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                free_and_replace(argument_direction, name);
+
+                                state = STATE_METHOD_ARG;
+                        } else {
+                                log_error("Unexpected token in method <arg>. (4)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_SIGNAL:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_SIGNAL_NAME;
+                                else {
+                                        log_error("Unexpected <signal> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+                        } else if (t == XML_TAG_OPEN) {
+                                if (streq_ptr(name, "arg"))
+                                        state = STATE_SIGNAL_ARG;
+                                else if (streq_ptr(name, "annotation")) {
+                                        r = parse_xml_annotation(context, &context->member_flags);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected <signal> tag %s.", name);
+                                        return -EINVAL;
+                                }
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) {
+
+                                if (n_depth == 0) {
+                                        if (context->ops->on_signal) {
+                                                r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata);
+                                                if (r < 0)
+                                                        return r;
+                                        }
+
+                                        context_reset_member(context);
+                                }
+
+                                state = STATE_INTERFACE;
+
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in <signal>. (1)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_SIGNAL_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                if (n_depth == 0)
+                                        free_and_replace(context->member_name, name);
+
+                                state = STATE_SIGNAL;
+                        } else {
+                                log_error("Unexpected token in <signal>. (2)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+
+                case STATE_SIGNAL_ARG:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_SIGNAL_ARG_NAME;
+                                else if (streq_ptr(name, "type"))
+                                        state = STATE_SIGNAL_ARG_TYPE;
+                                else if (streq_ptr(name, "direction"))
+                                        state = STATE_SIGNAL_ARG_DIRECTION;
+                                else {
+                                        log_error("Unexpected signal <arg> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+                        } else if (t == XML_TAG_OPEN) {
+                                if (streq_ptr(name, "annotation")) {
+                                        r = parse_xml_annotation(context, NULL);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected signal <arg> tag %s.", name);
+                                        return -EINVAL;
+                                }
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
+
+                                if (argument_type) {
+                                        if (!argument_direction || streq(argument_direction, "out")) {
+                                                if (!strextend(&context->member_signature, argument_type, NULL))
+                                                        return log_oom();
+                                        } else
+                                                log_error("Unexpected signal <arg> direction value '%s'.", argument_direction);
+
+                                        argument_type = mfree(argument_type);
+                                }
+
+                                state = STATE_SIGNAL;
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in signal <arg> (1).");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_SIGNAL_ARG_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE)
+                                state = STATE_SIGNAL_ARG;
+                        else {
+                                log_error("Unexpected token in signal <arg> (2).");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_SIGNAL_ARG_TYPE:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                free_and_replace(argument_type, name);
+
+                                state = STATE_SIGNAL_ARG;
+                        } else {
+                                log_error("Unexpected token in signal <arg> (3).");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_SIGNAL_ARG_DIRECTION:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                free_and_replace(argument_direction, name);
+
+                                state = STATE_SIGNAL_ARG;
+                        } else {
+                                log_error("Unexpected token in signal <arg>. (4)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_PROPERTY:
+
+                        if (t == XML_ATTRIBUTE_NAME) {
+                                if (streq_ptr(name, "name"))
+                                        state = STATE_PROPERTY_NAME;
+                                else if (streq_ptr(name, "type"))
+                                        state  = STATE_PROPERTY_TYPE;
+                                else if (streq_ptr(name, "access"))
+                                        state  = STATE_PROPERTY_ACCESS;
+                                else {
+                                        log_error("Unexpected <property> attribute %s.", name);
+                                        return -EBADMSG;
+                                }
+                        } else if (t == XML_TAG_OPEN) {
+
+                                if (streq_ptr(name, "annotation")) {
+                                        r = parse_xml_annotation(context, &context->member_flags);
+                                        if (r < 0)
+                                                return r;
+                                } else {
+                                        log_error("Unexpected <property> tag %s.", name);
+                                        return -EINVAL;
+                                }
+
+                        } else if (t == XML_TAG_CLOSE_EMPTY ||
+                                   (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) {
+
+                                if (n_depth == 0) {
+                                        if (context->ops->on_property) {
+                                                r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata);
+                                                if (r < 0)
+                                                        return r;
+                                        }
+
+                                        context_reset_member(context);
+                                }
+
+                                state = STATE_INTERFACE;
+
+                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                                log_error("Unexpected token in <property>. (1)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_PROPERTY_NAME:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                if (n_depth == 0)
+                                        free_and_replace(context->member_name, name);
+
+                                state = STATE_PROPERTY;
+                        } else {
+                                log_error("Unexpected token in <property>. (2)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_PROPERTY_TYPE:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+                                if (n_depth == 0)
+                                        free_and_replace(context->member_signature, name);
+
+                                state = STATE_PROPERTY;
+                        } else {
+                                log_error("Unexpected token in <property>. (3)");
+                                return -EINVAL;
+                        }
+
+                        break;
+
+                case STATE_PROPERTY_ACCESS:
+
+                        if (t == XML_ATTRIBUTE_VALUE) {
+
+                                if (streq(name, "readwrite") || streq(name, "write"))
+                                        context->member_writable = true;
+
+                                state = STATE_PROPERTY;
+                        } else {
+                                log_error("Unexpected token in <property>. (4)");
+                                return -EINVAL;
+                        }
+
+                        break;
+                }
+        }
+}
+
+int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) {
+        Context context = {
+                .ops = ops,
+                .userdata = userdata,
+                .current = xml,
+        };
+
+        int r;
+
+        assert(prefix);
+        assert(xml);
+        assert(ops);
+
+        for (;;) {
+                _cleanup_free_ char *name = NULL;
+
+                r = xml_tokenize(&context.current, &name, &context.xml_state, NULL);
+                if (r < 0) {
+                        log_error("XML parse error");
+                        goto finish;
+                }
+
+                if (r == XML_END) {
+                        r = 0;
+                        break;
+                }
+
+                if (r == XML_TAG_OPEN) {
+
+                        if (streq(name, "node")) {
+                                r = parse_xml_node(&context, prefix, 0);
+                                if (r < 0)
+                                        goto finish;
+                        } else {
+                                log_error("Unexpected tag '%s' in introspection data.", name);
+                                r = -EBADMSG;
+                                goto finish;
+                        }
+                } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) {
+                        log_error("Unexpected token.");
+                        r = -EBADMSG;
+                        goto finish;
+                }
+        }
+
+finish:
+        context_reset_interface(&context);
+
+        return r;
+}
diff --git a/src/busctl/busctl-introspect.h b/src/busctl/busctl-introspect.h
new file mode 100644 (file)
index 0000000..d922e35
--- /dev/null
@@ -0,0 +1,32 @@
+#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 <stdbool.h>
+
+typedef struct XMLIntrospectOps {
+        int (*on_path)(const char *path, void *userdata);
+        int (*on_interface)(const char *name, uint64_t flags, void *userdata);
+        int (*on_method)(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata);
+        int (*on_signal)(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata);
+        int (*on_property)(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata);
+} XMLIntrospectOps;
+
+int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata);
diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
new file mode 100644 (file)
index 0000000..b38d6c7
--- /dev/null
@@ -0,0 +1,2109 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2013 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 <getopt.h>
+
+#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-dump.h"
+#include "bus-internal.h"
+#include "bus-signature.h"
+#include "bus-type.h"
+#include "bus-util.h"
+#include "busctl-introspect.h"
+#include "escape.h"
+#include "fd-util.h"
+#include "locale-util.h"
+#include "log.h"
+#include "pager.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "set.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "user-util.h"
+#include "util.h"
+
+static bool arg_no_pager = false;
+static bool arg_legend = true;
+static char *arg_address = NULL;
+static bool arg_unique = false;
+static bool arg_acquired = false;
+static bool arg_activatable = false;
+static bool arg_show_machine = false;
+static char **arg_matches = NULL;
+static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
+static char *arg_host = NULL;
+static bool arg_user = false;
+static size_t arg_snaplen = 4096;
+static bool arg_list = false;
+static bool arg_quiet = false;
+static bool arg_verbose = false;
+static bool arg_expect_reply = true;
+static bool arg_auto_start = true;
+static bool arg_allow_interactive_authorization = true;
+static bool arg_augment_creds = true;
+static usec_t arg_timeout = 0;
+
+#define NAME_IS_ACQUIRED INT_TO_PTR(1)
+#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
+
+static int list_bus_names(sd_bus *bus, char **argv) {
+        _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
+        _cleanup_free_ char **merged = NULL;
+        _cleanup_hashmap_free_ Hashmap *names = NULL;
+        char **i;
+        int r;
+        size_t max_i = 0;
+        unsigned n = 0;
+        void *v;
+        char *k;
+        Iterator iterator;
+
+        assert(bus);
+
+        if (!arg_unique && !arg_acquired && !arg_activatable)
+                arg_unique = arg_acquired = arg_activatable = true;
+
+        r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to list names: %m");
+
+        pager_open(arg_no_pager, false);
+
+        names = hashmap_new(&string_hash_ops);
+        if (!names)
+                return log_oom();
+
+        STRV_FOREACH(i, acquired) {
+                max_i = MAX(max_i, strlen(*i));
+
+                r = hashmap_put(names, *i, NAME_IS_ACQUIRED);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to add to hashmap: %m");
+        }
+
+        STRV_FOREACH(i, activatable) {
+                max_i = MAX(max_i, strlen(*i));
+
+                r = hashmap_put(names, *i, NAME_IS_ACTIVATABLE);
+                if (r < 0 && r != -EEXIST)
+                        return log_error_errno(r, "Failed to add to hashmap: %m");
+        }
+
+        merged = new(char*, hashmap_size(names) + 1);
+        HASHMAP_FOREACH_KEY(v, k, names, iterator)
+                merged[n++] = k;
+
+        merged[n] = NULL;
+        strv_sort(merged);
+
+        if (arg_legend) {
+                printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s",
+                       (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION");
+
+                if (arg_show_machine)
+                        puts(" MACHINE");
+                else
+                        putchar('\n');
+        }
+
+        STRV_FOREACH(i, merged) {
+                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+                sd_id128_t mid;
+
+                if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) {
+                        /* Activatable */
+
+                        printf("%-*s", (int) max_i, *i);
+                        printf("          - -               -                (activatable) -                         -         ");
+                        if (arg_show_machine)
+                                puts(" -");
+                        else
+                                putchar('\n');
+                        continue;
+
+                }
+
+                if (!arg_unique && (*i)[0] == ':')
+                        continue;
+
+                if (!arg_acquired && (*i)[0] != ':')
+                        continue;
+
+                printf("%-*s", (int) max_i, *i);
+
+                r = sd_bus_get_name_creds(
+                                bus, *i,
+                                (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) |
+                                SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|
+                                SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION|
+                                SD_BUS_CREDS_DESCRIPTION, &creds);
+                if (r >= 0) {
+                        const char *unique, *session, *unit, *cn;
+                        pid_t pid;
+                        uid_t uid;
+
+                        r = sd_bus_creds_get_pid(creds, &pid);
+                        if (r >= 0) {
+                                const char *comm = NULL;
+
+                                sd_bus_creds_get_comm(creds, &comm);
+
+                                printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
+                        } else
+                                fputs("          - -              ", stdout);
+
+                        r = sd_bus_creds_get_euid(creds, &uid);
+                        if (r >= 0) {
+                                _cleanup_free_ char *u = NULL;
+
+                                u = uid_to_name(uid);
+                                if (!u)
+                                        return log_oom();
+
+                                if (strlen(u) > 16)
+                                        u[16] = 0;
+
+                                printf(" %-16s", u);
+                        } else
+                                fputs(" -               ", stdout);
+
+                        r = sd_bus_creds_get_unique_name(creds, &unique);
+                        if (r >= 0)
+                                printf(" %-13s", unique);
+                        else
+                                fputs(" -            ", stdout);
+
+                        r = sd_bus_creds_get_unit(creds, &unit);
+                        if (r >= 0) {
+                                _cleanup_free_ char *e;
+
+                                e = ellipsize(unit, 25, 100);
+                                if (!e)
+                                        return log_oom();
+
+                                printf(" %-25s", e);
+                        } else
+                                fputs(" -                        ", stdout);
+
+                        r = sd_bus_creds_get_session(creds, &session);
+                        if (r >= 0)
+                                printf(" %-10s", session);
+                        else
+                                fputs(" -         ", stdout);
+
+                        r = sd_bus_creds_get_description(creds, &cn);
+                        if (r >= 0)
+                                printf(" %-19s", cn);
+                        else
+                                fputs(" -                  ", stdout);
+
+                } else
+                        printf("          - -               -                -             -                         -          -                  ");
+
+                if (arg_show_machine) {
+                        r = sd_bus_get_name_machine_id(bus, *i, &mid);
+                        if (r >= 0) {
+                                char m[SD_ID128_STRING_MAX];
+                                printf(" %s\n", sd_id128_to_string(mid, m));
+                        } else
+                                puts(" -");
+                } else
+                        putchar('\n');
+        }
+
+        return 0;
+}
+
+static void print_subtree(const char *prefix, const char *path, char **l) {
+        const char *vertical, *space;
+        char **n;
+
+        /* We assume the list is sorted. Let's first skip over the
+         * entry we are looking at. */
+        for (;;) {
+                if (!*l)
+                        return;
+
+                if (!streq(*l, path))
+                        break;
+
+                l++;
+        }
+
+        vertical = strjoina(prefix, special_glyph(TREE_VERTICAL));
+        space = strjoina(prefix, special_glyph(TREE_SPACE));
+
+        for (;;) {
+                bool has_more = false;
+
+                if (!*l || !path_startswith(*l, path))
+                        break;
+
+                n = l + 1;
+                for (;;) {
+                        if (!*n || !path_startswith(*n, path))
+                                break;
+
+                        if (!path_startswith(*n, *l)) {
+                                has_more = true;
+                                break;
+                        }
+
+                        n++;
+                }
+
+                printf("%s%s%s\n", prefix, special_glyph(has_more ? TREE_BRANCH : TREE_RIGHT), *l);
+
+                print_subtree(has_more ? vertical : space, *l, l);
+                l = n;
+        }
+}
+
+static void print_tree(const char *prefix, char **l) {
+
+        pager_open(arg_no_pager, false);
+
+        prefix = strempty(prefix);
+
+        if (arg_list) {
+                char **i;
+
+                STRV_FOREACH(i, l)
+                        printf("%s%s\n", prefix, *i);
+                return;
+        }
+
+        if (strv_isempty(l)) {
+                printf("No objects discovered.\n");
+                return;
+        }
+
+        if (streq(l[0], "/") && !l[1]) {
+                printf("Only root object discovered.\n");
+                return;
+        }
+
+        print_subtree(prefix, "/", l);
+}
+
+static int on_path(const char *path, void *userdata) {
+        Set *paths = userdata;
+        int r;
+
+        assert(paths);
+
+        r = set_put_strdup(paths, path);
+        if (r < 0)
+                return log_oom();
+
+        return 0;
+}
+
+static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) {
+        static const XMLIntrospectOps ops = {
+                .on_path = on_path,
+        };
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *xml;
+        int r;
+
+        r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
+        if (r < 0) {
+                if (many)
+                        printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r));
+                else
+                        log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
+                return r;
+        }
+
+        r = sd_bus_message_read(reply, "s", &xml);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        return parse_xml_introspect(path, xml, &ops, paths);
+}
+
+static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) {
+        _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
+        _cleanup_free_ char **l = NULL;
+        char *m;
+        int r;
+
+        paths = set_new(&string_hash_ops);
+        if (!paths)
+                return log_oom();
+
+        done = set_new(&string_hash_ops);
+        if (!done)
+                return log_oom();
+
+        failed = set_new(&string_hash_ops);
+        if (!failed)
+                return log_oom();
+
+        m = strdup("/");
+        if (!m)
+                return log_oom();
+
+        r = set_put(paths, m);
+        if (r < 0) {
+                free(m);
+                return log_oom();
+        }
+
+        for (;;) {
+                _cleanup_free_ char *p = NULL;
+                int q;
+
+                p = set_steal_first(paths);
+                if (!p)
+                        break;
+
+                if (set_contains(done, p) ||
+                    set_contains(failed, p))
+                        continue;
+
+                q = find_nodes(bus, service, p, paths, many);
+                if (q < 0) {
+                        if (r >= 0)
+                                r = q;
+
+                        q = set_put(failed, p);
+                } else
+                        q = set_put(done, p);
+
+                if (q < 0)
+                        return log_oom();
+
+                assert(q != 0);
+                p = NULL;
+        }
+
+        pager_open(arg_no_pager, false);
+
+        l = set_get_strv(done);
+        if (!l)
+                return log_oom();
+
+        strv_sort(l);
+        print_tree(prefix, l);
+
+        fflush(stdout);
+
+        return r;
+}
+
+static int tree(sd_bus *bus, char **argv) {
+        char **i;
+        int r = 0;
+
+        if (!arg_unique && !arg_acquired)
+                arg_acquired = true;
+
+        if (strv_length(argv) <= 1) {
+                _cleanup_strv_free_ char **names = NULL;
+                bool not_first = false;
+
+                r = sd_bus_list_names(bus, &names, NULL);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get name list: %m");
+
+                pager_open(arg_no_pager, false);
+
+                STRV_FOREACH(i, names) {
+                        int q;
+
+                        if (!arg_unique && (*i)[0] == ':')
+                                continue;
+
+                        if (!arg_acquired && (*i)[0] == ':')
+                                continue;
+
+                        if (not_first)
+                                printf("\n");
+
+                        printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
+
+                        q = tree_one(bus, *i, NULL, true);
+                        if (q < 0 && r >= 0)
+                                r = q;
+
+                        not_first = true;
+                }
+        } else {
+                STRV_FOREACH(i, argv+1) {
+                        int q;
+
+                        if (i > argv+1)
+                                printf("\n");
+
+                        if (argv[2]) {
+                                pager_open(arg_no_pager, false);
+                                printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
+                        }
+
+                        q = tree_one(bus, *i, NULL, !!argv[2]);
+                        if (q < 0 && r >= 0)
+                                r = q;
+                }
+        }
+
+        return r;
+}
+
+static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
+        int r;
+
+        for (;;) {
+                const char *contents = NULL;
+                char type;
+                union {
+                        uint8_t u8;
+                        uint16_t u16;
+                        int16_t s16;
+                        uint32_t u32;
+                        int32_t s32;
+                        uint64_t u64;
+                        int64_t s64;
+                        double d64;
+                        const char *string;
+                        int i;
+                } basic;
+
+                r = sd_bus_message_peek_type(m, &type, &contents);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return needs_space;
+
+                if (bus_type_is_container(type) > 0) {
+
+                        r = sd_bus_message_enter_container(m, type, contents);
+                        if (r < 0)
+                                return r;
+
+                        if (type == SD_BUS_TYPE_ARRAY) {
+                                unsigned n = 0;
+
+                                /* count array entries */
+                                for (;;) {
+
+                                        r = sd_bus_message_skip(m, contents);
+                                        if (r < 0)
+                                                return r;
+                                        if (r == 0)
+                                                break;
+
+                                        n++;
+                                }
+
+                                r = sd_bus_message_rewind(m, false);
+                                if (r < 0)
+                                        return r;
+
+                                if (needs_space)
+                                        fputc(' ', f);
+
+                                fprintf(f, "%u", n);
+                                needs_space = true;
+
+                        } else if (type == SD_BUS_TYPE_VARIANT) {
+
+                                if (needs_space)
+                                        fputc(' ', f);
+
+                                fprintf(f, "%s", contents);
+                                needs_space = true;
+                        }
+
+                        r = format_cmdline(m, f, needs_space);
+                        if (r < 0)
+                                return r;
+
+                        needs_space = r > 0;
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return r;
+
+                        continue;
+                }
+
+                r = sd_bus_message_read_basic(m, type, &basic);
+                if (r < 0)
+                        return r;
+
+                if (needs_space)
+                        fputc(' ', f);
+
+                switch (type) {
+                case SD_BUS_TYPE_BYTE:
+                        fprintf(f, "%u", basic.u8);
+                        break;
+
+                case SD_BUS_TYPE_BOOLEAN:
+                        fputs(true_false(basic.i), f);
+                        break;
+
+                case SD_BUS_TYPE_INT16:
+                        fprintf(f, "%i", basic.s16);
+                        break;
+
+                case SD_BUS_TYPE_UINT16:
+                        fprintf(f, "%u", basic.u16);
+                        break;
+
+                case SD_BUS_TYPE_INT32:
+                        fprintf(f, "%i", basic.s32);
+                        break;
+
+                case SD_BUS_TYPE_UINT32:
+                        fprintf(f, "%u", basic.u32);
+                        break;
+
+                case SD_BUS_TYPE_INT64:
+                        fprintf(f, "%" PRIi64, basic.s64);
+                        break;
+
+                case SD_BUS_TYPE_UINT64:
+                        fprintf(f, "%" PRIu64, basic.u64);
+                        break;
+
+                case SD_BUS_TYPE_DOUBLE:
+                        fprintf(f, "%g", basic.d64);
+                        break;
+
+                case SD_BUS_TYPE_STRING:
+                case SD_BUS_TYPE_OBJECT_PATH:
+                case SD_BUS_TYPE_SIGNATURE: {
+                        _cleanup_free_ char *b = NULL;
+
+                        b = cescape(basic.string);
+                        if (!b)
+                                return -ENOMEM;
+
+                        fprintf(f, "\"%s\"", b);
+                        break;
+                }
+
+                case SD_BUS_TYPE_UNIX_FD:
+                        fprintf(f, "%i", basic.i);
+                        break;
+
+                default:
+                        assert_not_reached("Unknown basic type.");
+                }
+
+                needs_space = true;
+        }
+}
+
+typedef struct Member {
+        const char *type;
+        char *interface;
+        char *name;
+        char *signature;
+        char *result;
+        char *value;
+        bool writable;
+        uint64_t flags;
+} Member;
+
+static void member_hash_func(const void *p, struct siphash *state) {
+        const Member *m = p;
+        uint64_t arity = 1;
+
+        assert(m);
+        assert(m->type);
+
+        string_hash_func(m->type, state);
+
+        arity += !!m->name + !!m->interface;
+
+        uint64_hash_func(&arity, state);
+
+        if (m->name)
+                string_hash_func(m->name, state);
+
+        if (m->interface)
+                string_hash_func(m->interface, state);
+}
+
+static int member_compare_func(const void *a, const void *b) {
+        const Member *x = a, *y = b;
+        int d;
+
+        assert(x);
+        assert(y);
+        assert(x->type);
+        assert(y->type);
+
+        d = strcmp_ptr(x->interface, y->interface);
+        if (d != 0)
+                return d;
+
+        d = strcmp(x->type, y->type);
+        if (d != 0)
+                return d;
+
+        return strcmp_ptr(x->name, y->name);
+}
+
+static int member_compare_funcp(const void *a, const void *b) {
+        const Member *const * x = (const Member *const *) a, * const *y = (const Member *const *) b;
+
+        return member_compare_func(*x, *y);
+}
+
+static void member_free(Member *m) {
+        if (!m)
+                return;
+
+        free(m->interface);
+        free(m->name);
+        free(m->signature);
+        free(m->result);
+        free(m->value);
+        free(m);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
+
+static void member_set_free(Set *s) {
+        Member *m;
+
+        while ((m = set_steal_first(s)))
+                member_free(m);
+
+        set_free(s);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
+
+static int on_interface(const char *interface, uint64_t flags, void *userdata) {
+        _cleanup_(member_freep) Member *m;
+        Set *members = userdata;
+        int r;
+
+        assert(interface);
+        assert(members);
+
+        m = new0(Member, 1);
+        if (!m)
+                return log_oom();
+
+        m->type = "interface";
+        m->flags = flags;
+
+        r = free_and_strdup(&m->interface, interface);
+        if (r < 0)
+                return log_oom();
+
+        r = set_put(members, m);
+        if (r <= 0) {
+                log_error("Duplicate interface");
+                return -EINVAL;
+        }
+
+        m = NULL;
+        return 0;
+}
+
+static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) {
+        _cleanup_(member_freep) Member *m;
+        Set *members = userdata;
+        int r;
+
+        assert(interface);
+        assert(name);
+
+        m = new0(Member, 1);
+        if (!m)
+                return log_oom();
+
+        m->type = "method";
+        m->flags = flags;
+
+        r = free_and_strdup(&m->interface, interface);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->name, name);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->signature, signature);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->result, result);
+        if (r < 0)
+                return log_oom();
+
+        r = set_put(members, m);
+        if (r <= 0) {
+                log_error("Duplicate method");
+                return -EINVAL;
+        }
+
+        m = NULL;
+        return 0;
+}
+
+static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) {
+        _cleanup_(member_freep) Member *m;
+        Set *members = userdata;
+        int r;
+
+        assert(interface);
+        assert(name);
+
+        m = new0(Member, 1);
+        if (!m)
+                return log_oom();
+
+        m->type = "signal";
+        m->flags = flags;
+
+        r = free_and_strdup(&m->interface, interface);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->name, name);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->signature, signature);
+        if (r < 0)
+                return log_oom();
+
+        r = set_put(members, m);
+        if (r <= 0) {
+                log_error("Duplicate signal");
+                return -EINVAL;
+        }
+
+        m = NULL;
+        return 0;
+}
+
+static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) {
+        _cleanup_(member_freep) Member *m;
+        Set *members = userdata;
+        int r;
+
+        assert(interface);
+        assert(name);
+
+        m = new0(Member, 1);
+        if (!m)
+                return log_oom();
+
+        m->type = "property";
+        m->flags = flags;
+        m->writable = writable;
+
+        r = free_and_strdup(&m->interface, interface);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->name, name);
+        if (r < 0)
+                return log_oom();
+
+        r = free_and_strdup(&m->signature, signature);
+        if (r < 0)
+                return log_oom();
+
+        r = set_put(members, m);
+        if (r <= 0) {
+                log_error("Duplicate property");
+                return -EINVAL;
+        }
+
+        m = NULL;
+        return 0;
+}
+
+static const char *strdash(const char *x) {
+        return isempty(x) ? "-" : x;
+}
+
+static int introspect(sd_bus *bus, char **argv) {
+        static const struct hash_ops member_hash_ops = {
+                .hash = member_hash_func,
+                .compare = member_compare_func,
+        };
+
+        static const XMLIntrospectOps ops = {
+                .on_interface = on_interface,
+                .on_method = on_method,
+                .on_signal = on_signal,
+                .on_property = on_property,
+        };
+
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(member_set_freep) Set *members = NULL;
+        Iterator i;
+        Member *m;
+        const char *xml;
+        int r;
+        unsigned name_width,  type_width, signature_width, result_width;
+        Member **sorted = NULL;
+        unsigned k = 0, j, n_args;
+
+        n_args = strv_length(argv);
+        if (n_args < 3) {
+                log_error("Requires service and object path argument.");
+                return -EINVAL;
+        }
+
+        if (n_args > 4) {
+                log_error("Too many arguments.");
+                return -EINVAL;
+        }
+
+        members = set_new(&member_hash_ops);
+        if (!members)
+                return log_oom();
+
+        r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
+        if (r < 0) {
+                log_error("Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r));
+                return r;
+        }
+
+        r = sd_bus_message_read(reply, "s", &xml);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        /* First, get list of all properties */
+        r = parse_xml_introspect(argv[2], xml, &ops, members);
+        if (r < 0)
+                return r;
+
+        /* Second, find the current values for them */
+        SET_FOREACH(m, members, i) {
+
+                if (!streq(m->type, "property"))
+                        continue;
+
+                if (m->value)
+                        continue;
+
+                if (argv[3] && !streq(argv[3], m->interface))
+                        continue;
+
+                r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface);
+                if (r < 0) {
+                        log_error("%s", bus_error_message(&error, r));
+                        return r;
+                }
+
+                r = sd_bus_message_enter_container(reply, 'a', "{sv}");
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                for (;;) {
+                        Member *z;
+                        _cleanup_free_ char *buf = NULL;
+                        _cleanup_fclose_ FILE *mf = NULL;
+                        size_t sz = 0;
+                        const char *name;
+
+                        r = sd_bus_message_enter_container(reply, 'e', "sv");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (r == 0)
+                                break;
+
+                        r = sd_bus_message_read(reply, "s", &name);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_enter_container(reply, 'v', NULL);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        mf = open_memstream(&buf, &sz);
+                        if (!mf)
+                                return log_oom();
+
+                        r = format_cmdline(reply, mf, false);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        fclose(mf);
+                        mf = NULL;
+
+                        z = set_get(members, &((Member) {
+                                                .type = "property",
+                                                .interface = m->interface,
+                                                .name = (char*) name }));
+                        if (z) {
+                                free(z->value);
+                                z->value = buf;
+                                buf = NULL;
+                        }
+
+                        r = sd_bus_message_exit_container(reply);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_exit_container(reply);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+                }
+
+                r = sd_bus_message_exit_container(reply);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+        }
+
+        pager_open(arg_no_pager, false);
+
+        name_width = strlen("NAME");
+        type_width = strlen("TYPE");
+        signature_width = strlen("SIGNATURE");
+        result_width = strlen("RESULT/VALUE");
+
+        sorted = newa(Member*, set_size(members));
+
+        SET_FOREACH(m, members, i) {
+
+                if (argv[3] && !streq(argv[3], m->interface))
+                        continue;
+
+                if (m->interface)
+                        name_width = MAX(name_width, strlen(m->interface));
+                if (m->name)
+                        name_width = MAX(name_width, strlen(m->name) + 1);
+                if (m->type)
+                        type_width = MAX(type_width, strlen(m->type));
+                if (m->signature)
+                        signature_width = MAX(signature_width, strlen(m->signature));
+                if (m->result)
+                        result_width = MAX(result_width, strlen(m->result));
+                if (m->value)
+                        result_width = MAX(result_width, strlen(m->value));
+
+                sorted[k++] = m;
+        }
+
+        if (result_width > 40)
+                result_width = 40;
+
+        qsort(sorted, k, sizeof(Member*), member_compare_funcp);
+
+        if (arg_legend) {
+                printf("%-*s %-*s %-*s %-*s %s\n",
+                       (int) name_width, "NAME",
+                       (int) type_width, "TYPE",
+                       (int) signature_width, "SIGNATURE",
+                       (int) result_width, "RESULT/VALUE",
+                       "FLAGS");
+        }
+
+        for (j = 0; j < k; j++) {
+                _cleanup_free_ char *ellipsized = NULL;
+                const char *rv;
+                bool is_interface;
+
+                m = sorted[j];
+
+                if (argv[3] && !streq(argv[3], m->interface))
+                        continue;
+
+                is_interface = streq(m->type, "interface");
+
+                if (argv[3] && is_interface)
+                        continue;
+
+                if (m->value) {
+                        ellipsized = ellipsize(m->value, result_width, 100);
+                        if (!ellipsized)
+                                return log_oom();
+
+                        rv = ellipsized;
+                } else
+                        rv = strdash(m->result);
+
+                printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
+                       is_interface ? ansi_highlight() : "",
+                       is_interface ? "" : ".",
+                       - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
+                       is_interface ? ansi_normal() : "",
+                       (int) type_width, strdash(m->type),
+                       (int) signature_width, strdash(m->signature),
+                       (int) result_width, rv,
+                       (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"),
+                       (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "",
+                       (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "",
+                       (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "",
+                       (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "",
+                       m->writable ? " writable" : "");
+        }
+
+        return 0;
+}
+
+static int message_dump(sd_bus_message *m, FILE *f) {
+        return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER);
+}
+
+static int message_pcap(sd_bus_message *m, FILE *f) {
+        return bus_message_pcap_frame(m, arg_snaplen, f);
+}
+
+static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        char **i;
+        uint32_t flags = 0;
+        const char *unique_name;
+        bool is_monitor = false;
+        int r;
+
+        /* upgrade connection; it's not used for anything else after this call */
+        r = sd_bus_message_new_method_call(bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_open_container(message, 'a', "s");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        STRV_FOREACH(i, argv+1) {
+                _cleanup_free_ char *m = NULL;
+
+                if (!service_name_is_valid(*i)) {
+                        log_error("Invalid service name '%s'", *i);
+                        return -EINVAL;
+                }
+
+                m = strjoin("sender='", *i, "'");
+                if (!m)
+                        return log_oom();
+
+                r = sd_bus_message_append_basic(message, 's', m);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                free(m);
+                m = strjoin("destination='", *i, "'");
+                if (!m)
+                        return log_oom();
+
+                r = sd_bus_message_append_basic(message, 's', m);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        STRV_FOREACH(i, arg_matches) {
+                r = sd_bus_message_append_basic(message, 's', *i);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        r = sd_bus_message_close_container(message);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append_basic(message, 'u', &flags);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_call(bus, message, arg_timeout, &error, NULL);
+        if (r < 0) {
+                log_error("%s", bus_error_message(&error, r));
+                return r;
+        }
+
+        r = sd_bus_get_unique_name(bus, &unique_name);
+        if (r < 0)
+                return log_error_errno(r, "Failed to get unique name: %m");
+
+        log_info("Monitoring bus message stream.");
+
+        for (;;) {
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+
+                r = sd_bus_process(bus, &m);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to process bus: %m");
+
+                if (!is_monitor) {
+                        const char *name;
+
+                        /* wait until we lose our unique name */
+                        if (sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameLost") <= 0)
+                                continue;
+
+                        r = sd_bus_message_read(m, "s", &name);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to read lost name: %m");
+
+                        if (streq(name, unique_name))
+                                is_monitor = true;
+
+                        continue;
+                }
+
+                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.");
+                                return 0;
+                        }
+
+                        continue;
+                }
+
+                if (r > 0)
+                        continue;
+
+                r = sd_bus_wait(bus, (uint64_t) -1);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to wait for bus: %m");
+        }
+}
+
+static int capture(sd_bus *bus, char *argv[]) {
+        int r;
+
+        if (isatty(fileno(stdout)) > 0) {
+                log_error("Refusing to write message data to console, please redirect output to a file.");
+                return -EINVAL;
+        }
+
+        bus_pcap_header(arg_snaplen, stdout);
+
+        r = monitor(bus, argv, message_pcap);
+        if (r < 0)
+                return r;
+
+        if (ferror(stdout)) {
+                log_error("Couldn't write capture file.");
+                return -EIO;
+        }
+
+        return r;
+}
+
+static int status(sd_bus *bus, char *argv[]) {
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+        pid_t pid;
+        int r;
+
+        assert(bus);
+
+        if (strv_length(argv) > 2) {
+                log_error("Expects no or one argument.");
+                return -EINVAL;
+        }
+
+        if (argv[1]) {
+                r = parse_pid(argv[1], &pid);
+                if (r < 0)
+                        r = sd_bus_get_name_creds(
+                                        bus,
+                                        argv[1],
+                                        (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL,
+                                        &creds);
+                else
+                        r = sd_bus_creds_new_from_pid(
+                                        &creds,
+                                        pid,
+                                        _SD_BUS_CREDS_ALL);
+        } else {
+                const char *scope, *address;
+                sd_id128_t bus_id;
+
+                r = sd_bus_get_address(bus, &address);
+                if (r >= 0)
+                        printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_normal());
+
+                r = sd_bus_get_scope(bus, &scope);
+                if (r >= 0)
+                        printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_normal());
+
+                r = sd_bus_get_bus_id(bus, &bus_id);
+                if (r >= 0)
+                        printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal());
+
+                r = sd_bus_get_owner_creds(
+                                bus,
+                                (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL,
+                                &creds);
+        }
+
+        if (r < 0)
+                return log_error_errno(r, "Failed to get credentials: %m");
+
+        bus_creds_dump(creds, NULL, false);
+        return 0;
+}
+
+static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) {
+        char **p;
+        int r;
+
+        assert(m);
+        assert(signature);
+        assert(x);
+
+        p = *x;
+
+        for (;;) {
+                const char *v;
+                char t;
+
+                t = *signature;
+                v = *p;
+
+                if (t == 0)
+                        break;
+                if (!v) {
+                        log_error("Too few parameters for signature.");
+                        return -EINVAL;
+                }
+
+                signature++;
+                p++;
+
+                switch (t) {
+
+                case SD_BUS_TYPE_BOOLEAN:
+
+                        r = parse_boolean(v);
+                        if (r < 0) {
+                                log_error("Failed to parse as boolean: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &r);
+                        break;
+
+                case SD_BUS_TYPE_BYTE: {
+                        uint8_t z;
+
+                        r = safe_atou8(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as byte (unsigned 8bit integer): %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_INT16: {
+                        int16_t z;
+
+                        r = safe_atoi16(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as signed 16bit integer: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_UINT16: {
+                        uint16_t z;
+
+                        r = safe_atou16(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as unsigned 16bit integer: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_INT32: {
+                        int32_t z;
+
+                        r = safe_atoi32(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as signed 32bit integer: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_UINT32: {
+                        uint32_t z;
+
+                        r = safe_atou32(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as unsigned 32bit integer: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_INT64: {
+                        int64_t z;
+
+                        r = safe_atoi64(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as signed 64bit integer: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_UINT64: {
+                        uint64_t z;
+
+                        r = safe_atou64(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as unsigned 64bit integer: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+
+                case SD_BUS_TYPE_DOUBLE: {
+                        double z;
+
+                        r = safe_atod(v, &z);
+                        if (r < 0) {
+                                log_error("Failed to parse as double precision floating point: %s", v);
+                                return r;
+                        }
+
+                        r = sd_bus_message_append_basic(m, t, &z);
+                        break;
+                }
+
+                case SD_BUS_TYPE_STRING:
+                case SD_BUS_TYPE_OBJECT_PATH:
+                case SD_BUS_TYPE_SIGNATURE:
+
+                        r = sd_bus_message_append_basic(m, t, v);
+                        break;
+
+                case SD_BUS_TYPE_ARRAY: {
+                        uint32_t n;
+                        size_t k;
+
+                        r = safe_atou32(v, &n);
+                        if (r < 0) {
+                                log_error("Failed to parse number of array entries: %s", v);
+                                return r;
+                        }
+
+                        r = signature_element_length(signature, &k);
+                        if (r < 0) {
+                                log_error("Invalid array signature.");
+                                return r;
+                        }
+
+                        {
+                                unsigned i;
+                                char s[k + 1];
+                                memcpy(s, signature, k);
+                                s[k] = 0;
+
+                                r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
+                                if (r < 0)
+                                        return bus_log_create_error(r);
+
+                                for (i = 0; i < n; i++) {
+                                        r = message_append_cmdline(m, s, &p);
+                                        if (r < 0)
+                                                return r;
+                                }
+                        }
+
+                        signature += k;
+
+                        r = sd_bus_message_close_container(m);
+                        break;
+                }
+
+                case SD_BUS_TYPE_VARIANT:
+                        r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v);
+                        if (r < 0)
+                                return bus_log_create_error(r);
+
+                        r = message_append_cmdline(m, v, &p);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_close_container(m);
+                        break;
+
+                case SD_BUS_TYPE_STRUCT_BEGIN:
+                case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
+                        size_t k;
+
+                        signature--;
+                        p--;
+
+                        r = signature_element_length(signature, &k);
+                        if (r < 0) {
+                                log_error("Invalid struct/dict entry signature.");
+                                return r;
+                        }
+
+                        {
+                                char s[k-1];
+                                memcpy(s, signature + 1, k - 2);
+                                s[k - 2] = 0;
+
+                                r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
+                                if (r < 0)
+                                        return bus_log_create_error(r);
+
+                                r = message_append_cmdline(m, s, &p);
+                                if (r < 0)
+                                        return r;
+                        }
+
+                        signature += k;
+
+                        r = sd_bus_message_close_container(m);
+                        break;
+                }
+
+                case SD_BUS_TYPE_UNIX_FD:
+                        log_error("UNIX file descriptor not supported as type.");
+                        return -EINVAL;
+
+                default:
+                        log_error("Unknown signature type %c.", t);
+                        return -EINVAL;
+                }
+
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        *x = p;
+        return 0;
+}
+
+static int call(sd_bus *bus, char *argv[]) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+        int r;
+
+        assert(bus);
+
+        if (strv_length(argv) < 5) {
+                log_error("Expects at least four arguments.");
+                return -EINVAL;
+        }
+
+        r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_set_expect_reply(m, arg_expect_reply);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_set_auto_start(m, arg_auto_start);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_set_allow_interactive_authorization(m, arg_allow_interactive_authorization);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (!isempty(argv[5])) {
+                char **p;
+
+                p = argv+6;
+
+                r = message_append_cmdline(m, argv[5], &p);
+                if (r < 0)
+                        return r;
+
+                if (*p) {
+                        log_error("Too many parameters for signature.");
+                        return -EINVAL;
+                }
+        }
+
+        if (!arg_expect_reply) {
+                r = sd_bus_send(bus, m, NULL);
+                if (r < 0) {
+                        log_error("Failed to send message.");
+                        return r;
+                }
+
+                return 0;
+        }
+
+        r = sd_bus_call(bus, m, arg_timeout, &error, &reply);
+        if (r < 0) {
+                log_error("%s", bus_error_message(&error, r));
+                return r;
+        }
+
+        r = sd_bus_message_is_empty(reply);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        if (r == 0 && !arg_quiet) {
+
+                if (arg_verbose) {
+                        pager_open(arg_no_pager, false);
+
+                        r = bus_message_dump(reply, stdout, 0);
+                        if (r < 0)
+                                return r;
+                } else {
+
+                        fputs(sd_bus_message_get_signature(reply, true), stdout);
+                        fputc(' ', stdout);
+
+                        r = format_cmdline(reply, stdout, false);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        fputc('\n', stdout);
+                }
+        }
+
+        return 0;
+}
+
+static int get_property(sd_bus *bus, char *argv[]) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        unsigned n;
+        char **i;
+        int r;
+
+        assert(bus);
+
+        n = strv_length(argv);
+        if (n < 5) {
+                log_error("Expects at least four arguments.");
+                return -EINVAL;
+        }
+
+        STRV_FOREACH(i, argv + 4) {
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+                const char *contents = NULL;
+                char type;
+
+                r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i);
+                if (r < 0) {
+                        log_error("%s", bus_error_message(&error, r));
+                        return r;
+                }
+
+                r = sd_bus_message_peek_type(reply, &type, &contents);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                r = sd_bus_message_enter_container(reply, 'v', contents);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                if (arg_verbose)  {
+                        pager_open(arg_no_pager, false);
+
+                        r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
+                        if (r < 0)
+                                return r;
+                } else {
+                        fputs(contents, stdout);
+                        fputc(' ', stdout);
+
+                        r = format_cmdline(reply, stdout, false);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        fputc('\n', stdout);
+                }
+
+                r = sd_bus_message_exit_container(reply);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+        }
+
+        return 0;
+}
+
+static int set_property(sd_bus *bus, char *argv[]) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        unsigned n;
+        char **p;
+        int r;
+
+        assert(bus);
+
+        n = strv_length(argv);
+        if (n < 6) {
+                log_error("Expects at least five arguments.");
+                return -EINVAL;
+        }
+
+        r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(m, "ss", argv[3], argv[4]);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_open_container(m, 'v', argv[5]);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        p = argv+6;
+        r = message_append_cmdline(m, argv[5], &p);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_close_container(m);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (*p) {
+                log_error("Too many parameters for signature.");
+                return -EINVAL;
+        }
+
+        r = sd_bus_call(bus, m, arg_timeout, &error, NULL);
+        if (r < 0) {
+                log_error("%s", bus_error_message(&error, r));
+                return r;
+        }
+
+        return 0;
+}
+
+static int help(void) {
+        printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+               "Introspect the bus.\n\n"
+               "  -h --help               Show this help\n"
+               "     --version            Show package version\n"
+               "     --no-pager           Do not pipe output into a pager\n"
+               "     --no-legend          Do not show the headers and footers\n"
+               "     --system             Connect to system bus\n"
+               "     --user               Connect to user bus\n"
+               "  -H --host=[USER@]HOST   Operate on remote host\n"
+               "  -M --machine=CONTAINER  Operate on local container\n"
+               "     --address=ADDRESS    Connect to bus specified by address\n"
+               "     --show-machine       Show machine ID column in list\n"
+               "     --unique             Only show unique names\n"
+               "     --acquired           Only show acquired names\n"
+               "     --activatable        Only show activatable names\n"
+               "     --match=MATCH        Only show matching messages\n"
+               "     --size=SIZE          Maximum length of captured packet\n"
+               "     --list               Don't show tree, but simple object path list\n"
+               "     --quiet              Don't show method call reply\n"
+               "     --verbose            Show result values in long format\n"
+               "     --expect-reply=BOOL  Expect a method call reply\n"
+               "     --auto-start=BOOL    Auto-start destination service\n"
+               "     --allow-interactive-authorization=BOOL\n"
+               "                          Allow interactive authorization for operation\n"
+               "     --timeout=SECS       Maximum time to wait for method call completion\n"
+               "     --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n"
+               "Commands:\n"
+               "  list                    List bus names\n"
+               "  status [SERVICE]        Show bus service, process or bus owner credentials\n"
+               "  monitor [SERVICE...]    Show bus traffic\n"
+               "  capture [SERVICE...]    Capture bus traffic as pcap\n"
+               "  tree [SERVICE...]       Show object tree of service\n"
+               "  introspect SERVICE OBJECT [INTERFACE]\n"
+               "  call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
+               "                          Call a method\n"
+               "  get-property SERVICE OBJECT INTERFACE PROPERTY...\n"
+               "                          Get property value\n"
+               "  set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n"
+               "                          Set property value\n"
+               "  help                    Show this help\n"
+               , program_invocation_short_name);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_VERSION = 0x100,
+                ARG_NO_PAGER,
+                ARG_NO_LEGEND,
+                ARG_SYSTEM,
+                ARG_USER,
+                ARG_ADDRESS,
+                ARG_MATCH,
+                ARG_SHOW_MACHINE,
+                ARG_UNIQUE,
+                ARG_ACQUIRED,
+                ARG_ACTIVATABLE,
+                ARG_SIZE,
+                ARG_LIST,
+                ARG_VERBOSE,
+                ARG_EXPECT_REPLY,
+                ARG_AUTO_START,
+                ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
+                ARG_TIMEOUT,
+                ARG_AUGMENT_CREDS,
+        };
+
+        static const struct option options[] = {
+                { "help",         no_argument,       NULL, 'h'              },
+                { "version",      no_argument,       NULL, ARG_VERSION      },
+                { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
+                { "no-legend",    no_argument,       NULL, ARG_NO_LEGEND    },
+                { "system",       no_argument,       NULL, ARG_SYSTEM       },
+                { "user",         no_argument,       NULL, ARG_USER         },
+                { "address",      required_argument, NULL, ARG_ADDRESS      },
+                { "show-machine", no_argument,       NULL, ARG_SHOW_MACHINE },
+                { "unique",       no_argument,       NULL, ARG_UNIQUE       },
+                { "acquired",     no_argument,       NULL, ARG_ACQUIRED     },
+                { "activatable",  no_argument,       NULL, ARG_ACTIVATABLE  },
+                { "match",        required_argument, NULL, ARG_MATCH        },
+                { "host",         required_argument, NULL, 'H'              },
+                { "machine",      required_argument, NULL, 'M'              },
+                { "size",         required_argument, NULL, ARG_SIZE         },
+                { "list",         no_argument,       NULL, ARG_LIST         },
+                { "quiet",        no_argument,       NULL, 'q'              },
+                { "verbose",      no_argument,       NULL, ARG_VERBOSE      },
+                { "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY },
+                { "auto-start",   required_argument, NULL, ARG_AUTO_START   },
+                { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
+                { "timeout",      required_argument, NULL, ARG_TIMEOUT      },
+                { "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS},
+                {},
+        };
+
+        int c, r;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0)
+
+                switch (c) {
+
+                case 'h':
+                        return help();
+
+                case ARG_VERSION:
+                        return version();
+
+                case ARG_NO_PAGER:
+                        arg_no_pager = true;
+                        break;
+
+                case ARG_NO_LEGEND:
+                        arg_legend = false;
+                        break;
+
+                case ARG_USER:
+                        arg_user = true;
+                        break;
+
+                case ARG_SYSTEM:
+                        arg_user = false;
+                        break;
+
+                case ARG_ADDRESS:
+                        arg_address = optarg;
+                        break;
+
+                case ARG_SHOW_MACHINE:
+                        arg_show_machine = true;
+                        break;
+
+                case ARG_UNIQUE:
+                        arg_unique = true;
+                        break;
+
+                case ARG_ACQUIRED:
+                        arg_acquired = true;
+                        break;
+
+                case ARG_ACTIVATABLE:
+                        arg_activatable = true;
+                        break;
+
+                case ARG_MATCH:
+                        if (strv_extend(&arg_matches, optarg) < 0)
+                                return log_oom();
+                        break;
+
+                case ARG_SIZE: {
+                        uint64_t sz;
+
+                        r = parse_size(optarg, 1024, &sz);
+                        if (r < 0) {
+                                log_error("Failed to parse size: %s", optarg);
+                                return r;
+                        }
+
+                        if ((uint64_t) (size_t) sz !=  sz) {
+                                log_error("Size out of range.");
+                                return -E2BIG;
+                        }
+
+                        arg_snaplen = (size_t) sz;
+                        break;
+                }
+
+                case ARG_LIST:
+                        arg_list = true;
+                        break;
+
+                case 'H':
+                        arg_transport = BUS_TRANSPORT_REMOTE;
+                        arg_host = optarg;
+                        break;
+
+                case 'M':
+                        arg_transport = BUS_TRANSPORT_MACHINE;
+                        arg_host = optarg;
+                        break;
+
+                case 'q':
+                        arg_quiet = true;
+                        break;
+
+                case ARG_VERBOSE:
+                        arg_verbose = true;
+                        break;
+
+                case ARG_EXPECT_REPLY:
+                        r = parse_boolean(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse --expect-reply= parameter.");
+                                return r;
+                        }
+
+                        arg_expect_reply = !!r;
+                        break;
+
+
+                case ARG_AUTO_START:
+                        r = parse_boolean(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse --auto-start= parameter.");
+                                return r;
+                        }
+
+                        arg_auto_start = !!r;
+                        break;
+
+
+                case ARG_ALLOW_INTERACTIVE_AUTHORIZATION:
+                        r = parse_boolean(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse --allow-interactive-authorization= parameter.");
+                                return r;
+                        }
+
+                        arg_allow_interactive_authorization = !!r;
+                        break;
+
+                case ARG_TIMEOUT:
+                        r = parse_sec(optarg, &arg_timeout);
+                        if (r < 0) {
+                                log_error("Failed to parse --timeout= parameter.");
+                                return r;
+                        }
+
+                        break;
+
+                case ARG_AUGMENT_CREDS:
+                        r = parse_boolean(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse --augment-creds= parameter.");
+                                return r;
+                        }
+
+                        arg_augment_creds = !!r;
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached("Unhandled option");
+                }
+
+        return 1;
+}
+
+static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
+        assert(bus);
+
+        if (optind >= argc ||
+            streq(argv[optind], "list"))
+                return list_bus_names(bus, argv + optind);
+
+        if (streq(argv[optind], "monitor"))
+                return monitor(bus, argv + optind, message_dump);
+
+        if (streq(argv[optind], "capture"))
+                return capture(bus, argv + optind);
+
+        if (streq(argv[optind], "status"))
+                return status(bus, argv + optind);
+
+        if (streq(argv[optind], "tree"))
+                return tree(bus, argv + optind);
+
+        if (streq(argv[optind], "introspect"))
+                return introspect(bus, argv + optind);
+
+        if (streq(argv[optind], "call"))
+                return call(bus, argv + optind);
+
+        if (streq(argv[optind], "get-property"))
+                return get_property(bus, argv + optind);
+
+        if (streq(argv[optind], "set-property"))
+                return set_property(bus, argv + optind);
+
+        if (streq(argv[optind], "help"))
+                return help();
+
+        log_error("Unknown command '%s'", argv[optind]);
+        return -EINVAL;
+}
+
+int main(int argc, char *argv[]) {
+        sd_bus *bus = NULL;
+        int r;
+
+        log_parse_environment();
+        log_open();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
+        r = sd_bus_new(&bus);
+        if (r < 0) {
+                log_error_errno(r, "Failed to allocate bus: %m");
+                goto finish;
+        }
+
+        if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) {
+
+                r = sd_bus_set_monitor(bus, true);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to set monitor mode: %m");
+                        goto finish;
+                }
+
+                r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to enable credentials: %m");
+                        goto finish;
+                }
+
+                r = sd_bus_negotiate_timestamp(bus, true);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to enable timestamps: %m");
+                        goto finish;
+                }
+
+                r = sd_bus_negotiate_fds(bus, true);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to enable fds: %m");
+                        goto finish;
+                }
+        }
+
+        r = sd_bus_set_bus_client(bus, true);
+        if (r < 0) {
+                log_error_errno(r, "Failed to set bus client: %m");
+                goto finish;
+        }
+
+        if (arg_address)
+                r = sd_bus_set_address(bus, arg_address);
+        else {
+                switch (arg_transport) {
+
+                case BUS_TRANSPORT_LOCAL:
+                        if (arg_user) {
+                                bus->is_user = true;
+                                r = bus_set_address_user(bus);
+                        } else {
+                                bus->is_system = true;
+                                r = bus_set_address_system(bus);
+                        }
+                        break;
+
+                case BUS_TRANSPORT_REMOTE:
+                        r = bus_set_address_system_remote(bus, arg_host);
+                        break;
+
+                case BUS_TRANSPORT_MACHINE:
+                        r = bus_set_address_system_machine(bus, arg_host);
+                        break;
+
+                default:
+                        assert_not_reached("Hmm, unknown transport type.");
+                }
+        }
+        if (r < 0) {
+                log_error_errno(r, "Failed to set address: %m");
+                goto finish;
+        }
+
+        r = sd_bus_start(bus);
+        if (r < 0) {
+                log_error_errno(r, "Failed to connect to bus: %m");
+                goto finish;
+        }
+
+        r = busctl_main(bus, argc, argv);
+
+finish:
+        sd_bus_flush_close_unref(bus);
+        pager_close();
+
+        strv_free(arg_matches);
+
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
index a1c0f48c8906c69aee2ae9182816376b027bc8d9..7ebb02fa8ce1694adb409db06867402992afd26d 100644 (file)
@@ -75,6 +75,7 @@ static usec_t arg_delay = 1*USEC_PER_SEC;
 static char* arg_machine = NULL;
 static char* arg_root = NULL;
 static bool arg_recursive = true;
+static bool arg_recursive_unset = false;
 
 static enum {
         COUNT_PIDS,
@@ -118,7 +119,7 @@ static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64
         if (!is_valid)
                 return "-";
         if (arg_raw) {
-                snprintf(buf, l, "%jd", t);
+                snprintf(buf, l, "%" PRIu64, t);
                 return buf;
         }
         return format_bytes(buf, l, t);
@@ -732,7 +733,6 @@ static int parse_argv(int argc, char *argv[]) {
                 {}
         };
 
-        bool recursive_unset = false;
         int c, r;
 
         assert(argc >= 1);
@@ -852,7 +852,7 @@ static int parse_argv(int argc, char *argv[]) {
                         }
 
                         arg_recursive = r;
-                        recursive_unset = r == 0;
+                        arg_recursive_unset = r == 0;
                         break;
 
                 case 'M':
@@ -873,11 +873,6 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
-        if (recursive_unset && arg_count == COUNT_PIDS) {
-                log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
-                return -EINVAL;
-        }
-
         return 1;
 }
 
@@ -902,6 +897,10 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
         r = cg_mask_supported(&mask);
         if (r < 0) {
                 log_error_errno(r, "Failed to determine supported controllers: %m");
@@ -910,9 +909,10 @@ int main(int argc, char *argv[]) {
 
         arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES;
 
-        r = parse_argv(argc, argv);
-        if (r <= 0)
-                goto finish;
+        if (arg_recursive_unset && arg_count == COUNT_PIDS) {
+                log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
+                return -EINVAL;
+        }
 
         r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root);
         if (r < 0) {
index 76afe3fe15ad8aefa39bb9909172b6964e22abc7..a91906b626de037b5d33833673c9be91ff0eb17b 100644 (file)
@@ -27,6 +27,7 @@
 #include <libaudit.h>
 #include <stdbool.h>
 
+#include "capability-util.h"
 #include "fd-util.h"
 #include "log.h"
 #include "util.h"
@@ -37,6 +38,13 @@ static int audit_fd;
 int get_audit_fd(void) {
 
         if (!initialized) {
+                if (have_effective_cap(CAP_AUDIT_WRITE) == 0) {
+                        audit_fd = -EPERM;
+                        initialized = true;
+
+                        return audit_fd;
+                }
+
                 audit_fd = audit_open();
 
                 if (audit_fd < 0) {
index 99e804762069afaba4444e2c25cae28bebe303cb..0f72854ceb94c5e304be61fe80ccd543e4dad6c4 100644 (file)
@@ -415,8 +415,11 @@ static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) {
         init_autofs_dev_ioctl(&param);
         param.ioctlfd = ioctl_fd;
 
-        /* Convert to seconds, rounding up. */
-        param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC;
+        if (usec == USEC_INFINITY)
+                param.timeout.timeout = 0;
+        else
+                /* Convert to seconds, rounding up. */
+                param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC;
 
         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
                 return -errno;
@@ -471,10 +474,10 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) {
         while ((token = PTR_TO_UINT(set_steal_first(tokens)))) {
                 int k;
 
-                /* Autofs fun fact II:
+                /* Autofs fun fact:
                  *
-                 * if you pass a positive status code here, the kernel will
-                 * freeze! Yay! */
+                 * if you pass a positive status code here, kernels
+                 * prior to 4.12 will freeze! Yay! */
 
                 k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
                                       ioctl_fd,
@@ -616,12 +619,6 @@ static void automount_enter_waiting(Automount *a) {
         if (r < 0)
                 goto fail;
 
-        /* Autofs fun fact:
-         *
-         * Unless we close the ioctl fd here, for some weird reason
-         * the direct mount will not receive events from the
-         * kernel. */
-
         r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
         if (r < 0)
                 goto fail;
@@ -742,8 +739,9 @@ static void automount_stop_expire(Automount *a) {
         (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
 }
 
-static void automount_enter_runnning(Automount *a) {
+static void automount_enter_running(Automount *a) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *trigger;
         struct stat st;
         int r;
 
@@ -772,22 +770,24 @@ static void automount_enter_runnning(Automount *a) {
                 goto fail;
         }
 
-        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
+        /* The mount unit may have been explicitly started before we got the
+         * autofs request. Ack it to unblock anything waiting on the mount point. */
+        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) {
                 log_unit_info(UNIT(a), "Automount point already active?");
-        else {
-                Unit *trigger;
+                automount_send_ready(a, a->tokens, 0);
+                return;
+        }
 
-                trigger = UNIT_TRIGGER(UNIT(a));
-                if (!trigger) {
-                        log_unit_error(UNIT(a), "Unit to trigger vanished.");
-                        goto fail;
-                }
+        trigger = UNIT_TRIGGER(UNIT(a));
+        if (!trigger) {
+                log_unit_error(UNIT(a), "Unit to trigger vanished.");
+                goto fail;
+        }
 
-                r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
-                if (r < 0) {
-                        log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
-                        goto fail;
-                }
+        r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
+        if (r < 0) {
+                log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
+                goto fail;
         }
 
         automount_set_state(a, AUTOMOUNT_RUNNING);
@@ -970,7 +970,6 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         union autofs_v5_packet_union packet;
         Automount *a = AUTOMOUNT(userdata);
-        struct stat st;
         Unit *trigger;
         int r;
 
@@ -1012,7 +1011,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
                         goto fail;
                 }
 
-                automount_enter_runnning(a);
+                automount_enter_running(a);
                 break;
 
         case autofs_ptype_expire_direct:
@@ -1032,18 +1031,6 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
                         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;
-                }
-
                 trigger = UNIT_TRIGGER(UNIT(a));
                 if (!trigger) {
                         log_unit_error(UNIT(a), "Unit to trigger vanished.");
index 88b758eecbe086fb5ae97b07353224d86aca52f9..955f6f88d86c07b86370a5ad02bfe50eefd6e0fd 100644 (file)
@@ -764,7 +764,7 @@ static int busname_peek_message(BusName *n) {
         struct kdbus_item *d;
         struct kdbus_msg *k;
         size_t start, ps, sz, delta;
-        void *p = NULL;
+        void *p = MAP_FAILED;
         pid_t pid = 0;
         int r;
 
@@ -825,7 +825,7 @@ static int busname_peek_message(BusName *n) {
         r = 0;
 
 finish:
-        if (p)
+        if (p != MAP_FAILED)
                 (void) munmap(p, sz);
 
         cmd_free.offset = cmd_recv.msg.offset;
index 774b832a63c057fdd73a3b4b461bf2454c0818ba..71f307fb6cac8248b7f16b8507bfffa5e9a64459 100644 (file)
@@ -398,8 +398,7 @@ static int whitelist_major(const char *path, const char *name, char type, const
         return 0;
 
 fail:
-        log_warning_errno(errno, "Failed to read /proc/devices: %m");
-        return -errno;
+        return log_warning_errno(errno, "Failed to read /proc/devices: %m");
 }
 
 static bool cgroup_context_has_cpu_weight(CGroupContext *c) {
index c4067a95bfe1b9ceec614d687326d54b3d80a964..12d3ca076bdee0dac6ce014acca64614d4c689f3 100644 (file)
@@ -407,7 +407,15 @@ int bus_cgroup_set_property(
                 if (mode != UNIT_CHECK) {
                         c->cpu_quota_per_sec_usec = u64;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
-                        unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000));
+                        if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
+                                unit_write_drop_in_private_format(u, mode, "CPUQuota",
+                                                                  "CPUQuota=");
+                        else
+                                /* config_parse_cpu_quota() requires an integer, so
+                                 * truncating division is used on purpose here. */
+                                unit_write_drop_in_private_format(u, mode, "CPUQuota",
+                                                                  "CPUQuota=%0.f%%",
+                                                                  (double) (c->cpu_quota_per_sec_usec / 10000));
                 }
 
                 return 1;
index 7df4cab3f6f250e0d93f1c7ca5d9ce20d6331d06..c041a7d94c48b9c916d7c78581d4ef9b481530a8 100644 (file)
@@ -45,6 +45,7 @@
 #endif
 #include "strv.h"
 #include "syslog-util.h"
+#include "unit-printf.h"
 #include "user-util.h"
 #include "utf8.h"
 
@@ -159,21 +160,50 @@ static int property_get_ioprio(
 
 
         ExecContext *c = userdata;
-        int32_t n;
 
         assert(bus);
         assert(reply);
         assert(c);
 
-        if (c->ioprio_set)
-                n = c->ioprio;
-        else {
-                n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
-                if (n < 0)
-                        n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
-        }
+        return sd_bus_message_append(reply, "i", exec_context_get_effective_ioprio(c));
+}
 
-        return sd_bus_message_append(reply, "i", n);
+static int property_get_ioprio_class(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+
+        ExecContext *c = userdata;
+
+        assert(bus);
+        assert(reply);
+        assert(c);
+
+        return sd_bus_message_append(reply, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c)));
+}
+
+static int property_get_ioprio_priority(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+
+        ExecContext *c = userdata;
+
+        assert(bus);
+        assert(reply);
+        assert(c);
+
+        return sd_bus_message_append(reply, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c)));
 }
 
 static int property_get_cpu_sched_policy(
@@ -710,7 +740,7 @@ static int property_get_bind_paths(
                                 c->bind_mounts[i].source,
                                 c->bind_mounts[i].destination,
                                 c->bind_mounts[i].ignore_enoent,
-                                c->bind_mounts[i].recursive ? MS_REC : 0);
+                                c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0);
                 if (r < 0)
                         return r;
         }
@@ -761,7 +791,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -783,7 +814,6 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
         SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -793,9 +823,6 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
-        SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
-        SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
         SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -830,6 +857,14 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
+
+        /* Obsolete/redundant properties: */
+        SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+        SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
+
         SD_BUS_VTABLE_END
 };
 
@@ -1001,7 +1036,7 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
         } else if (streq(name, "SyslogLevel")) {
-                int level;
+                int32_t level;
 
                 r = sd_bus_message_read(message, "i", &level);
                 if (r < 0)
@@ -1017,7 +1052,7 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
         } else if (streq(name, "SyslogFacility")) {
-                int facility;
+                int32_t facility;
 
                 r = sd_bus_message_read(message, "i", &facility);
                 if (r < 0)
@@ -1033,7 +1068,7 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
         } else if (streq(name, "Nice")) {
-                int n;
+                int32_t n;
 
                 r = sd_bus_message_read(message, "i", &n);
                 if (r < 0)
@@ -1049,6 +1084,50 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
 
+        } else if (streq(name, "IOSchedulingClass")) {
+                int32_t q;
+
+                r = sd_bus_message_read(message, "i", &q);
+                if (r < 0)
+                        return r;
+
+                if (!ioprio_class_is_valid(q))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
+
+                if (mode != UNIT_CHECK) {
+                        _cleanup_free_ char *s = NULL;
+
+                        r = ioprio_class_to_string_alloc(q, &s);
+                        if (r < 0)
+                                return r;
+
+                        c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
+                        c->ioprio_set = true;
+
+                        unit_write_drop_in_private_format(u, mode, name, "IOSchedulingClass=%s", s);
+                }
+
+                return 1;
+
+        } else if (streq(name, "IOSchedulingPriority")) {
+                int32_t p;
+
+                r = sd_bus_message_read(message, "i", &p);
+                if (r < 0)
+                        return r;
+
+                if (!ioprio_priority_is_valid(p))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
+
+                if (mode != UNIT_CHECK) {
+                        c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
+                        c->ioprio_set = true;
+
+                        unit_write_drop_in_private_format(u, mode, name, "IOSchedulingPriority=%i", p);
+                }
+
+                return 1;
+
         } else if (STR_IN_SET(name, "TTYPath", "RootDirectory", "RootImage")) {
                 const char *s;
 
@@ -1317,7 +1396,7 @@ int bus_exec_context_set_transient_property(
 
         } else if (streq(name, "Environment")) {
 
-                _cleanup_strv_free_ char **l = NULL;
+                _cleanup_strv_free_ char **l = NULL, **q = NULL;
 
                 r = sd_bus_message_read_strv(message, &l);
                 if (r < 0)
@@ -1326,22 +1405,27 @@ int bus_exec_context_set_transient_property(
                 if (!strv_env_is_valid(l))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
 
-                if (mode != UNIT_CHECK) {
-                        _cleanup_free_ char *joined = NULL;
-                        char **e;
+                r = unit_full_printf_strv(u, l, &q);
+                if (r < 0)
+                        return r;
 
-                        if (strv_length(l) == 0) {
+                if (mode != UNIT_CHECK) {
+                        if (strv_length(q) == 0) {
                                 c->environment = strv_free(c->environment);
                                 unit_write_drop_in_private_format(u, mode, name, "Environment=");
                         } else {
-                                e = strv_env_merge(2, c->environment, l);
+                                _cleanup_free_ char *joined = NULL;
+                                char **e;
+
+                                e = strv_env_merge(2, c->environment, q);
                                 if (!e)
                                         return -ENOMEM;
 
                                 strv_free(c->environment);
                                 c->environment = e;
 
-                                joined = strv_join_quoted(c->environment);
+                                /* We write just the new settings out to file, with unresolved specifiers */
+                                joined = strv_join_quoted(q);
                                 if (!joined)
                                         return -ENOMEM;
 
index 85b67318ed112609f4dbf0b26ac498e5d7066248..6458ee5c121c45c5ffd361ae137f7754b114743a 100644 (file)
@@ -199,6 +199,39 @@ static int bus_service_set_transient_property(
 
                 return 1;
 
+        } else if (streq(name, "FileDescriptorStoreMax")) {
+                uint32_t u;
+
+                r = sd_bus_message_read(message, "u", &u);
+                if (r < 0)
+                        return r;
+
+                if (mode != UNIT_CHECK) {
+                        s->n_fd_store_max = (unsigned) u;
+                        unit_write_drop_in_private_format(UNIT(s), mode, name, "FileDescriptorStoreMax=%" PRIu32, u);
+                }
+
+                return 1;
+
+        } else if (streq(name, "NotifyAccess")) {
+                const char *t;
+                NotifyAccess k;
+
+                r = sd_bus_message_read(message, "s", &t);
+                if (r < 0)
+                        return r;
+
+                k = notify_access_from_string(t);
+                if (k < 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid notify access setting %s", t);
+
+                if (mode != UNIT_CHECK) {
+                        s->notify_access = k;
+                        unit_write_drop_in_private_format(UNIT(s), mode, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
+                }
+
+                return 1;
+
         } else if (streq(name, "ExecStart")) {
                 unsigned n = 0;
 
index efbb0e8915ce5a4d44f80feeb7ab87a6dd3fa547..c98282a5d4cece08f9784883eb45f23fd9252953 100644 (file)
@@ -144,28 +144,14 @@ static int property_get_next_elapse_monotonic(
                 sd_bus_error *error) {
 
         Timer *t = userdata;
-        usec_t x;
 
         assert(bus);
         assert(reply);
         assert(t);
 
-        if (t->next_elapse_monotonic_or_boottime <= 0)
-                x = 0;
-        else if (t->wake_system) {
-                usec_t a, b;
-
-                a = now(CLOCK_MONOTONIC);
-                b = now(clock_boottime_or_monotonic());
-
-                if (t->next_elapse_monotonic_or_boottime + a > b)
-                        x = t->next_elapse_monotonic_or_boottime + a - b;
-                else
-                        x = 0;
-        } else
-                x = t->next_elapse_monotonic_or_boottime;
-
-        return sd_bus_message_append(reply, "t", x);
+        return sd_bus_message_append(reply, "t",
+                                     (uint64_t) usec_shift_clock(t->next_elapse_monotonic_or_boottime,
+                                                                 TIMER_MONOTONIC_CLOCK(t), CLOCK_MONOTONIC));
 }
 
 const sd_bus_vtable bus_timer_vtable[] = {
index f15bb2196ccc85e3ea05e877ca39e2813016c6a1..b0645ce294071619932c09e2184edf8cb9cad511 100644 (file)
@@ -748,6 +748,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
index 065f2d81d6575d34425ae5e3fd1bdd063ccff187..cfc045d282c72ed5069f2fe4a8c6e3caeef67f43 100644 (file)
@@ -753,13 +753,13 @@ int manager_sync_bus_names(Manager *m, sd_bus *bus) {
                         /* If it is, determine its current owner */
                         r = sd_bus_get_name_creds(bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds);
                         if (r < 0) {
-                                log_error_errno(r, "Failed to get bus name owner %s: %m", name);
+                                log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name);
                                 continue;
                         }
 
                         r = sd_bus_creds_get_unique_name(creds, &unique);
                         if (r < 0) {
-                                log_error_errno(r, "Failed to get unique name for %s: %m", name);
+                                log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name);
                                 continue;
                         }
 
index 0e67c96552eac9cb6e29fcf906d2b88a09df0504..77601c5520bc6e2a69b16c42d7c1ee03dff2a03c 100644 (file)
@@ -112,7 +112,7 @@ static void device_init(Unit *u) {
          * indefinitely for plugged in devices, something which cannot
          * happen for the other units since their operations time out
          * anyway. */
-        u->job_timeout = u->manager->default_timeout_start_usec;
+        u->job_running_timeout = u->manager->default_timeout_start_usec;
 
         u->ignore_on_isolate = true;
 }
@@ -501,12 +501,16 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool
                  * now referenced by the kernel, then we assume the
                  * kernel knows it now, and udev might soon too. */
                 device_set_state(d, DEVICE_TENTATIVE);
-        else
+        else {
                 /* If nobody sees the device, or if the device was
                  * previously seen by udev and now is only referenced
                  * from the kernel, then we consider the device is
                  * gone, the kernel just hasn't noticed it yet. */
+
                 device_set_state(d, DEVICE_DEAD);
+                device_unset_sysfs(d);
+        }
+
 }
 
 static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
index d7798387c52cb51e2da67579257af045e1860fd9..d72e5bf08c499e8dcb8f78bb13eb41f355a1c7d4 100644 (file)
@@ -157,22 +157,26 @@ static int shift_fds(int fds[], unsigned n_fds) {
         return 0;
 }
 
-static int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
-        unsigned i;
+static int flags_fds(const int fds[], unsigned n_storage_fds, unsigned n_socket_fds, bool nonblock) {
+        unsigned i, n_fds;
         int r;
 
+        n_fds = n_storage_fds + n_socket_fds;
         if (n_fds <= 0)
                 return 0;
 
         assert(fds);
 
-        /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
+        /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags.
+         * O_NONBLOCK only applies to socket activation though. */
 
         for (i = 0; i < n_fds; i++) {
 
-                r = fd_nonblock(fds[i], nonblock);
-                if (r < 0)
-                        return r;
+                if (i < n_socket_fds) {
+                        r = fd_nonblock(fds[i], nonblock);
+                        if (r < 0)
+                                return r;
+                }
 
                 /* We unconditionally drop FD_CLOEXEC from the fds,
                  * since after all we want to pass these fds to our
@@ -1670,7 +1674,7 @@ static bool exec_needs_mount_namespace(
             context->protect_control_groups)
                 return true;
 
-        if (context->mount_apivfs)
+        if (context->mount_apivfs && (context->root_image || context->root_directory))
                 return true;
 
         return false;
@@ -2241,7 +2245,9 @@ static int exec_child(
                 char **argv,
                 int socket_fd,
                 int named_iofds[3],
-                int *fds, unsigned n_fds,
+                int *fds,
+                unsigned n_storage_fds,
+                unsigned n_socket_fds,
                 char **files_env,
                 int user_lookup_fd,
                 int *exit_status,
@@ -2258,6 +2264,7 @@ static int exec_child(
         uid_t uid = UID_INVALID;
         gid_t gid = GID_INVALID;
         int i, r, ngids = 0;
+        unsigned n_fds;
 
         assert(unit);
         assert(command);
@@ -2298,6 +2305,7 @@ static int exec_child(
 
         log_forget_fds();
 
+        n_fds = n_storage_fds + n_socket_fds;
         r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, fds, n_fds);
         if (r < 0) {
                 *exit_status = EXIT_FDS;
@@ -2669,7 +2677,7 @@ static int exec_child(
         if (r >= 0)
                 r = shift_fds(fds, n_fds);
         if (r >= 0)
-                r = flags_fds(fds, n_fds, context->non_blocking);
+                r = flags_fds(fds, n_storage_fds, n_socket_fds, context->non_blocking);
         if (r < 0) {
                 *exit_status = EXIT_FDS;
                 return r;
@@ -2887,9 +2895,9 @@ static int exec_child(
                 if (line) {
                         log_open();
                         log_struct(LOG_DEBUG,
-                                   LOG_UNIT_ID(unit),
                                    "EXECUTABLE=%s", command->path,
                                    LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
+                                   LOG_UNIT_ID(unit),
                                    NULL);
                         log_close();
                 }
@@ -2909,7 +2917,8 @@ int exec_spawn(Unit *unit,
                pid_t *ret) {
 
         _cleanup_strv_free_ char **files_env = NULL;
-        int *fds = NULL; unsigned n_fds = 0;
+        int *fds = NULL;
+        unsigned n_storage_fds = 0, n_socket_fds = 0;
         _cleanup_free_ char *line = NULL;
         int socket_fd, r;
         int named_iofds[3] = { -1, -1, -1 };
@@ -2921,22 +2930,28 @@ int exec_spawn(Unit *unit,
         assert(context);
         assert(ret);
         assert(params);
-        assert(params->fds || params->n_fds <= 0);
+        assert(params->fds || (params->n_storage_fds + params->n_socket_fds <= 0));
 
         if (context->std_input == EXEC_INPUT_SOCKET ||
             context->std_output == EXEC_OUTPUT_SOCKET ||
             context->std_error == EXEC_OUTPUT_SOCKET) {
 
-                if (params->n_fds != 1) {
+                if (params->n_socket_fds > 1) {
                         log_unit_error(unit, "Got more than one socket.");
                         return -EINVAL;
                 }
 
+                if (params->n_socket_fds == 0) {
+                        log_unit_error(unit, "Got no socket.");
+                        return -EINVAL;
+                }
+
                 socket_fd = params->fds[0];
         } else {
                 socket_fd = -1;
                 fds = params->fds;
-                n_fds = params->n_fds;
+                n_storage_fds = params->n_storage_fds;
+                n_socket_fds = params->n_socket_fds;
         }
 
         r = exec_context_named_iofds(unit, context, params, named_iofds);
@@ -2953,9 +2968,9 @@ int exec_spawn(Unit *unit,
                 return log_oom();
 
         log_struct(LOG_DEBUG,
-                   LOG_UNIT_ID(unit),
                    LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
                    "EXECUTABLE=%s", command->path,
+                   LOG_UNIT_ID(unit),
                    NULL);
         pid = fork();
         if (pid < 0)
@@ -2974,7 +2989,9 @@ int exec_spawn(Unit *unit,
                                argv,
                                socket_fd,
                                named_iofds,
-                               fds, n_fds,
+                               fds,
+                               n_storage_fds,
+                               n_socket_fds,
                                files_env,
                                unit->manager->user_lookup_fds[1],
                                &exit_status,
@@ -2989,6 +3006,14 @@ int exec_spawn(Unit *unit,
                                                                   error_message),
                                                  "EXECUTABLE=%s", command->path,
                                                  NULL);
+                        else if (r == -ENOENT && command->ignore)
+                                log_struct_errno(LOG_INFO, r,
+                                                 "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
+                                                 LOG_UNIT_ID(unit),
+                                                 LOG_UNIT_MESSAGE(unit, "Skipped spawning %s: %m",
+                                                                  command->path),
+                                                 "EXECUTABLE=%s", command->path,
+                                                 NULL);
                         else
                                 log_struct_errno(LOG_ERR, r,
                                                  "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
@@ -3175,6 +3200,7 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index) {
 int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) {
         unsigned i, targets;
         const char* stdio_fdname[3];
+        unsigned n_fds;
 
         assert(c);
         assert(p);
@@ -3186,7 +3212,9 @@ int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParamet
         for (i = 0; i < 3; i++)
                 stdio_fdname[i] = exec_context_fdname(c, i);
 
-        for (i = 0; i < p->n_fds && targets > 0; i++)
+        n_fds = p->n_storage_fds + p->n_socket_fds;
+
+        for (i = 0; i < n_fds  && targets > 0; i++)
                 if (named_iofds[STDIN_FILENO] < 0 &&
                     c->std_input == EXEC_INPUT_NAMED_FD &&
                     stdio_fdname[STDIN_FILENO] &&
@@ -3224,10 +3252,10 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
         STRV_FOREACH(i, c->environment_files) {
                 char *fn;
                 int k;
+                unsigned n;
                 bool ignore = false;
                 char **p;
                 _cleanup_globfree_ glob_t pglob = {};
-                int count, n;
 
                 fn = *i;
 
@@ -3245,23 +3273,19 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
                 }
 
                 /* Filename supports globbing, take all matching files */
-                errno = 0;
-                if (glob(fn, 0, NULL, &pglob) != 0) {
+                k = safe_glob(fn, 0, &pglob);
+                if (k < 0) {
                         if (ignore)
                                 continue;
 
                         strv_free(r);
-                        return errno > 0 ? -errno : -EINVAL;
+                        return k;
                 }
-                count = pglob.gl_pathc;
-                if (count == 0) {
-                        if (ignore)
-                                continue;
 
-                        strv_free(r);
-                        return -EINVAL;
-                }
-                for (n = 0; n < count; n++) {
+                /* When we don't match anything, -ENOENT should be returned */
+                assert(pglob.gl_pathc > 0);
+
+                for (n = 0; n < pglob.gl_pathc; n++) {
                         k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p);
                         if (k < 0) {
                                 if (ignore)
@@ -3677,6 +3701,21 @@ bool exec_context_maintains_privileges(ExecContext *c) {
         return false;
 }
 
+int exec_context_get_effective_ioprio(ExecContext *c) {
+        int p;
+
+        assert(c);
+
+        if (c->ioprio_set)
+                return c->ioprio;
+
+        p = ioprio_get(IOPRIO_WHO_PROCESS, 0);
+        if (p < 0)
+                return IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
+
+        return p;
+}
+
 void exec_status_start(ExecStatus *s, pid_t pid) {
         assert(s);
 
index 9f2b6fd39e334111c3996ba43cc4449c963c1212..9f07aa4aef2528f99b4d39ddfbfa200c24e929b9 100644 (file)
@@ -246,7 +246,8 @@ struct ExecParameters {
 
         int *fds;
         char **fd_names;
-        unsigned n_fds;
+        unsigned n_storage_fds;
+        unsigned n_socket_fds;
 
         ExecFlags flags;
         bool selinux_context_net:1;
@@ -306,6 +307,8 @@ const char* exec_context_fdname(const ExecContext *c, int fd_index);
 bool exec_context_may_touch_console(ExecContext *c);
 bool exec_context_maintains_privileges(ExecContext *c);
 
+int exec_context_get_effective_ioprio(ExecContext *c);
+
 void exec_status_start(ExecStatus *s, pid_t pid);
 void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status);
 void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix);
index 94ae429f46d071fa0a205ec5568dbeb4cab5a99a..7b5c98a57c93a2a8d5abf92e5dd0a0cac48e5485 100644 (file)
@@ -49,6 +49,11 @@ int ima_setup(void) {
                 return 0;
         }
 
+        if (access(IMA_POLICY_PATH, F_OK) < 0) {
+                log_debug("No IMA custom policy file "IMA_POLICY_PATH", ignoring.");
+                return 0;
+        }
+
         imafd = open(IMA_SECFS_POLICY, O_WRONLY|O_CLOEXEC);
         if (imafd < 0) {
                 log_error_errno(errno, "Failed to open the IMA kernel interface "IMA_SECFS_POLICY", ignoring: %m");
@@ -62,8 +67,7 @@ int ima_setup(void) {
         /* fall back to copying the policy line-by-line */
         input = fopen(IMA_POLICY_PATH, "re");
         if (!input) {
-                log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
-                               "Failed to open the IMA custom policy file "IMA_POLICY_PATH", ignoring: %m");
+                log_warning_errno(errno, "Failed to open the IMA custom policy file "IMA_POLICY_PATH", ignoring: %m");
                 return 0;
         }
 
index e2349830a82476829931f1cc5ec42c0aebe51754..8e2039d321473223d6133bd7cb769e12a0126e29 100644 (file)
@@ -576,6 +576,7 @@ int job_run_and_invalidate(Job *j) {
         if (!job_is_runnable(j))
                 return -EAGAIN;
 
+        job_start_timer(j, true);
         job_set_state(j, JOB_RUNNING);
         job_add_to_dbus_queue(j);
 
@@ -696,20 +697,20 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
         return NULL;
 }
 
-static void job_print_status_message(Unit *u, JobType t, JobResult result) {
-        static const struct {
-                const char *color, *word;
-        } statuses[_JOB_RESULT_MAX] = {
-                [JOB_DONE]        = { ANSI_GREEN,            "  OK  " },
-                [JOB_TIMEOUT]     = { ANSI_HIGHLIGHT_RED,    " TIME " },
-                [JOB_FAILED]      = { ANSI_HIGHLIGHT_RED,    "FAILED" },
-                [JOB_DEPENDENCY]  = { ANSI_HIGHLIGHT_YELLOW, "DEPEND" },
-                [JOB_SKIPPED]     = { ANSI_HIGHLIGHT,        " INFO " },
-                [JOB_ASSERT]      = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" },
-                [JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" },
-                [JOB_COLLECTED]   = { ANSI_HIGHLIGHT,        " INFO " },
-        };
+static const struct {
+        const char *color, *word;
+} job_print_status_messages [_JOB_RESULT_MAX] = {
+        [JOB_DONE]        = { ANSI_GREEN,            "  OK  " },
+        [JOB_TIMEOUT]     = { ANSI_HIGHLIGHT_RED,    " TIME " },
+        [JOB_FAILED]      = { ANSI_HIGHLIGHT_RED,    "FAILED" },
+        [JOB_DEPENDENCY]  = { ANSI_HIGHLIGHT_YELLOW, "DEPEND" },
+        [JOB_SKIPPED]     = { ANSI_HIGHLIGHT,        " INFO " },
+        [JOB_ASSERT]      = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" },
+        [JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" },
+        /* JOB_COLLECTED */
+};
 
+static void job_print_status_message(Unit *u, JobType t, JobResult result) {
         const char *format;
         const char *status;
 
@@ -721,14 +722,19 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
         if (t == JOB_RELOAD)
                 return;
 
+        if (!job_print_status_messages[result].word)
+                return;
+
         format = job_get_status_message_format(u, t, result);
         if (!format)
                 return;
 
         if (log_get_show_color())
-                status = strjoina(statuses[result].color, statuses[result].word, ANSI_NORMAL);
+                status = strjoina(job_print_status_messages[result].color,
+                                  job_print_status_messages[result].word,
+                                  ANSI_NORMAL);
         else
-                status = statuses[result].word;
+                status = job_print_status_messages[result].word;
 
         if (result != JOB_DONE)
                 manager_flip_auto_status(u->manager, true);
@@ -740,7 +746,7 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
         if (t == JOB_START && result == JOB_FAILED) {
                 _cleanup_free_ char *quoted;
 
-                quoted = shell_maybe_quote(u->id);
+                quoted = shell_maybe_quote(u->id, ESCAPE_BACKSLASH);
                 manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
         }
 }
@@ -765,10 +771,9 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
         assert(t >= 0);
         assert(t < _JOB_TYPE_MAX);
 
-        /* Skip this if it goes to the console. since we already print
-         * to the console anyway... */
-
-        if (log_on_console())
+        /* Skip printing if output goes to the console, and job_print_status_message()
+           will actually print something to the console. */
+        if (log_on_console() && job_print_status_messages[result].word)
                 return;
 
         format = job_get_status_message_format(u, t, result);
@@ -800,18 +805,18 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
 
         default:
                 log_struct(job_result_log_level[result],
-                           LOG_UNIT_ID(u),
                            LOG_MESSAGE("%s", buf),
                            "RESULT=%s", job_result_to_string(result),
+                           LOG_UNIT_ID(u),
                            NULL);
                 return;
         }
 
         log_struct(job_result_log_level[result],
-                   mid,
-                   LOG_UNIT_ID(u),
                    LOG_MESSAGE("%s", buf),
                    "RESULT=%s", job_result_to_string(result),
+                   LOG_UNIT_ID(u),
+                   mid,
                    NULL);
 }
 
@@ -949,22 +954,46 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user
         return 0;
 }
 
-int job_start_timer(Job *j) {
+int job_start_timer(Job *j, bool job_running) {
         int r;
+        usec_t timeout_time, old_timeout_time;
 
-        if (j->timer_event_source)
-                return 0;
+        if (job_running) {
+                j->begin_running_usec = now(CLOCK_MONOTONIC);
+
+                if (j->unit->job_running_timeout == USEC_INFINITY)
+                        return 0;
 
-        j->begin_usec = now(CLOCK_MONOTONIC);
+                timeout_time = usec_add(j->begin_running_usec, j->unit->job_running_timeout);
 
-        if (j->unit->job_timeout == USEC_INFINITY)
-                return 0;
+                if (j->timer_event_source) {
+                        /* Update only if JobRunningTimeoutSec= results in earlier timeout */
+                        r = sd_event_source_get_time(j->timer_event_source, &old_timeout_time);
+                        if (r < 0)
+                                return r;
+
+                        if (old_timeout_time <= timeout_time)
+                                return 0;
+
+                        return sd_event_source_set_time(j->timer_event_source, timeout_time);
+                }
+        } else {
+                if (j->timer_event_source)
+                        return 0;
+
+                j->begin_usec = now(CLOCK_MONOTONIC);
+
+                if (j->unit->job_timeout == USEC_INFINITY)
+                        return 0;
+
+                timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
+        }
 
         r = sd_event_add_time(
                         j->manager->event,
                         &j->timer_event_source,
                         CLOCK_MONOTONIC,
-                        usec_add(j->begin_usec, j->unit->job_timeout), 0,
+                        timeout_time, 0,
                         job_dispatch_timer, j);
         if (r < 0)
                 return r;
@@ -1027,6 +1056,8 @@ int job_serialize(Job *j, FILE *f) {
 
         if (j->begin_usec > 0)
                 fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
+        if (j->begin_running_usec > 0)
+                fprintf(f, "job-begin-running="USEC_FMT"\n", j->begin_running_usec);
 
         bus_track_serialize(j->bus_track, f, "subscribed");
 
@@ -1124,6 +1155,14 @@ int job_deserialize(Job *j, FILE *f) {
                         else
                                 j->begin_usec = ull;
 
+                } else if (streq(l, "job-begin-running")) {
+                        unsigned long long ull;
+
+                        if (sscanf(v, "%llu", &ull) != 1)
+                                log_debug("Failed to parse job-begin-running value %s", v);
+                        else
+                                j->begin_running_usec = ull;
+
                 } else if (streq(l, "subscribed")) {
 
                         if (strv_extend(&j->deserialized_clients, v) < 0)
@@ -1134,6 +1173,7 @@ int job_deserialize(Job *j, FILE *f) {
 
 int job_coldplug(Job *j) {
         int r;
+        usec_t timeout_time = USEC_INFINITY;
 
         assert(j);
 
@@ -1147,7 +1187,18 @@ int job_coldplug(Job *j) {
         /* Maybe due to new dependencies we don't actually need this job anymore? */
         job_add_to_gc_queue(j);
 
-        if (j->begin_usec == 0 || j->unit->job_timeout == USEC_INFINITY)
+        /* Create timer only when job began or began running and the respective timeout is finite.
+         * Follow logic of job_start_timer() if both timeouts are finite */
+        if (j->begin_usec == 0)
+                return 0;
+
+        if (j->unit->job_timeout != USEC_INFINITY)
+                timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
+
+        if (j->begin_running_usec > 0 && j->unit->job_running_timeout != USEC_INFINITY)
+                timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout));
+
+        if (timeout_time == USEC_INFINITY)
                 return 0;
 
         j->timer_event_source = sd_event_source_unref(j->timer_event_source);
@@ -1156,7 +1207,7 @@ int job_coldplug(Job *j) {
                         j->manager->event,
                         &j->timer_event_source,
                         CLOCK_MONOTONIC,
-                        usec_add(j->begin_usec, j->unit->job_timeout), 0,
+                        timeout_time, 0,
                         job_dispatch_timer, j);
         if (r < 0)
                 log_debug_errno(r, "Failed to restart timeout for job: %m");
@@ -1263,9 +1314,8 @@ bool job_check_gc(Job *j) {
                         return true;
         }
 
-        /* If we are going down, but something else is orederd After= us, then it needs to wait for us */
-        if (IN_SET(j->type, JOB_STOP, JOB_RESTART)) {
-
+        /* If we are going down, but something else is ordered After= us, then it needs to wait for us */
+        if (IN_SET(j->type, JOB_STOP, JOB_RESTART))
                 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i) {
                         if (!other->job)
                                 continue;
@@ -1275,7 +1325,6 @@ bool job_check_gc(Job *j) {
 
                         return true;
                 }
-        }
 
         /* The logic above is kinda the inverse of the job_is_runnable() logic. Specifically, if the job "we" is
          * ordered before the job "other":
index bea743f4620c0609c7acb31b2e5a4ce618eecc01..b17001889efb37a0573b90d5ebb6df8a07aa74df 100644 (file)
@@ -150,6 +150,7 @@ struct Job {
 
         sd_event_source *timer_event_source;
         usec_t begin_usec;
+        usec_t begin_running_usec;
 
         /*
          * This tracks where to send signals, and also which clients
@@ -220,7 +221,7 @@ int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u);
 void job_add_to_run_queue(Job *j);
 void job_add_to_dbus_queue(Job *j);
 
-int job_start_timer(Job *j);
+int job_start_timer(Job *j, bool job_running);
 
 int job_run_and_invalidate(Job *j);
 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already);
index ff3636149a8b0cae4c817564395965427dab9703..00f09ce60a3d40e64e08a2a56bc15666a7c93566 100644 (file)
 #include "unit-name.h"
 #include "unit.h"
 
-static bool unit_name_compatible(const char *a, const char *b) {
+static int unit_name_compatible(const char *a, const char *b) {
         _cleanup_free_ char *prefix = NULL;
         int r;
 
         /* the straightforward case: the symlink name matches the target */
         if (streq(a, b))
-                return true;
+                return 1;
 
         r = unit_name_template(a, &prefix);
-        if (r < 0) {
-                log_oom();
-                return true;
-        }
+        if (r == -EINVAL)
+                /* not a template */
+                return 0;
+        if (r < 0)
+                /* oom, or some other failure. Just skip the warning. */
+                return r;
 
         /* an instance name points to a target that is just the template name */
         if (streq(prefix, b))
-                return true;
+                return 1;
 
-        return false;
+        return 0;
 }
 
 static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) {
@@ -104,7 +106,12 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff
 
                 /* We don't treat this as an error, especially because we didn't check this for a
                  * long time. Nevertheless, we warn, because such mismatch can be mighty confusing. */
-                if (!unit_name_compatible(entry, basename(target)))
+                r = unit_name_compatible(entry, basename(target));
+                if (r < 0) {
+                        log_unit_warning_errno(u, r, "Can't check if names %s and %s are compatible, ignoring: %m", entry, basename(target));
+                        continue;
+                }
+                if (r == 0)
                         log_unit_warning(u, "%s dependency dropin %s target %s has different name",
                                          unit_dependency_to_string(dependency), *p, target);
 
diff --git a/src/core/load-fragment-gperf-nulstr.awk b/src/core/load-fragment-gperf-nulstr.awk
new file mode 100644 (file)
index 0000000..b52438a
--- /dev/null
@@ -0,0 +1,14 @@
+BEGIN{
+        keywords=0 ; FS="," ;
+        print "extern const char load_fragment_gperf_nulstr[];" ;
+        print "const char load_fragment_gperf_nulstr[] ="
+}
+keyword==1 {
+        print "\"" $$1 "\\0\""
+}
+/%%/ {
+        keyword=1
+}
+END {
+        print ";"
+}
index cb9e6fea2788244b99912309afce568571720ba5..5b5a86250e80e0d90bdcca0c30debb0643ce3ca9 100644 (file)
@@ -18,8 +18,8 @@ struct ConfigPerfItem;
 m4_dnl Define the context options only once
 m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
 `$1.WorkingDirectory,            config_parse_working_directory,     0,                             offsetof($1, exec_context)
-$1.RootDirectory,                config_parse_unit_path_printf,      0,                             offsetof($1, exec_context.root_directory)
-$1.RootImage,                    config_parse_unit_path_printf,      0,                             offsetof($1, exec_context.root_image)
+$1.RootDirectory,                config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_directory)
+$1.RootImage,                    config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_image)
 $1.User,                         config_parse_user_group,            0,                             offsetof($1, exec_context.user)
 $1.Group,                        config_parse_user_group,            0,                             offsetof($1, exec_context.group)
 $1.SupplementaryGroups,          config_parse_user_group_strv,       0,                             offsetof($1, exec_context.supplementary_groups)
@@ -35,7 +35,7 @@ $1.UMask,                        config_parse_mode,                  0,
 $1.Environment,                  config_parse_environ,               0,                             offsetof($1, exec_context.environment)
 $1.EnvironmentFile,              config_parse_unit_env_file,         0,                             offsetof($1, exec_context.environment_files)
 $1.PassEnvironment,              config_parse_pass_environ,          0,                             offsetof($1, exec_context.pass_environment)
-$1.DynamicUser,                  config_parse_bool,                  0,                             offsetof($1, exec_context.dynamic_user)
+$1.DynamicUser,                  config_parse_bool,                  true,                          offsetof($1, exec_context.dynamic_user)
 $1.StandardInput,                config_parse_exec_input,            0,                             offsetof($1, exec_context)
 $1.StandardOutput,               config_parse_exec_output,           0,                             offsetof($1, exec_context)
 $1.StandardError,                config_parse_exec_output,           0,                             offsetof($1, exec_context)
@@ -194,6 +194,7 @@ Unit.OnFailureIsolate,           config_parse_job_mode_isolate,      0,
 Unit.IgnoreOnIsolate,            config_parse_bool,                  0,                             offsetof(Unit, ignore_on_isolate)
 Unit.IgnoreOnSnapshot,           config_parse_warn_compat,           DISABLED_LEGACY,               0
 Unit.JobTimeoutSec,              config_parse_sec_fix_0,             0,                             offsetof(Unit, job_timeout)
+Unit.JobRunningTimeoutSec,       config_parse_sec,                   0,                             offsetof(Unit, job_running_timeout)
 Unit.JobTimeoutAction,           config_parse_emergency_action,      0,                             offsetof(Unit, job_timeout_action)
 Unit.JobTimeoutRebootArgument,   config_parse_unit_string_printf,    0,                             offsetof(Unit, job_timeout_reboot_arg)
 Unit.StartLimitIntervalSec,      config_parse_sec,                   0,                             offsetof(Unit, start_limit.interval)
@@ -220,6 +221,8 @@ Unit.ConditionSecurity,          config_parse_unit_condition_string, CONDITION_S
 Unit.ConditionCapability,        config_parse_unit_condition_string, CONDITION_CAPABILITY,          offsetof(Unit, conditions)
 Unit.ConditionHost,              config_parse_unit_condition_string, CONDITION_HOST,                offsetof(Unit, conditions)
 Unit.ConditionACPower,           config_parse_unit_condition_string, CONDITION_AC_POWER,            offsetof(Unit, conditions)
+Unit.ConditionUser,              config_parse_unit_condition_string, CONDITION_USER,                offsetof(Unit, conditions)
+Unit.ConditionGroup,             config_parse_unit_condition_string, CONDITION_GROUP,               offsetof(Unit, conditions)
 Unit.ConditionNull,              config_parse_unit_condition_null,   0,                             offsetof(Unit, conditions)
 Unit.AssertPathExists,           config_parse_unit_condition_path,   CONDITION_PATH_EXISTS,         offsetof(Unit, asserts)
 Unit.AssertPathExistsGlob,       config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB,    offsetof(Unit, asserts)
@@ -239,6 +242,8 @@ Unit.AssertSecurity,             config_parse_unit_condition_string, CONDITION_S
 Unit.AssertCapability,           config_parse_unit_condition_string, CONDITION_CAPABILITY,          offsetof(Unit, asserts)
 Unit.AssertHost,                 config_parse_unit_condition_string, CONDITION_HOST,                offsetof(Unit, asserts)
 Unit.AssertACPower,              config_parse_unit_condition_string, CONDITION_AC_POWER,            offsetof(Unit, asserts)
+Unit.AssertUser,                 config_parse_unit_condition_string, CONDITION_USER,                offsetof(Unit, asserts)
+Unit.AssertGroup,                config_parse_unit_condition_string, CONDITION_GROUP,               offsetof(Unit, asserts)
 Unit.AssertNull,                 config_parse_unit_condition_null,   0,                             offsetof(Unit, asserts)
 m4_dnl
 Service.PIDFile,                 config_parse_unit_path_printf,      0,                             offsetof(Service, pid_file)
@@ -298,7 +303,7 @@ Socket.ExecStartPre,             config_parse_exec,                  SOCKET_EXEC
 Socket.ExecStartPost,            config_parse_exec,                  SOCKET_EXEC_START_POST,        offsetof(Socket, exec_command)
 Socket.ExecStopPre,              config_parse_exec,                  SOCKET_EXEC_STOP_PRE,          offsetof(Socket, exec_command)
 Socket.ExecStopPost,             config_parse_exec,                  SOCKET_EXEC_STOP_POST,         offsetof(Socket, exec_command)
-Socket.TimeoutSec,               config_parse_sec,                   0,                             offsetof(Socket, timeout_usec)
+Socket.TimeoutSec,               config_parse_sec_fix_0,             0,                             offsetof(Socket, timeout_usec)
 Socket.SocketUser,               config_parse_user_group,            0,                             offsetof(Socket, user)
 Socket.SocketGroup,              config_parse_user_group,            0,                             offsetof(Socket, group)
 Socket.SocketMode,               config_parse_mode,                  0,                             offsetof(Socket, socket_mode)
@@ -362,7 +367,7 @@ Mount.What,                      config_parse_unit_string_printf,    0,
 Mount.Where,                     config_parse_path,                  0,                             offsetof(Mount, where)
 Mount.Options,                   config_parse_unit_string_printf,    0,                             offsetof(Mount, parameters_fragment.options)
 Mount.Type,                      config_parse_string,                0,                             offsetof(Mount, parameters_fragment.fstype)
-Mount.TimeoutSec,                config_parse_sec,                   0,                             offsetof(Mount, timeout_usec)
+Mount.TimeoutSec,                config_parse_sec_fix_0,             0,                             offsetof(Mount, timeout_usec)
 Mount.DirectoryMode,             config_parse_mode,                  0,                             offsetof(Mount, directory_mode)
 Mount.SloppyOptions,             config_parse_bool,                  0,                             offsetof(Mount, sloppy_options)
 Mount.LazyUnmount,               config_parse_bool,                  0,                             offsetof(Mount, lazy_unmount)
@@ -373,12 +378,12 @@ KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
 m4_dnl
 Automount.Where,                 config_parse_path,                  0,                             offsetof(Automount, where)
 Automount.DirectoryMode,         config_parse_mode,                  0,                             offsetof(Automount, directory_mode)
-Automount.TimeoutIdleSec,        config_parse_sec,                   0,                             offsetof(Automount, timeout_idle_usec)
+Automount.TimeoutIdleSec,        config_parse_sec_fix_0,             0,                             offsetof(Automount, timeout_idle_usec)
 m4_dnl
 Swap.What,                       config_parse_path,                  0,                             offsetof(Swap, parameters_fragment.what)
 Swap.Priority,                   config_parse_int,                   0,                             offsetof(Swap, parameters_fragment.priority)
 Swap.Options,                    config_parse_unit_string_printf,    0,                             offsetof(Swap, parameters_fragment.options)
-Swap.TimeoutSec,                 config_parse_sec,                   0,                             offsetof(Swap, timeout_usec)
+Swap.TimeoutSec,                 config_parse_sec_fix_0,             0,                             offsetof(Swap, timeout_usec)
 EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
 CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
 KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl
index 5b7471c0d0d202b45a28c138ec9f862c8128c6c8..9d5c39b3dd22a27c9b3ff47c79acdf3ded6c046d 100644 (file)
@@ -242,6 +242,7 @@ int config_parse_unit_path_printf(
         _cleanup_free_ char *k = NULL;
         Unit *u = userdata;
         int r;
+        bool fatal = ltype;
 
         assert(filename);
         assert(lvalue);
@@ -250,8 +251,10 @@ int config_parse_unit_path_printf(
 
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to resolve unit specifiers on %s%s: %m",
+                           fatal ? "" : ", ignoring", rvalue);
+                return fatal ? -ENOEXEC : 0;
         }
 
         return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
@@ -392,7 +395,9 @@ int config_parse_socket_listen(const char *unit,
 
                 r = socket_address_parse_and_warn(&p->address, k);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
+                        if (r != -EAFNOSUPPORT)
+                                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
+
                         return 0;
                 }
 
@@ -634,26 +639,36 @@ int config_parse_exec(
 
                 r = unit_full_printf(u, f, &path);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", f);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to resolve unit specifiers on %s%s: %m",
+                                   f, ignore ? ", ignoring" : "");
+                        return ignore ? 0 : -ENOEXEC;
                 }
 
                 if (isempty(path)) {
                         /* First word is either "-" or "@" with no command. */
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Empty path in command line%s: \"%s\"",
+                                   ignore ? ", ignoring" : "", rvalue);
+                        return ignore ? 0 : -ENOEXEC;
                 }
                 if (!string_is_safe(path)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Executable path contains special characters%s: %s",
+                                   ignore ? ", ignoring" : "", rvalue);
+                        return ignore ? 0 : -ENOEXEC;
                 }
                 if (!path_is_absolute(path)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Executable path is not absolute%s: %s",
+                                   ignore ? ", ignoring" : "", rvalue);
+                        return ignore ? 0 : -ENOEXEC;
                 }
                 if (endswith(path, "/")) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Executable path specifies a directory%s: %s",
+                                   ignore ? ", ignoring" : "", rvalue);
+                        return ignore ? 0 : -ENOEXEC;
                 }
 
                 if (!separate_argv0) {
@@ -706,12 +721,14 @@ int config_parse_exec(
                         if (r == 0)
                                 break;
                         if (r < 0)
-                                return 0;
+                                return ignore ? 0 : -ENOEXEC;
 
                         r = unit_full_printf(u, word, &resolved);
                         if (r < 0) {
-                                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to resolve unit specifiers on %s, ignoring: %m", word);
-                                return 0;
+                                log_syntax(unit, LOG_ERR, filename, line, r,
+                                           "Failed to resolve unit specifiers on %s%s: %m",
+                                           word, ignore ? ", ignoring" : "");
+                                return ignore ? 0 : -ENOEXEC;
                         }
 
                         if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
@@ -722,8 +739,10 @@ int config_parse_exec(
                 }
 
                 if (!n || !n[0]) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Empty executable name or zeroeth argument, ignoring: %s", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Empty executable name or zeroeth argument%s: %s",
+                                   ignore ? ", ignoring" : "", rvalue);
+                        return ignore ? 0 : -ENOEXEC;
                 }
 
                 nce = new0(ExecCommand, 1);
@@ -938,8 +957,8 @@ int config_parse_exec_io_priority(const char *unit,
         assert(rvalue);
         assert(data);
 
-        r = safe_atoi(rvalue, &i);
-        if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
+        r = ioprio_parse_priority(rvalue, &i);
+        if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue);
                 return 0;
         }
@@ -1330,8 +1349,10 @@ int config_parse_exec_selinux_context(
 
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to resolve specifiers%s: %m",
+                           ignore ? ", ignoring" : "");
+                return ignore ? 0 : -ENOEXEC;
         }
 
         free(c->selinux_context);
@@ -1378,8 +1399,10 @@ int config_parse_exec_apparmor_profile(
 
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to resolve specifiers%s: %m",
+                           ignore ? ", ignoring" : "");
+                return ignore ? 0 : -ENOEXEC;
         }
 
         free(c->apparmor_profile);
@@ -1426,8 +1449,10 @@ int config_parse_exec_smack_process_label(
 
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to resolve specifiers%s: %m",
+                           ignore ? ", ignoring" : "");
+                return ignore ? 0 : -ENOEXEC;
         }
 
         free(c->smack_process_label);
@@ -1645,19 +1670,19 @@ int config_parse_socket_service(
 
         r = unit_name_printf(UNIT(s), rvalue, &p);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", rvalue);
+                return -ENOEXEC;
         }
 
         if (!endswith(p, ".service")) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue);
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service: %s", rvalue);
+                return -ENOEXEC;
         }
 
         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s: %s", rvalue, bus_error_message(&error, r));
+                return -ENOEXEC;
         }
 
         unit_ref_set(&s->service, x);
@@ -1868,15 +1893,12 @@ int config_parse_sec_fix_0(
          * compatibility with older versions of systemd where 0 instead of infinity was used as indicator to turn off a
          * timeout. */
 
-        r = parse_sec(rvalue, usec);
+        r = parse_sec_fix_0(rvalue, usec);
         if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
                 return 0;
         }
 
-        if (*usec <= 0)
-                *usec = USEC_INFINITY;
-
         return 0;
 }
 
@@ -1908,13 +1930,13 @@ int config_parse_user_group(
 
                 r = unit_full_printf(u, rvalue, &k);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
+                        return -ENOEXEC;
                 }
 
                 if (!valid_user_group_name_or_id(k)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
+                        return -ENOEXEC;
                 }
 
                 n = k;
@@ -1972,19 +1994,19 @@ int config_parse_user_group_strv(
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
-                        break;
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue);
+                        return -ENOEXEC;
                 }
 
                 r = unit_full_printf(u, word, &k);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word);
-                        continue;
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", word);
+                        return -ENOEXEC;
                 }
 
                 if (!valid_user_group_name_or_id(k)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k);
-                        continue;
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
+                        return -ENOEXEC;
                 }
 
                 r = strv_push(users, k);
@@ -2143,25 +2165,28 @@ int config_parse_working_directory(
 
                 r = unit_full_printf(u, rvalue, &k);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s', ignoring: %m", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to resolve unit specifiers in working directory path '%s'%s: %m",
+                                   rvalue, missing_ok ? ", ignoring" : "");
+                        return missing_ok ? 0 : -ENOEXEC;
                 }
 
                 path_kill_slashes(k);
 
                 if (!utf8_is_valid(k)) {
                         log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
-                        return 0;
+                        return missing_ok ? 0 : -ENOEXEC;
                 }
 
                 if (!path_is_absolute(k)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Working directory path '%s' is not absolute, ignoring.", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Working directory path '%s' is not absolute%s.",
+                                   rvalue, missing_ok ? ", ignoring" : "");
+                        return missing_ok ? 0 : -ENOEXEC;
                 }
 
-                free_and_replace(c->working_directory, k);
-
                 c->working_directory_home = false;
+                free_and_replace(c->working_directory, k);
         }
 
         c->working_directory_missing_ok = missing_ok;
@@ -3907,6 +3932,7 @@ int config_parse_bind_paths(
                 void *userdata) {
 
         ExecContext *c = data;
+        Unit *u = userdata;
         const char *p;
         int r;
 
@@ -3926,6 +3952,7 @@ int config_parse_bind_paths(
         p = rvalue;
         for (;;) {
                 _cleanup_free_ char *source = NULL, *destination = NULL;
+                _cleanup_free_ char *sresolved = NULL, *dresolved = NULL;
                 char *s = NULL, *d = NULL;
                 bool rbind = true, ignore_enoent = false;
 
@@ -3939,7 +3966,14 @@ int config_parse_bind_paths(
                         return 0;
                 }
 
-                s = source;
+                r = unit_full_printf(u, source, &sresolved);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to resolved specifiers in \"%s\", ignoring: %m", source);
+                        return 0;
+                }
+
+                s = sresolved;
                 if (s[0] == '-') {
                         ignore_enoent = true;
                         s++;
@@ -3970,16 +4004,23 @@ int config_parse_bind_paths(
                                 return 0;
                         }
 
-                        if (!utf8_is_valid(destination)) {
-                                log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, destination);
+                        r = unit_full_printf(u, destination, &dresolved);
+                        if (r < 0) {
+                                log_syntax(unit, LOG_ERR, filename, line, r,
+                                           "Failed to resolved specifiers in \"%s\", ignoring: %m", destination);
+                                return 0;
+                        }
+
+                        if (!utf8_is_valid(dresolved)) {
+                                log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, dresolved);
                                 return 0;
                         }
-                        if (!path_is_absolute(destination)) {
-                                log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute destination path, ignoring: %s", destination);
+                        if (!path_is_absolute(dresolved)) {
+                                log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute destination path, ignoring: %s", dresolved);
                                 return 0;
                         }
 
-                        d = path_kill_slashes(destination);
+                        d = path_kill_slashes(dresolved);
 
                         /* Optionally, there's also a short option string specified */
                         if (p && p[-1] == ':') {
@@ -4441,8 +4482,11 @@ int unit_load_fragment(Unit *u) {
                         return r;
 
                 r = load_from_path(u, k);
-                if (r < 0)
+                if (r < 0) {
+                        if (r == -ENOEXEC)
+                                log_unit_notice(u, "Unit configuration has fatal error, unit will not be started.");
                         return r;
+                }
 
                 if (u->load_state == UNIT_STUB) {
                         SET_FOREACH(t, u->names, i) {
index 04062a7910a47db0d10884f8c10837574531e716..c167305ca9ba5e1111ca9643e91639143a72af2f 100644 (file)
 #include "missing.h"
 #include "netlink-util.h"
 
-static int start_loopback(sd_netlink *rtnl) {
+#define LOOPBACK_SETUP_TIMEOUT_USEC (5 * USEC_PER_SEC)
+
+struct state {
+        unsigned n_messages;
+        int rcode;
+        const char *title;
+};
+
+static int generic_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+        struct state *s = userdata;
+
+        assert(s);
+        assert(s->n_messages > 0);
+        s->n_messages--;
+
+        errno = 0;
+        log_debug_errno(sd_netlink_message_get_errno(m), "Failed to %s: %m", s->title);
+
+        s->rcode = sd_netlink_message_get_errno(m);
+
+        return 0;
+}
+
+static int start_loopback(sd_netlink *rtnl, struct state *s) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
+        assert(rtnl);
+        assert(s);
+
         r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, LOOPBACK_IFINDEX);
         if (r < 0)
                 return r;
@@ -38,10 +64,81 @@ static int start_loopback(sd_netlink *rtnl) {
         if (r < 0)
                 return r;
 
-        r = sd_netlink_call(rtnl, req, 0, NULL);
+        r = sd_netlink_call_async(rtnl, req, generic_handler, s, LOOPBACK_SETUP_TIMEOUT_USEC, NULL);
+        if (r < 0)
+                return r;
+
+        s->n_messages ++;
+        return 0;
+}
+
+static int add_ipv4_address(sd_netlink *rtnl, struct state *s) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(rtnl);
+        assert(s);
+
+        r = sd_rtnl_message_new_addr(rtnl, &req, RTM_NEWADDR, LOOPBACK_IFINDEX, AF_INET);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_addr_set_prefixlen(req, 8);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_HOST);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_append_in_addr(req, IFA_LOCAL, &(struct in_addr) { .s_addr = htobe32(INADDR_LOOPBACK) } );
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_call_async(rtnl, req, generic_handler, s, USEC_INFINITY, NULL);
         if (r < 0)
                 return r;
 
+        s->n_messages ++;
+        return 0;
+}
+
+static int add_ipv6_address(sd_netlink *rtnl, struct state *s) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(rtnl);
+        assert(s);
+
+        r = sd_rtnl_message_new_addr(rtnl, &req, RTM_NEWADDR, LOOPBACK_IFINDEX, AF_INET6);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_addr_set_prefixlen(req, 128);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_HOST);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_append_in6_addr(req, IFA_LOCAL, &in6addr_loopback);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_call_async(rtnl, req, generic_handler, s, USEC_INFINITY, NULL);
+        if (r < 0)
+                return r;
+
+        s->n_messages ++;
         return 0;
 }
 
@@ -54,7 +151,7 @@ static bool check_loopback(sd_netlink *rtnl) {
         if (r < 0)
                 return false;
 
-        r = sd_netlink_call(rtnl, req, 0, &reply);
+        r = sd_netlink_call(rtnl, req, USEC_INFINITY, &reply);
         if (r < 0)
                 return false;
 
@@ -67,23 +164,52 @@ static bool check_loopback(sd_netlink *rtnl) {
 
 int loopback_setup(void) {
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        struct state state_4 = { .title = "add address 127.0.0.1 to loopback interface" },
+                     state_6 = { .title = "add address ::1 to loopback interface"},
+                     state_up = { .title = "bring loopback interface up" };
         int r;
 
         r = sd_netlink_open(&rtnl);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to open netlink: %m");
+
+        /* Note that we add the IP addresses here explicitly even though the kernel does that too implicitly when
+         * setting up the loopback device. The reason we do this here a second time (and possibly race against the
+         * kernel) is that we want to synchronously wait until the IP addresses are set up correctly, see
+         *
+         * https://github.com/systemd/systemd/issues/5641 */
 
-        r = start_loopback(rtnl);
-        if (r < 0) {
+        r = add_ipv4_address(rtnl, &state_4);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enqueue IPv4 loopback address add request: %m");
+
+        r = add_ipv6_address(rtnl, &state_6);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enqueue IPv6 loopback address add request: %m");
+
+        r = start_loopback(rtnl, &state_up);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enqueue loopback interface start request: %m");
+
+        while (state_4.n_messages + state_6.n_messages + state_up.n_messages > 0) {
+                r = sd_netlink_wait(rtnl, LOOPBACK_SETUP_TIMEOUT_USEC);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to wait for netlink event: %m");
+
+                r = sd_netlink_process(rtnl, NULL);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to process netlink event: %m");
+        }
 
-                /* If we lack the permissions to configure the
-                 * loopback device, but we find it to be already
-                 * configured, let's exit cleanly, in order to
-                 * supported unprivileged containers. */
-                if (r == -EPERM && check_loopback(rtnl))
+        /* Note that we don't really care whether the addresses could be added or not */
+        if (state_up.rcode != 0) {
+                /* If we lack the permissions to configure the loopback device,
+                 * but we find it to be already configured, let's exit cleanly,
+                 * in order to supported unprivileged containers. */
+                if (state_up.rcode == -EPERM && check_loopback(rtnl))
                         return 0;
 
-                return log_warning_errno(r, "Failed to configure loopback device: %m");
+                return log_warning_errno(state_up.rcode, "Failed to configure loopback device: %m");
         }
 
         return 0;
index bcf9ea5f25a07379d1aad01d4be821848b17e126..88e2c9250425d6741689eb1a119fda578f9aed85 100644 (file)
@@ -536,7 +536,7 @@ static int config_parse_cpu_affinity2(
                 return ncpus;
 
         if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
-                log_warning("Failed to set CPU affinity: %m");
+                log_warning_errno(errno, "Failed to set CPU affinity: %m");
 
         return 0;
 }
@@ -1162,6 +1162,8 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
 static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
         struct rlimit nl;
         int r;
+        int min_max;
+        _cleanup_free_ char *nr_open = NULL;
 
         assert(saved_rlimit);
 
@@ -1182,8 +1184,16 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
                 arg_default_rlimit[RLIMIT_NOFILE] = rl;
         }
 
+        /* Get current RLIMIT_NOFILE maximum compiled into the kernel. */
+        r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open);
+        if (r == 0)
+                r = safe_atoi(nr_open, &min_max);
+        /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */
+        if (r < 0)
+                min_max = 1024 * 1024;
+
         /* Bump up the resource limit for ourselves substantially */
-        nl.rlim_cur = nl.rlim_max = 64*1024;
+        nl.rlim_cur = nl.rlim_max = min_max;
         r = setrlimit_closest(RLIMIT_NOFILE, &nl);
         if (r < 0)
                 return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m");
@@ -1770,7 +1780,7 @@ int main(int argc, char *argv[]) {
                 if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
                         log_error_errno(errno, "Failed to adjust timer slack: %m");
 
-        if (!cap_test_all(arg_capability_bounding_set)) {
+        if (arg_system && !cap_test_all(arg_capability_bounding_set)) {
                 r = capability_bounding_set_drop_usermode(arg_capability_bounding_set);
                 if (r < 0) {
                         log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m");
index cff38e28deaf4479761532def049f10ed7579b0e..283720750fc026455a9ac1f3cc17676f89963790 100644 (file)
@@ -2319,7 +2319,10 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e,
                 return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(invocation_id));
         }
 
-        /* If this didn't work, we use the suffix as unit name. */
+        /* If this didn't work, we check if this is a unit name */
+        if (!unit_name_is_valid(n, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
+                return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is neither a valid invocation ID nor unit name.", n);
+
         r = manager_load_unit(m, n, NULL, e, &u);
         if (r < 0)
                 return r;
@@ -2585,8 +2588,8 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
         m->n_reloading++;
 
         for (;;) {
-                char line[LINE_MAX], *l;
-                const char *val;
+                char line[LINE_MAX];
+                const char *val, *l;
 
                 if (!fgets(line, sizeof(line), f)) {
                         if (feof(f))
@@ -2607,7 +2610,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         uint32_t id;
 
                         if (safe_atou32(val, &id) < 0)
-                                log_debug("Failed to parse current job id value %s", val);
+                                log_notice("Failed to parse current job id value %s", val);
                         else
                                 m->current_job_id = MAX(m->current_job_id, id);
 
@@ -2615,7 +2618,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         uint32_t n;
 
                         if (safe_atou32(val, &n) < 0)
-                                log_debug("Failed to parse installed jobs counter %s", val);
+                                log_notice("Failed to parse installed jobs counter %s", val);
                         else
                                 m->n_installed_jobs += n;
 
@@ -2623,7 +2626,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         uint32_t n;
 
                         if (safe_atou32(val, &n) < 0)
-                                log_debug("Failed to parse failed jobs counter %s", val);
+                                log_notice("Failed to parse failed jobs counter %s", val);
                         else
                                 m->n_failed_jobs += n;
 
@@ -2632,7 +2635,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
 
                         b = parse_boolean(val);
                         if (b < 0)
-                                log_debug("Failed to parse taint /usr flag %s", val);
+                                log_notice("Failed to parse taint /usr flag %s", val);
                         else
                                 m->taint_usr = m->taint_usr || b;
 
@@ -2662,14 +2665,16 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         dual_timestamp_deserialize(val, &m->units_load_finish_timestamp);
                 else if (startswith(l, "env=")) {
                         r = deserialize_environment(&m->environment, l);
+                        if (r == -ENOMEM)
+                                goto finish;
                         if (r < 0)
-                                return r;
+                                log_notice_errno(r, "Failed to parse environment entry: \"%s\": %m", l);
 
                 } else if ((val = startswith(l, "notify-fd="))) {
                         int fd;
 
                         if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
-                                log_debug("Failed to parse notify fd: %s", val);
+                                log_notice("Failed to parse notify fd: \"%s\"", val);
                         else {
                                 m->notify_event_source = sd_event_source_unref(m->notify_event_source);
                                 safe_close(m->notify_fd);
@@ -2692,7 +2697,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         int fd;
 
                         if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
-                                log_debug("Failed to parse cgroups agent fd: %s", val);
+                                log_notice("Failed to parse cgroups agent fd: %s", val);
                         else {
                                 m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source);
                                 safe_close(m->cgroups_agent_fd);
@@ -2703,7 +2708,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         int fd0, fd1;
 
                         if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1))
-                                log_debug("Failed to parse user lookup fd: %s", val);
+                                log_notice("Failed to parse user lookup fd: %s", val);
                         else {
                                 m->user_lookup_event_source = sd_event_source_unref(m->user_lookup_event_source);
                                 safe_close_pair(m->user_lookup_fds);
@@ -2723,7 +2728,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_oom();
 
                 } else if (!startswith(l, "kdbus-fd=")) /* ignore this one */
-                        log_debug("Unknown serialization item '%s'", l);
+                        log_notice("Unknown serialization item '%s'", l);
         }
 
         for (;;) {
diff --git a/src/core/meson.build b/src/core/meson.build
new file mode 100644 (file)
index 0000000..fb8f9dc
--- /dev/null
@@ -0,0 +1,235 @@
+libcore_la_sources = '''
+        unit.c
+        unit.h
+        unit-printf.c
+        unit-printf.h
+        job.c
+        job.h
+        manager.c
+        manager.h
+        transaction.c
+        transaction.h
+        load-fragment.c
+        load-fragment.h
+        service.c
+        service.h
+        socket.c
+        socket.h
+        busname.c
+        busname.h
+        bus-policy.c
+        bus-policy.h
+        target.c
+        target.h
+        device.c
+        device.h
+        mount.c
+        mount.h
+        automount.c
+        automount.h
+        swap.c
+        swap.h
+        timer.c
+        timer.h
+        path.c
+        path.h
+        slice.c
+        slice.h
+        scope.c
+        scope.h
+        load-dropin.c
+        load-dropin.h
+        execute.c
+        execute.h
+        dynamic-user.c
+        dynamic-user.h
+        kill.c
+        kill.h
+        dbus.c
+        dbus.h
+        dbus-manager.c
+        dbus-manager.h
+        dbus-unit.c
+        dbus-unit.h
+        dbus-job.c
+        dbus-job.h
+        dbus-service.c
+        dbus-service.h
+        dbus-socket.c
+        dbus-socket.h
+        dbus-busname.c
+        dbus-busname.h
+        dbus-target.c
+        dbus-target.h
+        dbus-device.c
+        dbus-device.h
+        dbus-mount.c
+        dbus-mount.h
+        dbus-automount.c
+        dbus-automount.h
+        dbus-swap.c
+        dbus-swap.h
+        dbus-timer.c
+        dbus-timer.h
+        dbus-path.c
+        dbus-path.h
+        dbus-slice.c
+        dbus-slice.h
+        dbus-scope.c
+        dbus-scope.h
+        dbus-execute.c
+        dbus-execute.h
+        dbus-kill.c
+        dbus-kill.h
+        dbus-cgroup.c
+        dbus-cgroup.h
+        cgroup.c
+        cgroup.h
+        selinux-access.c
+        selinux-access.h
+        selinux-setup.c
+        selinux-setup.h
+        smack-setup.c
+        smack-setup.h
+        ima-setup.c
+        ima-setup.h
+        locale-setup.h
+        locale-setup.c
+        hostname-setup.c
+        hostname-setup.h
+        machine-id-setup.c
+        machine-id-setup.h
+        mount-setup.c
+        mount-setup.h
+        kmod-setup.c
+        kmod-setup.h
+        loopback-setup.h
+        loopback-setup.c
+        namespace.c
+        namespace.h
+        killall.h
+        killall.c
+        audit-fd.c
+        audit-fd.h
+        show-status.c
+        show-status.h
+        emergency-action.c
+        emergency-action.h
+'''.split()
+
+load_fragment_gperf_gperf = custom_target(
+        'load-fragment-gperf.gperf',
+        input : 'load-fragment-gperf.gperf.m4',
+        output: 'load-fragment-gperf.gperf',
+        command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+        capture : true)
+
+load_fragment_gperf_c = custom_target(
+        'load-fragment-gperf.c',
+        input : load_fragment_gperf_gperf,
+        output : 'load-fragment-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+awkscript = 'load-fragment-gperf-nulstr.awk'
+load_fragment_gperf_nulstr_c = custom_target(
+        'load-fragment-gperf-nulstr.c',
+        input : [awkscript, load_fragment_gperf_gperf],
+        output : 'load-fragment-gperf-nulstr.c',
+        command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+        capture : true)
+
+libcore = static_library(
+        'core',
+        libcore_la_sources,
+        load_fragment_gperf_c,
+        load_fragment_gperf_nulstr_c,
+        include_directories : includes,
+        link_with : [libshared_static],
+        dependencies : [threads,
+                        libseccomp,
+                        libpam,
+                        libaudit,
+                        libkmod,
+                        libapparmor,
+                        libmount])
+
+systemd_sources = files('main.c')
+
+systemd_shutdown_sources = files('''
+        shutdown.c
+        umount.c
+        umount.h
+        mount-setup.c
+        mount-setup.h
+        killall.c
+        killall.h
+'''.split())
+
+in_files = [['macros.systemd',   rpmmacrosdir],
+            ['triggers.systemd', ''],
+            ['systemd.pc',       pkgconfigdatadir]]
+
+foreach item : in_files
+        file = item[0]
+        dir = item[1]
+
+        # If 'no', disable generation completely.
+        # If '', generate, but do not install.
+        if dir != 'no'
+                gen = configure_file(
+                        input : file + '.in',
+                        output : file,
+                        configuration : substs)
+                if dir != ''
+                        install_data(gen,
+                                     install_dir : dir)
+                endif
+        endif
+endforeach
+
+install_data('org.freedesktop.systemd1.conf',
+             install_dir : dbuspolicydir)
+install_data('org.freedesktop.systemd1.service',
+             install_dir : dbussystemservicedir)
+
+policy_in = configure_file(
+        input : 'org.freedesktop.systemd1.policy.in.in',
+        output : 'org.freedesktop.systemd1.policy.in',
+        configuration : substs)
+
+custom_target(
+        'org.freedesktop.systemd1.policy',
+        input : policy_in,
+        output : 'org.freedesktop.systemd1.policy',
+        command : intltool_command,
+        install : install_polkit,
+        install_dir : polkitpolicydir)
+
+# TODO: this might work with meson from git, see
+# https://github.com/mesonbuild/meson/issues/1441#issuecomment-283585493
+#
+# i18n.merge_file(
+#   'org.freedesktop.systemd1.policy',
+#   po_dir : po_dir,
+#   input : policy_in,
+#   output : 'org.freedesktop.systemd1.policy',
+#   install : install_polkit,
+#   install_dir : polkitpolicydir)
+
+install_data('system.conf',
+             'user.conf',
+             install_dir : pkgsysconfdir)
+
+meson.add_install_script('sh', '-c', mkdir_p.format(systemshutdowndir))
+meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir))
+meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir))
+meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir))
+
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(pkgsysconfdir, 'system/multi-user.target.wants')))
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(pkgsysconfdir, 'system/getty.target.wants')))
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(pkgsysconfdir, 'user')))
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(sysconfdir, 'xdg/systemd')))
index ca0c4b0d5eed59bfc75ec966d55fc1160bf13d3d..214364d87d2565aba498c9aaecf3ccfaeaf22066 100644 (file)
@@ -886,7 +886,7 @@ static void mount_enter_unmounting(Mount *m) {
         m->control_command_id = MOUNT_EXEC_UNMOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
 
-        r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, NULL);
+        r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, "-c", NULL);
         if (r >= 0 && m->lazy_unmount)
                 r = exec_command_append(m->control_command, "-l", NULL);
         if (r >= 0 && m->force_unmount)
index 4f29217bc4a342e8cf56b4e6dd7f478078b6f681..05175e9552b11c59e95b02bb99d17071d1bc0b52 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/fs.h>
 
 #include "alloc-util.h"
+#include "base-filesystem.h"
 #include "dev-setup.h"
 #include "fd-util.h"
 #include "fs-util.h"
@@ -792,13 +793,14 @@ static int apply_mount(
         return 0;
 }
 
-static int make_read_only(MountEntry *m, char **blacklist) {
+static int make_read_only(MountEntry *m, char **blacklist, FILE *proc_self_mountinfo) {
         int r = 0;
 
         assert(m);
+        assert(proc_self_mountinfo);
 
         if (mount_entry_read_only(m))
-                r = bind_remount_recursive(mount_entry_path(m), true, blacklist);
+                r = bind_remount_recursive_with_mountinfo(mount_entry_path(m), true, blacklist, proc_self_mountinfo);
         else if (m->mode == PRIVATE_DEV) { /* Superblock can be readonly but the submounts can't */
                 if (mount(NULL, mount_entry_path(m), NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0)
                         r = -errno;
@@ -815,18 +817,24 @@ static int make_read_only(MountEntry *m, char **blacklist) {
         return r;
 }
 
-static bool namespace_info_mount_apivfs(const NameSpaceInfo *ns_info) {
+static bool namespace_info_mount_apivfs(const char *root_directory, const NameSpaceInfo *ns_info) {
         assert(ns_info);
 
-        /* ProtectControlGroups= and ProtectKernelTunables= imply MountAPIVFS=, since to protect the API VFS mounts,
-         * they need to be around in the first place... */
+        /*
+         * ProtectControlGroups= and ProtectKernelTunables= imply MountAPIVFS=,
+         * since to protect the API VFS mounts, they need to be around in the
+         * first place... and RootDirectory= or RootImage= need to be set.
+         */
 
-        return ns_info->mount_apivfs ||
-                ns_info->protect_control_groups ||
-                ns_info->protect_kernel_tunables;
+        /* root_directory should point to a mount point */
+        return root_directory &&
+                (ns_info->mount_apivfs ||
+                 ns_info->protect_control_groups ||
+                 ns_info->protect_kernel_tunables);
 }
 
 static unsigned namespace_calculate_mounts(
+                const char* root_directory,
                 const NameSpaceInfo *ns_info,
                 char** read_write_paths,
                 char** read_only_paths,
@@ -863,7 +871,7 @@ static unsigned namespace_calculate_mounts(
                 (ns_info->protect_control_groups ? 1 : 0) +
                 (ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) +
                 protect_home_cnt + protect_system_cnt +
-                (namespace_info_mount_apivfs(ns_info) ? ELEMENTSOF(apivfs_table) : 0);
+                (namespace_info_mount_apivfs(root_directory, ns_info) ? ELEMENTSOF(apivfs_table) : 0);
 }
 
 int setup_namespace(
@@ -931,6 +939,7 @@ int setup_namespace(
         }
 
         n_mounts = namespace_calculate_mounts(
+                        root_directory,
                         ns_info,
                         read_write_paths,
                         read_only_paths,
@@ -1009,7 +1018,7 @@ int setup_namespace(
                 if (r < 0)
                         goto finish;
 
-                if (namespace_info_mount_apivfs(ns_info)) {
+                if (namespace_info_mount_apivfs(root_directory, ns_info)) {
                         r = append_static_mounts(&m, apivfs_table, ELEMENTSOF(apivfs_table), ns_info->ignore_protect_paths);
                         if (r < 0)
                                 goto finish;
@@ -1044,6 +1053,10 @@ int setup_namespace(
                 }
         }
 
+        /* Try to set up the new root directory before mounting anything there */
+        if (root_directory)
+                (void) base_filesystem_create(root_directory, UID_INVALID, GID_INVALID);
+
         if (root_image) {
                 r = dissected_image_mount(dissected_image, root_directory, dissect_image_flags);
                 if (r < 0)
@@ -1070,9 +1083,18 @@ int setup_namespace(
         }
 
         if (n_mounts > 0) {
+                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
                 char **blacklist;
                 unsigned j;
 
+                /* Open /proc/self/mountinfo now as it may become unavailable if we mount anything on top of /proc.
+                 * For example, this is the case with the option: 'InaccessiblePaths=/proc' */
+                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+                if (!proc_self_mountinfo) {
+                        r = -errno;
+                        goto finish;
+                }
+
                 /* First round, add in all special mounts we need */
                 for (m = mounts; m < mounts + n_mounts; ++m) {
                         r = apply_mount(root_directory, m, tmp_dir, var_tmp_dir);
@@ -1088,7 +1110,7 @@ int setup_namespace(
 
                 /* Second round, flip the ro bits if necessary. */
                 for (m = mounts; m < mounts + n_mounts; ++m) {
-                        r = make_read_only(m, blacklist);
+                        r = make_read_only(m, blacklist, proc_self_mountinfo);
                         if (r < 0)
                                 goto finish;
                 }
index 2b96a9551b335a2db8b5698610545e7e50c46895..0f8a2d68e29e6de27a4559e915a27ea98cb4e06d 100644 (file)
@@ -135,7 +135,12 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
         fmt2 = strjoina("selinux: ", fmt);
 
         va_start(ap, fmt);
-        log_internalv(LOG_AUTH | callback_type_to_priority(type), 0, __FILE__, __LINE__, __FUNCTION__, fmt2, ap);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+        log_internalv(LOG_AUTH | callback_type_to_priority(type),
+                      0, __FILE__, __LINE__, __FUNCTION__,
+                      fmt2, ap);
+#pragma GCC diagnostic pop
         va_end(ap);
 
         return 0;
index 74054887b94bcafe8564fde58d8e3ddbecd8fadf..4c577db8d705f9849cc910604baa890e89403ad7 100644 (file)
@@ -45,6 +45,7 @@
 #include "service.h"
 #include "signal-util.h"
 #include "special.h"
+#include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
@@ -412,13 +413,12 @@ static int service_add_fd_store(Service *s, int fd, const char *name) {
         }
 
         r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs);
-        if (r < 0) {
+        if (r < 0 && r != -EPERM) { /* EPERM indicates fds that aren't pollable, which is OK */
                 free(fs->fdname);
                 free(fs);
                 return r;
-        }
-
-        (void) sd_event_source_set_description(fs->event_source, "service-fd-store");
+        } else if (r >= 0)
+                (void) sd_event_source_set_description(fs->event_source, "service-fd-store");
 
         LIST_PREPEND(fd_store, s->fd_store, fs);
         s->n_fd_store++;
@@ -1067,14 +1067,21 @@ static int service_coldplug(Unit *u) {
         return 0;
 }
 
-static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
+static int service_collect_fds(Service *s,
+                               int **fds,
+                               char ***fd_names,
+                               unsigned *n_storage_fds,
+                               unsigned *n_socket_fds) {
+
         _cleanup_strv_free_ char **rfd_names = NULL;
         _cleanup_free_ int *rfds = NULL;
-        int rn_fds = 0, r;
+        unsigned rn_socket_fds = 0, rn_storage_fds = 0;
+        int r;
 
         assert(s);
         assert(fds);
         assert(fd_names);
+        assert(n_socket_fds);
 
         if (s->socket_fd >= 0) {
 
@@ -1089,7 +1096,7 @@ static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
                 if (!rfd_names)
                         return -ENOMEM;
 
-                rn_fds = 1;
+                rn_socket_fds = 1;
         } else {
                 Iterator i;
                 Unit *u;
@@ -1115,20 +1122,20 @@ static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
 
                         if (!rfds) {
                                 rfds = cfds;
-                                rn_fds = cn_fds;
+                                rn_socket_fds = cn_fds;
 
                                 cfds = NULL;
                         } else {
                                 int *t;
 
-                                t = realloc(rfds, (rn_fds + cn_fds) * sizeof(int));
+                                t = realloc(rfds, (rn_socket_fds + cn_fds) * sizeof(int));
                                 if (!t)
                                         return -ENOMEM;
 
-                                memcpy(t + rn_fds, cfds, cn_fds * sizeof(int));
+                                memcpy(t + rn_socket_fds, cfds, cn_fds * sizeof(int));
 
                                 rfds = t;
-                                rn_fds += cn_fds;
+                                rn_socket_fds += cn_fds;
                         }
 
                         r = strv_extend_n(&rfd_names, socket_fdname(sock), cn_fds);
@@ -1139,40 +1146,45 @@ static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
 
         if (s->n_fd_store > 0) {
                 ServiceFDStore *fs;
+                unsigned n_fds;
                 char **nl;
                 int *t;
 
-                t = realloc(rfds, (rn_fds + s->n_fd_store) * sizeof(int));
+                t = realloc(rfds, (rn_socket_fds + s->n_fd_store) * sizeof(int));
                 if (!t)
                         return -ENOMEM;
 
                 rfds = t;
 
-                nl = realloc(rfd_names, (rn_fds + s->n_fd_store + 1) * sizeof(char*));
+                nl = realloc(rfd_names, (rn_socket_fds + s->n_fd_store + 1) * sizeof(char*));
                 if (!nl)
                         return -ENOMEM;
 
                 rfd_names = nl;
+                n_fds = rn_socket_fds;
 
                 LIST_FOREACH(fd_store, fs, s->fd_store) {
-                        rfds[rn_fds] = fs->fd;
-                        rfd_names[rn_fds] = strdup(strempty(fs->fdname));
-                        if (!rfd_names[rn_fds])
+                        rfds[n_fds] = fs->fd;
+                        rfd_names[n_fds] = strdup(strempty(fs->fdname));
+                        if (!rfd_names[n_fds])
                                 return -ENOMEM;
 
-                        rn_fds++;
+                        rn_storage_fds++;
+                        n_fds++;
                 }
 
-                rfd_names[rn_fds] = NULL;
+                rfd_names[n_fds] = NULL;
         }
 
         *fds = rfds;
         *fd_names = rfd_names;
+        *n_socket_fds = rn_socket_fds;
+        *n_storage_fds = rn_storage_fds;
 
         rfds = NULL;
         rfd_names = NULL;
 
-        return rn_fds;
+        return 0;
 }
 
 static bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) {
@@ -1203,7 +1215,7 @@ static int service_spawn(
 
         _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL, **fd_names = NULL;
         _cleanup_free_ int *fds = NULL;
-        unsigned n_fds = 0, n_env = 0;
+        unsigned n_storage_fds = 0, n_socket_fds = 0, n_env = 0;
         const char *path;
         pid_t pid;
 
@@ -1247,12 +1259,11 @@ static int service_spawn(
             s->exec_context.std_output == EXEC_OUTPUT_SOCKET ||
             s->exec_context.std_error == EXEC_OUTPUT_SOCKET) {
 
-                r = service_collect_fds(s, &fds, &fd_names);
+                r = service_collect_fds(s, &fds, &fd_names, &n_storage_fds, &n_socket_fds);
                 if (r < 0)
                         return r;
 
-                n_fds = r;
-                log_unit_debug(UNIT(s), "Passing %i fds to service", n_fds);
+                log_unit_debug(UNIT(s), "Passing %i fds to service", n_storage_fds + n_socket_fds);
         }
 
         r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), timeout));
@@ -1346,7 +1357,8 @@ static int service_spawn(
         exec_params.environment = final_env;
         exec_params.fds = fds;
         exec_params.fd_names = fd_names;
-        exec_params.n_fds = n_fds;
+        exec_params.n_storage_fds = n_storage_fds;
+        exec_params.n_socket_fds = n_socket_fds;
         exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
         exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
         exec_params.cgroup_path = path;
@@ -2140,6 +2152,79 @@ _pure_ static bool service_can_reload(Unit *u) {
         return !!s->exec_command[SERVICE_EXEC_RELOAD];
 }
 
+static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecCommand *current) {
+        Service *s = SERVICE(u);
+        unsigned idx = 0;
+        ExecCommand *first, *c;
+
+        assert(s);
+
+        first = s->exec_command[id];
+
+        /* Figure out where we are in the list by walking back to the beginning */
+        for (c = current; c != first; c = c->command_prev)
+                idx++;
+
+        return idx;
+}
+
+static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command) {
+        Service *s = SERVICE(u);
+        ServiceExecCommand id;
+        unsigned idx;
+        const char *type;
+        char **arg;
+        _cleanup_free_ char *args = NULL, *p = NULL;
+        size_t allocated = 0, length = 0;
+
+        assert(s);
+        assert(f);
+
+        if (!command)
+                return 0;
+
+        if (command == s->control_command) {
+                type = "control";
+                id = s->control_command_id;
+        } else {
+                type = "main";
+                id = SERVICE_EXEC_START;
+        }
+
+        idx = service_exec_command_index(u, id, command);
+
+        STRV_FOREACH(arg, command->argv) {
+                size_t n;
+                _cleanup_free_ char *e = NULL;
+
+                e = xescape(*arg, WHITESPACE);
+                if (!e)
+                        return -ENOMEM;
+
+                n = strlen(e);
+                if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1))
+                        return -ENOMEM;
+
+                if (length > 0)
+                        args[length++] = ' ';
+
+                memcpy(args + length, e, n);
+                length += n;
+        }
+
+        if (!GREEDY_REALLOC(args, allocated, length + 1))
+                return -ENOMEM;
+        args[length++] = 0;
+
+        p = xescape(command->path, WHITESPACE);
+        if (!p)
+                return -ENOMEM;
+
+        fprintf(f, "%s-command=%s %u %s %s\n", type, service_exec_command_to_string(id), idx, p, args);
+
+        return 0;
+}
+
 static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         Service *s = SERVICE(u);
         ServiceFDStore *fs;
@@ -2167,11 +2252,8 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         if (r < 0)
                 return r;
 
-        /* FIXME: There's a minor uncleanliness here: if there are
-         * multiple commands attached here, we will start from the
-         * first one again */
-        if (s->control_command_id >= 0)
-                unit_serialize_item(u, f, "control-command", service_exec_command_to_string(s->control_command_id));
+        service_serialize_exec_command(u, f, s->control_command);
+        service_serialize_exec_command(u, f, s->main_command);
 
         r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd);
         if (r < 0)
@@ -2227,6 +2309,106 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         return 0;
 }
 
+static int service_deserialize_exec_command(Unit *u, const char *key, const char *value) {
+        Service *s = SERVICE(u);
+        int r;
+        unsigned idx = 0, i;
+        bool control, found = false;
+        ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID;
+        ExecCommand *command = NULL;
+        _cleanup_free_ char *path = NULL;
+        _cleanup_strv_free_ char **argv = NULL;
+
+        enum ExecCommandState {
+                STATE_EXEC_COMMAND_TYPE,
+                STATE_EXEC_COMMAND_INDEX,
+                STATE_EXEC_COMMAND_PATH,
+                STATE_EXEC_COMMAND_ARGS,
+                _STATE_EXEC_COMMAND_MAX,
+                _STATE_EXEC_COMMAND_INVALID = -1,
+        } state;
+
+        assert(s);
+        assert(key);
+        assert(value);
+
+        control = streq(key, "control-command");
+
+        state = STATE_EXEC_COMMAND_TYPE;
+
+        for (;;) {
+                _cleanup_free_ char *arg = NULL;
+
+                r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE);
+                if (r == 0)
+                        break;
+                else if (r < 0)
+                        return r;
+
+                switch (state) {
+                case STATE_EXEC_COMMAND_TYPE:
+                        id = service_exec_command_from_string(arg);
+                        if (id < 0)
+                                return -EINVAL;
+
+                        state = STATE_EXEC_COMMAND_INDEX;
+                        break;
+                case STATE_EXEC_COMMAND_INDEX:
+                        r = safe_atou(arg, &idx);
+                        if (r < 0)
+                                return -EINVAL;
+
+                        state = STATE_EXEC_COMMAND_PATH;
+                        break;
+                case STATE_EXEC_COMMAND_PATH:
+                        path = arg;
+                        arg = NULL;
+                        state = STATE_EXEC_COMMAND_ARGS;
+
+                        if (!path_is_absolute(path))
+                                return -EINVAL;
+                        break;
+                case STATE_EXEC_COMMAND_ARGS:
+                        r = strv_extend(&argv, arg);
+                        if (r < 0)
+                                return -ENOMEM;
+                        break;
+                default:
+                        assert_not_reached("Unknown error at deserialization of exec command");
+                        break;
+                }
+        }
+
+        if (state != STATE_EXEC_COMMAND_ARGS)
+                return -EINVAL;
+
+        /* Let's check whether exec command on given offset matches data that we just deserialized */
+        for (command = s->exec_command[id], i = 0; command; command = command->command_next, i++) {
+                if (i != idx)
+                        continue;
+
+                found = strv_equal(argv, command->argv) && streq(command->path, path);
+                break;
+        }
+
+        if (!found) {
+                /* Command at the index we serialized is different, let's look for command that exactly
+                 * matches but is on different index. If there is no such command we will not resume execution. */
+                for (command = s->exec_command[id]; command; command = command->command_next)
+                        if (strv_equal(command->argv, argv) && streq(command->path, path))
+                                break;
+        }
+
+        if (command && control)
+                s->control_command = command;
+        else if (command)
+                s->main_command = command;
+        else
+                log_unit_warning(u, "Current command vanished from the unit file, execution of the command list won't be resumed.");
+
+        return 0;
+}
+
 static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
         Service *s = SERVICE(u);
         int r;
@@ -2309,16 +2491,6 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                         s->status_text = t;
                 }
 
-        } else if (streq(key, "control-command")) {
-                ServiceExecCommand id;
-
-                id = service_exec_command_from_string(value);
-                if (id < 0)
-                        log_unit_debug(u, "Failed to parse exec-command value: %s", value);
-                else {
-                        s->control_command_id = id;
-                        s->control_command = s->exec_command[id];
-                }
         } else if (streq(key, "accept-socket")) {
                 Unit *socket;
 
@@ -2437,6 +2609,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                         s->watchdog_override_enable = true;
                         s->watchdog_override_usec = watchdog_override_usec;
                 }
+        } else if (STR_IN_SET(key, "main-command", "control-command")) {
+                r = service_deserialize_exec_command(u, key, value);
+                if (r < 0)
+                        log_unit_debug_errno(u, r, "Failed to parse serialized command \"%s\": %m", value);
         } else
                 log_unit_debug(u, "Unknown serialization key: %s", key);
 
@@ -2693,7 +2869,6 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                 log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG :
                            (code == CLD_EXITED ? LOG_NOTICE : LOG_WARNING),
-                           LOG_UNIT_ID(u),
                            LOG_UNIT_MESSAGE(u, "Main process exited, code=%s, status=%i/%s",
                                             sigchld_code_to_string(code), status,
                                             strna(code == CLD_EXITED
@@ -2701,6 +2876,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                                                   : signal_to_string(status))),
                            "EXIT_CODE=%s", sigchld_code_to_string(code),
                            "EXIT_STATUS=%i", status,
+                           LOG_UNIT_ID(u),
                            NULL);
 
                 if (s->result == SERVICE_SUCCESS)
@@ -3407,15 +3583,6 @@ static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] =
 
 DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand);
 
-static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
-        [NOTIFY_NONE] = "none",
-        [NOTIFY_MAIN] = "main",
-        [NOTIFY_EXEC] = "exec",
-        [NOTIFY_ALL] = "all"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
-
 static const char* const notify_state_table[_NOTIFY_STATE_MAX] = {
         [NOTIFY_UNKNOWN] = "unknown",
         [NOTIFY_READY] = "ready",
index ff9cfaeb88e7498808c6e3f32409578387bca61b..f4ba604f69a0bf8cdf99796b5af354b14f542011 100644 (file)
@@ -61,15 +61,6 @@ typedef enum ServiceExecCommand {
         _SERVICE_EXEC_COMMAND_INVALID = -1
 } ServiceExecCommand;
 
-typedef enum NotifyAccess {
-        NOTIFY_NONE,
-        NOTIFY_ALL,
-        NOTIFY_MAIN,
-        NOTIFY_EXEC,
-        _NOTIFY_ACCESS_MAX,
-        _NOTIFY_ACCESS_INVALID = -1
-} NotifyAccess;
-
 typedef enum NotifyState {
         NOTIFY_UNKNOWN,
         NOTIFY_READY,
@@ -218,9 +209,6 @@ ServiceType service_type_from_string(const char *s) _pure_;
 const char* service_exec_command_to_string(ServiceExecCommand i) _const_;
 ServiceExecCommand service_exec_command_from_string(const char *s) _pure_;
 
-const char* notify_access_to_string(NotifyAccess i) _const_;
-NotifyAccess notify_access_from_string(const char *s) _pure_;
-
 const char* notify_state_to_string(NotifyState i) _const_;
 NotifyState notify_state_from_string(const char *s) _pure_;
 
index a2309b77264130e621c6a482de8372173e3268cd..a7d5e57936d18336f258733d01f2ece7e06ef72b 100644 (file)
@@ -403,7 +403,7 @@ int main(int argc, char *argv[]) {
                         _cleanup_free_ char *param = NULL;
 
                         r = read_one_line_file("/run/systemd/reboot-param", &param);
-                        if (r < 0)
+                        if (r < 0 && r != -ENOENT)
                                 log_warning_errno(r, "Failed to read reboot parameter file: %m");
 
                         if (!isempty(param)) {
index 5a6d11cfa1f5d3763d7bee9b64ad6691c2ab477c..adf22931422c8f30fb4c1b22c9037e2a2587e0fb 100644 (file)
@@ -264,6 +264,54 @@ static int write_netlabel_rules(const char* srcdir) {
         return r;
 }
 
+static int write_onlycap_list(void) {
+        _cleanup_close_ int onlycap_fd = -1;
+        _cleanup_free_ char *list = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        size_t len = 0, allocated = 0;
+        char buf[LINE_MAX];
+        int r;
+
+        f = fopen("/etc/smack/onlycap", "re");
+        if (!f) {
+                if (errno != ENOENT)
+                        log_warning_errno(errno, "Failed to read '/etc/smack/onlycap'");
+                return errno == ENOENT ? ENOENT : -errno;
+        }
+
+        FOREACH_LINE(buf, f, return -errno) {
+                size_t l;
+
+                if (isempty(truncate_nl(buf)) || strchr(COMMENTS, *buf))
+                        continue;
+
+                l = strlen(buf);
+                if (!GREEDY_REALLOC(list, allocated, len + l + 1))
+                        return log_oom();
+
+                stpcpy(list + len, buf)[0] = ' ';
+                len += l + 1;
+        }
+
+        if (!len)
+                return 0;
+
+        list[len - 1] = 0;
+
+        onlycap_fd = open("/sys/fs/smackfs/onlycap", O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+        if (onlycap_fd < 0) {
+                if (errno != ENOENT)
+                        log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/onlycap'");
+                return -errno; /* negative error */
+        }
+
+        r = write(onlycap_fd, list, len);
+        if (r < 0)
+                return log_error_errno(errno, "Failed to write onlycap list(%s) to '/sys/fs/smackfs/onlycap'", list);
+
+        return 0;
+}
+
 #endif
 
 int mac_smack_setup(bool *loaded_policy) {
@@ -338,6 +386,22 @@ int mac_smack_setup(bool *loaded_policy) {
                 break;
         }
 
+        r = write_onlycap_list();
+        switch(r) {
+        case -ENOENT:
+                log_debug("Smack is not enabled in the kernel.");
+                break;
+        case ENOENT:
+                log_debug("Smack onlycap list file '/etc/smack/onlycap' not found");
+                break;
+        case 0:
+                log_info("Successfully wrote Smack onlycap list.");
+                break;
+        default:
+                log_emergency_errno(r, "Failed to write Smack onlycap list.");
+                return r;
+        }
+
         *loaded_policy = true;
 
 #endif
index c4da227e0931144cd74c2e143bbbd78f68b869d1..8750643d926c3dcc357aa0aaa9e4ea2817e373a8 100644 (file)
@@ -2528,7 +2528,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                 else
                         LIST_FOREACH(port, p, s->ports)
                                 if (p->type == SOCKET_FIFO &&
-                                    path_equal_or_files_same(p->path, value+skip)) {
+                                    path_equal_or_files_same(p->path, value+skip, 0)) {
                                         socket_port_take_fd(p, fds, fd);
                                         break;
                                 }
@@ -2542,7 +2542,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                 else
                         LIST_FOREACH(port, p, s->ports)
                                 if (p->type == SOCKET_SPECIAL &&
-                                    path_equal_or_files_same(p->path, value+skip)) {
+                                    path_equal_or_files_same(p->path, value+skip, 0)) {
                                         socket_port_take_fd(p, fds, fd);
                                         break;
                                 }
@@ -2596,7 +2596,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                 else
                         LIST_FOREACH(port, p, s->ports)
                                 if (p->type == SOCKET_USB_FUNCTION &&
-                                    path_equal_or_files_same(p->path, value+skip)) {
+                                    path_equal_or_files_same(p->path, value+skip, 0)) {
                                         socket_port_take_fd(p, fds, fd);
                                         break;
                                 }
index e9468e105ca9c11b7aa807cc9318b6e293686b98..4c3a74ce00a17bcf1998983c38747b1b2b11a349 100644 (file)
@@ -487,13 +487,14 @@ static void swap_set_state(Swap *s, SwapState state) {
         old_state = s->state;
         s->state = state;
 
-        if (state != SWAP_ACTIVATING &&
-            state != SWAP_ACTIVATING_SIGTERM &&
-            state != SWAP_ACTIVATING_SIGKILL &&
-            state != SWAP_ACTIVATING_DONE &&
-            state != SWAP_DEACTIVATING &&
-            state != SWAP_DEACTIVATING_SIGTERM &&
-            state != SWAP_DEACTIVATING_SIGKILL) {
+        if (!IN_SET(state,
+                    SWAP_ACTIVATING,
+                    SWAP_ACTIVATING_SIGTERM,
+                    SWAP_ACTIVATING_SIGKILL,
+                    SWAP_ACTIVATING_DONE,
+                    SWAP_DEACTIVATING,
+                    SWAP_DEACTIVATING_SIGTERM,
+                    SWAP_DEACTIVATING_SIGKILL)) {
                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                 swap_unwatch_control_pid(s);
                 s->control_command = NULL;
@@ -695,20 +696,19 @@ static void swap_enter_active(Swap *s, SwapResult f) {
 
 static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
         int r;
+        KillOperation kop;
 
         assert(s);
 
         if (s->result == SWAP_SUCCESS)
                 s->result = f;
 
-        r = unit_kill_context(
-                        UNIT(s),
-                        &s->kill_context,
-                        (state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM) ?
-                        KILL_KILL : KILL_TERMINATE,
-                        -1,
-                        s->control_pid,
-                        false);
+        if (IN_SET(state, SWAP_ACTIVATING_SIGTERM, SWAP_DEACTIVATING_SIGTERM))
+                kop = KILL_TERMINATE;
+        else
+                kop = KILL_KILL;
+
+        r = unit_kill_context(UNIT(s), &s->kill_context, kop, -1, s->control_pid, false);
         if (r < 0)
                 goto fail;
 
@@ -829,17 +829,18 @@ static int swap_start(Unit *u) {
         /* We cannot fulfill this request right now, try again later
          * please! */
 
-        if (s->state == SWAP_DEACTIVATING ||
-            s->state == SWAP_DEACTIVATING_SIGTERM ||
-            s->state == SWAP_DEACTIVATING_SIGKILL ||
-            s->state == SWAP_ACTIVATING_SIGTERM ||
-            s->state == SWAP_ACTIVATING_SIGKILL)
+        if (IN_SET(s->state,
+                   SWAP_DEACTIVATING,
+                   SWAP_DEACTIVATING_SIGTERM,
+                   SWAP_DEACTIVATING_SIGKILL,
+                   SWAP_ACTIVATING_SIGTERM,
+                   SWAP_ACTIVATING_SIGKILL))
                 return -EAGAIN;
 
         if (s->state == SWAP_ACTIVATING)
                 return 0;
 
-        assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
+        assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED));
 
         if (detect_container() > 0)
                 return -EPERM;
@@ -873,16 +874,15 @@ static int swap_stop(Unit *u) {
 
         assert(s);
 
-        if (s->state == SWAP_DEACTIVATING ||
-            s->state == SWAP_DEACTIVATING_SIGTERM ||
-            s->state == SWAP_DEACTIVATING_SIGKILL ||
-            s->state == SWAP_ACTIVATING_SIGTERM ||
-            s->state == SWAP_ACTIVATING_SIGKILL)
+        if (IN_SET(s->state,
+                   SWAP_DEACTIVATING,
+                   SWAP_DEACTIVATING_SIGTERM,
+                   SWAP_DEACTIVATING_SIGKILL,
+                   SWAP_ACTIVATING_SIGTERM,
+                   SWAP_ACTIVATING_SIGKILL))
                 return 0;
 
-        assert(s->state == SWAP_ACTIVATING ||
-               s->state == SWAP_ACTIVATING_DONE ||
-               s->state == SWAP_ACTIVE);
+        assert(IN_SET(s->state, SWAP_ACTIVATING, SWAP_ACTIVATING_DONE, SWAP_ACTIVE));
 
         if (detect_container() > 0)
                 return -EPERM;
@@ -1340,7 +1340,7 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
         struct udev_list_entry *item = NULL, *first = NULL;
         _cleanup_free_ char *e = NULL;
         const char *dn;
-        Swap *s;
+        Unit *u;
         int r = 0;
 
         assert(m);
@@ -1354,9 +1354,9 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
         if (r < 0)
                 return r;
 
-        s = hashmap_get(m->units, e);
-        if (s)
-                r = swap_set_devnode(s, dn);
+        u = manager_get_unit(m, e);
+        if (u)
+                r = swap_set_devnode(SWAP(u), dn);
 
         first = udev_device_get_devlinks_list_entry(dev);
         udev_list_entry_foreach(item, first) {
@@ -1367,9 +1367,9 @@ int swap_process_device_new(Manager *m, struct udev_device *dev) {
                 if (q < 0)
                         return q;
 
-                s = hashmap_get(m->units, n);
-                if (s) {
-                        q = swap_set_devnode(s, dn);
+                u = manager_get_unit(m, n);
+                if (u) {
+                        q = swap_set_devnode(SWAP(u), dn);
                         if (q < 0)
                                 r = q;
                 }
index ff0d764fb5b7f5d16fa6b223ae42530db8762b3a..2a58dd394d09861534854b322208a99fd88c197b 100644 (file)
@@ -63,6 +63,9 @@ static int target_add_default_dependencies(Target *t) {
 
         assert(t);
 
+        if (!UNIT(t)->default_dependencies)
+                return 0;
+
         /* Imply ordering for requirement dependencies on target
          * units. Note that when the user created a contradicting
          * ordering manually we won't add anything in here to make
@@ -93,7 +96,7 @@ static int target_load(Unit *u) {
                 return r;
 
         /* This is a new unit? Then let's add in some extras */
-        if (u->load_state == UNIT_LOADED && u->default_dependencies) {
+        if (u->load_state == UNIT_LOADED) {
                 r = target_add_default_dependencies(t);
                 if (r < 0)
                         return r;
index af67b7591a54c658453f2111c3ab637c8a63bbca..701949fd60df580a3c84ce81f476bdd8d53f5cd8 100644 (file)
@@ -316,21 +316,6 @@ static void timer_enter_elapsed(Timer *t, bool leave_around) {
                 timer_enter_dead(t, TIMER_SUCCESS);
 }
 
-static usec_t monotonic_to_boottime(usec_t t) {
-        usec_t a, b;
-
-        if (t <= 0)
-                return 0;
-
-        a = now(clock_boottime_or_monotonic());
-        b = now(CLOCK_MONOTONIC);
-
-        if (t + a > b)
-                return t + a - b;
-        else
-                return 0;
-}
-
 static void add_random(Timer *t, usec_t *v) {
         char s[FORMAT_TIMESPAN_MAX];
         usec_t add;
@@ -355,9 +340,9 @@ static void add_random(Timer *t, usec_t *v) {
 
 static void timer_enter_waiting(Timer *t, bool initial) {
         bool found_monotonic = false, found_realtime = false;
-        usec_t ts_realtime, ts_monotonic;
-        usec_t base = 0;
         bool leave_around = false;
+        triple_timestamp ts;
+        usec_t base = 0;
         TimerValue *v;
         Unit *trigger;
         int r;
@@ -371,11 +356,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                 return;
         }
 
-        /* If we shall wake the system we use the boottime clock
-         * rather than the monotonic clock. */
-
-        ts_realtime = now(CLOCK_REALTIME);
-        ts_monotonic = now(t->wake_system ? clock_boottime_or_monotonic() : CLOCK_MONOTONIC);
+        triple_timestamp_get(&ts);
         t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
 
         LIST_FOREACH(value, v, t->values) {
@@ -391,7 +372,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                          * to that. If we don't just start from
                          * now. */
 
-                        b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts_realtime;
+                        b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts.realtime;
 
                         r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
                         if (r < 0)
@@ -405,13 +386,14 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                         found_realtime = true;
 
                 } else  {
+
                         switch (v->base) {
 
                         case TIMER_ACTIVE:
                                 if (state_translation_table[t->state] == UNIT_ACTIVE)
                                         base = UNIT(t)->inactive_exit_timestamp.monotonic;
                                 else
-                                        base = ts_monotonic;
+                                        base = ts.monotonic;
                                 break;
 
                         case TIMER_BOOT:
@@ -456,12 +438,11 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                                 assert_not_reached("Unknown timer base");
                         }
 
-                        if (t->wake_system)
-                                base = monotonic_to_boottime(base);
-
-                        v->next_elapse = base + v->value;
+                        v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
 
-                        if (!initial && v->next_elapse < ts_monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
+                        if (!initial &&
+                            v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
+                            IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
                                 /* This is a one time trigger, disable it now */
                                 v->disabled = true;
                                 continue;
@@ -488,7 +469,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
 
                 add_random(t, &t->next_elapse_monotonic_or_boottime);
 
-                left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0;
+                left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)));
                 log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
 
                 if (t->monotonic_event_source) {
index 9c4b64f8981ba2b2fc53485a877091113966d0b2..546c60d75075e5abf611c21eb2df3fa3506f8ab0 100644 (file)
@@ -78,6 +78,8 @@ struct Timer {
         char *stamp_path;
 };
 
+#define TIMER_MONOTONIC_CLOCK(t) ((t)->wake_system && clock_boottime_supported() ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC)
+
 void timer_free_values(Timer *t);
 
 extern const UnitVTable timer_vtable;
index b6d106241452ec59f1a71bf5904dc79c54b8f1a2..a2dfd8ae90024fda5888c1eabd4069cb853a9d93 100644 (file)
@@ -632,7 +632,7 @@ static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
 
                 job_add_to_run_queue(j);
                 job_add_to_dbus_queue(j);
-                job_start_timer(j);
+                job_start_timer(j, false);
                 job_shutdown_magic(j);
         }
 
index 2f4b12bdb9ca29a117cf8711e29fe04226238c56..591dac71f0364b97aecf62d6437f829859f5fb59 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/dm-ioctl.h>
 #include <linux/loop.h>
 #include <string.h>
 #include <sys/mount.h>
@@ -31,6 +30,7 @@
 #include "escape.h"
 #include "fd-util.h"
 #include "fstab-util.h"
+#include "linux-3.13/dm-ioctl.h"
 #include "list.h"
 #include "mount-setup.h"
 #include "path-util.h"
@@ -369,6 +369,14 @@ static int delete_dm(dev_t devnum) {
         return 0;
 }
 
+static bool nonunmountable_path(const char *path) {
+        return path_equal(path, "/")
+#ifndef HAVE_SPLIT_USR
+                || path_equal(path, "/usr")
+#endif
+                || path_startswith(path, "/run/initramfs");
+}
+
 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
         MountPoint *m, *n;
         int n_failed = 0;
@@ -404,21 +412,21 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
                          * somehwere else via a bind mount. If we
                          * explicitly remount the super block of that
                          * alias read-only we hence should be
-                         * relatively safe regarding keeping the fs we
-                         * can otherwise not see dirty. */
+                         * relatively safe regarding keeping dirty an fs
+                         * we cannot otherwise see. */
                         log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
-                        (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
+                        if (mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options) < 0) {
+                                if (log_error)
+                                        log_notice_errno(errno, "Failed to remount '%s' read-only: %m", m->path);
+                                if (nonunmountable_path(m->path))
+                                        n_failed++;
+                        }
                 }
 
                 /* Skip / and /usr since we cannot unmount that
                  * anyway, since we are running from it. They have
                  * already been remounted ro. */
-                if (path_equal(m->path, "/")
-#ifndef HAVE_SPLIT_USR
-                    || path_equal(m->path, "/usr")
-#endif
-                    || path_startswith(m->path, "/run/initramfs")
-                )
+                if (nonunmountable_path(m->path))
                         continue;
 
                 /* Trying to umount. We don't force here since we rely
@@ -430,8 +438,9 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
                                 *changed = true;
 
                         mount_point_free(head, m);
-                } else if (log_error) {
-                        log_warning_errno(errno, "Could not unmount %s: %m", m->path);
+                } else {
+                        if (log_error)
+                                log_warning_errno(errno, "Could not unmount %s: %m", m->path);
                         n_failed++;
                 }
         }
@@ -555,8 +564,6 @@ int umount_all(bool *changed) {
 
         /* umount one more time with logging enabled */
         r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
-        if (r <= 0)
-                goto end;
 
   end:
         mount_points_list_free(&mp_list_head);
index f76b6c30a83bed4c11b53f0a5a8986c0ff81809d..b28eeb2262ff69dfe314f8b889db56301d8f55ca 100644 (file)
@@ -99,6 +99,7 @@ Unit *unit_new(Manager *m, size_t size) {
         u->on_failure_job_mode = JOB_REPLACE;
         u->cgroup_inotify_wd = -1;
         u->job_timeout = USEC_INFINITY;
+        u->job_running_timeout = USEC_INFINITY;
         u->ref_uid = UID_INVALID;
         u->ref_gid = GID_INVALID;
         u->cpu_usage_last = NSEC_INFINITY;
@@ -955,9 +956,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 "%s\tPerpetual: %s\n"
                 "%s\tSlice: %s\n"
                 "%s\tCGroup: %s\n"
-                "%s\tCGroup realized: %s\n"
-                "%s\tCGroup mask: 0x%x\n"
-                "%s\tCGroup members mask: 0x%x\n",
+                "%s\tCGroup realized: %s\n",
                 prefix, u->id,
                 prefix, unit_description(u),
                 prefix, strna(u->instance),
@@ -974,9 +973,18 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, yes_no(u->perpetual),
                 prefix, strna(unit_slice_name(u)),
                 prefix, strna(u->cgroup_path),
-                prefix, yes_no(u->cgroup_realized),
-                prefix, u->cgroup_realized_mask,
-                prefix, u->cgroup_members_mask);
+                prefix, yes_no(u->cgroup_realized));
+
+        if (u->cgroup_realized_mask != 0) {
+                _cleanup_free_ char *s = NULL;
+                (void) cg_mask_to_string(u->cgroup_realized_mask, &s);
+                fprintf(f, "%s\tCGroup mask: %s\n", prefix, strnull(s));
+        }
+        if (u->cgroup_members_mask != 0) {
+                _cleanup_free_ char *s = NULL;
+                (void) cg_mask_to_string(u->cgroup_members_mask, &s);
+                fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
+        }
 
         SET_FOREACH(t, u->names, i)
                 fprintf(f, "%s\tName: %s\n", prefix, t);
@@ -1336,6 +1344,9 @@ int unit_load(Unit *u) {
                         goto fail;
                 }
 
+                if (u->job_running_timeout != USEC_INFINITY && u->job_running_timeout > u->job_timeout)
+                        log_unit_warning(u, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect.");
+
                 unit_update_cgroup_members_masks(u);
         }
 
@@ -1497,9 +1508,9 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
          * possible, which means we should avoid the low-level unit
          * name. */
         log_struct(LOG_INFO,
-                   mid,
-                   LOG_UNIT_ID(u),
                    LOG_MESSAGE("%s", buf),
+                   LOG_UNIT_ID(u),
+                   mid,
                    NULL);
 }
 
@@ -1821,6 +1832,10 @@ static void unit_check_binds_to(Unit *u) {
                 if (other->job)
                         continue;
 
+                if (!other->coldplugged)
+                        /* We might yet create a job for the other unit… */
+                        continue;
+
                 if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
                         continue;
 
@@ -2627,6 +2642,9 @@ static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd
                 return 0;
         }
 
+        old_owner = isempty(old_owner) ? NULL : old_owner;
+        new_owner = isempty(new_owner) ? NULL : new_owner;
+
         if (UNIT_VTABLE(u)->bus_name_owner_change)
                 UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
 
@@ -2693,6 +2711,25 @@ bool unit_can_serialize(Unit *u) {
         return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
 }
 
+static int unit_serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) {
+        _cleanup_free_ char *s = NULL;
+        int r = 0;
+
+        assert(f);
+        assert(key);
+
+        if (mask != 0) {
+                r = cg_mask_to_string(mask, &s);
+                if (r >= 0) {
+                        fputs(key, f);
+                        fputc('=', f);
+                        fputs(s, f);
+                        fputc('\n', f);
+                }
+        }
+        return r;
+}
+
 int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
         int r;
 
@@ -2740,6 +2777,8 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
         if (u->cgroup_path)
                 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
         unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
+        (void) unit_serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
+        (void) unit_serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
 
         if (uid_is_valid(u->ref_uid))
                 unit_serialize_item_format(u, f, "ref-uid", UID_FMT, u->ref_uid);
@@ -2997,6 +3036,20 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
 
                         continue;
 
+                } else if (streq(l, "cgroup-realized-mask")) {
+
+                        r = cg_mask_from_string(v, &u->cgroup_realized_mask);
+                        if (r < 0)
+                                log_unit_debug(u, "Failed to parse cgroup-realized-mask %s, ignoring.", v);
+                        continue;
+
+                } else if (streq(l, "cgroup-enabled-mask")) {
+
+                        r = cg_mask_from_string(v, &u->cgroup_enabled_mask);
+                        if (r < 0)
+                                log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v);
+                        continue;
+
                 } else if (streq(l, "ref-uid")) {
                         uid_t uid;
 
index 8052c234fdf23ffc412795294bf2ba35c82023d2..cf21b37e22d77d67e61d0c8c844964c317874263 100644 (file)
@@ -114,6 +114,7 @@ struct Unit {
 
         /* Job timeout and action to take */
         usec_t job_timeout;
+        usec_t job_running_timeout;
         EmergencyAction job_timeout_action;
         char *job_timeout_reboot_arg;
 
index 4c4f36aea097612a8a0937e72fd125df66e5ca20..a2c62e55a5f231915549b987000e2c1e5e304798 100644 (file)
@@ -144,10 +144,10 @@ static int parse_config(void) {
         };
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/coredump.conf",
-                                 CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
-                                 "Coredump\0",
-                                 config_item_table_lookup, items,
-                                 false, NULL);
+                                        CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
+                                        "Coredump\0",
+                                        config_item_table_lookup, items,
+                                        false, NULL);
 }
 
 static inline uint64_t storage_size_max(void) {
@@ -800,12 +800,11 @@ log:
         if (journald_crash) {
                 /* We cannot log to the journal, so just print the MESSAGE.
                  * The target was set previously to something safe. */
-                log_struct(LOG_ERR, core_message, NULL);
+                log_dispatch(LOG_ERR, 0, core_message);
                 return 0;
         }
 
-        if (core_message)
-                IOVEC_SET_STRING(iovec[n_iovec++], core_message);
+        IOVEC_SET_STRING(iovec[n_iovec++], core_message);
 
         if (truncated)
                 IOVEC_SET_STRING(iovec[n_iovec++], "COREDUMP_TRUNCATED=1");
@@ -1326,7 +1325,8 @@ static int process_backtrace(int argc, char *argv[]) {
                         log_error_errno(r, "Failed to parse journal entry on stdin: %m");
                         goto finish;
                 }
-                if (r == 1)
+                if (r == 1 ||                        /* complete entry */
+                    journal_importer_eof(&importer)) /* end of data */
                         break;
         }
 
diff --git a/src/coredump/meson.build b/src/coredump/meson.build
new file mode 100644 (file)
index 0000000..8f7d898
--- /dev/null
@@ -0,0 +1,24 @@
+systemd_coredump_sources = files('''
+        coredump.c
+        coredump-vacuum.c
+        coredump-vacuum.h
+'''.split())
+
+if conf.get('HAVE_ELFUTILS', false)
+        systemd_coredump_sources += files(['stacktrace.c',
+                                           'stacktrace.h'])
+endif
+
+coredumpctl_sources = files('coredumpctl.c')
+
+install_data('coredump.conf',
+             install_dir : pkgsysconfdir)
+
+tests += [
+        [['src/coredump/test-coredump-vacuum.c',
+          'src/coredump/coredump-vacuum.c',
+          'src/coredump/coredump-vacuum.h'],
+         [],
+         [],
+         'ENABLE_COREDUMP', 'manual'],
+]
index 91c653312ac050f7772152ce478140adb16b616a..3b4c086162d0bee2020e8116517dd12eedbd0837 100644 (file)
@@ -190,7 +190,7 @@ static int parse_one_option(const char *option) {
                 arg_type = CRYPT_PLAIN;
         else if ((val = startswith(option, "timeout="))) {
 
-                r = parse_sec(val, &arg_timeout);
+                r = parse_sec_fix_0(val, &arg_timeout);
                 if (r < 0) {
                         log_error_errno(r, "Failed to parse %s, ignoring: %m", option);
                         return 0;
index 9a44b15da71d238ebbf49ffa9a91f77829cbbb41..b0689ffff77f38663043a0f654f00373126a5a02 100644 (file)
@@ -205,7 +205,12 @@ static int found_override(const char *top, const char *bottom) {
         return k;
 }
 
-static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *toppath, const char *drop) {
+static int enumerate_dir_d(
+                OrderedHashmap *top,
+                OrderedHashmap *bottom,
+                OrderedHashmap *drops,
+                const char *toppath, const char *drop) {
+
         _cleanup_free_ char *unit = NULL;
         _cleanup_free_ char *path = NULL;
         _cleanup_strv_free_ char **list = NULL;
@@ -234,8 +239,10 @@ static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const
         if (r < 0)
                 return log_error_errno(r, "Failed to enumerate %s: %m", path);
 
+        strv_sort(list);
+
         STRV_FOREACH(file, list) {
-                Hashmap *h;
+                OrderedHashmap *h;
                 int k;
                 char *p;
                 char *d;
@@ -249,7 +256,7 @@ static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const
                 d = p + strlen(toppath) + 1;
 
                 log_debug("Adding at top: %s %s %s", d, special_glyph(ARROW), p);
-                k = hashmap_put(top, d, p);
+                k = ordered_hashmap_put(top, d, p);
                 if (k >= 0) {
                         p = strdup(p);
                         if (!p)
@@ -261,19 +268,19 @@ static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const
                 }
 
                 log_debug("Adding at bottom: %s %s %s", d, special_glyph(ARROW), p);
-                free(hashmap_remove(bottom, d));
-                k = hashmap_put(bottom, d, p);
+                free(ordered_hashmap_remove(bottom, d));
+                k = ordered_hashmap_put(bottom, d, p);
                 if (k < 0) {
                         free(p);
                         return k;
                 }
 
-                h = hashmap_get(drops, unit);
+                h = ordered_hashmap_get(drops, unit);
                 if (!h) {
-                        h = hashmap_new(&string_hash_ops);
+                        h = ordered_hashmap_new(&string_hash_ops);
                         if (!h)
                                 return -ENOMEM;
-                        hashmap_put(drops, unit, h);
+                        ordered_hashmap_put(drops, unit, h);
                         unit = strdup(unit);
                         if (!unit)
                                 return -ENOMEM;
@@ -285,7 +292,7 @@ static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const
 
                 log_debug("Adding to drops: %s %s %s %s %s",
                           unit, special_glyph(ARROW), basename(p), special_glyph(ARROW), p);
-                k = hashmap_put(h, basename(p), p);
+                k = ordered_hashmap_put(h, basename(p), p);
                 if (k < 0) {
                         free(p);
                         if (k != -EEXIST)
@@ -295,9 +302,18 @@ static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const
         return 0;
 }
 
-static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *path, bool dropins) {
-        _cleanup_closedir_ DIR *d;
+static int enumerate_dir(
+                OrderedHashmap *top,
+                OrderedHashmap *bottom,
+                OrderedHashmap *drops,
+                const char *path, bool dropins) {
+
+        _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
+        _cleanup_strv_free_ char **files = NULL, **dirs = NULL;
+        size_t n_files = 0, allocated_files = 0, n_dirs = 0, allocated_dirs = 0;
+        char **t;
+        int r;
 
         assert(top);
         assert(bottom);
@@ -315,40 +331,63 @@ static int enumerate_dir(Hashmap *top, Hashmap *bottom, Hashmap *drops, const ch
         }
 
         FOREACH_DIRENT_ALL(de, d, return -errno) {
-                int k;
-                char *p;
-
                 dirent_ensure_type(d, de);
 
-                if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d"))
-                        enumerate_dir_d(top, bottom, drops, path, de->d_name);
+                if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) {
+                        if (!GREEDY_REALLOC0(dirs, allocated_dirs, n_dirs + 2))
+                                return -ENOMEM;
+
+                        dirs[n_dirs] = strdup(de->d_name);
+                        if (!dirs[n_dirs])
+                                return -ENOMEM;
+                        n_dirs ++;
+                }
 
                 if (!dirent_is_file(de))
                         continue;
 
-                p = strjoin(path, "/", de->d_name);
+                if (!GREEDY_REALLOC0(files, allocated_files, n_files + 2))
+                        return -ENOMEM;
+
+                files[n_files] = strdup(de->d_name);
+                if (!files[n_files])
+                        return -ENOMEM;
+                n_files ++;
+        }
+
+        strv_sort(dirs);
+        strv_sort(files);
+
+        STRV_FOREACH(t, dirs) {
+                r = enumerate_dir_d(top, bottom, drops, path, *t);
+                if (r < 0)
+                        return r;
+        }
+
+        STRV_FOREACH(t, files) {
+                _cleanup_free_ char *p = NULL;
+
+                p = strjoin(path, "/", *t);
                 if (!p)
                         return -ENOMEM;
 
                 log_debug("Adding at top: %s %s %s", basename(p), special_glyph(ARROW), p);
-                k = hashmap_put(top, basename(p), p);
-                if (k >= 0) {
+                r = ordered_hashmap_put(top, basename(p), p);
+                if (r >= 0) {
                         p = strdup(p);
                         if (!p)
                                 return -ENOMEM;
-                } else if (k != -EEXIST) {
-                        free(p);
-                        return k;
-                }
+                } else if (r != -EEXIST)
+                        return r;
 
                 log_debug("Adding at bottom: %s %s %s", basename(p), special_glyph(ARROW), p);
-                free(hashmap_remove(bottom, basename(p)));
-                k = hashmap_put(bottom, basename(p), p);
-                if (k < 0) {
-                        free(p);
-                        return k;
-                }
+                free(ordered_hashmap_remove(bottom, basename(p)));
+                r = ordered_hashmap_put(bottom, basename(p), p);
+                if (r < 0)
+                        return r;
+                p = NULL;
         }
+
         return 0;
 }
 
@@ -370,8 +409,8 @@ static int should_skip_prefix(const char* p) {
 static int process_suffix(const char *suffix, const char *onlyprefix) {
         const char *p;
         char *f;
-        Hashmap *top, *bottom, *drops;
-        Hashmap *h;
+        OrderedHashmap *top, *bottom, *drops;
+        OrderedHashmap *h;
         char *key;
         int r = 0, k;
         Iterator i, j;
@@ -384,9 +423,9 @@ static int process_suffix(const char *suffix, const char *onlyprefix) {
 
         dropins = nulstr_contains(have_dropins, suffix);
 
-        top = hashmap_new(&string_hash_ops);
-        bottom = hashmap_new(&string_hash_ops);
-        drops = hashmap_new(&string_hash_ops);
+        top = ordered_hashmap_new(&string_hash_ops);
+        bottom = ordered_hashmap_new(&string_hash_ops);
+        drops = ordered_hashmap_new(&string_hash_ops);
         if (!top || !bottom || !drops) {
                 r = -ENOMEM;
                 goto finish;
@@ -415,10 +454,10 @@ static int process_suffix(const char *suffix, const char *onlyprefix) {
                         r = k;
         }
 
-        HASHMAP_FOREACH_KEY(f, key, top, i) {
+        ORDERED_HASHMAP_FOREACH_KEY(f, key, top, i) {
                 char *o;
 
-                o = hashmap_get(bottom, key);
+                o = ordered_hashmap_get(bottom, key);
                 assert(o);
 
                 if (!onlyprefix || startswith(o, onlyprefix)) {
@@ -433,23 +472,23 @@ static int process_suffix(const char *suffix, const char *onlyprefix) {
                         }
                 }
 
-                h = hashmap_get(drops, key);
+                h = ordered_hashmap_get(drops, key);
                 if (h)
-                        HASHMAP_FOREACH(o, h, j)
+                        ORDERED_HASHMAP_FOREACH(o, h, j)
                                 if (!onlyprefix || startswith(o, onlyprefix))
                                         n_found += notify_override_extended(f, o);
         }
 
 finish:
-        hashmap_free_free(top);
-        hashmap_free_free(bottom);
+        ordered_hashmap_free_free(top);
+        ordered_hashmap_free_free(bottom);
 
-        HASHMAP_FOREACH_KEY(h, key, drops, i) {
-                hashmap_free_free(hashmap_remove(drops, key));
-                hashmap_remove(drops, key);
+        ORDERED_HASHMAP_FOREACH_KEY(h, key, drops, i) {
+                ordered_hashmap_free_free(ordered_hashmap_remove(drops, key));
+                ordered_hashmap_remove(drops, key);
                 free(key);
         }
-        hashmap_free(drops);
+        ordered_hashmap_free(drops);
 
         return r < 0 ? r : n_found;
 }
index 2d4c4235e4bb7c213f78d87bd370d63a71b6d5a8..9c7250237340a3814e4e3db23edeef6a19559f85 100644 (file)
@@ -78,7 +78,7 @@ static int load_and_print(void) {
                 t = strchr(*i, '=');
                 assert(t);
 
-                q = shell_maybe_quote(t + 1);
+                q = shell_maybe_quote(t + 1, ESCAPE_BACKSLASH);
                 if (!q)
                         return log_oom();
 
index bc16290c7245dc0b5078e3524fec86d46e992b41..b3578d3e16bb835993cca2fdcd9a73a32944f323 100644 (file)
@@ -572,7 +572,7 @@ static int process_root_password(void) {
         if (!arg_root_password)
                 return 0;
 
-        r = dev_urandom(raw, 16);
+        r = acquire_random_bytes(raw, 16, true);
         if (r < 0)
                 return log_error_errno(r, "Failed to get salt: %m");
 
index 2677a3fb3212b78686efaba623303d315d310ca4..7f23b9fd7424813bc7bac9c5263319f47820fda3 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "fs-util.h"
 #include "fileio.h"
 #include "fstab-util.h"
 #include "generator.h"
@@ -176,7 +177,7 @@ static bool mount_in_initrd(struct mntent *me) {
 }
 
 static int write_timeout(FILE *f, const char *where, const char *opts,
-                const char *filter, const char *variable) {
+                         const char *filter, const char *variable) {
         _cleanup_free_ char *timeout = NULL;
         char timespan[FORMAT_TIMESPAN_MAX];
         usec_t u;
@@ -188,7 +189,7 @@ static int write_timeout(FILE *f, const char *where, const char *opts,
         if (r == 0)
                 return 0;
 
-        r = parse_sec(timeout, &u);
+        r = parse_sec_fix_0(timeout, &u);
         if (r < 0) {
                 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
                 return 0;
@@ -290,6 +291,7 @@ static int add_mount(
                 const char *dest,
                 const char *what,
                 const char *where,
+                const char *original_where,
                 const char *fstype,
                 const char *opts,
                 int passno,
@@ -358,7 +360,21 @@ static int add_mount(
                 "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
                 source);
 
-        if (!noauto && !nofail && !automount)
+        if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !automount &&
+            fstab_test_yes_no_option(opts, "bg\0" "fg\0")) {
+                /* The default retry timeout that mount.nfs uses for 'bg' mounts
+                 * is 10000 minutes, where as it uses 2 minutes for 'fg' mounts.
+                 * As we are making  'bg' mounts look like an 'fg' mount to
+                 * mount.nfs (so systemd can manage the job-control aspects of 'bg'),
+                 * we need to explicitly preserve that default, and also ensure
+                 * the systemd mount-timeout doesn't interfere.
+                 * By placing these options first, they can be over-ridden by
+                 * settings in /etc/fstab. */
+                opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,", opts, ",fg");
+                nofail = true;
+        }
+
+        if (!nofail && !automount)
                 fprintf(f, "Before=%s\n", post);
 
         if (!automount && opts) {
@@ -382,11 +398,10 @@ static int add_mount(
                         return r;
         }
 
-        fprintf(f,
-                "\n"
-                "[Mount]\n"
-                "Where=%s\n",
-                where);
+        fprintf(f, "\n[Mount]\n");
+        if (original_where)
+                fprintf(f, "# Canonicalized from %s\n", original_where);
+        fprintf(f, "Where=%s\n", where);
 
         r = write_what(f, what);
         if (r < 0)
@@ -399,6 +414,10 @@ static int add_mount(
         if (r < 0)
                 return r;
 
+        r = generator_write_device_deps(dest, what, where, opts);
+        if (r < 0)
+                return r;
+
         r = write_mount_timeout(f, where, opts);
         if (r < 0)
                 return r;
@@ -502,7 +521,7 @@ static int parse_fstab(bool initrd) {
         }
 
         while ((me = getmntent(f))) {
-                _cleanup_free_ char *where = NULL, *what = NULL;
+                _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
                 bool noauto, nofail;
                 int k;
 
@@ -522,8 +541,28 @@ static int parse_fstab(bool initrd) {
                 if (!where)
                         return log_oom();
 
-                if (is_path(where))
+                if (is_path(where)) {
                         path_kill_slashes(where);
+                        /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
+                         * mount units, but causes problems since it historically worked to have symlinks in e.g.
+                         * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
+                         * where a symlink refers to another mount target; this works assuming the sub-mountpoint
+                         * target is the final directory.
+                         */
+                        r = chase_symlinks(where, initrd ? "/sysroot" : NULL,
+                                           CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
+                                           &canonical_where);
+                        if (r < 0)
+                                /* In this case for now we continue on as if it wasn't a symlink */
+                                log_warning_errno(r, "Failed to read symlink target for %s: %m", where);
+                        else {
+                                if (streq(canonical_where, where))
+                                        canonical_where = mfree(canonical_where);
+                                else
+                                        log_debug("Canonicalized what=%s where=%s to %s",
+                                                  what, where, canonical_where);
+                        }
+                }
 
                 noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
                 nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
@@ -549,7 +588,8 @@ static int parse_fstab(bool initrd) {
 
                         k = add_mount(arg_dest,
                                       what,
-                                      where,
+                                      canonical_where ?: where,
+                                      canonical_where ? where: NULL,
                                       me->mnt_type,
                                       me->mnt_opts,
                                       me->mnt_passno,
@@ -612,6 +652,7 @@ static int add_sysroot_mount(void) {
         return add_mount(arg_dest,
                          what,
                          "/sysroot",
+                         NULL,
                          arg_root_fstype,
                          opts,
                          is_device_path(what) ? 1 : 0, /* passno */
@@ -666,6 +707,7 @@ static int add_sysroot_usr_mount(void) {
         return add_mount(arg_dest,
                          what,
                          "/sysroot/usr",
+                         NULL,
                          arg_usr_fstype,
                          opts,
                          is_device_path(what) ? 1 : 0, /* passno */
@@ -706,6 +748,7 @@ static int add_volatile_var(void) {
         return add_mount(arg_dest_late,
                          "tmpfs",
                          "/var",
+                         NULL,
                          "tmpfs",
                          "mode=0755",
                          0,
index 80f676e477b83353aa37aebc06a8778be3237362..a072242430a5c9575c1b6dd3dc6b746588edfa30 100644 (file)
@@ -17,7 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <blkid/blkid.h>
+#include <blkid.h>
 #include <stdlib.h>
 #include <sys/statfs.h>
 #include <unistd.h>
@@ -305,6 +305,15 @@ static int add_swap(const char *path) {
 
         assert(path);
 
+        /* Disable the swap auto logic if at least one swap is defined in /etc/fstab, see #6192. */
+        r = fstab_has_fstype("swap");
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse fstab: %m");
+        if (r > 0) {
+                log_debug("swap specified in fstab, ignoring.");
+                return 0;
+        }
+
         log_debug("Adding swap: %s", path);
 
         r = unit_name_from_path(path, ".swap", &name);
@@ -435,7 +444,10 @@ static int add_esp(DissectedPartition *p) {
         esp = access("/efi/", F_OK) >= 0 ? "/efi" : "/boot";
 
         /* We create an .automount which is not overridden by the .mount from the fstab generator. */
-        if (fstab_is_mount_point(esp)) {
+        r = fstab_is_mount_point(esp);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse fstab: %m");
+        if (r > 0) {
                 log_debug("%s specified in fstab, ignoring.", esp);
                 return 0;
         }
diff --git a/src/hostname/meson.build b/src/hostname/meson.build
new file mode 100644 (file)
index 0000000..d58caa6
--- /dev/null
@@ -0,0 +1,14 @@
+if conf.get('ENABLE_HOSTNAMED', false)
+        install_data('org.freedesktop.hostname1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.hostname1.service',
+                     install_dir : dbussystemservicedir)
+
+        custom_target(
+                'org.freedesktop.hostname1.policy',
+                input : 'org.freedesktop.hostname1.policy.in',
+                output : 'org.freedesktop.hostname1.policy',
+                command : intltool_command,
+                install : install_polkit,
+                install_dir : polkitpolicydir)
+endif
index a23b6147911b3df882d31fd65935d0364bb9df3d..793398ca6883a8ea6d3712dbf99366984c874959 100644 (file)
@@ -31,6 +31,7 @@
 #include "hwdb-util.h"
 #include "label.h"
 #include "mkdir.h"
+#include "path-util.h"
 #include "selinux-util.h"
 #include "strbuf.h"
 #include "string-util.h"
@@ -390,7 +391,7 @@ static int trie_store(struct trie *trie, const char *filename) {
         int64_t size;
         struct trie_header_f h = {
                 .signature = HWDB_SIG,
-                .tool_version = htole64(atoi(VERSION)),
+                .tool_version = htole64(atoi(PACKAGE_VERSION)),
                 .header_size = htole64(sizeof(struct trie_header_f)),
                 .node_size = htole64(sizeof(struct trie_node_f)),
                 .child_entry_size = htole64(sizeof(struct trie_child_entry_f)),
@@ -670,7 +671,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
         log_debug("strings dedup'ed: %8zu bytes (%8zu)",
                   trie->strings->dedup_len, trie->strings->dedup_count);
 
-        hwdb_bin = strjoin(arg_root, "/", arg_hwdb_bin_dir, "/hwdb.bin");
+        hwdb_bin = path_join(arg_root, arg_hwdb_bin_dir, "hwdb.bin");
         if (!hwdb_bin)
                 return -ENOMEM;
 
index 808eae38f88300c409d8f8068b2c6673c15fc590..55cf8e8edda36ed2f7acde75872499013befc2a3 100644 (file)
@@ -355,7 +355,7 @@ static int raw_import_process(RawImport *i) {
         }
         if (l == 0) {
                 if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
-                        log_error("Premature end of file: %m");
+                        log_error("Premature end of file.");
                         r = -EIO;
                         goto finish;
                 }
@@ -369,7 +369,7 @@ static int raw_import_process(RawImport *i) {
         if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
                 r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
                 if (r < 0) {
-                        log_error("Failed to detect file compression: %m");
+                        log_error_errno(r, "Failed to detect file compression: %m");
                         goto finish;
                 }
                 if (r == 0) /* Need more data */
index 1c229ec82fbdbd1550e9f748336591adc45b0602..ba140bccbdb006dc206592ee1fc9d91519bc26e6 100644 (file)
@@ -284,7 +284,7 @@ static int tar_import_process(TarImport *i) {
         }
         if (l == 0) {
                 if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
-                        log_error("Premature end of file: %m");
+                        log_error("Premature end of file.");
                         r = -EIO;
                         goto finish;
                 }
@@ -298,7 +298,7 @@ static int tar_import_process(TarImport *i) {
         if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
                 r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
                 if (r < 0) {
-                        log_error("Failed to detect file compression: %m");
+                        log_error_errno(r, "Failed to detect file compression: %m");
                         goto finish;
                 }
                 if (r == 0) /* Need more data */
diff --git a/src/import/meson.build b/src/import/meson.build
new file mode 100644 (file)
index 0000000..3fd58cc
--- /dev/null
@@ -0,0 +1,77 @@
+systemd_importd_sources = files('''
+        importd.c
+'''.split())
+
+systemd_pull_sources = files('''
+        pull.c
+        pull-raw.c
+        pull-raw.h
+        pull-tar.c
+        pull-tar.h
+        pull-job.c
+        pull-job.h
+        pull-common.c
+        pull-common.h
+        import-common.c
+        import-common.h
+        import-compress.c
+        import-compress.h
+        curl-util.c
+        curl-util.h
+        qcow2-util.c
+        qcow2-util.h
+'''.split())
+
+systemd_import_sources = files('''
+        import.c
+        import-raw.c
+        import-raw.h
+        import-tar.c
+        import-tar.h
+        import-common.c
+        import-common.h
+        import-compress.c
+        import-compress.h
+        qcow2-util.c
+        qcow2-util.h
+'''.split())
+
+systemd_export_sources = files('''
+        export.c
+        export-tar.c
+        export-tar.h
+        export-raw.c
+        export-raw.h
+        import-common.c
+        import-common.h
+        import-compress.c
+        import-compress.h
+'''.split())
+
+if conf.get('ENABLE_IMPORTD', false)
+        install_data('org.freedesktop.import1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.import1.service',
+                     install_dir : dbussystemservicedir)
+
+        custom_target(
+                'org.freedesktop.import1.policy',
+                input : 'org.freedesktop.import1.policy.in',
+                output : 'org.freedesktop.import1.policy',
+                command : intltool_command,
+                install : install_polkit,
+                install_dir : polkitpolicydir)
+
+        install_data('import-pubring.gpg',
+                     install_dir : rootlibexecdir)
+        # TODO: shouldn't this be in pkgdatadir?
+endif
+
+tests += [
+        [['src/import/test-qcow2.c',
+          'src/import/qcow2-util.c',
+          'src/import/qcow2-util.h'],
+         [libshared],
+         [libz],
+         'HAVE_ZLIB', 'manual'],
+]
index 62a9195cc49dad4574340d9756ae8376b3bb3050..78840dd8822835ee851f780562f7f6ad45c6f9aa 100644 (file)
@@ -275,6 +275,7 @@ int pull_make_verification_jobs(
 
         _cleanup_(pull_job_unrefp) PullJob *checksum_job = NULL, *signature_job = NULL;
         int r;
+        const char *chksums = NULL;
 
         assert(ret_checksum_job);
         assert(ret_signature_job);
@@ -284,10 +285,16 @@ int pull_make_verification_jobs(
         assert(glue);
 
         if (verify != IMPORT_VERIFY_NO) {
-                _cleanup_free_ char *checksum_url = NULL;
+                _cleanup_free_ char *checksum_url = NULL, *fn = NULL;
 
-                /* Queue job for the SHA256SUMS file for the image */
-                r = import_url_change_last_component(url, "SHA256SUMS", &checksum_url);
+                /* Queue jobs for the checksum file for the image. */
+                r = import_url_last_component(url, &fn);
+                if (r < 0)
+                        return r;
+
+                chksums = strjoina(fn, ".sha256");
+
+                r = import_url_change_last_component(url, chksums, &checksum_url);
                 if (r < 0)
                         return r;
 
@@ -362,6 +369,15 @@ static int verify_one(PullJob *checksum_job, PullJob *job) {
                    line,
                    strlen(line));
 
+        if (!p) {
+                line = strjoina(job->checksum, "  ", fn, "\n");
+
+                p = memmem(checksum_job->payload,
+                        checksum_job->payload_size,
+                        line,
+                        strlen(line));
+        }
+
         if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) {
                 log_error("DOWNLOAD INVALID: Checksum of %s file did not checkout, file has been tampered with.", fn);
                 return -EBADMSG;
@@ -378,7 +394,6 @@ int pull_verify(PullJob *main_job,
                 PullJob *signature_job) {
 
         _cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 };
-        _cleanup_free_ char *fn = NULL;
         _cleanup_close_ int sig_file = -1;
         char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX";
         _cleanup_(sigkill_waitp) pid_t pid = 0;
@@ -416,6 +431,9 @@ int pull_verify(PullJob *main_job,
         if (!signature_job)
                 return 0;
 
+        if (checksum_job->style == VERIFICATION_PER_FILE)
+                signature_job = checksum_job;
+
         assert(signature_job->state == PULL_JOB_DONE);
 
         if (!signature_job->payload || signature_job->payload_size <= 0) {
@@ -507,9 +525,11 @@ int pull_verify(PullJob *main_job,
                         cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH;
 
                 cmd[k++] = "--verify";
-                cmd[k++] = sig_file_path;
-                cmd[k++] = "-";
-                cmd[k++] = NULL;
+                if (checksum_job->style == VERIFICATION_PER_DIRECTORY) {
+                        cmd[k++] = sig_file_path;
+                        cmd[k++] = "-";
+                        cmd[k++] = NULL;
+                }
 
                 stdio_unset_cloexec();
 
index e550df2c57c5c9930c86eb1f04c90d5733cb89b0..320c21305addd68b27962252521fb551edb40c46 100644 (file)
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "hexdecoct.h"
+#include "import-util.h"
 #include "io-util.h"
 #include "machine-pool.h"
 #include "parse-util.h"
+#include "pull-common.h"
 #include "pull-job.h"
 #include "string-util.h"
 #include "strv.h"
@@ -73,6 +75,31 @@ static void pull_job_finish(PullJob *j, int ret) {
                 j->on_finished(j);
 }
 
+static int pull_job_restart(PullJob *j) {
+        int r;
+        char *chksum_url = NULL;
+
+        r = import_url_change_last_component(j->url, "SHA256SUMS", &chksum_url);
+        if (r < 0)
+                return r;
+
+        free(j->url);
+        j->url = chksum_url;
+        j->state = PULL_JOB_INIT;
+        j->payload = mfree(j->payload);
+        j->payload_size = 0;
+        j->payload_allocated = 0;
+        j->written_compressed = 0;
+        j->written_uncompressed = 0;
+        j->written_since_last_grow = 0;
+
+        r = pull_job_begin(j);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
         PullJob *j = NULL;
         CURLcode code;
@@ -102,6 +129,26 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
                 r = 0;
                 goto finish;
         } else if (status >= 300) {
+                if (status == 404 && j->style == VERIFICATION_PER_FILE) {
+
+                        /* retry pull job with SHA256SUMS file */
+                        r = pull_job_restart(j);
+                        if (r < 0)
+                                goto finish;
+
+                        code = curl_easy_getinfo(j->curl, CURLINFO_RESPONSE_CODE, &status);
+                        if (code != CURLE_OK) {
+                                log_error("Failed to retrieve response code: %s", curl_easy_strerror(code));
+                                r = -EIO;
+                                goto finish;
+                        }
+
+                        if (status == 0) {
+                                j->style = VERIFICATION_PER_DIRECTORY;
+                                return;
+                        }
+                }
+
                 log_error("HTTP request to %s failed with code %li.", j->url, status);
                 r = -EIO;
                 goto finish;
@@ -527,7 +574,8 @@ int pull_job_new(PullJob **ret, const char *url, CurlGlue *glue, void *userdata)
         j->glue = glue;
         j->content_length = (uint64_t) -1;
         j->start_usec = now(CLOCK_MONOTONIC);
-        j->compressed_max = j->uncompressed_max = 8LLU * 1024LLU * 1024LLU * 1024LLU; /* 8GB */
+        j->compressed_max = j->uncompressed_max = 64LLU * 1024LLU * 1024LLU * 1024LLU; /* 64GB safety limit */
+        j->style = VERIFICATION_STYLE_UNSET;
 
         j->url = strdup(url);
         if (!j->url)
index 3a152a50e3e88b592ffdabecb326f17b729d33f2..412b66cf22eb41b93d6075587135b739198b5452 100644 (file)
@@ -42,6 +42,12 @@ typedef enum PullJobState {
         _PULL_JOB_STATE_INVALID = -1,
 } PullJobState;
 
+typedef enum VerificationStyle {
+        VERIFICATION_STYLE_UNSET,
+        VERIFICATION_PER_FILE,        /* SuSE-style ".sha256" files with inline signature */
+        VERIFICATION_PER_DIRECTORY,   /* Ubuntu-style SHA256SUM files with detach SHA256SUM.gpg signatures */
+} VerificationStyle;
+
 #define PULL_JOB_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED))
 
 struct PullJob {
@@ -94,6 +100,8 @@ struct PullJob {
 
         bool grow_machine_directory;
         uint64_t written_since_last_grow;
+
+        VerificationStyle style;
 };
 
 int pull_job_new(PullJob **job, const char *url, CurlGlue *glue, void *userdata);
index 60a769e94438724e31362f95468ab68dd337fe0a..b45ac814a9fc0eb1bca8820942cdd3cb1e24dedd 100644 (file)
@@ -444,7 +444,7 @@ static int raw_pull_rename_auxiliary_file(
         assert(suffix);
         assert(path);
 
-        /* Regenerate final name for this auxiliary file, we might know the etag of the raw file now, and we shoud
+        /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and we should
          * incorporate it in the file name if we can */
         *path = mfree(*path);
         r = raw_pull_determine_path(i, suffix, path);
@@ -478,11 +478,9 @@ static void raw_pull_job_on_finished(PullJob *j) {
         } else if (j == i->settings_job) {
                 if (j->error != 0)
                         log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
-        } else if (j->error != 0) {
+        } else if (j->error != 0 && j != i->signature_job) {
                 if (j == i->checksum_job)
                         log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
-                else if (j == i->signature_job)
-                        log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
                 else
                         log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
 
@@ -500,6 +498,13 @@ static void raw_pull_job_on_finished(PullJob *j) {
         if (!raw_pull_is_done(i))
                 return;
 
+        if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
+                log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+
+                r = i->signature_job->error;
+                goto finish;
+        }
+
         if (i->roothash_job)
                 i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd);
         if (i->settings_job)
@@ -533,7 +538,7 @@ static void raw_pull_job_on_finished(PullJob *j) {
 
                 r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
                 if (r < 0) {
-                        log_error_errno(r, "Failed to move RAW file into place: %m");
+                        log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path);
                         goto finish;
                 }
 
@@ -575,7 +580,6 @@ static int raw_pull_job_on_open_disk_generic(
                 const char *extra,
                 char **temp_path) {
 
-        _cleanup_free_ char *p = NULL;
         int r;
 
         assert(i);
@@ -744,6 +748,7 @@ int raw_pull_start(
 
         if (i->checksum_job) {
                 i->checksum_job->on_progress = raw_pull_job_on_progress;
+                i->checksum_job->style = VERIFICATION_PER_FILE;
 
                 r = pull_job_begin(i->checksum_job);
                 if (r < 0)
index 91833d61747e4e1f3c3218bd3a3c99db4a653651..12211a6fc63e31e930fa2f8c8024118b644ddb21 100644 (file)
@@ -114,6 +114,7 @@ TarPull* tar_pull_unref(TarPull *i) {
         free(i->settings_path);
         free(i->image_root);
         free(i->local);
+
         return mfree(i);
 }
 
@@ -298,11 +299,9 @@ static void tar_pull_job_on_finished(PullJob *j) {
         if (j == i->settings_job) {
                 if (j->error != 0)
                         log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
-        } else if (j->error != 0) {
+        } else if (j->error != 0 && j != i->signature_job) {
                 if (j == i->checksum_job)
                         log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
-                else if (j == i->signature_job)
-                        log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
                 else
                         log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)");
 
@@ -317,6 +316,13 @@ static void tar_pull_job_on_finished(PullJob *j) {
         if (!tar_pull_is_done(i))
                 return;
 
+        if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) {
+                log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)");
+
+                r = i->signature_job->error;
+                goto finish;
+        }
+
         i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd);
         if (i->settings_job)
                 i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
@@ -353,7 +359,7 @@ static void tar_pull_job_on_finished(PullJob *j) {
 
                 r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
                 if (r < 0) {
-                        log_error_errno(r, "Failed to rename to final image name: %m");
+                        log_error_errno(r, "Failed to rename to final image name to %s: %m", i->final_path);
                         goto finish;
                 }
 
@@ -362,13 +368,14 @@ static void tar_pull_job_on_finished(PullJob *j) {
                 if (i->settings_job &&
                     i->settings_job->error == 0) {
 
-                        assert(i->settings_temp_path);
-                        assert(i->settings_path);
-
-                        /* Also move the settings file into place, if it exist. Note that we do so only if we also
+                        /* Also move the settings file into place, if it exists. Note that we do so only if we also
                          * moved the tar file in place, to keep things strictly in sync. */
+                        assert(i->settings_temp_path);
 
+                        /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and
+                         * we should incorporate it in the file name if we can */
                         i->settings_path = mfree(i->settings_path);
+
                         r = tar_pull_determine_path(i, ".nspawn", &i->settings_path);
                         if (r < 0)
                                 goto finish;
@@ -379,7 +386,7 @@ static void tar_pull_job_on_finished(PullJob *j) {
 
                         r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path);
                         if (r < 0) {
-                                log_error_errno(r, "Failed to rename settings file: %m");
+                                log_error_errno(r, "Failed to rename settings file to %s: %m", i->settings_path);
                                 goto finish;
                         }
 
@@ -547,6 +554,7 @@ int tar_pull_start(
 
         if (i->checksum_job) {
                 i->checksum_job->on_progress = tar_pull_job_on_progress;
+                i->checksum_job->style = VERIFICATION_PER_FILE;
 
                 r = pull_job_begin(i->checksum_job);
                 if (r < 0)
index 79afe6604c053805da62a5dfdb4fb7fe17f4d13a..d61d1c18f6850cee57e8be12e459ee904f6c3cec 100644 (file)
@@ -41,7 +41,7 @@ void source_free(RemoteSource *source) {
 
 /**
  * Initialize zero-filled source with given values. On success, takes
- * ownerhship of fd and writer, otherwise does not touch them.
+ * ownership of fd, name, and writer, otherwise does not touch them.
  */
 RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
 
index 202a5a3f97d23ca916a926b95f5362353f85ece9..36c1a32dcd8c2c77350c177575fb40157103525a 100644 (file)
@@ -529,7 +529,7 @@ static int process_http_upload(
                         log_warning("Failed to process data for connection %p", connection);
                         if (r == -E2BIG)
                                 return mhd_respondf(connection,
-                                                    r, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
+                                                    r, MHD_HTTP_PAYLOAD_TOO_LARGE,
                                                     "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.");
                         else
                                 return mhd_respondf(connection,
@@ -1200,9 +1200,9 @@ static int parse_config(void) {
                 {}};
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-remote.conf",
-                                 CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
-                                 "Remote\0", config_item_table_lookup, items,
-                                 false, NULL);
+                                        CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
+                                        "Remote\0", config_item_table_lookup, items,
+                                        false, NULL);
 }
 
 static void help(void) {
index 8ce8e1895e60200d249da685f9f71e0d7834ea7b..3a36e46ae073925a3ea9ea43575c98526d81d665 100644 (file)
@@ -251,7 +251,7 @@ static inline void check_update_watchdog(Uploader *u) {
                 return;
 
         after = now(CLOCK_MONOTONIC);
-        elapsed_time = usec_sub(after, u->watchdog_timestamp);
+        elapsed_time = usec_sub_unsigned(after, u->watchdog_timestamp);
         if (elapsed_time > u->watchdog_usec / 2) {
                 log_debug("Update watchdog timer");
                 sd_notify(false, "WATCHDOG=1");
index 371b6acc64e74413ab630e1d0ee38cde7e5ab620..e0858dda7bc9a9dd26ccb3fe55eaf25b73dbce9e 100644 (file)
@@ -541,9 +541,9 @@ static int parse_config(void) {
                 {}};
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-upload.conf",
-                                 CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"),
-                                 "Upload\0", config_item_table_lookup, items,
-                                 false, NULL);
+                                        CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"),
+                                        "Upload\0", config_item_table_lookup, items,
+                                        false, NULL);
 }
 
 static void help(void) {
index 7b434b334e65e101048408f2f07c7b45c44bd94c..c2f945bb47382c4eb5b3f901858dd4059c775623 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 import sys
 import argparse
 
diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build
new file mode 100644 (file)
index 0000000..d266b34
--- /dev/null
@@ -0,0 +1,49 @@
+systemd_journal_upload_sources = files('''
+        journal-upload.h
+        journal-upload.c
+        journal-upload-journal.c
+'''.split())
+
+systemd_journal_remote_sources = files('''
+        journal-remote-parse.h
+        journal-remote-parse.c
+        journal-remote-write.h
+        journal-remote-write.c
+        journal-remote.h
+        journal-remote.c
+        microhttpd-util.h
+        microhttpd-util.c
+'''.split())
+
+systemd_journal_gatewayd_sources = files('''
+        journal-gatewayd.c
+        microhttpd-util.h
+        microhttpd-util.c
+'''.split())
+
+if conf.get('ENABLE_REMOTE', false) and conf.get('HAVE_LIBCURL', false)
+        journal_upload_conf = configure_file(
+                input : 'journal-upload.conf.in',
+                output : 'journal-upload.conf',
+                configuration : substs)
+        install_data(journal_upload_conf,
+                     install_dir : pkgsysconfdir)
+endif
+
+if conf.get('ENABLE_REMOTE', false) and conf.get('HAVE_MICROHTTPD', false)
+        journal_remote_conf = configure_file(
+                input : 'journal-remote.conf.in',
+                output : 'journal-remote.conf',
+                configuration : substs)
+        install_data(journal_remote_conf,
+                     install_dir : pkgsysconfdir)
+
+        install_data('browse.html',
+                     install_dir : join_paths(pkgdatadir, 'gatewayd'))
+
+        meson.add_install_script('sh', '-c',
+                                 mkdir_p.format('/var/log/journal/remote'))
+        meson.add_install_script('sh', '-c',
+                                 'chown 0:0 $DESTDIR/var/log/journal/remote &&
+                                 chmod 755 $DESTDIR/var/log/journal/remote || :')
+endif
index cae10203c67a1a3d6da352be440a7fe6242e96e8..f5d2d7967acf5f1f1c0f1ed393ea022ebda86e26 100644 (file)
@@ -103,7 +103,10 @@ int mhd_respondf(struct MHD_Connection *connection,
         errno = -error;
         fmt = strjoina(format, "\n");
         va_start(ap, format);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
         r = vasprintf(&m, fmt, ap);
+#pragma GCC diagnostic pop
         va_end(ap);
 
         if (r < 0)
index 49def4f630f5ade05b047147ac1c70d69c5d66ee..7f88c2cb7d518dd821d358665235511be426357e 100644 (file)
 #  define MHD_HTTP_NOT_ACCEPTABLE MHD_HTTP_METHOD_NOT_ACCEPTABLE
 #endif
 
+/* Renamed in µhttpd 0.9.51 */
+#ifndef MHD_USE_PIPE_FOR_SHUTDOWN
+#  define MHD_USE_ITC MHD_USE_PIPE_FOR_SHUTDOWN
+#endif
+
 /* Renamed in µhttpd 0.9.52 */
 #ifndef MHD_USE_EPOLL_LINUX_ONLY
 #  define MHD_USE_EPOLL MHD_USE_EPOLL_LINUX_ONLY
 #endif
 
-/* Renamed in µhttpd 0.9.51 */
-#ifndef MHD_USE_PIPE_FOR_SHUTDOWN
-#  define MHD_USE_ITC MHD_USE_PIPE_FOR_SHUTDOWN
+/* Both the old and new names are defines, check for the new one. */
+
+/* Renamed in µhttpd 0.9.53 */
+#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE
+#  define MHD_HTTP_PAYLOAD_TOO_LARGE MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
 #endif
 
 #if MHD_VERSION < 0x00094203
diff --git a/src/journal/audit_type-to-name.awk b/src/journal/audit_type-to-name.awk
new file mode 100644 (file)
index 0000000..44fc702
--- /dev/null
@@ -0,0 +1,9 @@
+BEGIN{
+        print "const char *audit_type_to_string(int type) {\n\tswitch(type) {"
+}
+{
+        printf "        case AUDIT_%s: return \"%s\";\n", $1, $1
+}
+END{
+        print "        default: return NULL;\n\t}\n}\n"
+}
index 612b10f3a9afea1d90614b825680cf6b32052a61..e7c22880be65411a738c904f0e12586bb96f6767 100644 (file)
@@ -40,6 +40,9 @@
 #define RND_GEN_Q 0x02
 #define RND_GEN_X 0x03
 
+#pragma GCC diagnostic ignored "-Wpointer-arith"
+/* TODO: remove void* arithmetic and this work-around */
+
 /******************************************************************************/
 
 static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) {
diff --git a/src/journal/generate-audit_type-list.sh b/src/journal/generate-audit_type-list.sh
new file mode 100755 (executable)
index 0000000..18cbe05
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh -eu
+
+cpp="$1"
+shift
+
+includes=""
+for i in "$@"; do
+        includes="$includes -include $i"
+done
+
+$cpp -dM $includes - </dev/null | \
+        grep -vE 'AUDIT_.*(FIRST|LAST)_' | \
+        sed -r -n 's/^#define\s+AUDIT_(\w+)\s+([0-9]{4})\s*$$/\1\t\2/p' | \
+        sort -k2
index a6ccb679a8413b1096416050d37cba02522b78d5..4ff38de2e6a9a94d386fee007593bf93c9468ae1 100644 (file)
@@ -162,7 +162,7 @@ static int journal_file_set_offline_thread_join(JournalFile *f) {
 
         f->offline_state = OFFLINE_JOINED;
 
-        if (mmap_cache_got_sigbus(f->mmap, f->fd))
+        if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
                 return -EIO;
 
         return 0;
@@ -300,7 +300,7 @@ static int journal_file_set_online(JournalFile *f) {
                 }
         }
 
-        if (mmap_cache_got_sigbus(f->mmap, f->fd))
+        if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
                 return -EIO;
 
         switch (f->header->state) {
@@ -356,8 +356,8 @@ JournalFile* journal_file_close(JournalFile *f) {
 
         journal_file_set_offline(f, true);
 
-        if (f->mmap && f->fd >= 0)
-                mmap_cache_close_fd(f->mmap, f->fd);
+        if (f->mmap && f->cache_fd)
+                mmap_cache_free_fd(f->mmap, f->cache_fd);
 
         if (f->fd >= 0 && f->defrag_on_close) {
 
@@ -546,6 +546,8 @@ static bool warn_wrong_flags(const JournalFile *f, bool compatible) {
 }
 
 static int journal_file_verify_header(JournalFile *f) {
+        uint64_t arena_size, header_size;
+
         assert(f);
         assert(f->header);
 
@@ -564,17 +566,21 @@ static int journal_file_verify_header(JournalFile *f) {
         if (f->header->state >= _STATE_MAX)
                 return -EBADMSG;
 
+        header_size = le64toh(f->header->header_size);
+
         /* The first addition was n_data, so check that we are at least this large */
-        if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
+        if (header_size < HEADER_SIZE_MIN)
                 return -EBADMSG;
 
         if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
                 return -EBADMSG;
 
-        if ((le64toh(f->header->header_size) + le64toh(f->header->arena_size)) > (uint64_t) f->last_stat.st_size)
+        arena_size = le64toh(f->header->arena_size);
+
+        if (UINT64_MAX - header_size < arena_size || header_size + arena_size > (uint64_t) f->last_stat.st_size)
                 return -ENODATA;
 
-        if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
+        if (le64toh(f->header->tail_object_offset) > header_size + arena_size)
                 return -ENODATA;
 
         if (!VALID64(le64toh(f->header->data_hash_table_offset)) ||
@@ -607,6 +613,9 @@ static int journal_file_verify_header(JournalFile *f) {
                         return -EBUSY;
                 }
 
+                if (f->header->field_hash_table_size == 0 || f->header->data_hash_table_size == 0)
+                        return -EBADMSG;
+
                 /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't
                  * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks
                  * bisection. */
@@ -651,7 +660,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
          * for sure, since we always call posix_fallocate()
          * ourselves */
 
-        if (mmap_cache_got_sigbus(f->mmap, f->fd))
+        if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
                 return -EIO;
 
         old_size =
@@ -740,7 +749,7 @@ static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_alway
                         return -EADDRNOTAVAIL;
         }
 
-        return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret);
+        return mmap_cache_get(f->mmap, f->cache_fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret);
 }
 
 static uint64_t minimum_header_size(Object *o) {
@@ -1848,7 +1857,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
          * it is very likely just an effect of a nullified replacement
          * mapping page */
 
-        if (mmap_cache_got_sigbus(f->mmap, f->fd))
+        if (mmap_cache_got_sigbus(f->mmap, f->cache_fd))
                 r = -EIO;
 
         if (f->post_change_timer)
@@ -3135,6 +3144,12 @@ int journal_file_open(
                 f->close_fd = true;
         }
 
+        f->cache_fd = mmap_cache_add_fd(f->mmap, f->fd);
+        if (!f->cache_fd) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
         r = journal_file_fstat(f);
         if (r < 0)
                 goto fail;
@@ -3181,7 +3196,7 @@ int journal_file_open(
                 goto fail;
         }
 
-        r = mmap_cache_get(f->mmap, f->fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h);
+        r = mmap_cache_get(f->mmap, f->cache_fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h);
         if (r < 0)
                 goto fail;
 
@@ -3238,7 +3253,7 @@ int journal_file_open(
 #endif
         }
 
-        if (mmap_cache_got_sigbus(f->mmap, f->fd)) {
+        if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) {
                 r = -EIO;
                 goto fail;
         }
@@ -3260,7 +3275,7 @@ int journal_file_open(
         return 0;
 
 fail:
-        if (f->fd >= 0 && mmap_cache_got_sigbus(f->mmap, f->fd))
+        if (f->cache_fd && mmap_cache_got_sigbus(f->mmap, f->cache_fd))
                 r = -EIO;
 
         (void) journal_file_close(f);
@@ -3473,7 +3488,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
 
         r = journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset);
 
-        if (mmap_cache_got_sigbus(to->mmap, to->fd))
+        if (mmap_cache_got_sigbus(to->mmap, to->cache_fd))
                 return -EIO;
 
         return r;
index 564e1a8179b8c2bf2bbf049070d8fab0644b9b1d..df457c9a81de1370f957a5b79cdf62513e79c619 100644 (file)
@@ -75,6 +75,7 @@ typedef enum OfflineState {
 
 typedef struct JournalFile {
         int fd;
+        MMapFileDescriptor *cache_fd;
 
         mode_t mode;
 
index e38730d65c1207f28bf9fdecf6709dfee0aa315f..5ee10498d10a00e2b014706c0b5954279fc2309a 100644 (file)
@@ -17,7 +17,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
 #include <errno.h>
 #include <qrencode.h>
 #include <stdbool.h>
@@ -25,6 +24,7 @@
 #include <stdlib.h>
 
 #include "journal-qrcode.h"
+#include "macro.h"
 
 #define WHITE_ON_BLACK "\033[40;37;1m"
 #define NORMAL "\033[0m"
index 9e4d8a28a545e2f22f171a57e3e164b8994db594..9feb5b5ae6974d5cddee030f7082176d3ce42dd9 100644 (file)
@@ -377,12 +377,12 @@ static int write_uint64(int fd, uint64_t p) {
         return 0;
 }
 
-static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
+static int contains_uint64(MMapCache *m, MMapFileDescriptor *f, uint64_t n, uint64_t p) {
         uint64_t a, b;
         int r;
 
         assert(m);
-        assert(fd >= 0);
+        assert(f);
 
         /* Bisection ... */
 
@@ -392,7 +392,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
 
                 c = (a + b) / 2;
 
-                r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
+                r = mmap_cache_get(m, f, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
                 if (r < 0)
                         return r;
 
@@ -413,7 +413,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
 
 static int entry_points_to_data(
                 JournalFile *f,
-                int entry_fd,
+                MMapFileDescriptor *cache_entry_fd,
                 uint64_t n_entries,
                 uint64_t entry_p,
                 uint64_t data_p) {
@@ -424,9 +424,9 @@ static int entry_points_to_data(
         bool found = false;
 
         assert(f);
-        assert(entry_fd >= 0);
+        assert(cache_entry_fd);
 
-        if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
+        if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, entry_p)) {
                 error(data_p, "Data object references invalid entry at "OFSfmt, entry_p);
                 return -EBADMSG;
         }
@@ -500,16 +500,16 @@ static int entry_points_to_data(
 static int verify_data(
                 JournalFile *f,
                 Object *o, uint64_t p,
-                int entry_fd, uint64_t n_entries,
-                int entry_array_fd, uint64_t n_entry_arrays) {
+                MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
+                MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays) {
 
         uint64_t i, n, a, last, q;
         int r;
 
         assert(f);
         assert(o);
-        assert(entry_fd >= 0);
-        assert(entry_array_fd >= 0);
+        assert(cache_entry_fd);
+        assert(cache_entry_array_fd);
 
         n = le64toh(o->data.n_entries);
         a = le64toh(o->data.entry_array_offset);
@@ -527,7 +527,7 @@ static int verify_data(
         assert(o->data.entry_offset);
 
         last = q = le64toh(o->data.entry_offset);
-        r = entry_points_to_data(f, entry_fd, n_entries, q, p);
+        r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p);
         if (r < 0)
                 return r;
 
@@ -540,7 +540,7 @@ static int verify_data(
                         return -EBADMSG;
                 }
 
-                if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
+                if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) {
                         error(p, "Invalid array offset "OFSfmt, a);
                         return -EBADMSG;
                 }
@@ -565,7 +565,7 @@ static int verify_data(
                         }
                         last = q;
 
-                        r = entry_points_to_data(f, entry_fd, n_entries, q, p);
+                        r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p);
                         if (r < 0)
                                 return r;
 
@@ -583,9 +583,9 @@ static int verify_data(
 
 static int verify_hash_table(
                 JournalFile *f,
-                int data_fd, uint64_t n_data,
-                int entry_fd, uint64_t n_entries,
-                int entry_array_fd, uint64_t n_entry_arrays,
+                MMapFileDescriptor *cache_data_fd, uint64_t n_data,
+                MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
+                MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays,
                 usec_t *last_usec,
                 bool show_progress) {
 
@@ -593,9 +593,9 @@ static int verify_hash_table(
         int r;
 
         assert(f);
-        assert(data_fd >= 0);
-        assert(entry_fd >= 0);
-        assert(entry_array_fd >= 0);
+        assert(cache_data_fd);
+        assert(cache_entry_fd);
+        assert(cache_entry_array_fd);
         assert(last_usec);
 
         n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
@@ -617,7 +617,7 @@ static int verify_hash_table(
                         Object *o;
                         uint64_t next;
 
-                        if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
+                        if (!contains_uint64(f->mmap, cache_data_fd, n_data, p)) {
                                 error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n);
                                 return -EBADMSG;
                         }
@@ -637,7 +637,7 @@ static int verify_hash_table(
                                 return -EBADMSG;
                         }
 
-                        r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
+                        r = verify_data(f, o, p, cache_entry_fd, n_entries, cache_entry_array_fd, n_entry_arrays);
                         if (r < 0)
                                 return r;
 
@@ -689,14 +689,14 @@ static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p)
 static int verify_entry(
                 JournalFile *f,
                 Object *o, uint64_t p,
-                int data_fd, uint64_t n_data) {
+                MMapFileDescriptor *cache_data_fd, uint64_t n_data) {
 
         uint64_t i, n;
         int r;
 
         assert(f);
         assert(o);
-        assert(data_fd >= 0);
+        assert(cache_data_fd);
 
         n = journal_file_entry_n_items(o);
         for (i = 0; i < n; i++) {
@@ -706,7 +706,7 @@ static int verify_entry(
                 q = le64toh(o->entry.items[i].object_offset);
                 h = le64toh(o->entry.items[i].hash);
 
-                if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
+                if (!contains_uint64(f->mmap, cache_data_fd, n_data, q)) {
                         error(p, "Invalid data object of entry");
                         return -EBADMSG;
                 }
@@ -734,9 +734,9 @@ static int verify_entry(
 
 static int verify_entry_array(
                 JournalFile *f,
-                int data_fd, uint64_t n_data,
-                int entry_fd, uint64_t n_entries,
-                int entry_array_fd, uint64_t n_entry_arrays,
+                MMapFileDescriptor *cache_data_fd, uint64_t n_data,
+                MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
+                MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays,
                 usec_t *last_usec,
                 bool show_progress) {
 
@@ -744,9 +744,9 @@ static int verify_entry_array(
         int r;
 
         assert(f);
-        assert(data_fd >= 0);
-        assert(entry_fd >= 0);
-        assert(entry_array_fd >= 0);
+        assert(cache_data_fd);
+        assert(cache_entry_fd);
+        assert(cache_entry_array_fd);
         assert(last_usec);
 
         n = le64toh(f->header->n_entries);
@@ -763,7 +763,7 @@ static int verify_entry_array(
                         return -EBADMSG;
                 }
 
-                if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
+                if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) {
                         error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n);
                         return -EBADMSG;
                 }
@@ -789,7 +789,7 @@ static int verify_entry_array(
                         }
                         last = p;
 
-                        if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
+                        if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, p)) {
                                 error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n);
                                 return -EBADMSG;
                         }
@@ -798,7 +798,7 @@ static int verify_entry_array(
                         if (r < 0)
                                 return r;
 
-                        r = verify_entry(f, o, p, data_fd, n_data);
+                        r = verify_entry(f, o, p, cache_data_fd, n_data);
                         if (r < 0)
                                 return r;
 
@@ -829,6 +829,7 @@ int journal_file_verify(
         uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
         usec_t last_usec = 0;
         int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
+        MMapFileDescriptor *cache_data_fd = NULL, *cache_entry_fd = NULL, *cache_entry_array_fd = NULL;
         unsigned i;
         bool found_last = false;
         const char *tmp_dir = NULL;
@@ -876,6 +877,24 @@ int journal_file_verify(
                 goto fail;
         }
 
+        cache_data_fd = mmap_cache_add_fd(f->mmap, data_fd);
+        if (!cache_data_fd) {
+                r = log_oom();
+                goto fail;
+        }
+
+        cache_entry_fd = mmap_cache_add_fd(f->mmap, entry_fd);
+        if (!cache_entry_fd) {
+                r = log_oom();
+                goto fail;
+        }
+
+        cache_entry_array_fd = mmap_cache_add_fd(f->mmap, entry_array_fd);
+        if (!cache_entry_array_fd) {
+                r = log_oom();
+                goto fail;
+        }
+
         if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) {
                 log_error("Cannot verify file with unknown extensions.");
                 r = -EOPNOTSUPP;
@@ -1247,18 +1266,18 @@ int journal_file_verify(
          * referenced is consistent. */
 
         r = verify_entry_array(f,
-                               data_fd, n_data,
-                               entry_fd, n_entries,
-                               entry_array_fd, n_entry_arrays,
+                               cache_data_fd, n_data,
+                               cache_entry_fd, n_entries,
+                               cache_entry_array_fd, n_entry_arrays,
                                &last_usec,
                                show_progress);
         if (r < 0)
                 goto fail;
 
         r = verify_hash_table(f,
-                              data_fd, n_data,
-                              entry_fd, n_entries,
-                              entry_array_fd, n_entry_arrays,
+                              cache_data_fd, n_data,
+                              cache_entry_fd, n_entries,
+                              cache_entry_array_fd, n_entry_arrays,
                               &last_usec,
                               show_progress);
         if (r < 0)
@@ -1267,9 +1286,9 @@ int journal_file_verify(
         if (show_progress)
                 flush_progress();
 
-        mmap_cache_close_fd(f->mmap, data_fd);
-        mmap_cache_close_fd(f->mmap, entry_fd);
-        mmap_cache_close_fd(f->mmap, entry_array_fd);
+        mmap_cache_free_fd(f->mmap, cache_data_fd);
+        mmap_cache_free_fd(f->mmap, cache_entry_fd);
+        mmap_cache_free_fd(f->mmap, cache_entry_array_fd);
 
         safe_close(data_fd);
         safe_close(entry_fd);
@@ -1294,20 +1313,23 @@ fail:
                   (unsigned long long) f->last_stat.st_size,
                   100 * p / f->last_stat.st_size);
 
-        if (data_fd >= 0) {
-                mmap_cache_close_fd(f->mmap, data_fd);
+        if (data_fd >= 0)
                 safe_close(data_fd);
-        }
 
-        if (entry_fd >= 0) {
-                mmap_cache_close_fd(f->mmap, entry_fd);
+        if (entry_fd >= 0)
                 safe_close(entry_fd);
-        }
 
-        if (entry_array_fd >= 0) {
-                mmap_cache_close_fd(f->mmap, entry_array_fd);
+        if (entry_array_fd >= 0)
                 safe_close(entry_array_fd);
-        }
+
+        if (cache_data_fd)
+                mmap_cache_free_fd(f->mmap, cache_data_fd);
+
+        if (cache_entry_fd)
+                mmap_cache_free_fd(f->mmap, cache_entry_fd);
+
+        if (cache_entry_array_fd)
+                mmap_cache_free_fd(f->mmap, cache_entry_array_fd);
 
         return r;
 }
index ad11fb314d366f232e40a416508e1e804d8a1beb..2313c8c6786dceb17153e284f5751bc7374c2cdd 100644 (file)
@@ -299,8 +299,9 @@ static void help(void) {
                "     --no-tail             Show all lines, even in follow mode\n"
                "  -r --reverse             Show the newest entries first\n"
                "  -o --output=STRING       Change journal output mode (short, short-precise,\n"
-               "                             short-iso, short-full, short-monotonic, short-unix,\n"
-               "                             verbose, export, json, json-pretty, json-sse, cat)\n"
+               "                             short-iso, short-iso-precise, short-full,\n"
+               "                             short-monotonic, short-unix, verbose, export,\n"
+               "                             json, json-pretty, json-sse, cat)\n"
                "     --utc                 Express time in Coordinated Universal Time (UTC)\n"
                "  -x --catalog             Add message explanations where available\n"
                "     --no-full             Ellipsize fields\n"
@@ -2364,20 +2365,13 @@ int main(int argc, char *argv[]) {
                 log_error_errno(r, "Failed to iterate through journal: %m");
                 goto finish;
         }
-        if (r == 0) {
-                if (arg_follow)
-                        need_seek = true;
-                else {
-                        if (!arg_quiet)
-                                printf("-- No entries --\n");
-                        goto finish;
-                }
-        }
+        if (r == 0)
+                need_seek = true;
 
         if (!arg_follow)
                 pager_open(arg_no_pager, arg_pager_end);
 
-        if (!arg_quiet) {
+        if (!arg_quiet && (arg_lines != 0 || arg_follow)) {
                 usec_t start, end;
                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
 
@@ -2473,6 +2467,9 @@ int main(int argc, char *argv[]) {
                 }
 
                 if (!arg_follow) {
+                        if (n_shown == 0 && !arg_quiet)
+                                printf("-- No entries --\n");
+
                         if (arg_show_cursor) {
                                 _cleanup_free_ char *cursor = NULL;
 
@@ -2486,6 +2483,7 @@ int main(int argc, char *argv[]) {
                         break;
                 }
 
+                fflush(stdout);
                 r = sd_journal_wait(j, (uint64_t) -1);
                 if (r < 0) {
                         log_error_errno(r, "Couldn't wait for journal event: %m");
@@ -2496,6 +2494,7 @@ int main(int argc, char *argv[]) {
         }
 
 finish:
+        fflush(stdout);
         pager_close();
 
         strv_free(arg_file);
index 5126c2160eb527fcd408485256f9eaa8878a2a3b..5fbcdb43c2ba63623d93a56494771c86974bb55e 100644 (file)
@@ -72,9 +72,9 @@ void server_forward_console(
         /* First: timestamp */
         if (prefix_timestamp()) {
                 assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
-                xsprintf(tbuf, "[%5"PRI_TIME".%06ld] ",
+                xsprintf(tbuf, "[%5"PRI_TIME".%06"PRI_NSEC"] ",
                          ts.tv_sec,
-                         ts.tv_nsec / 1000);
+                         (nsec_t)ts.tv_nsec / 1000);
                 IOVEC_SET_STRING(iovec[n++], tbuf);
         }
 
index 3c03b83754dbae12931c9621bbbf32142322e75b..abd06b1adc02ea3a2bee326d1697228317578d21 100644 (file)
@@ -40,6 +40,7 @@
 #include "selinux-util.h"
 #include "socket-util.h"
 #include "string-util.h"
+#include "unaligned.h"
 
 bool valid_user_field(const char *p, size_t l, bool allow_protected) {
         const char *a;
@@ -80,60 +81,110 @@ static bool allow_object_pid(const struct ucred *ucred) {
         return ucred && ucred->uid == 0;
 }
 
-void server_process_native_message(
+static void server_process_entry_meta(
+                const char *p, size_t l,
+                const struct ucred *ucred,
+                int *priority,
+                char **identifier,
+                char **message,
+                pid_t *object_pid) {
+
+        /* We need to determine the priority of this entry for the rate limiting logic */
+
+        if (l == 10 &&
+            startswith(p, "PRIORITY=") &&
+            p[9] >= '0' && p[9] <= '9')
+                *priority = (*priority & LOG_FACMASK) | (p[9] - '0');
+
+        else if (l == 17 &&
+                 startswith(p, "SYSLOG_FACILITY=") &&
+                 p[16] >= '0' && p[16] <= '9')
+                *priority = (*priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
+
+        else if (l == 18 &&
+                 startswith(p, "SYSLOG_FACILITY=") &&
+                 p[16] >= '0' && p[16] <= '9' &&
+                 p[17] >= '0' && p[17] <= '9')
+                *priority = (*priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
+
+        else if (l >= 19 &&
+                 startswith(p, "SYSLOG_IDENTIFIER=")) {
+                char *t;
+
+                t = strndup(p + 18, l - 18);
+                if (t) {
+                        free(*identifier);
+                        *identifier = t;
+                }
+
+        } else if (l >= 8 &&
+                   startswith(p, "MESSAGE=")) {
+                char *t;
+
+                t = strndup(p + 8, l - 8);
+                if (t) {
+                        free(*message);
+                        *message = t;
+                }
+
+        } else if (l > strlen("OBJECT_PID=") &&
+                   l < strlen("OBJECT_PID=")  + DECIMAL_STR_MAX(pid_t) &&
+                   startswith(p, "OBJECT_PID=") &&
+                   allow_object_pid(ucred)) {
+                char buf[DECIMAL_STR_MAX(pid_t)];
+                memcpy(buf, p + strlen("OBJECT_PID="), l - strlen("OBJECT_PID="));
+                buf[l-strlen("OBJECT_PID=")] = '\0';
+
+                (void) parse_pid(buf, object_pid);
+        }
+}
+
+static int server_process_entry(
                 Server *s,
-                const void *buffer, size_t buffer_size,
+                const void *buffer, size_t *remaining,
                 const struct ucred *ucred,
                 const struct timeval *tv,
                 const char *label, size_t label_len) {
 
+        /* Process a single entry from a native message.
+         * Returns 0 if nothing special happened and the message processing should continue,
+         * and a negative or positive value otherwise.
+         *
+         * Note that *remaining is altered on both success and failure. */
+
         struct iovec *iovec = NULL;
         unsigned n = 0, j, tn = (unsigned) -1;
         const char *p;
-        size_t remaining, m = 0, entry_size = 0;
+        size_t m = 0, entry_size = 0;
         int priority = LOG_INFO;
         char *identifier = NULL, *message = NULL;
         pid_t object_pid = 0;
-
-        assert(s);
-        assert(buffer || buffer_size == 0);
+        int r = 0;
 
         p = buffer;
-        remaining = buffer_size;
 
-        while (remaining > 0) {
+        while (*remaining > 0) {
                 const char *e, *q;
 
-                e = memchr(p, '\n', remaining);
+                e = memchr(p, '\n', *remaining);
 
                 if (!e) {
                         /* Trailing noise, let's ignore it, and flush what we collected */
                         log_debug("Received message with trailing noise, ignoring.");
+                        r = 1; /* finish processing of the message */
                         break;
                 }
 
                 if (e == p) {
                         /* Entry separator */
-
-                        if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
-                                log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", n, entry_size);
-                                continue;
-                        }
-
-                        server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
-                        n = 0;
-                        priority = LOG_INFO;
-                        entry_size = 0;
-
-                        p++;
-                        remaining--;
-                        continue;
+                        *remaining -= 1;
+                        break;
                 }
 
                 if (*p == '.' || *p == '#') {
                         /* Ignore control commands for now, and
                          * comments too. */
-                        remaining -= (e - p) + 1;
+                        *remaining -= (e - p) + 1;
                         p = e + 1;
                         continue;
                 }
@@ -142,7 +193,7 @@ void server_process_native_message(
 
                 /* n existing properties, 1 new, +1 for _TRANSPORT */
                 if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) {
-                        log_oom();
+                        r = log_oom();
                         break;
                 }
 
@@ -155,87 +206,40 @@ void server_process_native_message(
 
                                 /* If the field name starts with an
                                  * underscore, skip the variable,
-                                 * since that indidates a trusted
+                                 * since that indicates a trusted
                                  * field */
                                 iovec[n].iov_base = (char*) p;
                                 iovec[n].iov_len = l;
-                                entry_size += iovec[n].iov_len;
+                                entry_size += l;
                                 n++;
 
-                                /* We need to determine the priority
-                                 * of this entry for the rate limiting
-                                 * logic */
-                                if (l == 10 &&
-                                    startswith(p, "PRIORITY=") &&
-                                    p[9] >= '0' && p[9] <= '9')
-                                        priority = (priority & LOG_FACMASK) | (p[9] - '0');
-
-                                else if (l == 17 &&
-                                         startswith(p, "SYSLOG_FACILITY=") &&
-                                         p[16] >= '0' && p[16] <= '9')
-                                        priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
-
-                                else if (l == 18 &&
-                                         startswith(p, "SYSLOG_FACILITY=") &&
-                                         p[16] >= '0' && p[16] <= '9' &&
-                                         p[17] >= '0' && p[17] <= '9')
-                                        priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
-
-                                else if (l >= 19 &&
-                                         startswith(p, "SYSLOG_IDENTIFIER=")) {
-                                        char *t;
-
-                                        t = strndup(p + 18, l - 18);
-                                        if (t) {
-                                                free(identifier);
-                                                identifier = t;
-                                        }
-
-                                } else if (l >= 8 &&
-                                           startswith(p, "MESSAGE=")) {
-                                        char *t;
-
-                                        t = strndup(p + 8, l - 8);
-                                        if (t) {
-                                                free(message);
-                                                message = t;
-                                        }
-
-                                } else if (l > strlen("OBJECT_PID=") &&
-                                           l < strlen("OBJECT_PID=")  + DECIMAL_STR_MAX(pid_t) &&
-                                           startswith(p, "OBJECT_PID=") &&
-                                           allow_object_pid(ucred)) {
-                                        char buf[DECIMAL_STR_MAX(pid_t)];
-                                        memcpy(buf, p + strlen("OBJECT_PID="), l - strlen("OBJECT_PID="));
-                                        buf[l-strlen("OBJECT_PID=")] = '\0';
-
-                                        /* ignore error */
-                                        parse_pid(buf, &object_pid);
-                                }
+                                server_process_entry_meta(p, l, ucred,
+                                                          &priority,
+                                                          &identifier,
+                                                          &message,
+                                                          &object_pid);
                         }
 
-                        remaining -= (e - p) + 1;
+                        *remaining -= (e - p) + 1;
                         p = e + 1;
                         continue;
                 } else {
-                        le64_t l_le;
                         uint64_t l;
                         char *k;
 
-                        if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
+                        if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) {
                                 log_debug("Failed to parse message, ignoring.");
                                 break;
                         }
 
-                        memcpy(&l_le, e + 1, sizeof(uint64_t));
-                        l = le64toh(l_le);
+                        l = unaligned_read_le64(e + 1);
 
                         if (l > DATA_SIZE_MAX) {
                                 log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l);
                                 break;
                         }
 
-                        if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
+                        if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
                             e[1+sizeof(uint64_t)+l] != '\n') {
                                 log_debug("Failed to parse message, ignoring.");
                                 break;
@@ -256,16 +260,24 @@ void server_process_native_message(
                                 iovec[n].iov_len = (e - p) + 1 + l;
                                 entry_size += iovec[n].iov_len;
                                 n++;
+
+                                server_process_entry_meta(k, (e - p) + 1 + l, ucred,
+                                                          &priority,
+                                                          &identifier,
+                                                          &message,
+                                                          &object_pid);
                         } else
                                 free(k);
 
-                        remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
+                        *remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
                         p = e + 1 + sizeof(uint64_t) + l + 1;
                 }
         }
 
-        if (n <= 0)
+        if (n <= 0) {
+                r = 1;
                 goto finish;
+        }
 
         tn = n++;
         IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
@@ -279,7 +291,7 @@ void server_process_native_message(
 
         if (message) {
                 if (s->forward_to_syslog)
-                        server_forward_syslog(s, priority, identifier, message, ucred, tv);
+                        server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv);
 
                 if (s->forward_to_kmsg)
                         server_forward_kmsg(s, priority, identifier, message, ucred);
@@ -299,13 +311,35 @@ finish:
                         continue;
 
                 if (iovec[j].iov_base < buffer ||
-                    (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
+                    (const char*) iovec[j].iov_base >= p + *remaining)
                         free(iovec[j].iov_base);
         }
 
         free(iovec);
         free(identifier);
         free(message);
+
+        return r;
+}
+
+void server_process_native_message(
+                Server *s,
+                const void *buffer, size_t buffer_size,
+                const struct ucred *ucred,
+                const struct timeval *tv,
+                const char *label, size_t label_len) {
+
+        int r;
+        size_t remaining = buffer_size;
+
+        assert(s);
+        assert(buffer || buffer_size == 0);
+
+        do {
+                r = server_process_entry(s,
+                                         (const uint8_t*) buffer + (buffer_size - remaining), &remaining,
+                                         ucred, tv, label, label_len);
+        } while (r == 0);
 }
 
 void server_process_native_file(
@@ -479,7 +513,7 @@ int server_open_native_socket(Server*s) {
                 return log_error_errno(errno, "SO_PASSCRED failed: %m");
 
 #ifdef HAVE_SELINUX
-        if (mac_selinux_have()) {
+        if (mac_selinux_use()) {
                 r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
                 if (r < 0)
                         log_warning_errno(errno, "SO_PASSSEC failed: %m");
index 6466e46cccfaba2fd98a00ca0c77c9aa3ba90562..05a1254d4a95f41c4010c86556712290bc7aa24e 100644 (file)
@@ -918,7 +918,7 @@ static void dispatch_message_real(
                 }
 
 #ifdef HAVE_SELINUX
-                if (mac_selinux_have()) {
+                if (mac_selinux_use()) {
                         if (label) {
                                 x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
 
@@ -1637,10 +1637,10 @@ static int server_parse_config_file(Server *s) {
         assert(s);
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/journald.conf",
-                                 CONF_PATHS_NULSTR("systemd/journald.conf.d"),
-                                 "Journal\0",
-                                 config_item_perf_lookup, journald_gperf_lookup,
-                                 false, s);
+                                        CONF_PATHS_NULSTR("systemd/journald.conf.d"),
+                                        "Journal\0",
+                                        config_item_perf_lookup, journald_gperf_lookup,
+                                        false, s);
 }
 
 static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) {
@@ -2177,6 +2177,8 @@ void server_done(Server *s) {
         free(s->tty_path);
         free(s->cgroup_root);
         free(s->hostname_field);
+        free(s->runtime_storage.path);
+        free(s->system_storage.path);
 
         if (s->mmap)
                 mmap_cache_unref(s->mmap);
index 75ac114d2493b30442a16891f4da44a4ae3023fb..203460c50ac756cfda5bf264ea924eac63af87f5 100644 (file)
@@ -61,7 +61,7 @@ typedef struct JournalStorageSpace {
 
 typedef struct JournalStorage {
         const char *name;
-        const char *path;
+        char *path;
 
         JournalMetrics metrics;
         JournalStorageSpace space;
index bc092f3c126fbac55a9f80c09a9c25e733c66d8e..77551dc14b25520f677dcf43bc5ae0fe77c210f3 100644 (file)
@@ -494,7 +494,7 @@ static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
         if (r < 0)
                 return log_error_errno(r, "Failed to determine peer credentials: %m");
 
-        if (mac_selinux_have()) {
+        if (mac_selinux_use()) {
                 r = getpeersec(fd, &stream->label);
                 if (r < 0 && r != -EOPNOTSUPP)
                         (void) log_warning_errno(r, "Failed to determine peer security context: %m");
index 474369039a6ce5501d73d7f2f941c404ea661057..8e034c8fa9cdaf5e9bfd8869d0d95f490ad50cda 100644 (file)
@@ -410,7 +410,7 @@ int server_open_syslog_socket(Server *s) {
                 return log_error_errno(errno, "SO_PASSCRED failed: %m");
 
 #ifdef HAVE_SELINUX
-        if (mac_selinux_have()) {
+        if (mac_selinux_use()) {
                 r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
                 if (r < 0)
                         log_warning_errno(errno, "SO_PASSSEC failed: %m");
diff --git a/src/journal/meson.build b/src/journal/meson.build
new file mode 100644 (file)
index 0000000..582f83a
--- /dev/null
@@ -0,0 +1,122 @@
+journal_internal_sources = files('''
+        audit-type.c
+        audit-type.h
+        catalog.c
+        catalog.h
+        compress.c
+        compress.h
+        journal-def.h
+        journal-file.c
+        journal-file.h
+        journal-send.c
+        journal-vacuum.c
+        journal-vacuum.h
+        journal-verify.c
+        journal-verify.h
+        lookup3.c
+        lookup3.h
+        mmap-cache.c
+        mmap-cache.h
+        sd-journal.c
+'''.split())
+
+if conf.get('HAVE_GCRYPT', false)
+        journal_internal_sources += files('''
+                journal-authenticate.c
+                journal-authenticate.h
+                fsprg.c
+                fsprg.h
+        '''.split())
+
+        journal_internal_sources += gcrypt_util_sources
+endif
+
+############################################################
+
+audit_type_includes = [config_h,
+                       missing_h,
+                       'linux/audit.h']
+if conf.get('HAVE_AUDIT', false)
+        audit_type_includes += 'libaudit.h'
+endif
+
+generate_audit_type_list = find_program('generate-audit_type-list.sh')
+audit_type_list_txt = custom_target(
+        'audit_type-list.txt',
+        output : 'audit_type-list.txt',
+        command : [generate_audit_type_list, cpp] + audit_type_includes,
+        capture : true)
+
+audit_type_to_name = custom_target(
+        'audit_type-to-name.h',
+        input : ['audit_type-to-name.awk', audit_type_list_txt],
+        output : 'audit_type-to-name.h',
+        command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+        capture : true)
+
+journal_internal_sources += [audit_type_to_name]
+
+############################################################
+
+libjournal_core_sources = files('''
+        journald-kmsg.c
+        journald-kmsg.h
+        journald-syslog.c
+        journald-syslog.h
+        journald-stream.c
+        journald-stream.h
+        journald-server.c
+        journald-server.h
+        journald-console.c
+        journald-console.h
+        journald-wall.c
+        journald-wall.h
+        journald-native.c
+        journald-native.h
+        journald-audit.c
+        journald-audit.h
+        journald-rate-limit.c
+        journald-rate-limit.h
+        journal-internal.h
+'''.split())
+
+systemd_journald_sources = files('''
+        journald.c
+        journald-server.h
+'''.split())
+
+journald_gperf_c = custom_target(
+        'journald-gperf.c',
+        input : 'journald-gperf.gperf',
+        output : 'journald-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+systemd_cat_sources = files('cat.c')
+
+journalctl_sources = files('journalctl.c')
+
+if conf.get('HAVE_QRENCODE', false)
+        journalctl_sources += files('journal-qrcode.c',
+                                    'journal-qrcode.h')
+endif
+
+install_data('journald.conf',
+             install_dir : pkgsysconfdir)
+
+meson.add_install_script(
+        'sh', '-c',
+        mkdir_p.format('/var/log/journal'))
+meson.add_install_script(
+        'sh', '-c',
+        'chown 0:0 $DESTDIR/var/log/journal &&
+         chmod 755 $DESTDIR/var/log/journal || :')
+if get_option('adm-group')
+        meson.add_install_script(
+                'sh', '-c',
+                'setfacl -nm g:adm:rx,d:g:adm:rx $DESTDIR/var/log/journal || :')
+endif
+if get_option('wheel-group')
+        meson.add_install_script(
+                'sh', '-c',
+                'setfacl -nm g:wheel:rx,d:g:wheel:rx $DESTDIR/var/log/journal || :')
+endif
index d91247b52449988c91bc74507b218f03b1e9cf41..5dfda73c56a7d7d7f3503c23c31631e7eea3f1e0 100644 (file)
@@ -33,7 +33,6 @@
 
 typedef struct Window Window;
 typedef struct Context Context;
-typedef struct FileDescriptor FileDescriptor;
 
 struct Window {
         MMapCache *cache;
@@ -47,7 +46,7 @@ struct Window {
         uint64_t offset;
         size_t size;
 
-        FileDescriptor *fd;
+        MMapFileDescriptor *fd;
 
         LIST_FIELDS(Window, by_fd);
         LIST_FIELDS(Window, unused);
@@ -63,7 +62,7 @@ struct Context {
         LIST_FIELDS(Context, by_window);
 };
 
-struct FileDescriptor {
+struct MMapFileDescriptor {
         MMapCache *cache;
         int fd;
         bool sigbus;
@@ -158,24 +157,24 @@ static void window_free(Window *w) {
         free(w);
 }
 
-_pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset, size_t size) {
+_pure_ static bool window_matches(Window *w, MMapFileDescriptor *f, int prot, uint64_t offset, size_t size) {
         assert(w);
-        assert(fd >= 0);
+        assert(f);
         assert(size > 0);
 
         return
                 w->fd &&
-                fd == w->fd->fd &&
+                f->fd == w->fd->fd &&
                 prot == w->prot &&
                 offset >= w->offset &&
                 offset + size <= w->offset + w->size;
 }
 
-static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) {
+static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) {
         Window *w;
 
         assert(m);
-        assert(fd);
+        assert(f);
 
         if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
 
@@ -193,14 +192,14 @@ static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_
         }
 
         w->cache = m;
-        w->fd = fd;
+        w->fd = f;
         w->prot = prot;
         w->keep_always = keep_always;
         w->offset = offset;
         w->size = size;
         w->ptr = ptr;
 
-        LIST_PREPEND(by_fd, fd->windows, w);
+        LIST_PREPEND(by_fd, f->windows, w);
 
         return w;
 }
@@ -290,49 +289,7 @@ static void context_free(Context *c) {
         free(c);
 }
 
-static void fd_free(FileDescriptor *f) {
-        assert(f);
-
-        while (f->windows)
-                window_free(f->windows);
-
-        if (f->cache)
-                assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd)));
-
-        free(f);
-}
-
-static FileDescriptor* fd_add(MMapCache *m, int fd) {
-        FileDescriptor *f;
-        int r;
-
-        assert(m);
-        assert(fd >= 0);
-
-        f = hashmap_get(m->fds, FD_TO_PTR(fd));
-        if (f)
-                return f;
-
-        r = hashmap_ensure_allocated(&m->fds, NULL);
-        if (r < 0)
-                return NULL;
-
-        f = new0(FileDescriptor, 1);
-        if (!f)
-                return NULL;
-
-        f->cache = m;
-        f->fd = fd;
-
-        r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
-        if (r < 0)
-                return mfree(f);
-
-        return f;
-}
-
 static void mmap_cache_free(MMapCache *m) {
-        FileDescriptor *f;
         int i;
 
         assert(m);
@@ -341,9 +298,6 @@ static void mmap_cache_free(MMapCache *m) {
                 if (m->contexts[i])
                         context_free(m->contexts[i]);
 
-        while ((f = hashmap_first(m->fds)))
-                fd_free(f);
-
         hashmap_free(m->fds);
 
         while (m->unused)
@@ -378,7 +332,7 @@ static int make_room(MMapCache *m) {
 
 static int try_context(
                 MMapCache *m,
-                int fd,
+                MMapFileDescriptor *f,
                 int prot,
                 unsigned context,
                 bool keep_always,
@@ -390,7 +344,7 @@ static int try_context(
 
         assert(m);
         assert(m->n_ref > 0);
-        assert(fd >= 0);
+        assert(f);
         assert(size > 0);
         assert(ret);
 
@@ -403,7 +357,7 @@ static int try_context(
         if (!c->window)
                 return 0;
 
-        if (!window_matches(c->window, fd, prot, offset, size)) {
+        if (!window_matches(c->window, f, prot, offset, size)) {
 
                 /* Drop the reference to the window, since it's unnecessary now */
                 context_detach_window(c);
@@ -421,7 +375,7 @@ static int try_context(
 
 static int find_mmap(
                 MMapCache *m,
-                int fd,
+                MMapFileDescriptor *f,
                 int prot,
                 unsigned context,
                 bool keep_always,
@@ -429,26 +383,19 @@ static int find_mmap(
                 size_t size,
                 void **ret) {
 
-        FileDescriptor *f;
         Window *w;
         Context *c;
 
         assert(m);
         assert(m->n_ref > 0);
-        assert(fd >= 0);
+        assert(f);
         assert(size > 0);
 
-        f = hashmap_get(m->fds, FD_TO_PTR(fd));
-        if (!f)
-                return 0;
-
-        assert(f->fd == fd);
-
         if (f->sigbus)
                 return -EIO;
 
         LIST_FOREACH(by_fd, w, f->windows)
-                if (window_matches(w, fd, prot, offset, size))
+                if (window_matches(w, f, prot, offset, size))
                         break;
 
         if (!w)
@@ -465,17 +412,17 @@ static int find_mmap(
         return 1;
 }
 
-static int mmap_try_harder(MMapCache *m, void *addr, int fd, int prot, int flags, uint64_t offset, size_t size, void **res) {
+static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int prot, int flags, uint64_t offset, size_t size, void **res) {
         void *ptr;
 
         assert(m);
-        assert(fd >= 0);
+        assert(f);
         assert(res);
 
         for (;;) {
                 int r;
 
-                ptr = mmap(addr, size, prot, flags, fd, offset);
+                ptr = mmap(addr, size, prot, flags, f->fd, offset);
                 if (ptr != MAP_FAILED)
                         break;
                 if (errno != ENOMEM)
@@ -494,7 +441,7 @@ static int mmap_try_harder(MMapCache *m, void *addr, int fd, int prot, int flags
 
 static int add_mmap(
                 MMapCache *m,
-                int fd,
+                MMapFileDescriptor *f,
                 int prot,
                 unsigned context,
                 bool keep_always,
@@ -505,14 +452,13 @@ static int add_mmap(
 
         uint64_t woffset, wsize;
         Context *c;
-        FileDescriptor *f;
         Window *w;
         void *d;
         int r;
 
         assert(m);
         assert(m->n_ref > 0);
-        assert(fd >= 0);
+        assert(f);
         assert(size > 0);
         assert(ret);
 
@@ -545,7 +491,7 @@ static int add_mmap(
                         wsize = PAGE_ALIGN(st->st_size - woffset);
         }
 
-        r = mmap_try_harder(m, NULL, fd, prot, MAP_SHARED, woffset, wsize, &d);
+        r = mmap_try_harder(m, NULL, f, prot, MAP_SHARED, woffset, wsize, &d);
         if (r < 0)
                 return r;
 
@@ -553,10 +499,6 @@ static int add_mmap(
         if (!c)
                 goto outofmem;
 
-        f = fd_add(m, fd);
-        if (!f)
-                goto outofmem;
-
         w = window_add(m, f, prot, keep_always, woffset, wsize, d);
         if (!w)
                 goto outofmem;
@@ -575,7 +517,7 @@ outofmem:
 
 int mmap_cache_get(
                 MMapCache *m,
-                int fd,
+                MMapFileDescriptor *f,
                 int prot,
                 unsigned context,
                 bool keep_always,
@@ -588,20 +530,20 @@ int mmap_cache_get(
 
         assert(m);
         assert(m->n_ref > 0);
-        assert(fd >= 0);
+        assert(f);
         assert(size > 0);
         assert(ret);
         assert(context < MMAP_CACHE_MAX_CONTEXTS);
 
         /* Check whether the current context is the right one already */
-        r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
+        r = try_context(m, f, prot, context, keep_always, offset, size, ret);
         if (r != 0) {
                 m->n_hit++;
                 return r;
         }
 
         /* Search for a matching mmap */
-        r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret);
+        r = find_mmap(m, f, prot, context, keep_always, offset, size, ret);
         if (r != 0) {
                 m->n_hit++;
                 return r;
@@ -610,7 +552,7 @@ int mmap_cache_get(
         m->n_missed++;
 
         /* Create a new mmap */
-        return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret);
+        return add_mmap(m, f, prot, context, keep_always, offset, size, st, ret);
 }
 
 unsigned mmap_cache_get_hit(MMapCache *m) {
@@ -627,7 +569,7 @@ unsigned mmap_cache_get_missed(MMapCache *m) {
 
 static void mmap_cache_process_sigbus(MMapCache *m) {
         bool found = false;
-        FileDescriptor *f;
+        MMapFileDescriptor *f;
         Iterator i;
         int r;
 
@@ -688,36 +630,59 @@ static void mmap_cache_process_sigbus(MMapCache *m) {
         }
 }
 
-bool mmap_cache_got_sigbus(MMapCache *m, int fd) {
-        FileDescriptor *f;
-
+bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f) {
         assert(m);
-        assert(fd >= 0);
+        assert(f);
 
         mmap_cache_process_sigbus(m);
 
-        f = hashmap_get(m->fds, FD_TO_PTR(fd));
-        if (!f)
-                return false;
-
         return f->sigbus;
 }
 
-void mmap_cache_close_fd(MMapCache *m, int fd) {
-        FileDescriptor *f;
+MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd) {
+        MMapFileDescriptor *f;
+        int r;
 
         assert(m);
         assert(fd >= 0);
 
+        f = hashmap_get(m->fds, FD_TO_PTR(fd));
+        if (f)
+                return f;
+
+        r = hashmap_ensure_allocated(&m->fds, NULL);
+        if (r < 0)
+                return NULL;
+
+        f = new0(MMapFileDescriptor, 1);
+        if (!f)
+                return NULL;
+
+        f->cache = m;
+        f->fd = fd;
+
+        r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
+        if (r < 0)
+                return mfree(f);
+
+        return f;
+}
+
+void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f) {
+        assert(m);
+        assert(f);
+
         /* Make sure that any queued SIGBUS are first dispatched, so
          * that we don't end up with a SIGBUS entry we cannot relate
          * to any existing memory map */
 
         mmap_cache_process_sigbus(m);
 
-        f = hashmap_get(m->fds, FD_TO_PTR(fd));
-        if (!f)
-                return;
+        while (f->windows)
+                window_free(f->windows);
+
+        if (f->cache)
+                assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd)));
 
-        fd_free(f);
+        free(f);
 }
index 199d944647938199167b1209317032047680f968..7b332185636c401418cc8f43b872479828020ecf 100644 (file)
@@ -26,6 +26,7 @@
 #define MMAP_CACHE_MAX_CONTEXTS 9
 
 typedef struct MMapCache MMapCache;
+typedef struct MMapFileDescriptor MMapFileDescriptor;
 
 MMapCache* mmap_cache_new(void);
 MMapCache* mmap_cache_ref(MMapCache *m);
@@ -33,7 +34,7 @@ MMapCache* mmap_cache_unref(MMapCache *m);
 
 int mmap_cache_get(
         MMapCache *m,
-        int fd,
+        MMapFileDescriptor *f,
         int prot,
         unsigned context,
         bool keep_always,
@@ -41,9 +42,10 @@ int mmap_cache_get(
         size_t size,
         struct stat *st,
         void **ret);
-void mmap_cache_close_fd(MMapCache *m, int fd);
+MMapFileDescriptor * mmap_cache_add_fd(MMapCache *m, int fd);
+void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f);
 
 unsigned mmap_cache_get_hit(MMapCache *m);
 unsigned mmap_cache_get_missed(MMapCache *m);
 
-bool mmap_cache_got_sigbus(MMapCache *m, int fd);
+bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f);
index 71967a0f3330573056a50a26eb0ada690435ae7e..cd56470a33a86aea9b43778e6da587c9ca00b1eb 100644 (file)
@@ -882,8 +882,11 @@ static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t
         if (skip == 0) {
                 /* If this is not a discrete skip, then at least
                  * resolve the current location */
-                if (j->current_location.type != LOCATION_DISCRETE)
-                        return real_journal_next(j, direction);
+                if (j->current_location.type != LOCATION_DISCRETE) {
+                        r = real_journal_next(j, direction);
+                        if (r < 0)
+                                return r;
+                }
 
                 return 0;
         }
@@ -2424,6 +2427,7 @@ _public_ int sd_journal_process(sd_journal *j) {
         assert_return(!journal_pid_changed(j), -ECHILD);
 
         j->last_process_usec = now(CLOCK_MONOTONIC);
+        j->last_invalidate_counter = j->current_invalidate_counter;
 
         for (;;) {
                 union inotify_event_buffer buffer;
index 6f6d71435d21419d51e7a29f1ba8b18ec6a6ff4f..4fb93ded73ef32b1156c2185243b8367434e6a3e 100644 (file)
@@ -30,6 +30,8 @@ typedef int (compress_t)(const void *src, uint64_t src_size, void *dst,
 typedef int (decompress_t)(const void *src, uint64_t src_size,
                            void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max);
 
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+
 static usec_t arg_duration = 2 * USEC_PER_SEC;
 static size_t arg_start;
 
@@ -151,8 +153,10 @@ static void test_compress_decompress(const char* label, const char* type,
                  100 - compressed * 100. / total,
                  skipped);
 }
+#endif
 
 int main(int argc, char *argv[]) {
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
         const char *i;
 
         log_set_max_level(LOG_INFO);
@@ -177,4 +181,7 @@ int main(int argc, char *argv[]) {
 #endif
         }
         return 0;
+#else
+        return EXIT_TEST_SKIP;
+#endif
 }
index 44a2cf5217315b6c87e3d3b384e9835bcec82acd..92108a84b3f13af2ed084b934b5b34927c73afe5 100644 (file)
@@ -54,6 +54,7 @@ typedef int (decompress_sw_t)(const void *src, uint64_t src_size,
 typedef int (compress_stream_t)(int fdf, int fdt, uint64_t max_bytes);
 typedef int (decompress_stream_t)(int fdf, int fdt, uint64_t max_size);
 
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
 static void test_compress_decompress(int compression,
                                      compress_blob_t compress,
                                      decompress_blob_t decompress,
@@ -203,6 +204,7 @@ static void test_compress_stream(int compression,
         assert_se(unlink(pattern) == 0);
         assert_se(unlink(pattern2) == 0);
 }
+#endif
 
 #ifdef HAVE_LZ4
 static void test_lz4_decompress_partial(void) {
@@ -247,6 +249,7 @@ static void test_lz4_decompress_partial(void) {
 #endif
 
 int main(int argc, char *argv[]) {
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
         const char text[] =
                 "text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"
                 "foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF";
@@ -312,4 +315,7 @@ int main(int argc, char *argv[]) {
 #endif
 
         return 0;
+#else
+        return EXIT_TEST_SKIP;
+#endif
 }
index 0ad49aeb5fd5322a6294275d94b212c5b9a3728e..c51b069f8bd200eb90703c0d2c6ad1d4908e528c 100644 (file)
@@ -29,6 +29,7 @@
 #include "util.h"
 
 int main(int argc, char *argv[]) {
+        MMapFileDescriptor *fx;
         int x, y, z, r;
         char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX";
         MMapCache *m;
@@ -40,6 +41,8 @@ int main(int argc, char *argv[]) {
         assert_se(x >= 0);
         unlink(px);
 
+        assert_se(fx = mmap_cache_add_fd(m, x));
+
         y = mkostemp_safe(py);
         assert_se(y >= 0);
         unlink(py);
@@ -48,27 +51,28 @@ int main(int argc, char *argv[]) {
         assert_se(z >= 0);
         unlink(pz);
 
-        r = mmap_cache_get(m, x, PROT_READ, 0, false, 1, 2, NULL, &p);
+        r = mmap_cache_get(m, fx, PROT_READ, 0, false, 1, 2, NULL, &p);
         assert_se(r >= 0);
 
-        r = mmap_cache_get(m, x, PROT_READ, 0, false, 2, 2, NULL, &q);
+        r = mmap_cache_get(m, fx, PROT_READ, 0, false, 2, 2, NULL, &q);
         assert_se(r >= 0);
 
         assert_se((uint8_t*) p + 1 == (uint8_t*) q);
 
-        r = mmap_cache_get(m, x, PROT_READ, 1, false, 3, 2, NULL, &q);
+        r = mmap_cache_get(m, fx, PROT_READ, 1, false, 3, 2, NULL, &q);
         assert_se(r >= 0);
 
         assert_se((uint8_t*) p + 2 == (uint8_t*) q);
 
-        r = mmap_cache_get(m, x, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p);
+        r = mmap_cache_get(m, fx, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p);
         assert_se(r >= 0);
 
-        r = mmap_cache_get(m, x, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q);
+        r = mmap_cache_get(m, fx, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q);
         assert_se(r >= 0);
 
         assert_se((uint8_t*) p + 1 == (uint8_t*) q);
 
+        mmap_cache_free_fd(m, fx);
         mmap_cache_unref(m);
 
         safe_close(x);
index 68c24bed7a1b56091b84e1127523bdc3693071f8..56925c8a5d8770b69ded67849fd58a3c7c8f9739 100644 (file)
@@ -2,7 +2,15 @@
 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
 # ex: ts=8 sw=4 sts=4 et filetype=sh
 
-[[ $1 == "add" ]] || exit 0
 [[ $2 ]] || exit 1
 
-exec depmod -a "$2"
+case "$1" in
+    add)
+        exec depmod -a "$2"
+        ;;
+    remove)
+        exec rm -f /lib/modules/"$2"/modules.{alias{,.bin},builtin.bin,dep{,.bin},devname,softdep,symbols{,.bin}}
+        ;;
+    *)
+        exit 0
+esac
index a0bca05c9a17579d7a4bc5b80bad948fdc65d173..305ea8f5c97f9466376daf6e4aa8f6b11619edb0 100644 (file)
@@ -7,13 +7,11 @@ KERNEL_VERSION="$2"
 BOOT_DIR_ABS="$3"
 KERNEL_IMAGE="$4"
 
-if [[ -f /etc/machine-id ]]; then
-    read MACHINE_ID < /etc/machine-id
+if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then
+    exit 0
 fi
 
-if ! [[ $MACHINE_ID ]]; then
-    exit 1
-fi
+MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
 
 BOOT_DIR="/$MACHINE_ID/$KERNEL_VERSION"
 BOOT_ROOT=${BOOT_DIR_ABS%$BOOT_DIR}
index c7d9f4eea9e4611f8d9c9ca54129b4e346935aae..66bc4a6e8e2327d9837702357812fdacfe8b972f 100644 (file)
@@ -77,18 +77,15 @@ if [[ -f /etc/machine-id ]]; then
     read MACHINE_ID < /etc/machine-id
 fi
 
-if ! [[ $MACHINE_ID ]]; then
-    echo "Could not determine your machine ID from /etc/machine-id." >&2
-    echo "Please run 'systemd-machine-id-setup' as root. See man:machine-id(5)" >&2
-    exit 1
-fi
-
 if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then
     echo "Not enough arguments" >&2
     exit 1
 fi
 
-if [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then
+if ! [[ $MACHINE_ID ]]; then
+    BOOT_DIR_ABS=$(mktemp -d /tmp/kernel-install.XXXXX) || exit 1
+    trap "rm -rf '$BOOT_DIR_ABS'" EXIT INT QUIT PIPE
+elif [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then
     BOOT_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
 elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then
     BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
@@ -102,6 +99,8 @@ else
     BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
 fi
 
+export KERNEL_INSTALL_MACHINE_ID=$MACHINE_ID
+
 ret=0
 
 readarray -t PLUGINS <<<"$(
@@ -127,11 +126,20 @@ case $COMMAND in
                 "$f" add "$KERNEL_VERSION" "$BOOT_DIR_ABS" "$KERNEL_IMAGE"
                 x=$?
                 if [[ $x == $SKIP_REMAINING ]]; then
-                    exit 0
+                    ret=0
+                    break
                 fi
                 ((ret+=$x))
             fi
         done
+
+        if ! [[ $MACHINE_ID ]] && ! rmdir "$BOOT_DIR_ABS"; then
+            echo "Warning: In kernel-install plugins, requiring BOOT_DIR_ABS to be preset is deprecated." >&2
+            echo "         All plugins should not put anything in BOOT_DIR_ABS if the environment" >&2
+            echo "         variable KERNEL_INSTALL_MACHINE_ID is empty." >&2
+            rm -rf "$BOOT_DIR_ABS"
+            ((ret+=$?))
+        fi
         ;;
 
     remove)
@@ -140,7 +148,8 @@ case $COMMAND in
                 "$f" remove "$KERNEL_VERSION" "$BOOT_DIR_ABS"
                 x=$?
                 if [[ $x == $SKIP_REMAINING ]]; then
-                    exit 0
+                    ret=0
+                    break
                 fi
                 ((ret+=$x))
             fi
diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build
new file mode 100644 (file)
index 0000000..ede3323
--- /dev/null
@@ -0,0 +1,11 @@
+install_data('kernel-install',
+             install_mode : 'rwxr-xr-x',
+             install_dir : bindir)
+
+install_data('50-depmod.install',
+             '90-loaderentry.install',
+             install_mode : 'rwxr-xr-x',
+             install_dir : kernelinstalldir)
+
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(sysconfdir, 'kernel/install.d')))
index 82cae2300ac72ba72cf438bb471a95cd853a9124..7847ce07095b4b2439c074f3efe08ed76aad8a63 100644 (file)
@@ -75,6 +75,7 @@ struct sd_dhcp_lease {
         uint16_t mtu; /* 0 if unset */
 
         char *domainname;
+        char **search_domains;
         char *hostname;
         char *root_path;
 
@@ -92,6 +93,7 @@ struct sd_dhcp_lease {
 int dhcp_lease_new(sd_dhcp_lease **ret);
 
 int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata);
+int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains);
 int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len);
 
 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
index c2e4b0e9e3cdc0ecbd897c365d377660f6cf2030..7fbebd6f2757385f044ae2581f0843eefb1932af 100644 (file)
@@ -32,6 +32,7 @@
 #include "fd-util.h"
 #include "icmp6-util.h"
 #include "socket-util.h"
+#include "in-addr-util.h"
 
 #define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
         { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
         { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
 
-int icmp6_bind_router_solicitation(int index) {
-        struct icmp6_filter filter = { };
-        struct ipv6_mreq mreq = {
-                .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
-                .ipv6mr_interface = index,
-        };
+static int icmp6_bind_router_message(const struct icmp6_filter *filter,
+                                     const struct ipv6_mreq *mreq) {
+        int index = mreq->ipv6mr_interface;
         _cleanup_close_ int s = -1;
         char ifname[IF_NAMESIZE] = "";
         static const int zero = 0, one = 1, hops = 255;
@@ -56,9 +54,11 @@ int icmp6_bind_router_solicitation(int index) {
         if (s < 0)
                 return -errno;
 
-        ICMP6_FILTER_SETBLOCKALL(&filter);
-        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
-        r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
+        r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, filter, sizeof(*filter));
+        if (r < 0)
+                return -errno;
+
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq, sizeof(*mreq));
         if (r < 0)
                 return -errno;
 
@@ -78,7 +78,7 @@ int icmp6_bind_router_solicitation(int index) {
         if (r < 0)
                 return -errno;
 
-        r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+        r = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops));
         if (r < 0)
                 return -errno;
 
@@ -102,6 +102,32 @@ int icmp6_bind_router_solicitation(int index) {
         return r;
 }
 
+int icmp6_bind_router_solicitation(int index) {
+        struct icmp6_filter filter = {};
+        struct ipv6_mreq mreq = {
+                .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
+                .ipv6mr_interface = index,
+        };
+
+        ICMP6_FILTER_SETBLOCKALL(&filter);
+        ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
+
+        return icmp6_bind_router_message(&filter, &mreq);
+}
+
+int icmp6_bind_router_advertisement(int index) {
+        struct icmp6_filter filter = {};
+        struct ipv6_mreq mreq = {
+                .ipv6mr_multiaddr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
+                .ipv6mr_interface = index,
+        };
+
+        ICMP6_FILTER_SETBLOCKALL(&filter);
+        ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
+
+        return icmp6_bind_router_message(&filter, &mreq);
+}
+
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
         struct sockaddr_in6 dst = {
                 .sin6_family = AF_INET6,
@@ -139,3 +165,74 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
 
         return 0;
 }
+
+int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
+                  triple_timestamp *timestamp) {
+        union {
+                struct cmsghdr cmsghdr;
+                uint8_t buf[CMSG_SPACE(sizeof(int)) + /* ttl */
+                            CMSG_SPACE(sizeof(struct timeval))];
+        } control = {};
+        struct iovec iov = {};
+        union sockaddr_union sa = {};
+        struct msghdr msg = {
+                .msg_name = &sa.sa,
+                .msg_namelen = sizeof(sa),
+                .msg_iov = &iov,
+                .msg_iovlen = 1,
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
+        };
+        struct cmsghdr *cmsg;
+        ssize_t len;
+
+        iov.iov_base = buffer;
+        iov.iov_len = size;
+
+        len = recvmsg(fd, &msg, MSG_DONTWAIT);
+        if (len < 0) {
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
+                return -errno;
+        }
+
+        if ((size_t) len != size)
+                return -EINVAL;
+
+        if (msg.msg_namelen == sizeof(struct sockaddr_in6) &&
+            sa.in6.sin6_family == AF_INET6)  {
+
+                *dst = sa.in6.sin6_addr;
+                if (in_addr_is_link_local(AF_INET6, (union in_addr_union*) dst) <= 0)
+                        return -EADDRNOTAVAIL;
+
+        } else if (msg.msg_namelen > 0)
+                return -EPFNOSUPPORT;
+
+        /* namelen == 0 only happens when running the test-suite over a socketpair */
+
+        assert(!(msg.msg_flags & MSG_CTRUNC));
+        assert(!(msg.msg_flags & MSG_TRUNC));
+
+        CMSG_FOREACH(cmsg, &msg) {
+                if (cmsg->cmsg_level == SOL_IPV6 &&
+                    cmsg->cmsg_type == IPV6_HOPLIMIT &&
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+                        int hops = *(int*) CMSG_DATA(cmsg);
+
+                        if (hops != 255)
+                                return -EMULTIHOP;
+                }
+
+                if (cmsg->cmsg_level == SOL_SOCKET &&
+                    cmsg->cmsg_type == SO_TIMESTAMP &&
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
+                        triple_timestamp_from_realtime(timestamp, timeval_load((struct timeval*) CMSG_DATA(cmsg)));
+        }
+
+        if (!triple_timestamp_is_set(timestamp))
+                triple_timestamp_get(timestamp);
+
+        return 0;
+}
index 2b4dbc76cee5fe98fbfb08d685b72925a8bc45aa..16b8be8298d655fd28fde9caba8cf088874dbdcb 100644 (file)
 
 #include <net/ethernet.h>
 
+#include "time-util.h"
+
+#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
+        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } }
+
+#define IN6ADDR_ALL_NODES_MULTICAST_INIT \
+        { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
+
 int icmp6_bind_router_solicitation(int index);
+int icmp6_bind_router_advertisement(int index);
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr);
+int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
+                  triple_timestamp *timestamp);
index 53e29377b35dd482f525e598d346d3ce80353372..f1fecba6fa4f8b2031fe2e9c9c3583b89ffc8a2d 100644 (file)
@@ -249,10 +249,9 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                                 log_lldp("End marker TLV not zero-sized, ignoring datagram.");
                                 return -EBADMSG;
                         }
-                        if (left != 0) {
-                                log_lldp("Trailing garbage in datagram, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+
+                        /* Note that after processing the SD_LLDP_TYPE_END left could still be > 0
+                         * as the message may contain padding (see IEEE 802.1AB-2016, sec. 8.5.12) */
 
                         goto end_marker;
 
diff --git a/src/libsystemd-network/meson.build b/src/libsystemd-network/meson.build
new file mode 100644 (file)
index 0000000..78c7456
--- /dev/null
@@ -0,0 +1,48 @@
+sources = files('''
+        sd-dhcp-client.c
+        sd-dhcp-server.c
+        dhcp-network.c
+        dhcp-option.c
+        dhcp-packet.c
+        dhcp-internal.h
+        dhcp-server-internal.h
+        dhcp-protocol.h
+        dhcp-lease-internal.h
+        sd-dhcp-lease.c
+        sd-ipv4ll.c
+        sd-ipv4acd.c
+        arp-util.h
+        arp-util.c
+        network-internal.c
+        sd-ndisc.c
+        ndisc-internal.h
+        ndisc-router.h
+        ndisc-router.c
+        sd-radv.c
+        radv-internal.h
+        icmp6-util.h
+        icmp6-util.c
+        sd-dhcp6-client.c
+        dhcp6-internal.h
+        dhcp6-protocol.h
+        dhcp6-network.c
+        dhcp6-option.c
+        dhcp6-lease-internal.h
+        sd-dhcp6-lease.c
+        dhcp-identifier.h
+        dhcp-identifier.c
+        lldp-internal.h
+        lldp-network.h
+        lldp-network.c
+        lldp-neighbor.h
+        lldp-neighbor.c
+        sd-lldp.c
+'''.split())
+
+network_internal_h = files('network-internal.h')
+
+libsystemd_network = static_library(
+        'systemd-network',
+        sources,
+        network_internal_h,
+        include_directories : includes)
index 60e183ff8cedd8cd79cbf47edc4f2b12e8343237..82b896dba3cf8b485f32e0ebfae8460549b9934a 100644 (file)
 
 #include "sd-ndisc.h"
 
+#define NDISC_ROUTER_SOLICITATION_INTERVAL (4U * USEC_PER_SEC)
+#define NDISC_MAX_ROUTER_SOLICITATION_INTERVAL (3600U * USEC_PER_SEC)
+#define NDISC_MAX_ROUTER_SOLICITATIONS 3U
+
 struct sd_ndisc {
         unsigned n_ref;
 
@@ -38,8 +42,9 @@ struct sd_ndisc {
 
         sd_event_source *recv_event_source;
         sd_event_source *timeout_event_source;
+        sd_event_source *timeout_no_ra;
 
-        unsigned nd_sent;
+        usec_t retransmit_time;
 
         sd_ndisc_callback_t callback;
         void *userdata;
index 092a1eabb07dd5eb79a6bdecc22b0dba4bc95161..337241a815e41323fa42bc05c0da459727700637 100644 (file)
@@ -349,6 +349,45 @@ int config_parse_iaid(const char *unit,
         return 0;
 }
 
+int config_parse_bridge_port_priority(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        uint16_t i;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou16(rvalue, &i);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse bridge port priority, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue);
+                return 0;
+        }
+
+        *((uint16_t *)data) = i;
+
+        return 0;
+}
+
+
 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
         unsigned i;
 
index 5bcd577167d4e9149577ed6209268f09276bce2e..4666f174e9edaee920149dcbc14bf5f2d2d277dc 100644 (file)
@@ -26,6 +26,9 @@
 #include "condition.h"
 #include "udev.h"
 
+#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
+#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
+
 bool net_match_config(const struct ether_addr *match_mac,
                       char * const *match_path,
                       char * const *match_driver,
@@ -62,6 +65,10 @@ int config_parse_iaid(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_bridge_port_priority(const char *unit, const char *filename, unsigned line,
+                      const char *section, unsigned section_line, const char *lvalue,
+                      int ltype, const char *rvalue, void *data, void *userdata);
+
 int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
 const char *net_get_name(struct udev_device *device);
 
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h
new file mode 100644 (file)
index 0000000..b21d4e5
--- /dev/null
@@ -0,0 +1,88 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2017 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (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 "sd-radv.h"
+
+#include "log.h"
+#include "list.h"
+#include "sparse-endian.h"
+
+#define SD_RADV_DEFAULT_MIN_TIMEOUT_USEC        (200*USEC_PER_SEC)
+#define SD_RADV_DEFAULT_MAX_TIMEOUT_USEC        (600*USEC_PER_SEC)
+assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC)
+
+#define SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC (16*USEC_PER_SEC)
+#define SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS  3
+#define SD_RADV_MAX_FINAL_RTR_ADVERTISEMENTS    3
+#define SD_RADV_MIN_DELAY_BETWEEN_RAS           3
+#define SD_RADV_MAX_RA_DELAY_TIME_USEC          (500*USEC_PER_MSEC)
+
+enum RAdvState {
+        SD_RADV_STATE_IDLE                      = 0,
+        SD_RADV_STATE_ADVERTISING               = 1,
+};
+typedef enum RAdvState RAdvState;
+
+struct sd_radv {
+        unsigned n_ref;
+        RAdvState state;
+
+        int ifindex;
+
+        sd_event *event;
+        int event_priority;
+
+        struct ether_addr mac_addr;
+        uint8_t hop_limit;
+        uint8_t flags;
+        uint32_t mtu;
+        uint16_t lifetime;
+
+        int fd;
+        unsigned ra_sent;
+        sd_event_source *recv_event_source;
+        sd_event_source *timeout_event_source;
+
+        unsigned n_prefixes;
+        LIST_HEAD(sd_radv_prefix, prefixes);
+};
+
+struct sd_radv_prefix {
+        unsigned n_ref;
+
+        struct {
+                uint8_t type;
+                uint8_t length;
+                uint8_t prefixlen;
+                uint8_t flags;
+                be32_t valid_lifetime;
+                be32_t preferred_lifetime;
+                uint32_t reserved;
+                struct in6_addr in6_addr;
+        } _packed_ opt;
+
+        LIST_FIELDS(struct sd_radv_prefix, prefix);
+};
+
+#define log_radv_full(level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__)
+#define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__)
+#define log_radv_warning_errno(error, fmt, ...) log_radv_full(LOG_WARNING, error, fmt, ##__VA_ARGS__)
+#define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__)
index 7c0317640fa5e84485296608596e30a6383204a2..e20d339bd504c08c5974705f9a25cb3d915050a9 100644 (file)
@@ -1655,7 +1655,8 @@ static int client_receive_message_udp(
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
 
-                return log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket: %m");
+                return log_dhcp_client_errno(client, errno,
+                                             "Could not receive message from UDP socket: %m");
         }
         if ((size_t) len < sizeof(DHCPMessage)) {
                 log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
@@ -1748,9 +1749,8 @@ static int client_receive_message_raw(
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
 
-                log_dhcp_client(client, "Could not receive message from raw socket: %m");
-
-                return -errno;
+                return log_dhcp_client_errno(client, errno,
+                                             "Could not receive message from raw socket: %m");
         } else if ((size_t)len < sizeof(DHCPPacket))
                 return 0;
 
index 7fed55c5fc88eec6fdbb7e5d08ec7f73a73ac734..1661874a55bb422f75d8fcbd6d1aabe325351128 100644 (file)
@@ -231,6 +231,21 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
         return (int) lease->static_route_size;
 }
 
+int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
+        unsigned r;
+
+        assert_return(lease, -EINVAL);
+        assert_return(domains, -EINVAL);
+
+        r = strv_length(lease->search_domains);
+        if (r > 0) {
+                *domains = lease->search_domains;
+                return (int) r;
+        }
+
+        return -ENODATA;
+}
+
 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {
         assert_return(lease, -EINVAL);
         assert_return(data, -EINVAL);
@@ -282,6 +297,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
         free(lease->static_route);
         free(lease->client_id);
         free(lease->vendor_specific);
+        strv_free(lease->search_domains);
         return mfree(lease);
 }
 
@@ -594,6 +610,11 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
                 r = lease_parse_u16(option, len, &lease->mtu, 68);
                 if (r < 0)
                         log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
+                if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) {
+                        log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE);
+                        lease->mtu = DHCP_DEFAULT_MIN_SIZE;
+                }
+
                 break;
 
         case SD_DHCP_OPTION_DOMAIN_NAME:
@@ -605,6 +626,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
 
                 break;
 
+        case SD_DHCP_OPTION_DOMAIN_SEARCH_LIST:
+                r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m");
+                break;
+
         case SD_DHCP_OPTION_HOST_NAME:
                 r = lease_parse_domain(option, len, &lease->hostname);
                 if (r < 0) {
@@ -696,6 +723,96 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
         return 0;
 }
 
+/* Parses compressed domain names. */
+int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains) {
+        _cleanup_strv_free_ char **names = NULL;
+        size_t pos = 0, cnt = 0;
+        int r;
+
+        assert(domains);
+        assert_return(option && len > 0, -ENODATA);
+
+        while (pos < len) {
+                _cleanup_free_ char *name = NULL;
+                size_t n = 0, allocated = 0;
+                size_t jump_barrier = pos, next_chunk = 0;
+                bool first = true;
+
+                for (;;) {
+                        uint8_t c;
+                        c = option[pos++];
+
+                        if (c == 0) {
+                                /* End of name */
+                                break;
+                        } else if (c <= 63) {
+                                const char *label;
+
+                                /* Literal label */
+                                label = (const char*) (option + pos);
+                                pos += c;
+                                if (pos >= len)
+                                        return -EBADMSG;
+
+                                if (!GREEDY_REALLOC(name, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+                                        return -ENOMEM;
+
+                                if (first)
+                                        first = false;
+                                else
+                                        name[n++] = '.';
+
+                                r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX);
+                                if (r < 0)
+                                        return r;
+
+                                n += r;
+                        } else if ((c & 0xc0) == 0xc0) {
+                                /* Pointer */
+
+                                uint8_t d;
+                                uint16_t ptr;
+
+                                if (pos >= len)
+                                        return -EBADMSG;
+
+                                d = option[pos++];
+                                ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
+
+                                /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
+                                if (ptr >= jump_barrier)
+                                        return -EBADMSG;
+                                jump_barrier = ptr;
+
+                                /* Save current location so we don't end up re-parsing what's parsed so far. */
+                                if (next_chunk == 0)
+                                        next_chunk = pos;
+
+                                pos = ptr;
+                        } else
+                                return -EBADMSG;
+                }
+
+                if (!GREEDY_REALLOC(name, allocated, n + 1))
+                        return -ENOMEM;
+                name[n] = 0;
+
+                r = strv_extend(&names, name);
+                if (r < 0)
+                        return r;
+
+                cnt++;
+
+                if (next_chunk != 0)
+                      pos = next_chunk;
+        }
+
+        *domains = names;
+        names = NULL;
+
+        return cnt;
+}
+
 int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) {
         struct sd_dhcp_raw_option *cur, *option;
 
@@ -751,6 +868,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         const char *string;
         uint16_t mtu;
         _cleanup_free_ sd_dhcp_route **routes = NULL;
+        char **search_domains = NULL;
         uint32_t t1, t2, lifetime;
         int r;
 
@@ -824,6 +942,13 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         if (r >= 0)
                 fprintf(f, "DOMAINNAME=%s\n", string);
 
+        r = sd_dhcp_lease_get_search_domains(lease, &search_domains);
+        if (r > 0) {
+                fputs("DOMAIN_SEARCH_LIST=", f);
+                fputstrv(f, search_domains, NULL, NULL);
+                fputs("\n", f);
+        }
+
         r = sd_dhcp_lease_get_hostname(lease, &string);
         if (r >= 0)
                 fprintf(f, "HOSTNAME=%s\n", string);
@@ -905,6 +1030,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                 *ntp = NULL,
                 *mtu = NULL,
                 *routes = NULL,
+                *domains = NULL,
                 *client_id_hex = NULL,
                 *vendor_specific_hex = NULL,
                 *lifetime = NULL,
@@ -933,6 +1059,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                            "MTU", &mtu,
                            "DOMAINNAME", &lease->domainname,
                            "HOSTNAME", &lease->hostname,
+                           "DOMAIN_SEARCH_LIST", &domains,
                            "ROOT_PATH", &lease->root_path,
                            "ROUTES", &routes,
                            "CLIENTID", &client_id_hex,
@@ -1038,6 +1165,18 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu);
         }
 
+        if (domains) {
+                _cleanup_strv_free_ char **a = NULL;
+                a = strv_split(domains, " ");
+                if (!a)
+                        return -ENOMEM;
+
+                if (!strv_isempty(a)) {
+                        lease->search_domains = a;
+                        a = NULL;
+                }
+        }
+
         if (routes) {
                 r = deserialize_dhcp_routes(
                                 &lease->static_route,
index 289068156179d720a8a5d6e0ea4f9b6e6741e52b..5a59c377f8c210d30a58907937dbcfecf4e6d617 100644 (file)
 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
 
+static void dhcp_lease_free(DHCPLease *lease) {
+        if (!lease)
+                return;
+
+        free(lease->client_id.data);
+        free(lease);
+}
+
 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
  * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
  * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
@@ -47,7 +55,6 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres
         assert_return(address, -EINVAL);
         assert_return(address->s_addr != INADDR_ANY, -EINVAL);
         assert_return(prefixlen <= 32, -ERANGE);
-        assert_return(server->address == INADDR_ANY, -EBUSY);
 
         assert_se(in_addr_prefixlen_to_netmask(&netmask_addr, prefixlen));
         netmask = netmask_addr.s_addr;
@@ -78,19 +85,28 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres
         else
                 size = size_max;
 
-        server->bound_leases = new0(DHCPLease*, size);
-        if (!server->bound_leases)
-                return -ENOMEM;
+        if (server->address != address->s_addr || server->netmask != netmask || server->pool_size != size || server->pool_offset != offset) {
+                DHCPLease *lease;
+
+                free(server->bound_leases);
+                server->bound_leases = new0(DHCPLease*, size);
+                if (!server->bound_leases)
+                        return -ENOMEM;
+
+                server->pool_offset = offset;
+                server->pool_size = size;
 
-        server->pool_offset = offset;
-        server->pool_size = size;
+                server->address = address->s_addr;
+                server->netmask = netmask;
+                server->subnet = address->s_addr & netmask;
 
-        server->address = address->s_addr;
-        server->netmask = netmask;
-        server->subnet = address->s_addr & netmask;
+                if (server_off >= offset && server_off - offset < size)
+                        server->bound_leases[server_off - offset] = &server->invalid_lease;
 
-        if (server_off >= offset && server_off - offset < size)
-                server->bound_leases[server_off - offset] = &server->invalid_lease;
+                /* Drop any leases associated with the old address range */
+                while ((lease = hashmap_steal_first(server->leases_by_client_id)))
+                        dhcp_lease_free(lease);
+        }
 
         return 0;
 }
@@ -143,14 +159,6 @@ static const struct hash_ops client_id_hash_ops = {
         .compare = client_id_compare_func
 };
 
-static void dhcp_lease_free(DHCPLease *lease) {
-        if (!lease)
-                return;
-
-        free(lease->client_id.data);
-        free(lease);
-}
-
 sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
         DHCPLease *lease;
 
@@ -197,7 +205,11 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
         server->address = htobe32(INADDR_ANY);
         server->netmask = htobe32(INADDR_ANY);
         server->ifindex = ifindex;
+
         server->leases_by_client_id = hashmap_new(&client_id_hash_ops);
+        if (!server->leases_by_client_id)
+                return -ENOMEM;
+
         server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC);
         server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC);
 
@@ -857,6 +869,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
 
                         if (!existing_lease) {
                                 lease = new0(DHCPLease, 1);
+                                if (!lease)
+                                        return -ENOMEM;
                                 lease->address = address;
                                 lease->client_id.data = memdup(req->client_id.data,
                                                                req->client_id.length);
index 13209261f94b2c00672a4dd30ed28455103cfbe1..88a90e593b48ba14f2ec5cae2319be71015d9a9a 100644 (file)
@@ -248,6 +248,12 @@ static int ipv4ll_pick_address(sd_ipv4ll *ll) {
         return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr });
 }
 
+int sd_ipv4ll_restart(sd_ipv4ll *ll) {
+        ll->address = 0;
+
+        return sd_ipv4ll_start(ll);
+}
+
 #define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
 
 int sd_ipv4ll_start(sd_ipv4ll *ll) {
index 0702241506b1522d82e26a580bc77464a5c943b4..39ddb2461afb421327d19698a17651dcb0275058 100644 (file)
@@ -19,6 +19,7 @@
 ***/
 
 #include <arpa/inet.h>
+#include <linux/sockios.h>
 
 #include "sd-lldp.h"
 
index 1d3be9b86239ca61227068a8b62e932175142d78..4bf558b12bae56896d21ed0918d7fcf070ef857c 100644 (file)
 #include "in-addr-util.h"
 #include "ndisc-internal.h"
 #include "ndisc-router.h"
+#include "random-util.h"
 #include "socket-util.h"
 #include "string-util.h"
 #include "util.h"
 
-#define NDISC_ROUTER_SOLICITATION_INTERVAL (4U * USEC_PER_SEC)
-#define NDISC_MAX_ROUTER_SOLICITATIONS 3U
+#define NDISC_TIMEOUT_NO_RA_USEC (NDISC_ROUTER_SOLICITATION_INTERVAL * NDISC_MAX_ROUTER_SOLICITATIONS)
 
 static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event event, sd_ndisc_router *rt) {
         assert(ndisc);
@@ -129,6 +129,8 @@ static int ndisc_reset(sd_ndisc *nd) {
         assert(nd);
 
         nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
+        nd->timeout_no_ra = sd_event_source_unref(nd->timeout_no_ra);
+        nd->retransmit_time = 0;
         nd->recv_event_source = sd_event_source_unref(nd->recv_event_source);
         nd->fd = safe_close(nd->fd);
 
@@ -221,23 +223,9 @@ static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) {
 static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         _cleanup_(sd_ndisc_router_unrefp) sd_ndisc_router *rt = NULL;
         sd_ndisc *nd = userdata;
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int)) + /* ttl */
-                            CMSG_SPACE(sizeof(struct timeval))];
-        } control = {};
-        struct iovec iov = {};
-        union sockaddr_union sa = {};
-        struct msghdr msg = {
-                .msg_name = &sa.sa,
-                .msg_namelen = sizeof(sa),
-                .msg_iov = &iov,
-                .msg_iovlen = 1,
-                .msg_control = &control,
-                .msg_controllen = sizeof(control),
-        };
-        struct cmsghdr *cmsg;
-        ssize_t len, buflen;
+        ssize_t buflen;
+        int r;
+        _cleanup_free_ char *addr = NULL;
 
         assert(s);
         assert(nd);
@@ -251,110 +239,90 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
         if (!rt)
                 return -ENOMEM;
 
-        iov.iov_base = NDISC_ROUTER_RAW(rt);
-        iov.iov_len = rt->raw_size;
-
-        len = recvmsg(fd, &msg, MSG_DONTWAIT);
-        if (len < 0) {
-                if (errno == EAGAIN || errno == EINTR)
-                        return 0;
-
-                return log_ndisc_errno(errno, "Could not receive message from ICMPv6 socket: %m");
-        }
-
-        if ((size_t) len != rt->raw_size) {
-                log_ndisc("Packet size mismatch.");
-                return -EINVAL;
-        }
-
-        if (msg.msg_namelen == sizeof(struct sockaddr_in6) &&
-            sa.in6.sin6_family == AF_INET6)  {
-
-                if (in_addr_is_link_local(AF_INET6, (union in_addr_union*) &sa.in6.sin6_addr) <= 0) {
-                        _cleanup_free_ char *addr = NULL;
-
-                        (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &sa.in6.sin6_addr, &addr);
-                        log_ndisc("Received RA from non-link-local address %s. Ignoring.", strna(addr));
-                        return 0;
-                }
-
-                rt->address = sa.in6.sin6_addr;
-
-        } else if (msg.msg_namelen > 0) {
-                log_ndisc("Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t) msg.msg_namelen);
-                return -EINVAL;
-        }
-
-        /* namelen == 0 only happens when running the test-suite over a socketpair */
-
-        assert(!(msg.msg_flags & MSG_CTRUNC));
-        assert(!(msg.msg_flags & MSG_TRUNC));
-
-        CMSG_FOREACH(cmsg, &msg) {
-                if (cmsg->cmsg_level == SOL_IPV6 &&
-                    cmsg->cmsg_type == IPV6_HOPLIMIT &&
-                    cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
-                        int hops = *(int*) CMSG_DATA(cmsg);
-
-                        if (hops != 255) {
-                                log_ndisc("Received RA with invalid hop limit %d. Ignoring.", hops);
-                                return 0;
-                        }
+        r = icmp6_receive(fd, NDISC_ROUTER_RAW(rt), rt->raw_size, &rt->address,
+                     &rt->timestamp);
+        if (r < 0) {
+                switch (r) {
+                case -EADDRNOTAVAIL:
+                        (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &rt->address, &addr);
+                        log_ndisc("Received RA from non-link-local address %s. Ignoring", addr);
+                        break;
+
+                case -EMULTIHOP:
+                        log_ndisc("Received RA with invalid hop limit. Ignoring.");
+                        break;
+
+                case -EPFNOSUPPORT:
+                        log_ndisc("Received invalid source address from ICMPv6 socket.");
+                        break;
                 }
 
-                if (cmsg->cmsg_level == SOL_SOCKET &&
-                    cmsg->cmsg_type == SO_TIMESTAMP &&
-                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
-                        triple_timestamp_from_realtime(&rt->timestamp, timeval_load((struct timeval*) CMSG_DATA(cmsg)));
+                return 0;
         }
 
-        if (!triple_timestamp_is_set(&rt->timestamp))
-                triple_timestamp_get(&rt->timestamp);
-
         nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
 
         return ndisc_handle_datagram(nd, rt);
 }
 
+static usec_t ndisc_timeout_compute_random(usec_t val) {
+        /* compute a time that is random within ±10% of the given value */
+        return val - val / 10 +
+                (random_u64() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
+}
+
 static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_ndisc *nd = userdata;
-        usec_t time_now, next_timeout;
+        usec_t time_now;
         int r;
+        char time_string[FORMAT_TIMESPAN_MAX];
 
         assert(s);
         assert(nd);
         assert(nd->event);
 
-        if (nd->nd_sent >= NDISC_MAX_ROUTER_SOLICITATIONS) {
-                nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
-                ndisc_callback(nd, SD_NDISC_EVENT_TIMEOUT, NULL);
-                return 0;
+        assert_se(sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
+
+        nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
+
+        if (!nd->retransmit_time)
+                nd->retransmit_time = ndisc_timeout_compute_random(NDISC_ROUTER_SOLICITATION_INTERVAL);
+        else {
+                if (nd->retransmit_time > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 2)
+                        nd->retransmit_time = ndisc_timeout_compute_random(NDISC_MAX_ROUTER_SOLICITATION_INTERVAL);
+                else
+                        nd->retransmit_time += ndisc_timeout_compute_random(nd->retransmit_time);
         }
 
-        r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr);
-        if (r < 0) {
-                log_ndisc_errno(r, "Error sending Router Solicitation: %m");
+        r = sd_event_add_time(nd->event, &nd->timeout_event_source,
+                              clock_boottime_or_monotonic(),
+                              time_now + nd->retransmit_time,
+                              10 * USEC_PER_MSEC, ndisc_timeout, nd);
+        if (r < 0)
                 goto fail;
-        }
 
-        log_ndisc("Sent Router Solicitation");
-        nd->nd_sent++;
+        r = sd_event_source_set_priority(nd->timeout_event_source, nd->event_priority);
+        if (r < 0)
+                goto fail;
 
-        assert_se(sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
-        next_timeout = time_now + NDISC_ROUTER_SOLICITATION_INTERVAL;
+        (void) sd_event_source_set_description(nd->timeout_event_source, "ndisc-timeout-no-ra");
 
-        r = sd_event_source_set_time(nd->timeout_event_source, next_timeout);
+        r = sd_event_source_set_enabled(nd->timeout_event_source, SD_EVENT_ONESHOT);
         if (r < 0) {
-                log_ndisc_errno(r, "Error updating timer: %m");
+                log_ndisc_errno(r, "Error reenabling timer: %m");
                 goto fail;
         }
 
-        r = sd_event_source_set_enabled(nd->timeout_event_source, SD_EVENT_ONESHOT);
+        r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr);
         if (r < 0) {
-                log_ndisc_errno(r, "Error reenabling timer: %m");
+                log_ndisc_errno(r, "Error sending Router Solicitation: %m");
                 goto fail;
         }
 
+        log_ndisc("Sent Router Solicitation, next solicitation in %s",
+                  format_timespan(time_string, FORMAT_TIMESPAN_MAX,
+                                  nd->retransmit_time, USEC_PER_SEC));
+
         return 0;
 
 fail:
@@ -362,6 +330,20 @@ fail:
         return 0;
 }
 
+static int ndisc_timeout_no_ra(sd_event_source *s, uint64_t usec, void *userdata) {
+        sd_ndisc *nd = userdata;
+
+        assert(s);
+        assert(nd);
+
+        log_ndisc("No RA received before link confirmation timeout");
+
+        nd->timeout_no_ra = sd_event_source_unref(nd->timeout_no_ra);
+        ndisc_callback(nd, SD_NDISC_EVENT_TIMEOUT, NULL);
+
+        return 0;
+}
+
 _public_ int sd_ndisc_stop(sd_ndisc *nd) {
         assert_return(nd, -EINVAL);
 
@@ -376,6 +358,7 @@ _public_ int sd_ndisc_stop(sd_ndisc *nd) {
 
 _public_ int sd_ndisc_start(sd_ndisc *nd) {
         int r;
+        usec_t time_now;
 
         assert_return(nd, -EINVAL);
         assert_return(nd->event, -EINVAL);
@@ -387,6 +370,10 @@ _public_ int sd_ndisc_start(sd_ndisc *nd) {
         assert(!nd->recv_event_source);
         assert(!nd->timeout_event_source);
 
+        r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
+        if (r < 0)
+                goto fail;
+
         nd->fd = icmp6_bind_router_solicitation(nd->ifindex);
         if (nd->fd < 0)
                 return nd->fd;
@@ -411,6 +398,19 @@ _public_ int sd_ndisc_start(sd_ndisc *nd) {
 
         (void) sd_event_source_set_description(nd->timeout_event_source, "ndisc-timeout");
 
+        r = sd_event_add_time(nd->event, &nd->timeout_no_ra,
+                              clock_boottime_or_monotonic(),
+                              time_now + NDISC_TIMEOUT_NO_RA_USEC,
+                              10 * USEC_PER_MSEC, ndisc_timeout_no_ra, nd);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(nd->timeout_no_ra, nd->event_priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(nd->timeout_no_ra, "ndisc-timeout-no-ra");
+
         log_ndisc("Started IPv6 Router Solicitation client");
         return 1;
 
diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c
new file mode 100644 (file)
index 0000000..f23275a
--- /dev/null
@@ -0,0 +1,653 @@
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2017 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (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 <netinet/icmp6.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <linux/in6.h>
+
+#include "sd-radv.h"
+
+#include "macro.h"
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "icmp6-util.h"
+#include "in-addr-util.h"
+#include "radv-internal.h"
+#include "socket-util.h"
+#include "string-util.h"
+#include "util.h"
+#include "random-util.h"
+
+_public_ int sd_radv_new(sd_radv **ret) {
+        _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
+
+        assert_return(ret, -EINVAL);
+
+        ra = new0(sd_radv, 1);
+        if (!ra)
+                return -ENOMEM;
+
+        ra->n_ref = 1;
+        ra->fd = -1;
+
+        LIST_HEAD_INIT(ra->prefixes);
+
+        *ret = ra;
+        ra = NULL;
+
+        return 0;
+}
+
+_public_ int sd_radv_attach_event(sd_radv *ra, sd_event *event, int64_t priority) {
+        int r;
+
+        assert_return(ra, -EINVAL);
+        assert_return(!ra->event, -EBUSY);
+
+        if (event)
+                ra->event = sd_event_ref(event);
+        else {
+                r = sd_event_default(&ra->event);
+                if (r < 0)
+                        return 0;
+        }
+
+        ra->event_priority = priority;
+
+        return 0;
+}
+
+_public_ int sd_radv_detach_event(sd_radv *ra) {
+
+        assert_return(ra, -EINVAL);
+
+        ra->event = sd_event_unref(ra->event);
+        return 0;
+}
+
+_public_ sd_event *sd_radv_get_event(sd_radv *ra) {
+        assert_return(ra, NULL);
+
+        return ra->event;
+}
+
+static void radv_reset(sd_radv *ra) {
+
+        ra->timeout_event_source =
+                sd_event_source_unref(ra->timeout_event_source);
+
+        ra->recv_event_source =
+                sd_event_source_unref(ra->recv_event_source);
+
+        ra->ra_sent = 0;
+}
+
+_public_ sd_radv *sd_radv_ref(sd_radv *ra) {
+        if (!ra)
+                return NULL;
+
+        assert(ra->n_ref > 0);
+        ra->n_ref++;
+
+        return ra;
+}
+
+_public_ sd_radv *sd_radv_unref(sd_radv *ra) {
+        if (!ra)
+                return NULL;
+
+        assert(ra->n_ref > 0);
+        ra->n_ref--;
+
+        if (ra->n_ref > 0)
+                return NULL;
+
+        while (ra->prefixes) {
+                sd_radv_prefix *p = ra->prefixes;
+
+                LIST_REMOVE(prefix, ra->prefixes, p);
+                sd_radv_prefix_unref(p);
+        }
+
+        radv_reset(ra);
+
+        sd_radv_detach_event(ra);
+        return mfree(ra);
+}
+
+static int radv_send(sd_radv *ra, const struct in6_addr *dst,
+                     const uint32_t router_lifetime) {
+        static const struct ether_addr mac_zero = {};
+        sd_radv_prefix *p;
+        struct sockaddr_in6 dst_addr = {
+                .sin6_family = AF_INET6,
+                .sin6_addr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
+        };
+        struct nd_router_advert adv = {};
+        struct {
+                struct nd_opt_hdr opthdr;
+                struct ether_addr slladdr;
+        } _packed_ opt_mac = {
+                .opthdr = {
+                        .nd_opt_type = ND_OPT_SOURCE_LINKADDR,
+                        .nd_opt_len = (sizeof(struct nd_opt_hdr) +
+                                       sizeof(struct ether_addr) - 1) /8 + 1,
+                },
+        };
+        struct nd_opt_mtu opt_mtu =  {
+                .nd_opt_mtu_type = ND_OPT_MTU,
+                .nd_opt_mtu_len = 1,
+        };
+        /* Reserve iov space for RA header, linkaddr, MTU + N prefixes */
+        struct iovec iov[3 + ra->n_prefixes];
+        struct msghdr msg = {
+                .msg_name = &dst_addr,
+                .msg_namelen = sizeof(dst_addr),
+                .msg_iov = iov,
+        };
+
+        if (dst && !in_addr_is_null(AF_INET6, (union in_addr_union*) dst))
+                dst_addr.sin6_addr = *dst;
+
+        adv.nd_ra_type = ND_ROUTER_ADVERT;
+        adv.nd_ra_curhoplimit = ra->hop_limit;
+        adv.nd_ra_flags_reserved = ra->flags;
+        adv.nd_ra_router_lifetime = htobe16(router_lifetime);
+        iov[msg.msg_iovlen].iov_base = &adv;
+        iov[msg.msg_iovlen].iov_len = sizeof(adv);
+        msg.msg_iovlen++;
+
+        /* MAC address is optional, either because the link does not use L2
+           addresses or load sharing is desired. See RFC 4861, Section 4.2 */
+        if (memcmp(&mac_zero, &ra->mac_addr, sizeof(mac_zero))) {
+                opt_mac.slladdr = ra->mac_addr;
+                iov[msg.msg_iovlen].iov_base = &opt_mac;
+                iov[msg.msg_iovlen].iov_len = sizeof(opt_mac);
+                msg.msg_iovlen++;
+        }
+
+        if (ra->mtu) {
+                opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu);
+                iov[msg.msg_iovlen].iov_base = &opt_mtu;
+                iov[msg.msg_iovlen].iov_len = sizeof(opt_mtu);
+                msg.msg_iovlen++;
+        }
+
+        LIST_FOREACH(prefix, p, ra->prefixes) {
+                iov[msg.msg_iovlen].iov_base = &p->opt;
+                iov[msg.msg_iovlen].iov_len = sizeof(p->opt);
+                msg.msg_iovlen++;
+        }
+
+        if (sendmsg(ra->fd, &msg, 0) < 0)
+                return -errno;
+
+        return 0;
+}
+
+static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        sd_radv *ra = userdata;
+        _cleanup_free_ char *addr = NULL;
+        struct in6_addr src;
+        triple_timestamp timestamp;
+        int r;
+        ssize_t buflen;
+        _cleanup_free_ char *buf = NULL;
+
+        assert(s);
+        assert(ra);
+        assert(ra->event);
+
+        buflen = next_datagram_size_fd(fd);
+
+        if ((unsigned) buflen < sizeof(struct nd_router_solicit))
+                return log_radv("Too short packet received");
+
+        buf = new0(char, buflen);
+        if (!buf)
+                return 0;
+
+        r = icmp6_receive(fd, buf, buflen, &src, &timestamp);
+        if (r < 0) {
+                switch (r) {
+                case -EADDRNOTAVAIL:
+                        (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr);
+                        log_radv("Received RS from non-link-local address %s. Ignoring", addr);
+                        break;
+
+                case -EMULTIHOP:
+                        log_radv("Received RS with invalid hop limit. Ignoring.");
+                        break;
+
+                case -EPFNOSUPPORT:
+                        log_radv("Received invalid source address from ICMPv6 socket. Ignoring.");
+                        break;
+
+                default:
+                        log_radv_warning_errno(r, "Error receiving from ICMPv6 socket: %m");
+                        break;
+                }
+
+                return 0;
+        }
+
+        (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr);
+
+        r = radv_send(ra, &src, ra->lifetime);
+        if (r < 0)
+                log_radv_warning_errno(r, "Unable to send solicited Router Advertisment to %s: %m", addr);
+        else
+                log_radv("Sent solicited Router Advertisement to %s", addr);
+
+        return 0;
+}
+
+static usec_t radv_compute_timeout(usec_t min, usec_t max) {
+        assert_return(min <= max, SD_RADV_DEFAULT_MIN_TIMEOUT_USEC);
+
+        return min + (random_u32() % (max - min));
+}
+
+static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
+        int r;
+        sd_radv *ra = userdata;
+        usec_t min_timeout = SD_RADV_DEFAULT_MIN_TIMEOUT_USEC;
+        usec_t max_timeout = SD_RADV_DEFAULT_MAX_TIMEOUT_USEC;
+        usec_t time_now, timeout;
+        char time_string[FORMAT_TIMESPAN_MAX];
+
+        assert(s);
+        assert(ra);
+        assert(ra->event);
+
+        ra->timeout_event_source = sd_event_source_unref(ra->timeout_event_source);
+
+        r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
+        if (r < 0)
+                goto fail;
+
+        r = radv_send(ra, NULL, ra->lifetime);
+        if (r < 0)
+                log_radv_warning_errno(r, "Unable to send Router Advertisement: %m");
+
+        /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
+        if (ra->ra_sent < SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) {
+                max_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
+                min_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC / 3;
+        }
+
+        timeout = radv_compute_timeout(min_timeout, max_timeout);
+
+        log_radv("Next Router Advertisement in %s",
+                 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
+                                 timeout, USEC_PER_SEC));
+
+        r = sd_event_add_time(ra->event, &ra->timeout_event_source,
+                              clock_boottime_or_monotonic(),
+                              time_now + timeout, MSEC_PER_SEC,
+                              radv_timeout, ra);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(ra->timeout_event_source,
+                                         ra->event_priority);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_description(ra->timeout_event_source,
+                                            "radv-timeout");
+        if (r < 0)
+                goto fail;
+
+        ra->ra_sent++;
+
+fail:
+        if (r < 0)
+                sd_radv_stop(ra);
+
+        return 0;
+}
+
+_public_ int sd_radv_stop(sd_radv *ra) {
+        int r;
+
+        assert_return(ra, -EINVAL);
+
+        log_radv("Stopping IPv6 Router Advertisement daemon");
+
+        /* RFC 4861, Section 6.2.5, send at least one Router Advertisement
+           with zero lifetime  */
+        r = radv_send(ra, NULL, 0);
+        if (r < 0)
+                log_radv_warning_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
+
+        radv_reset(ra);
+        ra->fd = safe_close(ra->fd);
+        ra->state = SD_RADV_STATE_IDLE;
+
+        return 0;
+}
+
+_public_ int sd_radv_start(sd_radv *ra) {
+        int r = 0;
+
+        assert_return(ra, -EINVAL);
+        assert_return(ra->event, -EINVAL);
+        assert_return(ra->ifindex > 0, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return 0;
+
+        r = sd_event_add_time(ra->event, &ra->timeout_event_source,
+                              clock_boottime_or_monotonic(), 0, 0,
+                              radv_timeout, ra);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(ra->timeout_event_source,
+                                         ra->event_priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(ra->timeout_event_source,
+                                               "radv-timeout");
+
+        r = icmp6_bind_router_advertisement(ra->ifindex);
+        if (r < 0)
+                goto fail;
+
+        ra->fd = r;
+
+        r = sd_event_add_io(ra->event, &ra->recv_event_source, ra->fd, EPOLLIN, radv_recv, ra);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(ra->recv_event_source, ra->event_priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(ra->recv_event_source, "radv-receive-message");
+
+        ra->state = SD_RADV_STATE_ADVERTISING;
+
+        log_radv("Started IPv6 Router Advertisement daemon");
+
+        return 0;
+
+ fail:
+        radv_reset(ra);
+
+        return r;
+}
+
+_public_ int sd_radv_set_ifindex(sd_radv *ra, int ifindex) {
+        assert_return(ra, -EINVAL);
+        assert_return(ifindex >= -1, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        ra->ifindex = ifindex;
+
+        return 0;
+}
+
+_public_ int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        if (mac_addr)
+                ra->mac_addr = *mac_addr;
+        else
+                zero(ra->mac_addr);
+
+        return 0;
+}
+
+_public_ int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu) {
+        assert_return(ra, -EINVAL);
+        assert_return(mtu >= 1280, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        ra->mtu = mtu;
+
+        return 0;
+}
+
+_public_ int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        ra->hop_limit = hop_limit;
+
+        return 0;
+}
+
+_public_ int sd_radv_set_router_lifetime(sd_radv *ra, uint32_t router_lifetime) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the
+           preference value MUST be set to (00) by the sender..." */
+        if (router_lifetime == 0 &&
+            (ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3))
+                return -ETIME;
+
+        ra->lifetime = router_lifetime;
+
+        return 0;
+}
+
+_public_ int sd_radv_set_managed_information(sd_radv *ra, int managed) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, managed);
+
+        return 0;
+}
+
+_public_ int sd_radv_set_other_information(sd_radv *ra, int other) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != SD_RADV_STATE_IDLE)
+                return -EBUSY;
+
+        SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, other);
+
+        return 0;
+}
+
+_public_ int sd_radv_set_preference(sd_radv *ra, unsigned preference) {
+        int r = 0;
+
+        assert_return(ra, -EINVAL);
+        assert_return(IN_SET(preference,
+                             SD_NDISC_PREFERENCE_LOW,
+                             SD_NDISC_PREFERENCE_MEDIUM,
+                             SD_NDISC_PREFERENCE_HIGH), -EINVAL);
+
+        ra->flags = (ra->flags & ~(0x3 << 3)) | (preference << 3);
+
+        return r;
+}
+
+_public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) {
+        sd_radv_prefix *cur;
+        _cleanup_free_ char *addr_p = NULL;
+
+        assert_return(ra, -EINVAL);
+
+        if (!p)
+                return -EINVAL;
+
+        LIST_FOREACH(prefix, cur, ra->prefixes) {
+                int r;
+
+                r = in_addr_prefix_intersect(AF_INET6,
+                                             (union in_addr_union*) &cur->opt.in6_addr,
+                                             cur->opt.prefixlen,
+                                             (union in_addr_union*) &p->opt.in6_addr,
+                                             p->opt.prefixlen);
+                if (r > 0) {
+                        _cleanup_free_ char *addr_cur = NULL;
+
+                        (void) in_addr_to_string(AF_INET6,
+                                                 (union in_addr_union*) &cur->opt.in6_addr,
+                                                 &addr_cur);
+                        (void) in_addr_to_string(AF_INET6,
+                                                 (union in_addr_union*) &p->opt.in6_addr,
+                                                 &addr_p);
+
+                        log_radv("IPv6 prefix %s/%u already configured, ignoring %s/%u",
+                                 addr_cur, cur->opt.prefixlen,
+                                 addr_p, p->opt.prefixlen);
+
+                        return -EEXIST;
+                }
+        }
+
+        p = sd_radv_prefix_ref(p);
+
+        LIST_APPEND(prefix, ra->prefixes, p);
+
+        ra->n_prefixes++;
+
+        (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &p->opt.in6_addr, &addr_p);
+        log_radv("Added prefix %s/%d", addr_p, p->opt.prefixlen);
+
+        return 0;
+}
+
+_public_ int sd_radv_prefix_new(sd_radv_prefix **ret) {
+        _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
+
+        assert_return(ret, -EINVAL);
+
+        p = new0(sd_radv_prefix, 1);
+        if (!p)
+                return -ENOMEM;
+
+        p->n_ref = 1;
+
+        p->opt.type = ND_OPT_PREFIX_INFORMATION;
+        p->opt.length = (sizeof(p->opt) - 1) /8 + 1;
+
+        p->opt.prefixlen = 64;
+
+        /* RFC 4861, Section 6.2.1 */
+        SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, true);
+        SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, true);
+        p->opt.preferred_lifetime = htobe32(604800);
+        p->opt.valid_lifetime = htobe32(2592000);
+
+        LIST_INIT(prefix, p);
+
+        *ret = p;
+        p = NULL;
+
+        return 0;
+}
+
+_public_ sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *p) {
+        if (!p)
+                return NULL;
+
+        assert(p->n_ref > 0);
+        p->n_ref++;
+
+        return p;
+}
+
+_public_ sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *p) {
+        if (!p)
+                return NULL;
+
+        assert(p->n_ref > 0);
+        p->n_ref--;
+
+        if (p->n_ref > 0)
+                return NULL;
+
+        return mfree(p);
+}
+
+_public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, struct in6_addr *in6_addr,
+                                       unsigned char prefixlen) {
+        assert_return(p, -EINVAL);
+        assert_return(in6_addr, -EINVAL);
+
+        if (prefixlen < 3 || prefixlen > 128)
+                return -EINVAL;
+
+        if (prefixlen > 64)
+                /* unusual but allowed, log it */
+                log_radv("Unusual prefix length %d greater than 64", prefixlen);
+
+        p->opt.in6_addr = *in6_addr;
+        p->opt.prefixlen = prefixlen;
+
+        return 0;
+}
+
+_public_ int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink) {
+        assert_return(p, -EINVAL);
+
+        SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, onlink);
+
+        return 0;
+}
+
+_public_ int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p,
+                                                          int address_autoconfiguration) {
+        assert_return(p, -EINVAL);
+
+        SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, address_autoconfiguration);
+
+        return 0;
+}
+
+_public_ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p,
+                                               uint32_t valid_lifetime) {
+        assert_return(p, -EINVAL);
+
+        p->opt.valid_lifetime = htobe32(valid_lifetime);
+
+        return 0;
+}
+
+_public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p,
+                                                   uint32_t preferred_lifetime) {
+        assert_return(p, -EINVAL);
+
+        p->opt.preferred_lifetime = htobe32(preferred_lifetime);
+
+        return 0;
+}
index e81c508c7ff1e1f712b7f6d1cf2f5756d35608d6..26f217835fb3de5b3a905c75c42c2a151c1f7de2 100644 (file)
@@ -63,7 +63,7 @@ static int test_basic(sd_event *event) {
         assert_se(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0) == -EINVAL);
         assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0) == -ERANGE);
         assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
-        assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) == -EBUSY);
+        assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
 
         test_pool(&address_any, 1, -EINVAL);
         test_pool(&address_lo, 1, 0);
index fe70697075a4ff309a44812a0d6245dad133a1a7..89864fd39cf9f6263695c83b339c2503101dbda0 100644 (file)
@@ -17,7 +17,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <assert.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -72,10 +71,10 @@ int arp_send_probe(int fd, int ifindex,
                     be32_t pa, const struct ether_addr *ha) {
         struct ether_arp ea = {};
 
-        assert(fd >= 0);
-        assert(ifindex > 0);
-        assert(pa != 0);
-        assert(ha);
+        assert_se(fd >= 0);
+        assert_se(ifindex > 0);
+        assert_se(pa != 0);
+        assert_se(ha);
 
         return arp_network_send_raw_socket(fd, ifindex, &ea);
 }
@@ -84,10 +83,10 @@ int arp_send_announcement(int fd, int ifindex,
                           be32_t pa, const struct ether_addr *ha) {
         struct ether_arp ea = {};
 
-        assert(fd >= 0);
-        assert(ifindex > 0);
-        assert(pa != 0);
-        assert(ha);
+        assert_se(fd >= 0);
+        assert_se(ifindex > 0);
+        assert_se(pa != 0);
+        assert_se(ha);
 
         return arp_network_send_raw_socket(fd, ifindex, &ea);
 }
diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c
new file mode 100644 (file)
index 0000000..6e6d056
--- /dev/null
@@ -0,0 +1,359 @@
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2017 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (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 <netinet/icmp6.h>
+#include <arpa/inet.h>
+
+#include "sd-radv.h"
+
+#include "alloc-util.h"
+#include "hexdecoct.h"
+#include "icmp6-util.h"
+#include "socket-util.h"
+#include "strv.h"
+
+static struct ether_addr mac_addr = {
+        .ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 }
+};
+
+static uint8_t advertisement[] = {
+        /* ICMPv6 Router Advertisement, no checksum */
+        0x86, 0x00, 0x00, 0x00,  0x40, 0xc0, 0x00, 0xb4,
+        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+        /* Source Link Layer Address Option */
+        0x01, 0x01, 0x78, 0x2b,  0xcb, 0xb3, 0x6d, 0x53,
+        /* Prefix Information Option */
+        0x03, 0x04, 0x40, 0xc0,  0x00, 0x00, 0x01, 0xf4,
+        0x00, 0x00, 0x01, 0xb8,  0x00, 0x00, 0x00, 0x00,
+        0x20, 0x01, 0x0d, 0xb8,  0xde, 0xad, 0xbe, 0xef,
+        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+        /* Prefix Information Option */
+        0x03, 0x04, 0x40, 0xc0,  0x00, 0x27, 0x8d, 0x00,
+        0x00, 0x09, 0x3a, 0x80,  0x00, 0x00, 0x00, 0x00,
+        0x20, 0x01, 0x0d, 0xb8,  0x0b, 0x16, 0xd0, 0x0d,
+        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+        /* Prefix Information Option */
+        0x03, 0x04, 0x30, 0xc0,  0x00, 0x27, 0x8d, 0x00,
+        0x00, 0x09, 0x3a, 0x80,  0x00, 0x00, 0x00, 0x00,
+        0x20, 0x01, 0x0d, 0xb8,  0xc0, 0x01, 0x0d, 0xad,
+        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+        /* Recursive DNS Server Option - not yet supported */
+        0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+        0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+        /* DNS Search List Option - not yet supported */
+        0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+        0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
+        0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static sd_event_source *test_hangcheck;
+static bool test_stopped;
+static int test_fd[2];
+static sd_event_source *recv_router_advertisement;
+static struct {
+        struct in6_addr address;
+        unsigned char prefixlen;
+        uint32_t valid;
+        uint32_t preferred;
+        bool succesful;
+} prefix[] = {
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
+          500, 440, true },
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
+          /* indicate default valid and preferred lifetimes for the test code */
+          0, 0, true },
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 58,
+          0, 0,
+          /* indicate that this prefix already exists */
+          false },
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 120,
+          0, 0,
+          /* indicate that this prefix already exists */
+          false },
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 12,
+          0, 0,
+          /* indicate that this prefix already exists */
+          false },
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 48,
+          0, 0, true },
+        { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 60,
+          0, 0,
+          /* indicate that this prefix already exists */
+          false },
+};
+
+static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
+                             void *userdata) {
+        assert_se(false);
+
+        return 0;
+}
+
+static void test_radv_prefix(void) {
+        sd_radv_prefix *p;
+
+        printf("* %s\n", __FUNCTION__);
+
+        assert_se(sd_radv_prefix_new(&p) >= 0);
+
+        assert_se(sd_radv_prefix_set_onlink(NULL, true) < 0);
+        assert_se(sd_radv_prefix_set_onlink(p, true) >= 0);
+        assert_se(sd_radv_prefix_set_onlink(p, false) >= 0);
+
+        assert_se(sd_radv_prefix_set_address_autoconfiguration(NULL, true) < 0);
+        assert_se(sd_radv_prefix_set_address_autoconfiguration(p, true) >= 0);
+        assert_se(sd_radv_prefix_set_address_autoconfiguration(p, false) >= 0);
+
+        assert_se(sd_radv_prefix_set_valid_lifetime(NULL, true) < 0);
+        assert_se(sd_radv_prefix_set_valid_lifetime(p, ~0) >= 0);
+        assert_se(sd_radv_prefix_set_valid_lifetime(p, 42) >= 0);
+        assert_se(sd_radv_prefix_set_valid_lifetime(p, 0) >= 0);
+
+        assert_se(sd_radv_prefix_set_preferred_lifetime(NULL, true) < 0);
+        assert_se(sd_radv_prefix_set_preferred_lifetime(p, ~0) >= 0);
+        assert_se(sd_radv_prefix_set_preferred_lifetime(p, 42) >= 0);
+        assert_se(sd_radv_prefix_set_preferred_lifetime(p, 0) >= 0);
+
+        assert_se(sd_radv_prefix_set_prefix(NULL, NULL, 0) < 0);
+        assert_se(sd_radv_prefix_set_prefix(p, NULL, 0) < 0);
+
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 64) >= 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 0) < 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 1) < 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 2) < 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 3) >= 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 125) >= 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 128) >= 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 129) < 0);
+        assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 255) < 0);
+
+        p = sd_radv_prefix_unref(p);
+        assert_se(!p);
+}
+
+static void test_radv(void) {
+        sd_radv *ra;
+
+        printf("* %s\n", __FUNCTION__);
+
+        assert_se(sd_radv_new(&ra) >= 0);
+        assert_se(ra);
+
+        assert_se(sd_radv_set_ifindex(NULL, 0) < 0);
+        assert_se(sd_radv_set_ifindex(ra, 0) >= 0);
+        assert_se(sd_radv_set_ifindex(ra, -1) >= 0);
+        assert_se(sd_radv_set_ifindex(ra, -2) < 0);
+        assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
+
+        assert_se(sd_radv_set_mac(NULL, NULL) < 0);
+        assert_se(sd_radv_set_mac(ra, NULL) >= 0);
+        assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
+
+        assert_se(sd_radv_set_mtu(NULL, 0) < 0);
+        assert_se(sd_radv_set_mtu(ra, 0) < 0);
+        assert_se(sd_radv_set_mtu(ra, 1279) < 0);
+        assert_se(sd_radv_set_mtu(ra, 1280) >= 0);
+        assert_se(sd_radv_set_mtu(ra, ~0) >= 0);
+
+        assert_se(sd_radv_set_hop_limit(NULL, 0) < 0);
+        assert_se(sd_radv_set_hop_limit(ra, 0) >= 0);
+        assert_se(sd_radv_set_hop_limit(ra, ~0) >= 0);
+
+        assert_se(sd_radv_set_router_lifetime(NULL, 0) < 0);
+        assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
+        assert_se(sd_radv_set_router_lifetime(ra, ~0) >= 0);
+
+        assert_se(sd_radv_set_preference(NULL, 0) < 0);
+        assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_LOW) >= 0);
+        assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
+        assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
+        assert_se(sd_radv_set_preference(ra, ~0) < 0);
+
+        assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
+        assert_se(sd_radv_set_router_lifetime(ra, 42000) >= 0);
+        assert_se(sd_radv_set_router_lifetime(ra, 0) < 0);
+        assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
+        assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
+
+        assert_se(sd_radv_set_managed_information(NULL, true) < 0);
+        assert_se(sd_radv_set_managed_information(ra, true) >= 0);
+        assert_se(sd_radv_set_managed_information(ra, false) >= 0);
+
+        assert_se(sd_radv_set_other_information(NULL, true) < 0);
+        assert_se(sd_radv_set_other_information(ra, true) >= 0);
+        assert_se(sd_radv_set_other_information(ra, false) >= 0);
+
+        ra = sd_radv_unref(ra);
+        assert_se(!ra);
+}
+
+int icmp6_bind_router_solicitation(int index) {
+        return -ENOSYS;
+}
+
+int icmp6_bind_router_advertisement(int index) {
+        assert_se(index == 42);
+
+        return test_fd[1];
+}
+
+int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
+
+        return 0;
+}
+
+int icmp6_receive(int fd, void *iov_base, size_t iov_len,
+                  struct in6_addr *dst, triple_timestamp *timestamp) {
+        assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len);
+
+        if (timestamp)
+                triple_timestamp_get(timestamp);
+
+        return 0;
+}
+
+static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        sd_radv *ra = userdata;
+        unsigned char buf[120];
+        size_t i;
+
+        read(test_fd[0], &buf, sizeof(buf));
+
+        /* router lifetime must be zero when test is stopped */
+        if (test_stopped) {
+                advertisement[6] = 0x00;
+                advertisement[7] = 0x00;
+        }
+
+        printf ("Received Router Advertisement with lifetime %u\n",
+                (advertisement[6] << 8) + advertisement[7]);
+
+        /* test only up to buf size, rest is not yet implemented */
+        for (i = 0; i < sizeof(buf); i++) {
+                printf("0x%02x", buf[i]);
+
+                assert_se(buf[i] == advertisement[i]);
+
+                if ((i + 1) % 8)
+                        printf(", ");
+                else
+                        printf("\n");
+        }
+
+        if (test_stopped) {
+                sd_event *e;
+
+                e = sd_radv_get_event(ra);
+                sd_event_exit(e, 0);
+
+                return 0;
+        }
+
+        assert_se(sd_radv_stop(ra) >= 0);
+        test_stopped = true;
+
+        return 0;
+}
+
+static void test_ra(void) {
+        sd_event *e;
+        sd_radv *ra;
+        usec_t time_now = now(clock_boottime_or_monotonic());
+        unsigned int i;
+
+        printf("* %s\n", __FUNCTION__);
+
+        assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, test_fd) >= 0);
+
+        assert_se(sd_event_new(&e) >= 0);
+
+        assert_se(sd_radv_new(&ra) >= 0);
+        assert_se(ra);
+
+        assert_se(sd_radv_attach_event(ra, e, 0) >= 0);
+
+        assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
+        assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
+        assert_se(sd_radv_set_router_lifetime(ra, 180) >= 0);
+        assert_se(sd_radv_set_hop_limit(ra, 64) >= 0);
+        assert_se(sd_radv_set_managed_information(ra, true) >= 0);
+        assert_se(sd_radv_set_other_information(ra, true) >= 0);
+
+        for (i = 0; i < ELEMENTSOF(prefix); i++) {
+                sd_radv_prefix *p;
+
+                printf("Test prefix %u\n", i);
+                assert_se(sd_radv_prefix_new(&p) >= 0);
+
+                assert_se(sd_radv_prefix_set_prefix(p, &prefix[i].address,
+                                                    prefix[i].prefixlen) >= 0);
+                if (prefix[i].valid)
+                        assert_se(sd_radv_prefix_set_valid_lifetime(p, prefix[i].valid) >= 0);
+                if (prefix[i].preferred)
+                        assert_se(sd_radv_prefix_set_preferred_lifetime(p, prefix[i].preferred) >= 0);
+
+                assert_se((sd_radv_add_prefix(ra, p) >= 0) == prefix[i].succesful);
+                assert_se(sd_radv_add_prefix(ra, p) < 0);
+
+                p = sd_radv_prefix_unref(p);
+                assert_se(!p);
+        }
+
+        assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0],
+                                  EPOLLIN, radv_recv, ra) >= 0);
+
+        assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
+                                 time_now + 2 *USEC_PER_SEC, 0,
+                                 test_rs_hangcheck, NULL) >= 0);
+
+        assert_se(sd_radv_start(ra) >= 0);
+
+        sd_event_loop(e);
+
+        test_hangcheck = sd_event_source_unref(test_hangcheck);
+
+        ra = sd_radv_unref(ra);
+        assert_se(!ra);
+
+        close(test_fd[0]);
+
+        sd_event_unref(e);
+}
+
+int main(int argc, char *argv[]) {
+
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
+        test_radv_prefix();
+        test_radv();
+        test_ra();
+
+        printf("* done\n");
+        return 0;
+}
index d9669488be37d4f06e9213da3345596c0a1fc389..c3e1a8e340b8145942dd85c8469de4d3eb9ee3cb 100644 (file)
@@ -27,6 +27,7 @@
 #include "icmp6-util.h"
 #include "socket-util.h"
 #include "strv.h"
+#include "ndisc-internal.h"
 
 static struct ether_addr mac_addr = {
         .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
@@ -35,6 +36,7 @@ static struct ether_addr mac_addr = {
 static bool verbose = false;
 static sd_event_source *test_hangcheck;
 static int test_fd[2];
+static sd_ndisc *test_timeout_nd;
 
 typedef int (*send_ra_t)(uint8_t flags);
 static send_ra_t send_ra_function;
@@ -193,6 +195,21 @@ int icmp6_bind_router_solicitation(int index) {
         return test_fd[0];
 }
 
+int icmp6_bind_router_advertisement(int index) {
+
+        return -ENOSYS;
+}
+
+int icmp6_receive(int fd, void *iov_base, size_t iov_len,
+                  struct in6_addr *dst, triple_timestamp *timestamp) {
+        assert (read (fd, iov_base, iov_len) == (ssize_t)iov_len);
+
+        if (timestamp)
+                triple_timestamp_get(timestamp);
+
+        return 0;
+}
+
 static int send_ra(uint8_t flags) {
         uint8_t advertisement[] = {
                 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
@@ -222,6 +239,9 @@ static int send_ra(uint8_t flags) {
 }
 
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
+        if (!send_ra_function)
+                return 0;
+
         return send_ra_function(0);
 }
 
@@ -305,6 +325,100 @@ static void test_rs(void) {
         sd_event_unref(e);
 }
 
+static int test_timeout_value(uint8_t flags) {
+        static int count = 0;
+        static usec_t last = 0;
+        sd_ndisc *nd = test_timeout_nd;
+        usec_t min, max;
+        char time_string_min[FORMAT_TIMESPAN_MAX];
+        char time_string_nd[FORMAT_TIMESPAN_MAX];
+        char time_string_max[FORMAT_TIMESPAN_MAX];
+
+        assert_se(nd);
+        assert_se(nd->event);
+
+        if (++count >= 20)
+                sd_event_exit(nd->event, 0);
+
+        if (last == 0) {
+                /* initial RT = IRT + RAND*IRT  */
+                min = NDISC_ROUTER_SOLICITATION_INTERVAL -
+                        NDISC_ROUTER_SOLICITATION_INTERVAL / 10;
+                max = NDISC_ROUTER_SOLICITATION_INTERVAL +
+                        NDISC_ROUTER_SOLICITATION_INTERVAL / 10;
+        } else {
+                /* next RT = 2*RTprev + RAND*RTprev */
+                min = 2 * last - last / 10;
+                max = 2 * last + last / 10;
+        }
+
+        /* final RT > MRT */
+        if (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL) {
+                min = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL -
+                        NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10;
+                max = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL +
+                        NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10;
+        }
+
+        format_timespan(time_string_min, FORMAT_TIMESPAN_MAX,
+                        min, USEC_PER_MSEC);
+        format_timespan(time_string_nd, FORMAT_TIMESPAN_MAX,
+                        nd->retransmit_time, USEC_PER_MSEC);
+        format_timespan(time_string_max, FORMAT_TIMESPAN_MAX,
+                        max, USEC_PER_MSEC);
+
+        log_info("backoff timeout interval %2d %s%s <= %s <= %s",
+                 count,
+                 (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL)? "(max) ": "",
+                 time_string_min, time_string_nd, time_string_max);
+
+        assert_se(min <= nd->retransmit_time);
+        assert_se(max >= nd->retransmit_time);
+
+        last = nd->retransmit_time;
+
+        assert_se(sd_event_source_set_time(nd->timeout_event_source, 0) >= 0);
+
+        return 0;
+}
+
+static void test_timeout(void) {
+        sd_event *e;
+        sd_ndisc *nd;
+        usec_t time_now = now(clock_boottime_or_monotonic());
+
+        if (verbose)
+                printf("* %s\n", __FUNCTION__);
+
+        send_ra_function = test_timeout_value;
+
+        assert_se(sd_event_new(&e) >= 0);
+
+        assert_se(sd_ndisc_new(&nd) >= 0);
+        assert_se(nd);
+
+        test_timeout_nd = nd;
+
+        assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
+
+        assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
+        assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
+
+        assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
+                                 time_now + 2U * USEC_PER_SEC, 0,
+                                 test_rs_hangcheck, NULL) >= 0);
+
+        assert_se(sd_ndisc_start(nd) >= 0);
+
+        sd_event_loop(e);
+
+        test_hangcheck = sd_event_source_unref(test_hangcheck);
+
+        nd = sd_ndisc_unref(nd);
+
+        sd_event_unref(e);
+}
+
 int main(int argc, char *argv[]) {
 
         log_set_max_level(LOG_DEBUG);
@@ -312,6 +426,7 @@ int main(int argc, char *argv[]) {
         log_open();
 
         test_rs();
+        test_timeout();
 
         return 0;
 }
diff --git a/src/libsystemd-network/test-sd-dhcp-lease.c b/src/libsystemd-network/test-sd-dhcp-lease.c
new file mode 100644 (file)
index 0000000..0f88180
--- /dev/null
@@ -0,0 +1,90 @@
+#include <errno.h>
+
+#include "dhcp-lease-internal.h"
+#include "macro.h"
+#include "string-util.h"
+#include "strv.h"
+
+/* According to RFC1035 section 4.1.4, a domain name in a message can be either:
+ *      - a sequence of labels ending in a zero octet
+ *      - a pointer
+ *      - a sequence of labels ending with a pointer
+ */
+static void test_dhcp_lease_parse_search_domains_basic(void) {
+        int r;
+        _cleanup_strv_free_ char **domains = NULL;
+        static const uint8_t optionbuf[] = {
+                0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00,
+                0x04, 'A', 'B', 'C', 'D', 0x03, 'E', 'F', 'G', 0x00,
+        };
+
+        r = dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains);
+        assert_se(r == 2);
+        assert_se(streq(domains[0], "FOO.BAR"));
+        assert_se(streq(domains[1], "ABCD.EFG"));
+}
+
+static void test_dhcp_lease_parse_search_domains_ptr(void) {
+        int r;
+        _cleanup_strv_free_ char **domains = NULL;
+        static const uint8_t optionbuf[] = {
+                0x03, 'F', 'O', 'O', 0x00, 0xC0, 0x00,
+        };
+
+        r = dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains);
+        assert_se(r == 2);
+        assert_se(streq(domains[0], "FOO"));
+        assert_se(streq(domains[1], "FOO"));
+}
+
+static void test_dhcp_lease_parse_search_domains_labels_and_ptr(void) {
+        int r;
+        _cleanup_strv_free_ char **domains = NULL;
+        static const uint8_t optionbuf[] = {
+                0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00,
+                0x03, 'A', 'B', 'C', 0xC0, 0x04,
+        };
+
+        r = dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains);
+        assert_se(r == 2);
+        assert_se(streq(domains[0], "FOO.BAR"));
+        assert_se(streq(domains[1], "ABC.BAR"));
+}
+
+/* Tests for exceptions. */
+
+static void test_dhcp_lease_parse_search_domains_no_data(void) {
+        _cleanup_strv_free_ char **domains = NULL;
+        static const uint8_t optionbuf[3] = {0, 0, 0};
+
+        assert_se(dhcp_lease_parse_search_domains(NULL, 0, &domains) == -ENODATA);
+        assert_se(dhcp_lease_parse_search_domains(optionbuf, 0, &domains) == -ENODATA);
+}
+
+static void test_dhcp_lease_parse_search_domains_loops(void) {
+        _cleanup_strv_free_ char **domains = NULL;
+        static const uint8_t optionbuf[] = {
+                0x03, 'F', 'O', 'O', 0x00, 0x03, 'B', 'A', 'R', 0xC0, 0x06,
+        };
+
+        assert_se(dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains) == -EBADMSG);
+}
+
+static void test_dhcp_lease_parse_search_domains_wrong_len(void) {
+        _cleanup_strv_free_ char **domains = NULL;
+        static const uint8_t optionbuf[] = {
+                0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00,
+                0x04, 'A', 'B', 'C', 'D', 0x03, 'E', 'F', 'G', 0x00,
+        };
+
+        assert_se(dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf) - 5, &domains) == -EBADMSG);
+}
+
+int main(int argc, char *argv[]) {
+        test_dhcp_lease_parse_search_domains_basic();
+        test_dhcp_lease_parse_search_domains_ptr();
+        test_dhcp_lease_parse_search_domains_labels_and_ptr();
+        test_dhcp_lease_parse_search_domains_no_data();
+        test_dhcp_lease_parse_search_domains_loops();
+        test_dhcp_lease_parse_search_domains_wrong_len();
+}
index c1135ffa226ec1ff52deda9055819529ebd5463a..92cb790d499fd4ad3444874461cc09498445bc9b 100644 (file)
@@ -517,3 +517,8 @@ global:
         sd_id128_get_machine_app_specific;
         sd_is_socket_sockaddr;
 } LIBSYSTEMD_232;
+
+LIBSYSTEMD_234 {
+global:
+        sd_bus_message_appendv;
+} LIBSYSTEMD_233;
diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build
new file mode 100644 (file)
index 0000000..ab69afe
--- /dev/null
@@ -0,0 +1,96 @@
+sd_login_c = files('sd-login/sd-login.c')
+
+libsystemd_internal_sources = files('''
+        sd-bus/bus-bloom.c
+        sd-bus/bus-bloom.h
+        sd-bus/bus-common-errors.c
+        sd-bus/bus-common-errors.h
+        sd-bus/bus-container.c
+        sd-bus/bus-container.h
+        sd-bus/bus-control.c
+        sd-bus/bus-control.h
+        sd-bus/bus-convenience.c
+        sd-bus/bus-creds.c
+        sd-bus/bus-creds.h
+        sd-bus/bus-dump.c
+        sd-bus/bus-dump.h
+        sd-bus/bus-error.c
+        sd-bus/bus-error.h
+        sd-bus/bus-gvariant.c
+        sd-bus/bus-gvariant.h
+        sd-bus/bus-internal.c
+        sd-bus/bus-internal.h
+        sd-bus/bus-introspect.c
+        sd-bus/bus-introspect.h
+        sd-bus/bus-kernel.c
+        sd-bus/bus-kernel.h
+        sd-bus/bus-match.c
+        sd-bus/bus-match.h
+        sd-bus/bus-message.c
+        sd-bus/bus-message.h
+        sd-bus/bus-objects.c
+        sd-bus/bus-objects.h
+        sd-bus/bus-protocol.h
+        sd-bus/bus-signature.c
+        sd-bus/bus-signature.h
+        sd-bus/bus-slot.c
+        sd-bus/bus-slot.h
+        sd-bus/bus-socket.c
+        sd-bus/bus-socket.h
+        sd-bus/bus-track.c
+        sd-bus/bus-track.h
+        sd-bus/bus-type.c
+        sd-bus/bus-type.h
+        sd-bus/kdbus.h
+        sd-bus/sd-bus.c
+        sd-daemon/sd-daemon.c
+        sd-device/device-enumerator-private.h
+        sd-device/device-enumerator.c
+        sd-device/device-internal.h
+        sd-device/device-private.c
+        sd-device/device-private.h
+        sd-device/device-util.h
+        sd-device/sd-device.c
+        sd-event/sd-event.c
+        sd-hwdb/hwdb-internal.h
+        sd-hwdb/hwdb-util.h
+        sd-hwdb/sd-hwdb.c
+        sd-id128/id128-util.c
+        sd-id128/id128-util.h
+        sd-id128/sd-id128.c
+        sd-netlink/local-addresses.c
+        sd-netlink/local-addresses.h
+        sd-netlink/netlink-internal.h
+        sd-netlink/netlink-message.c
+        sd-netlink/netlink-socket.c
+        sd-netlink/netlink-types.c
+        sd-netlink/netlink-types.h
+        sd-netlink/netlink-util.c
+        sd-netlink/netlink-util.h
+        sd-netlink/rtnl-message.c
+        sd-netlink/sd-netlink.c
+        sd-network/network-util.c
+        sd-network/network-util.h
+        sd-network/sd-network.c
+        sd-path/sd-path.c
+        sd-resolve/sd-resolve.c
+        sd-utf8/sd-utf8.c
+'''.split()) + sd_login_c
+
+libsystemd_internal = static_library(
+        'systemd',
+        libsystemd_internal_sources,
+        install : false,
+        include_directories : includes,
+        link_with : libbasic,
+        dependencies : [threads,
+                        librt])
+
+libsystemd_sym = 'src/libsystemd/libsystemd.sym'
+
+libsystemd_pc = configure_file(
+        input : 'libsystemd.pc.in',
+        output : 'libsystemd.pc',
+        configuration : substs)
+install_data(libsystemd_pc,
+             install_dir : pkgconfiglibdir)
diff --git a/src/libsystemd/sd-bus/DIFFERENCES b/src/libsystemd/sd-bus/DIFFERENCES
deleted file mode 100644 (file)
index db26967..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Known differences between dbus1 and kdbus:
-
-- NameAcquired/NameLost is gone entirely on kdbus backends if
-  libsystemd is used. It is still added in by systemd-bus-proxyd
-  for old dbus1 clients, and it is available if libsystemd is used
-  against the classic dbus1 daemon. If you want to write compatible
-  code with libsystem-bus you need to explicitly subscribe to
-  NameOwnerChanged signals and just ignore NameAcquired/NameLost
-
-- Applications have to deal with spurious signals they didn't expect,
-  due to the probabilistic bloom filters. They need to handle this
-  anyway, given that any client can send anything to arbitrary clients
-  anyway, even in dbus1, so not much changes.
-
-- clients of the system bus when kdbus is used must roll their own
-  security. Only legacy dbus1 clients get the old XML policy enforced,
-  which is implemented by systemd-bus-proxyd.
-
-- Serial numbers of synthesized messages are always (uint32_t) -1.
-
-- NameOwnerChanged is a synthetic message, generated locally and not
-  by the driver. On dbus1 only the Disconnected message was
-  synthesized like this.
-
-- There's no standard per-session bus anymore. Only a per-user bus.
index 6aeb11364a415f832e14275b8da10bd75f0a2141..3110d579134bca191fa6dde588f6f3922f950bfa 100644 (file)
@@ -73,10 +73,9 @@ the reply_cookie/reply_serial additional header field has been
 increased from 32bit to 64bit, too!
 
 The header field identifiers have been extended from 8bit to
-64bit. This has been done to simplify things (as kdbus otherwise uses
-exclusively 64bit types, unless there is a strong reason not to), and
-has no effect on the serialization size, as due to alignment for each
-8bit header field identifier 56 bits of padding had to be added.
+64bit. This has been done to simplify things, and has no effect
+on the serialization size, as due to alignment for each 8bit
+header field identifier 56 bits of padding had to be added.
 
 Note that the header size changed, due to these changes. However,
 consider that on dbus1 the beginning of the fields array contains the
@@ -94,16 +93,12 @@ array, the size of the header on dbus1 and dbus2 stays identical, at
 
 And that's already it.
 
-Note: to simplify parsing, valid kdbus/dbus2 messages must include the
-entire fixed header and additional header fields in a single non-memfd
-message part. Also, the signature string of the body variant all the
-way to the end of the message must be in a single non-memfd part
-too. The parts for this extended header and footer can be the same
-one, and can also continue any amount of additional body bytes.
-
-Note: on kdbus only native endian messages marshalled in gvariant may
-      be sent. If a client receives a message in non-native endianness
-      or in dbus1 marshalling it shall ignore the message.
+Note: To simplify parsing, valid dbus2 messages must include the entire
+      fixed header and additional header fields in a single non-memfd
+      message part. Also, the signature string of the body variant all the
+      way to the end of the message must be in a single non-memfd part
+      too. The parts for this extended header and footer can be the same
+      one, and can also continue any amount of additional body bytes.
 
 Note: The GVariant "MAYBE" type is not supported, so that messages can
       be fully converted forth and back between dbus1 and gvariant
diff --git a/src/libsystemd/sd-bus/PORTING-DBUS1 b/src/libsystemd/sd-bus/PORTING-DBUS1
deleted file mode 100644 (file)
index 2dedb28..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-A few hints on supporting kdbus as backend in your favorite D-Bus library.
-
-~~~
-
-Before you read this, have a look at the DIFFERENCES and
-GVARIANT_SERIALIZATION texts you find in the same directory where you
-found this.
-
-We invite you to port your favorite D-Bus protocol implementation
-over to kdbus. However, there are a couple of complexities
-involved. On kdbus we only speak GVariant marshaling, kdbus clients
-ignore traffic in dbus1 marshaling. Thus, you need to add a second,
-GVariant compatible marshaler to your library first.
-
-After you have done that: here's the basic principle how kdbus works:
-
-You connect to a bus by opening its bus node in /sys/fs/kdbus/. All
-buses have a device node there, it starts with a numeric UID of the
-owner of the bus, followed by a dash and a string identifying the
-bus. The system bus is thus called /sys/fs/kdbus/0-system, and for user
-buses the device node is /sys/fs/kdbus/1000-user (if 1000 is your user
-id).
-
-(Before we proceed, please always keep a copy of libsystemd next
-to you, ultimately that's where the details are, this document simply
-is a rough overview to help you grok things.)
-
-CONNECTING
-
-To connect to a bus, simply open() its device node and issue the
-KDBUS_CMD_HELLO call. That's it. Now you are connected. Do not send
-Hello messages or so (as you would on dbus1), that does not exist for
-kdbus.
-
-The structure you pass to the ioctl will contain a couple of
-parameters that you need to know, to operate on the bus.
-
-There are two flags fields, one indicating features of the kdbus
-kernel side ("conn_flags"), the other one ("bus_flags") indicating
-features of the bus owner (i.e. systemd). Both flags fields are 64bit
-in width.
-
-When calling into the ioctl, you need to place your own supported
-feature bits into these fields. This tells the kernel about the
-features you support. When the ioctl returns, it will contain the
-features the kernel supports.
-
-If any of the higher 32bit are set on the two flags fields and your
-client does not know what they mean, it must disconnect. The upper
-32bit are used to indicate "incompatible" feature additions on the bus
-system, the lower 32bit indicate "compatible" feature additions. A
-client that does not support a "compatible" feature addition can go on
-communicating with the bus, however a client that does not support an
-"incompatible" feature must not proceed with the connection. When a
-client encountes such an "incompatible" feature it should immediately
-try the next bus address configured in the bus address string.
-
-The hello structure also contains another flags field "attach_flags"
-which indicates metadata that is optionally attached to all incoming
-messages. You probably want to set KDBUS_ATTACH_NAMES unconditionally
-in it. This has the effect that all well-known names of a sender are
-attached to all incoming messages. You need this information to
-implement matches that match on a message sender name correctly. Of
-course, you should only request the attachment of as little metadata
-fields as you need.
-
-The kernel will return in the "id" field your unique id. This is a
-simple numeric value. For compatibility with classic dbus1 simply
-format this as string and prefix ":1.".
-
-The kernel will also return the bloom filter size and bloom filter
-hash function number used for the signal broadcast bloom filter (see
-below).
-
-The kernel will also return the bus ID of the bus in a 128bit field.
-
-The pool size field specifies the size of the memory mapped buffer.
-After the calling the hello ioctl, you should memory map the kdbus
-fd. In this memory mapped region, the kernel will place all your incoming
-messages.
-
-SENDING MESSAGES
-
-Use the MSG_SEND ioctl to send a message to another peer. The ioctl
-takes a structure that contains a variety of fields:
-
-The flags field corresponds closely to the old dbus1 message header
-flags field, though the DONT_EXPECT_REPLY field got inverted into
-EXPECT_REPLY.
-
-The dst_id/src_id field contains the unique id of the destination and
-the sender. The sender field is overridden by the kernel usually, hence
-you shouldn't fill it in. The destination field can also take the
-special value KDBUS_DST_ID_BROADCAST for broadcast messages. For
-messages intended to a well-known name set the field to
-KDBUS_DST_ID_NAME, and attach the name in a special "items" entry to
-the message (see below).
-
-The payload field indicates the payload. For all dbus traffic it
-should carry the value 0x4442757344427573ULL. (Which encodes
-'DBusDBus').
-
-The cookie field corresponds with the "serial" field of classic
-dbus1. We simply renamed it here (and extended it to 64bit) since we
-didn't want to imply the monotonicity of the assignment the way the
-word "serial" indicates it.
-
-When sending a message that expects a reply, you need to set the
-EXPECT_REPLY flag in the message flag field. In this case you should
-also fill out the "timeout_ns" value which indicates the timeout in
-nsec for this call. If the peer does not respond in this time you will
-get a notification of a timeout. Note that this is also used for
-security purposes: a single reply messages is only allowed through the
-bus as long as the timeout has not ended. With this timeout value you
-hence "open a time window" in which the peer might respond to your
-request and the policy allows the response to go through.
-
-When sending a message that is a reply, you need to fill in the
-cookie_reply field, which is similar to the reply_serial field of
-dbus1. Note that a message cannot have EXPECT_REPLY and a reply_serial
-at the same time!
-
-This pretty much explains the ioctl header. The actual payload of the
-data is now referenced in additional items that are attached to this
-ioctl header structure at the end. When sending a message, you attach
-items of the type PAYLOAD_VEC, PAYLOAD_MEMFD, FDS, BLOOM_FILTER,
-DST_NAME to it:
-
-   KDBUS_ITEM_PAYLOAD_VEC: contains a pointer + length pair for
-   referencing arbitrary user memory. This is how you reference most
-   of your data. It's a lot like the good old iovec structure of glibc.
-
-   KDBUS_ITEM_PAYLOAD_MEMFD: for large data blocks it is preferable
-   to send prepared "memfds" (see below) over. This item contains an
-   fd for a memfd plus a size.
-
-   KDBUS_ITEM_FDS: for sending over fds attach an item of this type with
-   an array of fds.
-
-   KDBUS_ITEM_BLOOM_FILTER: the calculated bloom filter of this message,
-   only for undirected (broadcast) message.
-
-   KDBUS_ITEM_DST_NAME: for messages that are directed to a well-known
-   name (instead of a unique name), this item contains the well-known
-   name field.
-
-A single message may consists of no, one or more payload items of type
-PAYLOAD_VEC or PAYLOAD_MEMFD. D-Bus protocol implementations should
-treat them as a single block that just happens to be split up into
-multiple items. Some restrictions apply however:
-
-   The message header in its entirety must be contained in a single
-   PAYLOAD_VEC item.
-
-   You may only split your message up right in front of each GVariant
-   contained in the payload, as well is immediately before framing of a
-   Gvariant, as well after as any padding bytes if there are any. The
-   padding bytes must be wholly contained in the preceding
-   PAYLOAD_VEC/PAYLOAD_MEMFD item. You may not split up basic types
-   nor arrays of fixed types. The latter is necessary to allow APIs
-   to return direct pointers to linear arrays of numeric
-   values. Examples: The basic types "u", "s", "t" have to be in the
-   same payload item. The array of fixed types "ay", "ai" have to be
-   fully in contained in the same payload item. For an array "as" or
-   "a(si)" the only restriction however is to keep each string
-   individually in an uninterrupted item, to keep the framing of each
-   element and the array in a single uninterrupted item, however the
-   various strings might end up in different items.
-
-Note again, that splitting up messages into separate items is up to the
-implementation. Also note that the kdbus kernel side might merge
-separate items if it deems this to be useful. However, the order in
-which items are contained in the message is left untouched.
-
-PAYLOAD_MEMFD items allow zero-copy data transfer (see below regarding
-the memfd concept). Note however that the overhead of mapping these
-makes them relatively expensive, and only worth the trouble for memory
-blocks > 512K (this value appears to be quite universal across
-architectures, as we tested). Thus we recommend sending PAYLOAD_VEC
-items over for small messages and restore to PAYLOAD_MEMFD items for
-messages > 512K. Since while building up the message you might not
-know yet whether it will grow beyond this boundary a good approach is
-to simply build the message unconditionally in a memfd
-object. However, when the message is sealed to be sent away check for
-the size limit. If the size of the message is < 512K, then simply send
-the data as PAYLOAD_VEC and reuse the memfd. If it is >= 512K, seal
-the memfd and send it as PAYLOAD_MEMFD, and allocate a new memfd for
-the next message.
-
-RECEIVING MESSAGES
-
-Use the MSG_RECV ioctl to read a message from kdbus. This will return
-an offset into the pool memory map, relative to its beginning.
-
-The received message structure more or less follows the structure of
-the message originally sent. However, certain changes have been
-made. In the header the src_id field will be filled in.
-
-The payload items might have gotten merged and PAYLOAD_VEC items are
-not used. Instead, you will only find PAYLOAD_OFF and PAYLOAD_MEMFD
-items. The former contain an offset and size into your memory mapped
-pool where you find the payload.
-
-If during the HELLO ioctl you asked for getting metadata attached to
-your message, you will find additional KDBUS_ITEM_CREDS,
-KDBUS_ITEM_PID_COMM, KDBUS_ITEM_TID_COMM, KDBUS_ITEM_TIMESTAMP,
-KDBUS_ITEM_EXE, KDBUS_ITEM_CMDLINE, KDBUS_ITEM_CGROUP,
-KDBUS_ITEM_CAPS, KDBUS_ITEM_SECLABEL, KDBUS_ITEM_AUDIT items that
-contain this metadata. This metadata will be gathered from the sender
-at the point in time it sends the message. This information is
-uncached, and since it is appended by the kernel, trustable. The
-KDBUS_ITEM_SECLABEL item usually contains the SELinux security label,
-if it is used.
-
-After processing the message you need to call the KDBUS_CMD_FREE
-ioctl, which releases the message from the pool, and allows the kernel
-to store another message there. Note that the memory used by the pool
-is ordinary anonymous, swappable memory that is backed by tmpfs. Hence
-there is no need to copy the message out of it quickly, instead you
-can just leave it there as long as you need it and release it via the
-FREE ioctl only after that's done.
-
-BLOOM FILTERS
-
-The kernel does not understand dbus marshaling, it will not look into
-the message payload. To allow clients to subscribe to specific subsets
-of the broadcast matches we employ bloom filters.
-
-When broadcasting messages, a bloom filter needs to be attached to the
-message in a KDBUS_ITEM_BLOOM item (and only for broadcasting
-messages!). If you don't know what bloom filters are, read up now on
-Wikipedia. In short: they are a very efficient way how to
-probabilistically check whether a certain word is contained in a
-vocabulary. It knows no false negatives, but it does know false
-positives.
-
-The parameters for the bloom filters that need to be included in
-broadcast message is communicated to userspace as part of the hello
-response structure (see above). By default it has the parameters m=512
-(bits in the filter), k=8 (nr of hash functions). Note however, that
-this is subject to change in later versions, and userspace
-implementations must be capable of handling m values between at least
-m=8 and m=2^32, and k values between at least k=1 and k=32. The
-underlying hash function is SipHash-2-4. It is used with a number of
-constant (yet originally randomly generated) 128bit hash keys, more
-specifically:
-
-   b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15,
-   aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b,
-   63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8,
-   23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5,
-   56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10,
-   31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29,
-   7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d,
-   f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35
-
-When calculating the first bit index into the bloom filter, the
-SipHash-2-4 hash value is calculated for the input data and the first
-16 bytes of the array above as hash key. Of the resulting 8 bytes of
-output, as many full bytes are taken for the bit index as necessary,
-starting from the output's first byte. For the second bit index the
-same hash value is used, continuing with the next unused output byte,
-and so on. Each time the bytes returned by the hash function are
-depleted it is recalculated with the next 16 byte hash key from the
-array above and the same input data.
-
-For each message to send across the bus we populate the bloom filter
-with all possible matchable strings. If a client then wants to
-subscribe to messages of this type, it simply tells the kernel to test
-its own calculated bit mask against the bloom filter of each message.
-
-More specifically, the following strings are added to the bloom filter
-of each message that is broadcasted:
-
-  The string "interface:" suffixed by the interface name
-
-  The string "member:" suffixed by the member name
-
-  The string "path:" suffixed by the path name
-
-  The string "path-slash-prefix:" suffixed with the path name, and
-  also all prefixes of the path name (cut off at "/"), also prefixed
-  with "path-slash-prefix".
-
-  The string "message-type:" suffixed with the strings "signal",
-  "method_call", "error" or "method_return" for the respective message
-  type of the message.
-
-  If the first argument of the message is a string, "arg0:" suffixed
-  with the first argument.
-
-  If the first argument of the message is a string, "arg0-dot-prefix"
-  suffixed with the first argument, and also all prefixes of the
-  argument (cut off at "."), also prefixed with "arg0-dot-prefix".
-
-  If the first argument of the message is a string,
-  "arg0-slash-prefix" suffixed with the first argument, and also all
-  prefixes of the argument (cut off at "/"), also prefixed with
-  "arg0-slash-prefix".
-
-  Similar for all further arguments that are strings up to 63, for the
-  arguments and their "dot" and "slash" prefixes. On the first
-  argument that is not a string, addition to the bloom filter should be
-  stopped however.
-
-(Note that the bloom filter does not contain sender nor receiver
-names!)
-
-When a client wants to subscribe to messages matching a certain
-expression, it should calculate the bloom mask following the same
-algorithm. The kernel will then simply test the mask against the
-attached bloom filters.
-
-Note that bloom filters are probabilistic, which means that clients
-might get messages they did not expect. Your bus protocol
-implementation must be capable of dealing with these unexpected
-messages (which it needs to anyway, given that transfers are
-relatively unrestricted on kdbus and people can send you all kinds of
-non-sense).
-
-If a client connects to a bus whose bloom filter metrics (i.e. filter
-size and number of hash functions) are outside of the range the client
-supports it must immediately disconnect and continue connection with
-the next bus address of the bus connection string.
-
-INSTALLING MATCHES
-
-To install matches for broadcast messages, use the KDBUS_CMD_ADD_MATCH
-ioctl. It takes a structure that contains an encoded match expression,
-and that is followed by one or more items, which are combined in an
-AND way. (Meaning: a message is matched exactly when all items
-attached to the original ioctl struct match).
-
-To match against other user messages add a KDBUS_ITEM_BLOOM item in
-the match (see above). Note that the bloom filter does not include
-matches to the sender names. To additionally check against sender
-names, use the KDBUS_ITEM_ID (for unique id matches) and
-KDBUS_ITEM_NAME (for well-known name matches) item types.
-
-To match against kernel generated messages (see below) you should add
-items of the same type as the kernel messages include,
-i.e. KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE,
-KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD, KDBUS_ITEM_ID_REMOVE and
-fill them out. Note however, that you have some wildcards in this
-case, for example the .id field of KDBUS_ITEM_ID_ADD/KDBUS_ITEM_ID_REMOVE
-structures may be set to 0 to match against any id addition/removal.
-
-Note that dbus match strings do no map 1:1 to these ioctl() calls. In
-many cases (where the match string is "underspecified") you might need
-to issue up to six different ioctl() calls for the same match. For
-example, the empty match (which matches against all messages), would
-translate into one KDBUS_ITEM_BLOOM ioctl, one KDBUS_ITEM_NAME_ADD,
-one KDBUS_ITEM_NAME_CHANGE, one KDBUS_ITEM_NAME_REMOVE, one
-KDBUS_ITEM_ID_ADD and one KDBUS_ITEM_ID_REMOVE.
-
-When creating a match, you may attach a "cookie" value to them, which
-is used for deleting this match again. The cookie can be selected freely
-by the client. When issuing KDBUS_CMD_REMOVE_MATCH, simply pass the
-same cookie as before and all matches matching the same "cookie" value
-will be removed. This is particularly handy for the case where multiple
-ioctl()s are added for a single match strings.
-
-MEMFDS
-
-memfds may be sent across kdbus via KDBUS_ITEM_PAYLOAD_MEMFD items
-attached to messages. If this is done, the data included in the memfd
-is considered part of the payload stream of a message, and are treated
-the same way as KDBUS_ITEM_PAYLOAD_VEC by the receiving side. It is
-possible to interleave KDBUS_ITEM_PAYLOAD_MEMFD and
-KDBUS_ITEM_PAYLOAD_VEC items freely, by the reader they will be
-considered a single stream of bytes in the order these items appear in
-the message, that just happens to be split up at various places
-(regarding rules how they may be split up, see above). The kernel will
-refuse taking KDBUS_ITEM_PAYLOAD_MEMFD items that refer to memfds that
-are not sealed.
-
-Note that sealed memfds may be unsealed again if they are not mapped
-you have the only fd reference to them.
-
-Alternatively to sending memfds as KDBUS_ITEM_PAYLOAD_MEMFD items
-(where they are just a part of the payload stream of a message) you can
-also simply attach any memfd to a message using
-KDBUS_ITEM_PAYLOAD_FDS. In this case, the memfd contents is not
-considered part of the payload stream of the message, but simply fds
-like any other, that happen to be attached to the message.
-
-MESSAGES FROM THE KERNEL
-
-A couple of messages previously generated by the dbus1 bus driver are
-now generated by the kernel. Since the kernel does not understand the
-payload marshaling, they are generated by the kernel  in a different
-format. This is indicated with the "payload type" field of the
-messages set to 0. Library implementations should take these messages
-and synthesize traditional driver messages for them on reception.
-
-More specifically:
-
-   Instead of the NameOwnerChanged, NameLost, NameAcquired signals
-   there are kernel messages containing KDBUS_ITEM_NAME_ADD,
-   KDBUS_ITEM_NAME_REMOVE, KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD,
-   KDBUS_ITEM_ID_REMOVE items are generated (each message will contain
-   exactly one of these items). Note that in libsystemd we have
-   obsoleted NameLost/NameAcquired messages, since they are entirely
-   redundant to NameOwnerChanged. This library will hence only
-   synthesize NameOwnerChanged messages from these kernel messages,
-   and never generate NameLost/NameAcquired. If your library needs to
-   stay compatible to the old dbus1 userspace, you possibly might need
-   to synthesize both a NameOwnerChanged and NameLost/NameAcquired
-   message from the same kernel message.
-
-   When a method call times out, a KDBUS_ITEM_REPLY_TIMEOUT message is
-   generated. This should be synthesized into a method error reply
-   message to the original call.
-
-   When a method call fails because the peer terminated the connection
-   before responding, a KDBUS_ITEM_REPLY_DEAD message is
-   generated. Similarly, it should be synthesized into a method error
-   reply message.
-
-For synthesized messages we recommend setting the cookie field to
-(uint32_t) -1 (and not (uint64_t) -1!), so that the cookie is not 0
-(which the dbus1 spec does not allow), but clearly recognizable as
-synthetic.
-
-Note that the KDBUS_ITEM_NAME_XYZ messages will actually inform you
-about all kinds of names, including activatable ones. Classic dbus1
-NameOwnerChanged messages OTOH are only generated when a name is
-really acquired on the bus and not just simply activatable. This means
-you must explicitly check for the case where an activatable name
-becomes acquired or an acquired name is lost and returns to be
-activatable.
-
-NAME REGISTRY
-
-To acquire names on the bus, use the KDBUS_CMD_NAME_ACQUIRE ioctl(). It
-takes a flags field similar to dbus1's RequestName() bus driver call,
-however the NO_QUEUE flag got inverted into a QUEUE flag instead.
-
-To release a previously acquired name use the KDBUS_CMD_NAME_RELEASE
-ioctl().
-
-To list acquired names use the KDBUS_CMD_CONN_INFO ioctl. It may be
-used to list unique names, well known names as well as activatable
-names and clients currently queuing for ownership of a well-known
-name. The ioctl will return an offset into the memory pool. After
-reading all the data you need, you need to release this via the
-KDBUS_CMD_FREE ioctl(), similar how you release a received message.
-
-CREDENTIALS
-
-kdbus can optionally attach various kinds of metadata about the sender at
-the point of time of sending ("credentials") to messages, on request
-of the receiver. This is both supported on directed and undirected
-(broadcast) messages. The metadata to attach is selected at time of
-the HELLO ioctl of the receiver via a flags field (see above). Note
-that clients must be able to handle that messages contain more
-metadata than they asked for themselves, to simplify implementation of
-broadcasting in the kernel. The receiver should not rely on this data
-to be around though, even though it will be correct if it happens to
-be attached. In order to avoid programming errors in applications, we
-recommend though not passing this data on to clients that did not
-explicitly ask for it.
-
-Credentials may also be queried for a well-known or unique name. Use
-the KDBUS_CMD_CONN_INFO for this. It will return an offset to the pool
-area again, which will contain the same credential items as messages
-have attached. Note that when issuing the ioctl, you can select a
-different set of credentials to gather, than what was originally requested
-for being attached to incoming messages.
-
-Credentials are always specific to the sender's domain that was
-current at the time of sending, and of the process that opened the
-bus connection at the time of opening it. Note that this latter data
-is cached!
-
-POLICY
-
-The kernel enforces only very limited policy on names. It will not do
-access filtering by userspace payload, and thus not by interface or
-method name.
-
-This ultimately means that most fine-grained policy enforcement needs
-to be done by the receiving process. We recommend using PolicyKit for
-any more complex checks. However, libraries should make simple static
-policy decisions regarding privileged/unprivileged method calls
-easy. We recommend doing this by enabling KDBUS_ATTACH_CAPS and
-KDBUS_ATTACH_CREDS for incoming messages, and then discerning client
-access by some capability, or if sender and receiver UIDs match.
-
-BUS ADDRESSES
-
-When connecting to kdbus use the "kernel:" protocol prefix in DBus
-address strings. The device node path is encoded in its "path="
-parameter.
-
-Client libraries should use the following connection string when
-connecting to the system bus:
-
-   kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket
-
-This will ensure that kdbus is preferred over the legacy AF_UNIX
-socket, but compatibility is kept. For the user bus use:
-
-   kernel:path=/sys/fs/kdbus/$UID-user/bus;unix:path=$XDG_RUNTIME_DIR/bus
-
-With $UID replaced by the callers numer user ID, and $XDG_RUNTIME_DIR
-following the XDG basedir spec.
-
-Of course the $DBUS_SYSTEM_BUS_ADDRESS and $DBUS_SESSION_BUS_ADDRESS
-variables should still take precedence.
-
-DBUS SERVICE FILES
-
-Activatable services for kdbus may not use classic dbus1 service
-activation files. Instead, programs should drop in native systemd
-.service and .busname unit files, so that they are treated uniformly
-with other types of units and activation of the system.
-
-Note that this results in a major difference to classic dbus1:
-activatable bus names can be established at any time in the boot process.
-This is unlike dbus1 where activatable names are unconditionally available
-as long as dbus-daemon is running. Being able to control when
-activatable names are established is essential to allow usage of kdbus
-during early boot and in initrds, without the risk of triggering
-services too early.
-
-DISCLAIMER
-
-This all is so far just the status quo. We are putting this together, because
-we are quite confident that further API changes will be smaller, but
-to make this very clear: this is all subject to change, still!
-
-We invite you to port over your favorite dbus library to this new
-scheme, but please be prepared to make minor changes when we still
-change these interfaces!
index 9e58ffbd88c1b8fe280788aa78e8c8009771e3e6..b56bb07713ccb990301fdcfd6aade7ef6e58efcd 100644 (file)
@@ -264,10 +264,13 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
                 if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
                         char *n;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
                         if (asprintf(&n, ":1.%llu", name->id) < 0) {
                                 r = -ENOMEM;
                                 goto fail;
                         }
+#pragma GCC diagnostic pop
 
                         r = strv_consume(x, n);
                         if (r < 0)
@@ -711,10 +714,13 @@ int bus_get_name_creds_kdbus(
         }
 
         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
                 if (asprintf(&c->unique_name, ":1.%llu", conn_info->id) < 0) {
                         r = -ENOMEM;
                         goto fail;
                 }
+#pragma GCC diagnostic pop
 
                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
         }
@@ -780,6 +786,8 @@ static int bus_get_name_creds_dbus1(
         }
 
         if (mask != 0) {
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                bool need_pid, need_uid, need_selinux, need_separate_calls;
                 c = bus_creds_new();
                 if (!c)
                         return -ENOMEM;
@@ -792,99 +800,216 @@ static int bus_get_name_creds_dbus1(
                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
                 }
 
-                if ((mask & SD_BUS_CREDS_PID) ||
-                    ((mask & SD_BUS_CREDS_AUGMENT) &&
-                     (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
-                              SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
-                              SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
-                              SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
-                              SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
-                              SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
-                              SD_BUS_CREDS_SELINUX_CONTEXT|
-                              SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
+                need_pid = (mask & SD_BUS_CREDS_PID) ||
+                        ((mask & SD_BUS_CREDS_AUGMENT) &&
+                         (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+                                  SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+                                  SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
+                                  SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
+                                  SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
+                                  SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
+                                  SD_BUS_CREDS_SELINUX_CONTEXT|
+                                  SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
+                need_uid = mask & SD_BUS_CREDS_EUID;
+                need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
 
-                        uint32_t u;
+                if (need_pid + need_uid + need_selinux > 1) {
+
+                        /* If we need more than one of the credentials, then use GetConnectionCredentials() */
 
                         r = sd_bus_call_method(
                                         bus,
                                         "org.freedesktop.DBus",
                                         "/org/freedesktop/DBus",
                                         "org.freedesktop.DBus",
-                                        "GetConnectionUnixProcessID",
-                                        NULL,
+                                        "GetConnectionCredentials",
+                                        &error,
                                         &reply,
                                         "s",
-                                        unique ? unique : name);
-                        if (r < 0)
-                                return r;
+                                        unique ?: name);
 
-                        r = sd_bus_message_read(reply, "u", &u);
-                        if (r < 0)
-                                return r;
+                        if (r < 0) {
 
-                        pid = u;
-                        if (mask & SD_BUS_CREDS_PID) {
-                                c->pid = u;
-                                c->mask |= SD_BUS_CREDS_PID;
-                        }
+                                if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
+                                        return r;
 
-                        reply = sd_bus_message_unref(reply);
-                }
+                                /* If we got an unknown method error, fall back to the invidual calls... */
+                                need_separate_calls = true;
+                                sd_bus_error_free(&error);
 
-                if (mask & SD_BUS_CREDS_EUID) {
-                        uint32_t u;
+                        } else {
+                                need_separate_calls = false;
 
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.DBus",
-                                        "/org/freedesktop/DBus",
-                                        "org.freedesktop.DBus",
-                                        "GetConnectionUnixUser",
-                                        NULL,
-                                        &reply,
-                                        "s",
-                                        unique ? unique : name);
-                        if (r < 0)
-                                return r;
+                                r = sd_bus_message_enter_container(reply, 'a', "{sv}");
+                                if (r < 0)
+                                        return r;
 
-                        r = sd_bus_message_read(reply, "u", &u);
-                        if (r < 0)
-                                return r;
+                                for (;;) {
+                                        const char *m;
 
-                        c->euid = u;
-                        c->mask |= SD_BUS_CREDS_EUID;
+                                        r = sd_bus_message_enter_container(reply, 'e', "sv");
+                                        if (r < 0)
+                                                return r;
+                                        if (r == 0)
+                                                break;
 
-                        reply = sd_bus_message_unref(reply);
-                }
+                                        r = sd_bus_message_read(reply, "s", &m);
+                                        if (r < 0)
+                                                return r;
 
-                if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
-                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-                        const void *p = NULL;
-                        size_t sz = 0;
+                                        if (need_uid && streq(m, "UnixUserID")) {
+                                                uint32_t u;
 
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.DBus",
-                                        "/org/freedesktop/DBus",
-                                        "org.freedesktop.DBus",
-                                        "GetConnectionSELinuxSecurityContext",
-                                        &error,
-                                        &reply,
-                                        "s",
-                                        unique ? unique : name);
-                        if (r < 0) {
-                                if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
+                                                r = sd_bus_message_read(reply, "v", "u", &u);
+                                                if (r < 0)
+                                                        return r;
+
+                                                c->euid = u;
+                                                c->mask |= SD_BUS_CREDS_EUID;
+
+                                        } else if (need_pid && streq(m, "ProcessID")) {
+                                                uint32_t p;
+
+                                                r = sd_bus_message_read(reply, "v", "u", &p);
+                                                if (r < 0)
+                                                        return r;
+
+                                                pid = p;
+                                                if (mask & SD_BUS_CREDS_PID) {
+                                                        c->pid = p;
+                                                        c->mask |= SD_BUS_CREDS_PID;
+                                                }
+
+                                        } else if (need_selinux && streq(m, "LinuxSecurityLabel")) {
+                                                const void *p = NULL;
+                                                size_t sz = 0;
+
+                                                r = sd_bus_message_enter_container(reply, 'v', "ay");
+                                                if (r < 0)
+                                                        return r;
+
+                                                r = sd_bus_message_read_array(reply, 'y', &p, &sz);
+                                                if (r < 0)
+                                                        return r;
+
+                                                free(c->label);
+                                                c->label = strndup(p, sz);
+                                                if (!c->label)
+                                                        return -ENOMEM;
+
+                                                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+
+                                                r = sd_bus_message_exit_container(reply);
+                                                if (r < 0)
+                                                        return r;
+                                        } else {
+                                                r = sd_bus_message_skip(reply, "v");
+                                                if (r < 0)
+                                                        return r;
+                                        }
+
+                                        r = sd_bus_message_exit_container(reply);
+                                        if (r < 0)
+                                                return r;
+                                }
+
+                                r = sd_bus_message_exit_container(reply);
+                                if (r < 0)
                                         return r;
-                        } else {
-                                r = sd_bus_message_read_array(reply, 'y', &p, &sz);
+
+                                if (need_pid && pid == 0)
+                                        return -EPROTO;
+                        }
+
+                } else /* When we only need a single field, then let's use separate calls */
+                        need_separate_calls = true;
+
+                if (need_separate_calls) {
+                        if (need_pid) {
+                                uint32_t u;
+
+                                r = sd_bus_call_method(
+                                                bus,
+                                                "org.freedesktop.DBus",
+                                                "/org/freedesktop/DBus",
+                                                "org.freedesktop.DBus",
+                                                "GetConnectionUnixProcessID",
+                                                NULL,
+                                                &reply,
+                                                "s",
+                                                unique ?: name);
                                 if (r < 0)
                                         return r;
 
-                                c->label = strndup(p, sz);
-                                if (!c->label)
-                                        return -ENOMEM;
+                                r = sd_bus_message_read(reply, "u", &u);
+                                if (r < 0)
+                                        return r;
 
-                                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+                                pid = u;
+                                if (mask & SD_BUS_CREDS_PID) {
+                                        c->pid = u;
+                                        c->mask |= SD_BUS_CREDS_PID;
+                                }
+
+                                reply = sd_bus_message_unref(reply);
+                        }
+
+                        if (need_uid) {
+                                uint32_t u;
+
+                                r = sd_bus_call_method(
+                                                bus,
+                                                "org.freedesktop.DBus",
+                                                "/org/freedesktop/DBus",
+                                                "org.freedesktop.DBus",
+                                                "GetConnectionUnixUser",
+                                                NULL,
+                                                &reply,
+                                                "s",
+                                                unique ? unique : name);
+                                if (r < 0)
+                                        return r;
+
+                                r = sd_bus_message_read(reply, "u", &u);
+                                if (r < 0)
+                                        return r;
+
+                                c->euid = u;
+                                c->mask |= SD_BUS_CREDS_EUID;
+
+                                reply = sd_bus_message_unref(reply);
+                        }
+
+                        if (need_selinux) {
+                                const void *p = NULL;
+                                size_t sz = 0;
+
+                                r = sd_bus_call_method(
+                                                bus,
+                                                "org.freedesktop.DBus",
+                                                "/org/freedesktop/DBus",
+                                                "org.freedesktop.DBus",
+                                                "GetConnectionSELinuxSecurityContext",
+                                                &error,
+                                                &reply,
+                                                "s",
+                                                unique ? unique : name);
+                                if (r < 0) {
+                                        if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
+                                                return r;
+
+                                        /* no data is fine */
+                                } else {
+                                        r = sd_bus_message_read_array(reply, 'y', &p, &sz);
+                                        if (r < 0)
+                                                return r;
+
+                                        c->label = strndup(p, sz);
+                                        if (!c->label)
+                                                return -ENOMEM;
+
+                                        c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+                                }
                         }
                 }
 
@@ -917,9 +1042,17 @@ _public_ int sd_bus_get_name_creds(
         if (!bus->bus_client)
                 return -EINVAL;
 
+        /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
+         * going to match. */
+        if (!bus->is_local)
+                mask &= ~SD_BUS_CREDS_AUGMENT;
+
         if (streq(name, "org.freedesktop.DBus.Local"))
                 return -EINVAL;
 
+        if (streq(name, "org.freedesktop.DBus"))
+                return sd_bus_get_owner_creds(bus, mask, creds);
+
         if (!BUS_IS_OPEN(bus->state))
                 return -ENOTCONN;
 
@@ -1040,6 +1173,9 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
         if (!BUS_IS_OPEN(bus->state))
                 return -ENOTCONN;
 
+        if (!bus->is_local)
+                mask &= ~SD_BUS_CREDS_AUGMENT;
+
         if (bus->is_kernel)
                 return bus_get_owner_creds_kdbus(bus, mask, ret);
         else
index 2d06bf541f7df9a4963d499f09f062c365e9ad72..04158cae4d3ccfc718a00b403f926e5140e0f1db 100644 (file)
@@ -48,7 +48,7 @@ _public_ int sd_bus_emit_signal(
                 va_list ap;
 
                 va_start(ap, types);
-                r = bus_message_append_ap(m, types, ap);
+                r = sd_bus_message_appendv(m, types, ap);
                 va_end(ap);
                 if (r < 0)
                         return r;
@@ -85,7 +85,7 @@ _public_ int sd_bus_call_method_async(
                 va_list ap;
 
                 va_start(ap, types);
-                r = bus_message_append_ap(m, types, ap);
+                r = sd_bus_message_appendv(m, types, ap);
                 va_end(ap);
                 if (r < 0)
                         return r;
@@ -123,7 +123,7 @@ _public_ int sd_bus_call_method(
                 va_list ap;
 
                 va_start(ap, types);
-                r = bus_message_append_ap(m, types, ap);
+                r = sd_bus_message_appendv(m, types, ap);
                 va_end(ap);
                 if (r < 0)
                         goto fail;
@@ -162,7 +162,7 @@ _public_ int sd_bus_reply_method_return(
                 va_list ap;
 
                 va_start(ap, types);
-                r = bus_message_append_ap(m, types, ap);
+                r = sd_bus_message_appendv(m, types, ap);
                 va_end(ap);
                 if (r < 0)
                         return r;
@@ -493,7 +493,7 @@ _public_ int sd_bus_set_property(
                 goto fail;
 
         va_start(ap, type);
-        r = bus_message_append_ap(m, type, ap);
+        r = sd_bus_message_appendv(m, type, ap);
         va_end(ap);
         if (r < 0)
                 goto fail;
index bb0414c4d6d12d3d6ae27b7a30cedb3e541ee215..3575ea8cdea6b00e43cf640bee14e1541bb842c8 100644 (file)
@@ -212,6 +212,7 @@ struct sd_bus {
         bool exit_on_disconnect:1;
         bool exited:1;
         bool exit_triggered:1;
+        bool is_local:1;
 
         int use_memfd;
 
index c82caeb3fcfba15ba9089f9d174b52c4c3afdfec..ca6aee7c06cc9c25faf09e9630b31afc3252b316 100644 (file)
@@ -51,6 +51,8 @@
 #include "user-util.h"
 #include "util.h"
 
+#pragma GCC diagnostic ignored "-Wformat"
+
 #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
 
 int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
index 5cec804e326145773e17af103802e74dedd00b16..da6fd3b89664d647a1c93a143d3efdf6f07df301 100644 (file)
@@ -2341,7 +2341,7 @@ static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const cha
         return 1;
 }
 
-int bus_message_append_ap(
+_public_ int sd_bus_message_appendv(
                 sd_bus_message *m,
                 const char *types,
                 va_list ap) {
@@ -2351,10 +2351,10 @@ int bus_message_append_ap(
         unsigned stack_ptr = 0;
         int r;
 
-        assert(m);
-
-        if (!types)
-                return 0;
+        assert_return(m, -EINVAL);
+        assert_return(types, -EINVAL);
+        assert_return(!m->sealed, -EPERM);
+        assert_return(!m->poisoned, -ESTALE);
 
         n_array = (unsigned) -1;
         n_struct = strlen(types);
@@ -2555,7 +2555,7 @@ _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
         assert_return(!m->poisoned, -ESTALE);
 
         va_start(ap, types);
-        r = bus_message_append_ap(m, types, ap);
+        r = sd_bus_message_appendv(m, types, ap);
         va_end(ap);
 
         return r;
index 4710c106b95293e054396aa9df400a4bb0239809..a59aa73833c80a9ea12a4554f6769ce6e07c02be 100644 (file)
@@ -220,8 +220,6 @@ int bus_message_from_malloc(
 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str);
 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv);
 
-int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap);
-
 int bus_message_parse_fields(sd_bus_message *m);
 
 struct bus_body_part *message_append_part(sd_bus_message *m);
index 9bd07ffcabbac14d7b21b7de95959b88e4c65895..98911d520366004e04bedeffec522e65d1199363 100644 (file)
@@ -974,8 +974,10 @@ static int process_introspect(
                 /* Nothing?, let's see if we exist at all, and if not
                  * refuse to do anything */
                 r = bus_node_exists(bus, n, m->path, require_fallback);
-                if (r <= 0)
+                if (r <= 0) {
+                        r = bus_maybe_reply_error(m, r, &error);
                         goto finish;
+                }
                 if (bus->nodes_modified) {
                         r = 0;
                         goto finish;
@@ -1057,6 +1059,22 @@ static int object_manager_serialize_path(
                         if (r < 0)
                                 return r;
 
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0);
+                        if (r < 0)
+                                return r;
+
                         found_something = true;
                 }
 
@@ -1183,7 +1201,7 @@ static int process_get_managed_objects(
 
         r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error);
         if (r < 0)
-                return r;
+                return bus_maybe_reply_error(m, r, &error);
         if (bus->nodes_modified)
                 return 0;
 
@@ -1198,7 +1216,7 @@ static int process_get_managed_objects(
         SET_FOREACH(path, s, i) {
                 r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
                 if (r < 0)
-                        return r;
+                        return bus_maybe_reply_error(m, r, &error);
 
                 if (bus->nodes_modified)
                         return 0;
@@ -1328,7 +1346,7 @@ static int object_find_and_run(
         if (!*found_object) {
                 r = bus_node_exists(bus, n, m->path, require_fallback);
                 if (r < 0)
-                        return r;
+                        return bus_maybe_reply_error(m, r, NULL);
                 if (bus->nodes_modified)
                         return 0;
                 if (r > 0)
index e6ed15eb71d4d97f4c7993db4d601c7abda5ea19..8b25002f0106b3718662b378bbe0723b33245077 100644 (file)
@@ -607,7 +607,7 @@ static void bus_get_peercred(sd_bus *b) {
         b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
 
         /* Get the SELinux context of the peer */
-        if (mac_selinux_have()) {
+        if (mac_selinux_use()) {
                 r = getpeersec(b->input_fd, &b->label);
                 if (r < 0 && r != -EOPNOTSUPP)
                         log_debug_errno(r, "Failed to determine peer security context: %m");
diff --git a/src/libsystemd/sd-bus/busctl-introspect.c b/src/libsystemd/sd-bus/busctl-introspect.c
deleted file mode 100644 (file)
index a057949..0000000
+++ /dev/null
@@ -1,782 +0,0 @@
-/***
-  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 "sd-bus.h"
-
-#include "alloc-util.h"
-#include "busctl-introspect.h"
-#include "string-util.h"
-#include "util.h"
-#include "xml.h"
-
-#define NODE_DEPTH_MAX 16
-
-typedef struct Context {
-        const XMLIntrospectOps *ops;
-        void *userdata;
-
-        char *interface_name;
-        uint64_t interface_flags;
-
-        char *member_name;
-        char *member_signature;
-        char *member_result;
-        uint64_t member_flags;
-        bool member_writable;
-
-        const char *current;
-        void *xml_state;
-} Context;
-
-static void context_reset_member(Context *c) {
-        free(c->member_name);
-        free(c->member_signature);
-        free(c->member_result);
-
-        c->member_name = c->member_signature = c->member_result = NULL;
-        c->member_flags = 0;
-        c->member_writable = false;
-}
-
-static void context_reset_interface(Context *c) {
-        c->interface_name = mfree(c->interface_name);
-        c->interface_flags = 0;
-
-        context_reset_member(c);
-}
-
-static int parse_xml_annotation(Context *context, uint64_t *flags) {
-
-        enum {
-                STATE_ANNOTATION,
-                STATE_NAME,
-                STATE_VALUE
-        } state = STATE_ANNOTATION;
-
-        _cleanup_free_ char *field = NULL, *value = NULL;
-
-        assert(context);
-
-        for (;;) {
-                _cleanup_free_ char *name = NULL;
-
-                int t;
-
-                t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
-                if (t < 0) {
-                        log_error("XML parse error.");
-                        return t;
-                }
-
-                if (t == XML_END) {
-                        log_error("Premature end of XML data.");
-                        return -EBADMSG;
-                }
-
-                switch (state) {
-
-                case STATE_ANNOTATION:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_NAME;
-
-                                else if (streq_ptr(name, "value"))
-                                        state = STATE_VALUE;
-
-                                else {
-                                        log_error("Unexpected <annotation> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) {
-
-                                if (flags) {
-                                        if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) {
-
-                                                if (streq_ptr(value, "true"))
-                                                        *flags |= SD_BUS_VTABLE_DEPRECATED;
-
-                                        } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) {
-
-                                                if (streq_ptr(value, "true"))
-                                                        *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY;
-
-                                        } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) {
-
-                                                if (streq_ptr(value, "const"))
-                                                        *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST;
-                                                else if (streq_ptr(value, "invalidates"))
-                                                        *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION;
-                                                else if (streq_ptr(value, "false"))
-                                                        *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION);
-                                        }
-                                }
-
-                                return 0;
-
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in <annotation>. (1)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                free_and_replace(field, name);
-
-                                state = STATE_ANNOTATION;
-                        } else {
-                                log_error("Unexpected token in <annotation>. (2)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_VALUE:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                free_and_replace(value, name);
-
-                                state = STATE_ANNOTATION;
-                        } else {
-                                log_error("Unexpected token in <annotation>. (3)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                default:
-                        assert_not_reached("Bad state");
-                }
-        }
-}
-
-static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) {
-
-        enum {
-                STATE_NODE,
-                STATE_NODE_NAME,
-                STATE_INTERFACE,
-                STATE_INTERFACE_NAME,
-                STATE_METHOD,
-                STATE_METHOD_NAME,
-                STATE_METHOD_ARG,
-                STATE_METHOD_ARG_NAME,
-                STATE_METHOD_ARG_TYPE,
-                STATE_METHOD_ARG_DIRECTION,
-                STATE_SIGNAL,
-                STATE_SIGNAL_NAME,
-                STATE_SIGNAL_ARG,
-                STATE_SIGNAL_ARG_NAME,
-                STATE_SIGNAL_ARG_TYPE,
-                STATE_SIGNAL_ARG_DIRECTION,
-                STATE_PROPERTY,
-                STATE_PROPERTY_NAME,
-                STATE_PROPERTY_TYPE,
-                STATE_PROPERTY_ACCESS,
-        } state = STATE_NODE;
-
-        _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL;
-        const char *np = prefix;
-        int r;
-
-        assert(context);
-        assert(prefix);
-
-        if (n_depth > NODE_DEPTH_MAX) {
-                log_error("<node> depth too high.");
-                return -EINVAL;
-        }
-
-        for (;;) {
-                _cleanup_free_ char *name = NULL;
-                int t;
-
-                t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
-                if (t < 0) {
-                        log_error("XML parse error.");
-                        return t;
-                }
-
-                if (t == XML_END) {
-                        log_error("Premature end of XML data.");
-                        return -EBADMSG;
-                }
-
-                switch (state) {
-
-                case STATE_NODE:
-                        if (t == XML_ATTRIBUTE_NAME) {
-
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_NODE_NAME;
-                                else {
-                                        log_error("Unexpected <node> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-
-                        } else if (t == XML_TAG_OPEN) {
-
-                                if (streq_ptr(name, "interface"))
-                                        state = STATE_INTERFACE;
-                                else if (streq_ptr(name, "node")) {
-
-                                        r = parse_xml_node(context, np, n_depth+1);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected <node> tag %s.", name);
-                                        return -EBADMSG;
-                                }
-
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) {
-
-                                if (context->ops->on_path) {
-                                        r = context->ops->on_path(node_path ? node_path : np, context->userdata);
-                                        if (r < 0)
-                                                return r;
-                                }
-
-                                return 0;
-
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in <node>. (1)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_NODE_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-
-                                free(node_path);
-
-                                if (name[0] == '/') {
-                                        node_path = name;
-                                        name = NULL;
-                                } else {
-
-                                        if (endswith(prefix, "/"))
-                                                node_path = strappend(prefix, name);
-                                        else
-                                                node_path = strjoin(prefix, "/", name);
-                                        if (!node_path)
-                                                return log_oom();
-                                }
-
-                                np = node_path;
-                                state = STATE_NODE;
-                        } else {
-                                log_error("Unexpected token in <node>. (2)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_INTERFACE:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_INTERFACE_NAME;
-                                else {
-                                        log_error("Unexpected <interface> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-
-                        } else if (t == XML_TAG_OPEN) {
-                                if (streq_ptr(name, "method"))
-                                        state = STATE_METHOD;
-                                else if (streq_ptr(name, "signal"))
-                                        state = STATE_SIGNAL;
-                                else if (streq_ptr(name, "property")) {
-                                        context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE;
-                                        state = STATE_PROPERTY;
-                                } else if (streq_ptr(name, "annotation")) {
-                                        r = parse_xml_annotation(context, &context->interface_flags);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected <interface> tag %s.", name);
-                                        return -EINVAL;
-                                }
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) {
-
-                                if (n_depth == 0) {
-                                        if (context->ops->on_interface) {
-                                                r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata);
-                                                if (r < 0)
-                                                        return r;
-                                        }
-
-                                        context_reset_interface(context);
-                                }
-
-                                state = STATE_NODE;
-
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in <interface>. (1)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_INTERFACE_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                if (n_depth == 0)
-                                        free_and_replace(context->interface_name, name);
-
-                                state = STATE_INTERFACE;
-                        } else {
-                                log_error("Unexpected token in <interface>. (2)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_METHOD:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_METHOD_NAME;
-                                else {
-                                        log_error("Unexpected <method> attribute %s", name);
-                                        return -EBADMSG;
-                                }
-                        } else if (t == XML_TAG_OPEN) {
-                                if (streq_ptr(name, "arg"))
-                                        state = STATE_METHOD_ARG;
-                                else if (streq_ptr(name, "annotation")) {
-                                        r = parse_xml_annotation(context, &context->member_flags);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected <method> tag %s.", name);
-                                        return -EINVAL;
-                                }
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) {
-
-                                if (n_depth == 0) {
-                                        if (context->ops->on_method) {
-                                                r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata);
-                                                if (r < 0)
-                                                        return r;
-                                        }
-
-                                        context_reset_member(context);
-                                }
-
-                                state = STATE_INTERFACE;
-
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in <method> (1).");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_METHOD_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                if (n_depth == 0)
-                                        free_and_replace(context->member_name, name);
-
-                                state = STATE_METHOD;
-                        } else {
-                                log_error("Unexpected token in <method> (2).");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_METHOD_ARG:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_METHOD_ARG_NAME;
-                                else if (streq_ptr(name, "type"))
-                                        state = STATE_METHOD_ARG_TYPE;
-                                else if (streq_ptr(name, "direction"))
-                                        state = STATE_METHOD_ARG_DIRECTION;
-                                else {
-                                        log_error("Unexpected method <arg> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-                        } else if (t == XML_TAG_OPEN) {
-                                if (streq_ptr(name, "annotation")) {
-                                        r = parse_xml_annotation(context, NULL);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected method <arg> tag %s.", name);
-                                        return -EINVAL;
-                                }
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
-
-                                if (n_depth == 0) {
-
-                                        if (argument_type) {
-                                                if (!argument_direction || streq(argument_direction, "in")) {
-                                                        if (!strextend(&context->member_signature, argument_type, NULL))
-                                                                return log_oom();
-                                                } else if (streq(argument_direction, "out")) {
-                                                        if (!strextend(&context->member_result, argument_type, NULL))
-                                                                return log_oom();
-                                                } else
-                                                        log_error("Unexpected method <arg> direction value '%s'.", argument_direction);
-                                        }
-
-                                        argument_type = mfree(argument_type);
-                                        argument_direction = mfree(argument_direction);
-                                }
-
-                                state = STATE_METHOD;
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in method <arg>. (1)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_METHOD_ARG_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE)
-                                state = STATE_METHOD_ARG;
-                        else {
-                                log_error("Unexpected token in method <arg>. (2)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_METHOD_ARG_TYPE:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                free_and_replace(argument_type, name);
-
-                                state = STATE_METHOD_ARG;
-                        } else {
-                                log_error("Unexpected token in method <arg>. (3)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_METHOD_ARG_DIRECTION:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                free_and_replace(argument_direction, name);
-
-                                state = STATE_METHOD_ARG;
-                        } else {
-                                log_error("Unexpected token in method <arg>. (4)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_SIGNAL:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_SIGNAL_NAME;
-                                else {
-                                        log_error("Unexpected <signal> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-                        } else if (t == XML_TAG_OPEN) {
-                                if (streq_ptr(name, "arg"))
-                                        state = STATE_SIGNAL_ARG;
-                                else if (streq_ptr(name, "annotation")) {
-                                        r = parse_xml_annotation(context, &context->member_flags);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected <signal> tag %s.", name);
-                                        return -EINVAL;
-                                }
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) {
-
-                                if (n_depth == 0) {
-                                        if (context->ops->on_signal) {
-                                                r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata);
-                                                if (r < 0)
-                                                        return r;
-                                        }
-
-                                        context_reset_member(context);
-                                }
-
-                                state = STATE_INTERFACE;
-
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in <signal>. (1)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_SIGNAL_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                if (n_depth == 0)
-                                        free_and_replace(context->member_name, name);
-
-                                state = STATE_SIGNAL;
-                        } else {
-                                log_error("Unexpected token in <signal>. (2)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-
-                case STATE_SIGNAL_ARG:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_SIGNAL_ARG_NAME;
-                                else if (streq_ptr(name, "type"))
-                                        state = STATE_SIGNAL_ARG_TYPE;
-                                else if (streq_ptr(name, "direction"))
-                                        state = STATE_SIGNAL_ARG_DIRECTION;
-                                else {
-                                        log_error("Unexpected signal <arg> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-                        } else if (t == XML_TAG_OPEN) {
-                                if (streq_ptr(name, "annotation")) {
-                                        r = parse_xml_annotation(context, NULL);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected signal <arg> tag %s.", name);
-                                        return -EINVAL;
-                                }
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
-
-                                if (argument_type) {
-                                        if (!argument_direction || streq(argument_direction, "out")) {
-                                                if (!strextend(&context->member_signature, argument_type, NULL))
-                                                        return log_oom();
-                                        } else
-                                                log_error("Unexpected signal <arg> direction value '%s'.", argument_direction);
-
-                                        argument_type = mfree(argument_type);
-                                }
-
-                                state = STATE_SIGNAL;
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in signal <arg> (1).");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_SIGNAL_ARG_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE)
-                                state = STATE_SIGNAL_ARG;
-                        else {
-                                log_error("Unexpected token in signal <arg> (2).");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_SIGNAL_ARG_TYPE:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                free_and_replace(argument_type, name);
-
-                                state = STATE_SIGNAL_ARG;
-                        } else {
-                                log_error("Unexpected token in signal <arg> (3).");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_SIGNAL_ARG_DIRECTION:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                free_and_replace(argument_direction, name);
-
-                                state = STATE_SIGNAL_ARG;
-                        } else {
-                                log_error("Unexpected token in signal <arg>. (4)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_PROPERTY:
-
-                        if (t == XML_ATTRIBUTE_NAME) {
-                                if (streq_ptr(name, "name"))
-                                        state = STATE_PROPERTY_NAME;
-                                else if (streq_ptr(name, "type"))
-                                        state  = STATE_PROPERTY_TYPE;
-                                else if (streq_ptr(name, "access"))
-                                        state  = STATE_PROPERTY_ACCESS;
-                                else {
-                                        log_error("Unexpected <property> attribute %s.", name);
-                                        return -EBADMSG;
-                                }
-                        } else if (t == XML_TAG_OPEN) {
-
-                                if (streq_ptr(name, "annotation")) {
-                                        r = parse_xml_annotation(context, &context->member_flags);
-                                        if (r < 0)
-                                                return r;
-                                } else {
-                                        log_error("Unexpected <property> tag %s.", name);
-                                        return -EINVAL;
-                                }
-
-                        } else if (t == XML_TAG_CLOSE_EMPTY ||
-                                   (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) {
-
-                                if (n_depth == 0) {
-                                        if (context->ops->on_property) {
-                                                r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata);
-                                                if (r < 0)
-                                                        return r;
-                                        }
-
-                                        context_reset_member(context);
-                                }
-
-                                state = STATE_INTERFACE;
-
-                        } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                                log_error("Unexpected token in <property>. (1)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_PROPERTY_NAME:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                if (n_depth == 0)
-                                        free_and_replace(context->member_name, name);
-
-                                state = STATE_PROPERTY;
-                        } else {
-                                log_error("Unexpected token in <property>. (2)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_PROPERTY_TYPE:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-                                if (n_depth == 0)
-                                        free_and_replace(context->member_signature, name);
-
-                                state = STATE_PROPERTY;
-                        } else {
-                                log_error("Unexpected token in <property>. (3)");
-                                return -EINVAL;
-                        }
-
-                        break;
-
-                case STATE_PROPERTY_ACCESS:
-
-                        if (t == XML_ATTRIBUTE_VALUE) {
-
-                                if (streq(name, "readwrite") || streq(name, "write"))
-                                        context->member_writable = true;
-
-                                state = STATE_PROPERTY;
-                        } else {
-                                log_error("Unexpected token in <property>. (4)");
-                                return -EINVAL;
-                        }
-
-                        break;
-                }
-        }
-}
-
-int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) {
-        Context context = {
-                .ops = ops,
-                .userdata = userdata,
-                .current = xml,
-        };
-
-        int r;
-
-        assert(prefix);
-        assert(xml);
-        assert(ops);
-
-        for (;;) {
-                _cleanup_free_ char *name = NULL;
-
-                r = xml_tokenize(&context.current, &name, &context.xml_state, NULL);
-                if (r < 0) {
-                        log_error("XML parse error");
-                        goto finish;
-                }
-
-                if (r == XML_END) {
-                        r = 0;
-                        break;
-                }
-
-                if (r == XML_TAG_OPEN) {
-
-                        if (streq(name, "node")) {
-                                r = parse_xml_node(&context, prefix, 0);
-                                if (r < 0)
-                                        goto finish;
-                        } else {
-                                log_error("Unexpected tag '%s' in introspection data.", name);
-                                r = -EBADMSG;
-                                goto finish;
-                        }
-                } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) {
-                        log_error("Unexpected token.");
-                        r = -EBADMSG;
-                        goto finish;
-                }
-        }
-
-finish:
-        context_reset_interface(&context);
-
-        return r;
-}
diff --git a/src/libsystemd/sd-bus/busctl-introspect.h b/src/libsystemd/sd-bus/busctl-introspect.h
deleted file mode 100644 (file)
index d922e35..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#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 <stdbool.h>
-
-typedef struct XMLIntrospectOps {
-        int (*on_path)(const char *path, void *userdata);
-        int (*on_interface)(const char *name, uint64_t flags, void *userdata);
-        int (*on_method)(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata);
-        int (*on_signal)(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata);
-        int (*on_property)(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata);
-} XMLIntrospectOps;
-
-int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata);
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
deleted file mode 100644 (file)
index 9dd3828..0000000
+++ /dev/null
@@ -1,2086 +0,0 @@
-/***
-  This file is part of systemd.
-
-  Copyright 2013 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 <getopt.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-internal.h"
-#include "bus-signature.h"
-#include "bus-type.h"
-#include "bus-util.h"
-#include "busctl-introspect.h"
-#include "escape.h"
-#include "fd-util.h"
-#include "locale-util.h"
-#include "log.h"
-#include "pager.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "set.h"
-#include "strv.h"
-#include "terminal-util.h"
-#include "user-util.h"
-#include "util.h"
-
-static bool arg_no_pager = false;
-static bool arg_legend = true;
-static char *arg_address = NULL;
-static bool arg_unique = false;
-static bool arg_acquired = false;
-static bool arg_activatable = false;
-static bool arg_show_machine = false;
-static char **arg_matches = NULL;
-static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static char *arg_host = NULL;
-static bool arg_user = false;
-static size_t arg_snaplen = 4096;
-static bool arg_list = false;
-static bool arg_quiet = false;
-static bool arg_verbose = false;
-static bool arg_expect_reply = true;
-static bool arg_auto_start = true;
-static bool arg_allow_interactive_authorization = true;
-static bool arg_augment_creds = true;
-static usec_t arg_timeout = 0;
-
-#define NAME_IS_ACQUIRED INT_TO_PTR(1)
-#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
-
-static int list_bus_names(sd_bus *bus, char **argv) {
-        _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
-        _cleanup_free_ char **merged = NULL;
-        _cleanup_hashmap_free_ Hashmap *names = NULL;
-        char **i;
-        int r;
-        size_t max_i = 0;
-        unsigned n = 0;
-        void *v;
-        char *k;
-        Iterator iterator;
-
-        assert(bus);
-
-        if (!arg_unique && !arg_acquired && !arg_activatable)
-                arg_unique = arg_acquired = arg_activatable = true;
-
-        r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
-        if (r < 0)
-                return log_error_errno(r, "Failed to list names: %m");
-
-        pager_open(arg_no_pager, false);
-
-        names = hashmap_new(&string_hash_ops);
-        if (!names)
-                return log_oom();
-
-        STRV_FOREACH(i, acquired) {
-                max_i = MAX(max_i, strlen(*i));
-
-                r = hashmap_put(names, *i, NAME_IS_ACQUIRED);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to add to hashmap: %m");
-        }
-
-        STRV_FOREACH(i, activatable) {
-                max_i = MAX(max_i, strlen(*i));
-
-                r = hashmap_put(names, *i, NAME_IS_ACTIVATABLE);
-                if (r < 0 && r != -EEXIST)
-                        return log_error_errno(r, "Failed to add to hashmap: %m");
-        }
-
-        merged = new(char*, hashmap_size(names) + 1);
-        HASHMAP_FOREACH_KEY(v, k, names, iterator)
-                merged[n++] = k;
-
-        merged[n] = NULL;
-        strv_sort(merged);
-
-        if (arg_legend) {
-                printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s",
-                       (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION");
-
-                if (arg_show_machine)
-                        puts(" MACHINE");
-                else
-                        putchar('\n');
-        }
-
-        STRV_FOREACH(i, merged) {
-                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
-                sd_id128_t mid;
-
-                if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) {
-                        /* Activatable */
-
-                        printf("%-*s", (int) max_i, *i);
-                        printf("          - -               -                (activatable) -                         -         ");
-                        if (arg_show_machine)
-                                puts(" -");
-                        else
-                                putchar('\n');
-                        continue;
-
-                }
-
-                if (!arg_unique && (*i)[0] == ':')
-                        continue;
-
-                if (!arg_acquired && (*i)[0] != ':')
-                        continue;
-
-                printf("%-*s", (int) max_i, *i);
-
-                r = sd_bus_get_name_creds(
-                                bus, *i,
-                                (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) |
-                                SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|
-                                SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION|
-                                SD_BUS_CREDS_DESCRIPTION, &creds);
-                if (r >= 0) {
-                        const char *unique, *session, *unit, *cn;
-                        pid_t pid;
-                        uid_t uid;
-
-                        r = sd_bus_creds_get_pid(creds, &pid);
-                        if (r >= 0) {
-                                const char *comm = NULL;
-
-                                sd_bus_creds_get_comm(creds, &comm);
-
-                                printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
-                        } else
-                                fputs("          - -              ", stdout);
-
-                        r = sd_bus_creds_get_euid(creds, &uid);
-                        if (r >= 0) {
-                                _cleanup_free_ char *u = NULL;
-
-                                u = uid_to_name(uid);
-                                if (!u)
-                                        return log_oom();
-
-                                if (strlen(u) > 16)
-                                        u[16] = 0;
-
-                                printf(" %-16s", u);
-                        } else
-                                fputs(" -               ", stdout);
-
-                        r = sd_bus_creds_get_unique_name(creds, &unique);
-                        if (r >= 0)
-                                printf(" %-13s", unique);
-                        else
-                                fputs(" -            ", stdout);
-
-                        r = sd_bus_creds_get_unit(creds, &unit);
-                        if (r >= 0) {
-                                _cleanup_free_ char *e;
-
-                                e = ellipsize(unit, 25, 100);
-                                if (!e)
-                                        return log_oom();
-
-                                printf(" %-25s", e);
-                        } else
-                                fputs(" -                        ", stdout);
-
-                        r = sd_bus_creds_get_session(creds, &session);
-                        if (r >= 0)
-                                printf(" %-10s", session);
-                        else
-                                fputs(" -         ", stdout);
-
-                        r = sd_bus_creds_get_description(creds, &cn);
-                        if (r >= 0)
-                                printf(" %-19s", cn);
-                        else
-                                fputs(" -                  ", stdout);
-
-                } else
-                        printf("          - -               -                -             -                         -          -                  ");
-
-                if (arg_show_machine) {
-                        r = sd_bus_get_name_machine_id(bus, *i, &mid);
-                        if (r >= 0) {
-                                char m[SD_ID128_STRING_MAX];
-                                printf(" %s\n", sd_id128_to_string(mid, m));
-                        } else
-                                puts(" -");
-                } else
-                        putchar('\n');
-        }
-
-        return 0;
-}
-
-static void print_subtree(const char *prefix, const char *path, char **l) {
-        const char *vertical, *space;
-        char **n;
-
-        /* We assume the list is sorted. Let's first skip over the
-         * entry we are looking at. */
-        for (;;) {
-                if (!*l)
-                        return;
-
-                if (!streq(*l, path))
-                        break;
-
-                l++;
-        }
-
-        vertical = strjoina(prefix, special_glyph(TREE_VERTICAL));
-        space = strjoina(prefix, special_glyph(TREE_SPACE));
-
-        for (;;) {
-                bool has_more = false;
-
-                if (!*l || !path_startswith(*l, path))
-                        break;
-
-                n = l + 1;
-                for (;;) {
-                        if (!*n || !path_startswith(*n, path))
-                                break;
-
-                        if (!path_startswith(*n, *l)) {
-                                has_more = true;
-                                break;
-                        }
-
-                        n++;
-                }
-
-                printf("%s%s%s\n", prefix, special_glyph(has_more ? TREE_BRANCH : TREE_RIGHT), *l);
-
-                print_subtree(has_more ? vertical : space, *l, l);
-                l = n;
-        }
-}
-
-static void print_tree(const char *prefix, char **l) {
-
-        pager_open(arg_no_pager, false);
-
-        prefix = strempty(prefix);
-
-        if (arg_list) {
-                char **i;
-
-                STRV_FOREACH(i, l)
-                        printf("%s%s\n", prefix, *i);
-                return;
-        }
-
-        if (strv_isempty(l)) {
-                printf("No objects discovered.\n");
-                return;
-        }
-
-        if (streq(l[0], "/") && !l[1]) {
-                printf("Only root object discovered.\n");
-                return;
-        }
-
-        print_subtree(prefix, "/", l);
-}
-
-static int on_path(const char *path, void *userdata) {
-        Set *paths = userdata;
-        int r;
-
-        assert(paths);
-
-        r = set_put_strdup(paths, path);
-        if (r < 0)
-                return log_oom();
-
-        return 0;
-}
-
-static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) {
-        static const XMLIntrospectOps ops = {
-                .on_path = on_path,
-        };
-
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        const char *xml;
-        int r;
-
-        r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
-        if (r < 0) {
-                if (many)
-                        printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r));
-                else
-                        log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
-                return r;
-        }
-
-        r = sd_bus_message_read(reply, "s", &xml);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        return parse_xml_introspect(path, xml, &ops, paths);
-}
-
-static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) {
-        _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
-        _cleanup_free_ char **l = NULL;
-        char *m;
-        int r;
-
-        paths = set_new(&string_hash_ops);
-        if (!paths)
-                return log_oom();
-
-        done = set_new(&string_hash_ops);
-        if (!done)
-                return log_oom();
-
-        failed = set_new(&string_hash_ops);
-        if (!failed)
-                return log_oom();
-
-        m = strdup("/");
-        if (!m)
-                return log_oom();
-
-        r = set_put(paths, m);
-        if (r < 0) {
-                free(m);
-                return log_oom();
-        }
-
-        for (;;) {
-                _cleanup_free_ char *p = NULL;
-                int q;
-
-                p = set_steal_first(paths);
-                if (!p)
-                        break;
-
-                if (set_contains(done, p) ||
-                    set_contains(failed, p))
-                        continue;
-
-                q = find_nodes(bus, service, p, paths, many);
-                if (q < 0) {
-                        if (r >= 0)
-                                r = q;
-
-                        q = set_put(failed, p);
-                } else
-                        q = set_put(done, p);
-
-                if (q < 0)
-                        return log_oom();
-
-                assert(q != 0);
-                p = NULL;
-        }
-
-        pager_open(arg_no_pager, false);
-
-        l = set_get_strv(done);
-        if (!l)
-                return log_oom();
-
-        strv_sort(l);
-        print_tree(prefix, l);
-
-        fflush(stdout);
-
-        return r;
-}
-
-static int tree(sd_bus *bus, char **argv) {
-        char **i;
-        int r = 0;
-
-        if (!arg_unique && !arg_acquired)
-                arg_acquired = true;
-
-        if (strv_length(argv) <= 1) {
-                _cleanup_strv_free_ char **names = NULL;
-                bool not_first = false;
-
-                r = sd_bus_list_names(bus, &names, NULL);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to get name list: %m");
-
-                pager_open(arg_no_pager, false);
-
-                STRV_FOREACH(i, names) {
-                        int q;
-
-                        if (!arg_unique && (*i)[0] == ':')
-                                continue;
-
-                        if (!arg_acquired && (*i)[0] == ':')
-                                continue;
-
-                        if (not_first)
-                                printf("\n");
-
-                        printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
-
-                        q = tree_one(bus, *i, NULL, true);
-                        if (q < 0 && r >= 0)
-                                r = q;
-
-                        not_first = true;
-                }
-        } else {
-                STRV_FOREACH(i, argv+1) {
-                        int q;
-
-                        if (i > argv+1)
-                                printf("\n");
-
-                        if (argv[2]) {
-                                pager_open(arg_no_pager, false);
-                                printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
-                        }
-
-                        q = tree_one(bus, *i, NULL, !!argv[2]);
-                        if (q < 0 && r >= 0)
-                                r = q;
-                }
-        }
-
-        return r;
-}
-
-static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
-        int r;
-
-        for (;;) {
-                const char *contents = NULL;
-                char type;
-                union {
-                        uint8_t u8;
-                        uint16_t u16;
-                        int16_t s16;
-                        uint32_t u32;
-                        int32_t s32;
-                        uint64_t u64;
-                        int64_t s64;
-                        double d64;
-                        const char *string;
-                        int i;
-                } basic;
-
-                r = sd_bus_message_peek_type(m, &type, &contents);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        return needs_space;
-
-                if (bus_type_is_container(type) > 0) {
-
-                        r = sd_bus_message_enter_container(m, type, contents);
-                        if (r < 0)
-                                return r;
-
-                        if (type == SD_BUS_TYPE_ARRAY) {
-                                unsigned n = 0;
-
-                                /* count array entries */
-                                for (;;) {
-
-                                        r = sd_bus_message_skip(m, contents);
-                                        if (r < 0)
-                                                return r;
-                                        if (r == 0)
-                                                break;
-
-                                        n++;
-                                }
-
-                                r = sd_bus_message_rewind(m, false);
-                                if (r < 0)
-                                        return r;
-
-                                if (needs_space)
-                                        fputc(' ', f);
-
-                                fprintf(f, "%u", n);
-                                needs_space = true;
-
-                        } else if (type == SD_BUS_TYPE_VARIANT) {
-
-                                if (needs_space)
-                                        fputc(' ', f);
-
-                                fprintf(f, "%s", contents);
-                                needs_space = true;
-                        }
-
-                        r = format_cmdline(m, f, needs_space);
-                        if (r < 0)
-                                return r;
-
-                        needs_space = r > 0;
-
-                        r = sd_bus_message_exit_container(m);
-                        if (r < 0)
-                                return r;
-
-                        continue;
-                }
-
-                r = sd_bus_message_read_basic(m, type, &basic);
-                if (r < 0)
-                        return r;
-
-                if (needs_space)
-                        fputc(' ', f);
-
-                switch (type) {
-                case SD_BUS_TYPE_BYTE:
-                        fprintf(f, "%u", basic.u8);
-                        break;
-
-                case SD_BUS_TYPE_BOOLEAN:
-                        fputs(true_false(basic.i), f);
-                        break;
-
-                case SD_BUS_TYPE_INT16:
-                        fprintf(f, "%i", basic.s16);
-                        break;
-
-                case SD_BUS_TYPE_UINT16:
-                        fprintf(f, "%u", basic.u16);
-                        break;
-
-                case SD_BUS_TYPE_INT32:
-                        fprintf(f, "%i", basic.s32);
-                        break;
-
-                case SD_BUS_TYPE_UINT32:
-                        fprintf(f, "%u", basic.u32);
-                        break;
-
-                case SD_BUS_TYPE_INT64:
-                        fprintf(f, "%" PRIi64, basic.s64);
-                        break;
-
-                case SD_BUS_TYPE_UINT64:
-                        fprintf(f, "%" PRIu64, basic.u64);
-                        break;
-
-                case SD_BUS_TYPE_DOUBLE:
-                        fprintf(f, "%g", basic.d64);
-                        break;
-
-                case SD_BUS_TYPE_STRING:
-                case SD_BUS_TYPE_OBJECT_PATH:
-                case SD_BUS_TYPE_SIGNATURE: {
-                        _cleanup_free_ char *b = NULL;
-
-                        b = cescape(basic.string);
-                        if (!b)
-                                return -ENOMEM;
-
-                        fprintf(f, "\"%s\"", b);
-                        break;
-                }
-
-                case SD_BUS_TYPE_UNIX_FD:
-                        fprintf(f, "%i", basic.i);
-                        break;
-
-                default:
-                        assert_not_reached("Unknown basic type.");
-                }
-
-                needs_space = true;
-        }
-}
-
-typedef struct Member {
-        const char *type;
-        char *interface;
-        char *name;
-        char *signature;
-        char *result;
-        char *value;
-        bool writable;
-        uint64_t flags;
-} Member;
-
-static void member_hash_func(const void *p, struct siphash *state) {
-        const Member *m = p;
-        uint64_t arity = 1;
-
-        assert(m);
-        assert(m->type);
-
-        string_hash_func(m->type, state);
-
-        arity += !!m->name + !!m->interface;
-
-        uint64_hash_func(&arity, state);
-
-        if (m->name)
-                string_hash_func(m->name, state);
-
-        if (m->interface)
-                string_hash_func(m->interface, state);
-}
-
-static int member_compare_func(const void *a, const void *b) {
-        const Member *x = a, *y = b;
-        int d;
-
-        assert(x);
-        assert(y);
-        assert(x->type);
-        assert(y->type);
-
-        d = strcmp_ptr(x->interface, y->interface);
-        if (d != 0)
-                return d;
-
-        d = strcmp(x->type, y->type);
-        if (d != 0)
-                return d;
-
-        return strcmp_ptr(x->name, y->name);
-}
-
-static int member_compare_funcp(const void *a, const void *b) {
-        const Member *const * x = (const Member *const *) a, * const *y = (const Member *const *) b;
-
-        return member_compare_func(*x, *y);
-}
-
-static void member_free(Member *m) {
-        if (!m)
-                return;
-
-        free(m->interface);
-        free(m->name);
-        free(m->signature);
-        free(m->result);
-        free(m->value);
-        free(m);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
-
-static void member_set_free(Set *s) {
-        Member *m;
-
-        while ((m = set_steal_first(s)))
-                member_free(m);
-
-        set_free(s);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
-
-static int on_interface(const char *interface, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
-        Set *members = userdata;
-        int r;
-
-        assert(interface);
-        assert(members);
-
-        m = new0(Member, 1);
-        if (!m)
-                return log_oom();
-
-        m->type = "interface";
-        m->flags = flags;
-
-        r = free_and_strdup(&m->interface, interface);
-        if (r < 0)
-                return log_oom();
-
-        r = set_put(members, m);
-        if (r <= 0) {
-                log_error("Duplicate interface");
-                return -EINVAL;
-        }
-
-        m = NULL;
-        return 0;
-}
-
-static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
-        Set *members = userdata;
-        int r;
-
-        assert(interface);
-        assert(name);
-
-        m = new0(Member, 1);
-        if (!m)
-                return log_oom();
-
-        m->type = "method";
-        m->flags = flags;
-
-        r = free_and_strdup(&m->interface, interface);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->name, name);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->signature, signature);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->result, result);
-        if (r < 0)
-                return log_oom();
-
-        r = set_put(members, m);
-        if (r <= 0) {
-                log_error("Duplicate method");
-                return -EINVAL;
-        }
-
-        m = NULL;
-        return 0;
-}
-
-static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
-        Set *members = userdata;
-        int r;
-
-        assert(interface);
-        assert(name);
-
-        m = new0(Member, 1);
-        if (!m)
-                return log_oom();
-
-        m->type = "signal";
-        m->flags = flags;
-
-        r = free_and_strdup(&m->interface, interface);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->name, name);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->signature, signature);
-        if (r < 0)
-                return log_oom();
-
-        r = set_put(members, m);
-        if (r <= 0) {
-                log_error("Duplicate signal");
-                return -EINVAL;
-        }
-
-        m = NULL;
-        return 0;
-}
-
-static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) {
-        _cleanup_(member_freep) Member *m;
-        Set *members = userdata;
-        int r;
-
-        assert(interface);
-        assert(name);
-
-        m = new0(Member, 1);
-        if (!m)
-                return log_oom();
-
-        m->type = "property";
-        m->flags = flags;
-        m->writable = writable;
-
-        r = free_and_strdup(&m->interface, interface);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->name, name);
-        if (r < 0)
-                return log_oom();
-
-        r = free_and_strdup(&m->signature, signature);
-        if (r < 0)
-                return log_oom();
-
-        r = set_put(members, m);
-        if (r <= 0) {
-                log_error("Duplicate property");
-                return -EINVAL;
-        }
-
-        m = NULL;
-        return 0;
-}
-
-static const char *strdash(const char *x) {
-        return isempty(x) ? "-" : x;
-}
-
-static int introspect(sd_bus *bus, char **argv) {
-        static const struct hash_ops member_hash_ops = {
-                .hash = member_hash_func,
-                .compare = member_compare_func,
-        };
-
-        static const XMLIntrospectOps ops = {
-                .on_interface = on_interface,
-                .on_method = on_method,
-                .on_signal = on_signal,
-                .on_property = on_property,
-        };
-
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(member_set_freep) Set *members = NULL;
-        Iterator i;
-        Member *m;
-        const char *xml;
-        int r;
-        unsigned name_width,  type_width, signature_width, result_width;
-        Member **sorted = NULL;
-        unsigned k = 0, j, n_args;
-
-        n_args = strv_length(argv);
-        if (n_args < 3) {
-                log_error("Requires service and object path argument.");
-                return -EINVAL;
-        }
-
-        if (n_args > 4) {
-                log_error("Too many arguments.");
-                return -EINVAL;
-        }
-
-        members = set_new(&member_hash_ops);
-        if (!members)
-                return log_oom();
-
-        r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
-        if (r < 0) {
-                log_error("Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r));
-                return r;
-        }
-
-        r = sd_bus_message_read(reply, "s", &xml);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        /* First, get list of all properties */
-        r = parse_xml_introspect(argv[2], xml, &ops, members);
-        if (r < 0)
-                return r;
-
-        /* Second, find the current values for them */
-        SET_FOREACH(m, members, i) {
-
-                if (!streq(m->type, "property"))
-                        continue;
-
-                if (m->value)
-                        continue;
-
-                if (argv[3] && !streq(argv[3], m->interface))
-                        continue;
-
-                r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface);
-                if (r < 0) {
-                        log_error("%s", bus_error_message(&error, r));
-                        return r;
-                }
-
-                r = sd_bus_message_enter_container(reply, 'a', "{sv}");
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                for (;;) {
-                        Member *z;
-                        _cleanup_free_ char *buf = NULL;
-                        _cleanup_fclose_ FILE *mf = NULL;
-                        size_t sz = 0;
-                        const char *name;
-
-                        r = sd_bus_message_enter_container(reply, 'e', "sv");
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        if (r == 0)
-                                break;
-
-                        r = sd_bus_message_read(reply, "s", &name);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        r = sd_bus_message_enter_container(reply, 'v', NULL);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        mf = open_memstream(&buf, &sz);
-                        if (!mf)
-                                return log_oom();
-
-                        r = format_cmdline(reply, mf, false);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        fclose(mf);
-                        mf = NULL;
-
-                        z = set_get(members, &((Member) {
-                                                .type = "property",
-                                                .interface = m->interface,
-                                                .name = (char*) name }));
-                        if (z) {
-                                free(z->value);
-                                z->value = buf;
-                                buf = NULL;
-                        }
-
-                        r = sd_bus_message_exit_container(reply);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        r = sd_bus_message_exit_container(reply);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-                }
-
-                r = sd_bus_message_exit_container(reply);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-        }
-
-        pager_open(arg_no_pager, false);
-
-        name_width = strlen("NAME");
-        type_width = strlen("TYPE");
-        signature_width = strlen("SIGNATURE");
-        result_width = strlen("RESULT/VALUE");
-
-        sorted = newa(Member*, set_size(members));
-
-        SET_FOREACH(m, members, i) {
-
-                if (argv[3] && !streq(argv[3], m->interface))
-                        continue;
-
-                if (m->interface)
-                        name_width = MAX(name_width, strlen(m->interface));
-                if (m->name)
-                        name_width = MAX(name_width, strlen(m->name) + 1);
-                if (m->type)
-                        type_width = MAX(type_width, strlen(m->type));
-                if (m->signature)
-                        signature_width = MAX(signature_width, strlen(m->signature));
-                if (m->result)
-                        result_width = MAX(result_width, strlen(m->result));
-                if (m->value)
-                        result_width = MAX(result_width, strlen(m->value));
-
-                sorted[k++] = m;
-        }
-
-        if (result_width > 40)
-                result_width = 40;
-
-        qsort(sorted, k, sizeof(Member*), member_compare_funcp);
-
-        if (arg_legend) {
-                printf("%-*s %-*s %-*s %-*s %s\n",
-                       (int) name_width, "NAME",
-                       (int) type_width, "TYPE",
-                       (int) signature_width, "SIGNATURE",
-                       (int) result_width, "RESULT/VALUE",
-                       "FLAGS");
-        }
-
-        for (j = 0; j < k; j++) {
-                _cleanup_free_ char *ellipsized = NULL;
-                const char *rv;
-                bool is_interface;
-
-                m = sorted[j];
-
-                if (argv[3] && !streq(argv[3], m->interface))
-                        continue;
-
-                is_interface = streq(m->type, "interface");
-
-                if (argv[3] && is_interface)
-                        continue;
-
-                if (m->value) {
-                        ellipsized = ellipsize(m->value, result_width, 100);
-                        if (!ellipsized)
-                                return log_oom();
-
-                        rv = ellipsized;
-                } else
-                        rv = strdash(m->result);
-
-                printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
-                       is_interface ? ansi_highlight() : "",
-                       is_interface ? "" : ".",
-                       - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
-                       is_interface ? ansi_normal() : "",
-                       (int) type_width, strdash(m->type),
-                       (int) signature_width, strdash(m->signature),
-                       (int) result_width, rv,
-                       (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"),
-                       (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "",
-                       (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "",
-                       (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "",
-                       (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "",
-                       m->writable ? " writable" : "");
-        }
-
-        return 0;
-}
-
-static int message_dump(sd_bus_message *m, FILE *f) {
-        return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER);
-}
-
-static int message_pcap(sd_bus_message *m, FILE *f) {
-        return bus_message_pcap_frame(m, arg_snaplen, f);
-}
-
-static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        char **i;
-        uint32_t flags = 0;
-        int r;
-
-        /* upgrade connection; it's not used for anything else after this call */
-        r = sd_bus_message_new_method_call(bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_open_container(message, 'a', "s");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        STRV_FOREACH(i, argv+1) {
-                _cleanup_free_ char *m = NULL;
-
-                if (!service_name_is_valid(*i)) {
-                        log_error("Invalid service name '%s'", *i);
-                        return -EINVAL;
-                }
-
-                m = strjoin("sender='", *i, "'");
-                if (!m)
-                        return log_oom();
-
-                r = sd_bus_message_append_basic(message, 's', m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                free(m);
-                m = strjoin("destination='", *i, "'");
-                if (!m)
-                        return log_oom();
-
-                r = sd_bus_message_append_basic(message, 's', m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-        }
-
-        STRV_FOREACH(i, arg_matches) {
-                r = sd_bus_message_append_basic(message, 's', *i);
-                if (r < 0)
-                        return bus_log_create_error(r);
-        }
-
-        r = sd_bus_message_close_container(message);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append_basic(message, 'u', &flags);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_call(bus, message, arg_timeout, &error, NULL);
-        if (r < 0) {
-                log_error("%s", bus_error_message(&error, r));
-                return r;
-        }
-
-        log_info("Monitoring bus message stream.");
-
-        for (;;) {
-                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
-                r = sd_bus_process(bus, &m);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to process bus: %m");
-
-                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.");
-                                return 0;
-                        }
-
-                        continue;
-                }
-
-                if (r > 0)
-                        continue;
-
-                r = sd_bus_wait(bus, (uint64_t) -1);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to wait for bus: %m");
-        }
-}
-
-static int capture(sd_bus *bus, char *argv[]) {
-        int r;
-
-        if (isatty(fileno(stdout)) > 0) {
-                log_error("Refusing to write message data to console, please redirect output to a file.");
-                return -EINVAL;
-        }
-
-        bus_pcap_header(arg_snaplen, stdout);
-
-        r = monitor(bus, argv, message_pcap);
-        if (r < 0)
-                return r;
-
-        if (ferror(stdout)) {
-                log_error("Couldn't write capture file.");
-                return -EIO;
-        }
-
-        return r;
-}
-
-static int status(sd_bus *bus, char *argv[]) {
-        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
-        pid_t pid;
-        int r;
-
-        assert(bus);
-
-        if (strv_length(argv) > 2) {
-                log_error("Expects no or one argument.");
-                return -EINVAL;
-        }
-
-        if (argv[1]) {
-                r = parse_pid(argv[1], &pid);
-                if (r < 0)
-                        r = sd_bus_get_name_creds(
-                                        bus,
-                                        argv[1],
-                                        (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL,
-                                        &creds);
-                else
-                        r = sd_bus_creds_new_from_pid(
-                                        &creds,
-                                        pid,
-                                        _SD_BUS_CREDS_ALL);
-        } else {
-                const char *scope, *address;
-                sd_id128_t bus_id;
-
-                r = sd_bus_get_address(bus, &address);
-                if (r >= 0)
-                        printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_normal());
-
-                r = sd_bus_get_scope(bus, &scope);
-                if (r >= 0)
-                        printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_normal());
-
-                r = sd_bus_get_bus_id(bus, &bus_id);
-                if (r >= 0)
-                        printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal());
-
-                r = sd_bus_get_owner_creds(
-                                bus,
-                                (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL,
-                                &creds);
-        }
-
-        if (r < 0)
-                return log_error_errno(r, "Failed to get credentials: %m");
-
-        bus_creds_dump(creds, NULL, false);
-        return 0;
-}
-
-static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) {
-        char **p;
-        int r;
-
-        assert(m);
-        assert(signature);
-        assert(x);
-
-        p = *x;
-
-        for (;;) {
-                const char *v;
-                char t;
-
-                t = *signature;
-                v = *p;
-
-                if (t == 0)
-                        break;
-                if (!v) {
-                        log_error("Too few parameters for signature.");
-                        return -EINVAL;
-                }
-
-                signature++;
-                p++;
-
-                switch (t) {
-
-                case SD_BUS_TYPE_BOOLEAN:
-
-                        r = parse_boolean(v);
-                        if (r < 0) {
-                                log_error("Failed to parse as boolean: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &r);
-                        break;
-
-                case SD_BUS_TYPE_BYTE: {
-                        uint8_t z;
-
-                        r = safe_atou8(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as byte (unsigned 8bit integer): %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_INT16: {
-                        int16_t z;
-
-                        r = safe_atoi16(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as signed 16bit integer: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_UINT16: {
-                        uint16_t z;
-
-                        r = safe_atou16(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as unsigned 16bit integer: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_INT32: {
-                        int32_t z;
-
-                        r = safe_atoi32(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as signed 32bit integer: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_UINT32: {
-                        uint32_t z;
-
-                        r = safe_atou32(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as unsigned 32bit integer: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_INT64: {
-                        int64_t z;
-
-                        r = safe_atoi64(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as signed 64bit integer: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_UINT64: {
-                        uint64_t z;
-
-                        r = safe_atou64(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as unsigned 64bit integer: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-
-                case SD_BUS_TYPE_DOUBLE: {
-                        double z;
-
-                        r = safe_atod(v, &z);
-                        if (r < 0) {
-                                log_error("Failed to parse as double precision floating point: %s", v);
-                                return r;
-                        }
-
-                        r = sd_bus_message_append_basic(m, t, &z);
-                        break;
-                }
-
-                case SD_BUS_TYPE_STRING:
-                case SD_BUS_TYPE_OBJECT_PATH:
-                case SD_BUS_TYPE_SIGNATURE:
-
-                        r = sd_bus_message_append_basic(m, t, v);
-                        break;
-
-                case SD_BUS_TYPE_ARRAY: {
-                        uint32_t n;
-                        size_t k;
-
-                        r = safe_atou32(v, &n);
-                        if (r < 0) {
-                                log_error("Failed to parse number of array entries: %s", v);
-                                return r;
-                        }
-
-                        r = signature_element_length(signature, &k);
-                        if (r < 0) {
-                                log_error("Invalid array signature.");
-                                return r;
-                        }
-
-                        {
-                                unsigned i;
-                                char s[k + 1];
-                                memcpy(s, signature, k);
-                                s[k] = 0;
-
-                                r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
-                                if (r < 0)
-                                        return bus_log_create_error(r);
-
-                                for (i = 0; i < n; i++) {
-                                        r = message_append_cmdline(m, s, &p);
-                                        if (r < 0)
-                                                return r;
-                                }
-                        }
-
-                        signature += k;
-
-                        r = sd_bus_message_close_container(m);
-                        break;
-                }
-
-                case SD_BUS_TYPE_VARIANT:
-                        r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
-                        r = message_append_cmdline(m, v, &p);
-                        if (r < 0)
-                                return r;
-
-                        r = sd_bus_message_close_container(m);
-                        break;
-
-                case SD_BUS_TYPE_STRUCT_BEGIN:
-                case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
-                        size_t k;
-
-                        signature--;
-                        p--;
-
-                        r = signature_element_length(signature, &k);
-                        if (r < 0) {
-                                log_error("Invalid struct/dict entry signature.");
-                                return r;
-                        }
-
-                        {
-                                char s[k-1];
-                                memcpy(s, signature + 1, k - 2);
-                                s[k - 2] = 0;
-
-                                r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
-                                if (r < 0)
-                                        return bus_log_create_error(r);
-
-                                r = message_append_cmdline(m, s, &p);
-                                if (r < 0)
-                                        return r;
-                        }
-
-                        signature += k;
-
-                        r = sd_bus_message_close_container(m);
-                        break;
-                }
-
-                case SD_BUS_TYPE_UNIX_FD:
-                        log_error("UNIX file descriptor not supported as type.");
-                        return -EINVAL;
-
-                default:
-                        log_error("Unknown signature type %c.", t);
-                        return -EINVAL;
-                }
-
-                if (r < 0)
-                        return bus_log_create_error(r);
-        }
-
-        *x = p;
-        return 0;
-}
-
-static int call(sd_bus *bus, char *argv[]) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
-        int r;
-
-        assert(bus);
-
-        if (strv_length(argv) < 5) {
-                log_error("Expects at least four arguments.");
-                return -EINVAL;
-        }
-
-        r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_set_expect_reply(m, arg_expect_reply);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_set_auto_start(m, arg_auto_start);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_set_allow_interactive_authorization(m, arg_allow_interactive_authorization);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        if (!isempty(argv[5])) {
-                char **p;
-
-                p = argv+6;
-
-                r = message_append_cmdline(m, argv[5], &p);
-                if (r < 0)
-                        return r;
-
-                if (*p) {
-                        log_error("Too many parameters for signature.");
-                        return -EINVAL;
-                }
-        }
-
-        if (!arg_expect_reply) {
-                r = sd_bus_send(bus, m, NULL);
-                if (r < 0) {
-                        log_error("Failed to send message.");
-                        return r;
-                }
-
-                return 0;
-        }
-
-        r = sd_bus_call(bus, m, arg_timeout, &error, &reply);
-        if (r < 0) {
-                log_error("%s", bus_error_message(&error, r));
-                return r;
-        }
-
-        r = sd_bus_message_is_empty(reply);
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        if (r == 0 && !arg_quiet) {
-
-                if (arg_verbose) {
-                        pager_open(arg_no_pager, false);
-
-                        r = bus_message_dump(reply, stdout, 0);
-                        if (r < 0)
-                                return r;
-                } else {
-
-                        fputs(sd_bus_message_get_signature(reply, true), stdout);
-                        fputc(' ', stdout);
-
-                        r = format_cmdline(reply, stdout, false);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        fputc('\n', stdout);
-                }
-        }
-
-        return 0;
-}
-
-static int get_property(sd_bus *bus, char *argv[]) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned n;
-        char **i;
-        int r;
-
-        assert(bus);
-
-        n = strv_length(argv);
-        if (n < 5) {
-                log_error("Expects at least four arguments.");
-                return -EINVAL;
-        }
-
-        STRV_FOREACH(i, argv + 4) {
-                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-                const char *contents = NULL;
-                char type;
-
-                r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i);
-                if (r < 0) {
-                        log_error("%s", bus_error_message(&error, r));
-                        return r;
-                }
-
-                r = sd_bus_message_peek_type(reply, &type, &contents);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                r = sd_bus_message_enter_container(reply, 'v', contents);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                if (arg_verbose)  {
-                        pager_open(arg_no_pager, false);
-
-                        r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
-                        if (r < 0)
-                                return r;
-                } else {
-                        fputs(contents, stdout);
-                        fputc(' ', stdout);
-
-                        r = format_cmdline(reply, stdout, false);
-                        if (r < 0)
-                                return bus_log_parse_error(r);
-
-                        fputc('\n', stdout);
-                }
-
-                r = sd_bus_message_exit_container(reply);
-                if (r < 0)
-                        return bus_log_parse_error(r);
-        }
-
-        return 0;
-}
-
-static int set_property(sd_bus *bus, char *argv[]) {
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        unsigned n;
-        char **p;
-        int r;
-
-        assert(bus);
-
-        n = strv_length(argv);
-        if (n < 6) {
-                log_error("Expects at least five arguments.");
-                return -EINVAL;
-        }
-
-        r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set");
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_append(m, "ss", argv[3], argv[4]);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        r = sd_bus_message_open_container(m, 'v', argv[5]);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        p = argv+6;
-        r = message_append_cmdline(m, argv[5], &p);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_close_container(m);
-        if (r < 0)
-                return bus_log_create_error(r);
-
-        if (*p) {
-                log_error("Too many parameters for signature.");
-                return -EINVAL;
-        }
-
-        r = sd_bus_call(bus, m, arg_timeout, &error, NULL);
-        if (r < 0) {
-                log_error("%s", bus_error_message(&error, r));
-                return r;
-        }
-
-        return 0;
-}
-
-static int help(void) {
-        printf("%s [OPTIONS...] {COMMAND} ...\n\n"
-               "Introspect the bus.\n\n"
-               "  -h --help               Show this help\n"
-               "     --version            Show package version\n"
-               "     --no-pager           Do not pipe output into a pager\n"
-               "     --no-legend          Do not show the headers and footers\n"
-               "     --system             Connect to system bus\n"
-               "     --user               Connect to user bus\n"
-               "  -H --host=[USER@]HOST   Operate on remote host\n"
-               "  -M --machine=CONTAINER  Operate on local container\n"
-               "     --address=ADDRESS    Connect to bus specified by address\n"
-               "     --show-machine       Show machine ID column in list\n"
-               "     --unique             Only show unique names\n"
-               "     --acquired           Only show acquired names\n"
-               "     --activatable        Only show activatable names\n"
-               "     --match=MATCH        Only show matching messages\n"
-               "     --size=SIZE          Maximum length of captured packet\n"
-               "     --list               Don't show tree, but simple object path list\n"
-               "     --quiet              Don't show method call reply\n"
-               "     --verbose            Show result values in long format\n"
-               "     --expect-reply=BOOL  Expect a method call reply\n"
-               "     --auto-start=BOOL    Auto-start destination service\n"
-               "     --allow-interactive-authorization=BOOL\n"
-               "                          Allow interactive authorization for operation\n"
-               "     --timeout=SECS       Maximum time to wait for method call completion\n"
-               "     --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n"
-               "Commands:\n"
-               "  list                    List bus names\n"
-               "  status [SERVICE]        Show bus service, process or bus owner credentials\n"
-               "  monitor [SERVICE...]    Show bus traffic\n"
-               "  capture [SERVICE...]    Capture bus traffic as pcap\n"
-               "  tree [SERVICE...]       Show object tree of service\n"
-               "  introspect SERVICE OBJECT [INTERFACE]\n"
-               "  call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
-               "                          Call a method\n"
-               "  get-property SERVICE OBJECT INTERFACE PROPERTY...\n"
-               "                          Get property value\n"
-               "  set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n"
-               "                          Set property value\n"
-               "  help                    Show this help\n"
-               , program_invocation_short_name);
-
-        return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_NO_PAGER,
-                ARG_NO_LEGEND,
-                ARG_SYSTEM,
-                ARG_USER,
-                ARG_ADDRESS,
-                ARG_MATCH,
-                ARG_SHOW_MACHINE,
-                ARG_UNIQUE,
-                ARG_ACQUIRED,
-                ARG_ACTIVATABLE,
-                ARG_SIZE,
-                ARG_LIST,
-                ARG_VERBOSE,
-                ARG_EXPECT_REPLY,
-                ARG_AUTO_START,
-                ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
-                ARG_TIMEOUT,
-                ARG_AUGMENT_CREDS,
-        };
-
-        static const struct option options[] = {
-                { "help",         no_argument,       NULL, 'h'              },
-                { "version",      no_argument,       NULL, ARG_VERSION      },
-                { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
-                { "no-legend",    no_argument,       NULL, ARG_NO_LEGEND    },
-                { "system",       no_argument,       NULL, ARG_SYSTEM       },
-                { "user",         no_argument,       NULL, ARG_USER         },
-                { "address",      required_argument, NULL, ARG_ADDRESS      },
-                { "show-machine", no_argument,       NULL, ARG_SHOW_MACHINE },
-                { "unique",       no_argument,       NULL, ARG_UNIQUE       },
-                { "acquired",     no_argument,       NULL, ARG_ACQUIRED     },
-                { "activatable",  no_argument,       NULL, ARG_ACTIVATABLE  },
-                { "match",        required_argument, NULL, ARG_MATCH        },
-                { "host",         required_argument, NULL, 'H'              },
-                { "machine",      required_argument, NULL, 'M'              },
-                { "size",         required_argument, NULL, ARG_SIZE         },
-                { "list",         no_argument,       NULL, ARG_LIST         },
-                { "quiet",        no_argument,       NULL, 'q'              },
-                { "verbose",      no_argument,       NULL, ARG_VERBOSE      },
-                { "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY },
-                { "auto-start",   required_argument, NULL, ARG_AUTO_START   },
-                { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
-                { "timeout",      required_argument, NULL, ARG_TIMEOUT      },
-                { "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS},
-                {},
-        };
-
-        int c, r;
-
-        assert(argc >= 0);
-        assert(argv);
-
-        while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0)
-
-                switch (c) {
-
-                case 'h':
-                        return help();
-
-                case ARG_VERSION:
-                        return version();
-
-                case ARG_NO_PAGER:
-                        arg_no_pager = true;
-                        break;
-
-                case ARG_NO_LEGEND:
-                        arg_legend = false;
-                        break;
-
-                case ARG_USER:
-                        arg_user = true;
-                        break;
-
-                case ARG_SYSTEM:
-                        arg_user = false;
-                        break;
-
-                case ARG_ADDRESS:
-                        arg_address = optarg;
-                        break;
-
-                case ARG_SHOW_MACHINE:
-                        arg_show_machine = true;
-                        break;
-
-                case ARG_UNIQUE:
-                        arg_unique = true;
-                        break;
-
-                case ARG_ACQUIRED:
-                        arg_acquired = true;
-                        break;
-
-                case ARG_ACTIVATABLE:
-                        arg_activatable = true;
-                        break;
-
-                case ARG_MATCH:
-                        if (strv_extend(&arg_matches, optarg) < 0)
-                                return log_oom();
-                        break;
-
-                case ARG_SIZE: {
-                        uint64_t sz;
-
-                        r = parse_size(optarg, 1024, &sz);
-                        if (r < 0) {
-                                log_error("Failed to parse size: %s", optarg);
-                                return r;
-                        }
-
-                        if ((uint64_t) (size_t) sz !=  sz) {
-                                log_error("Size out of range.");
-                                return -E2BIG;
-                        }
-
-                        arg_snaplen = (size_t) sz;
-                        break;
-                }
-
-                case ARG_LIST:
-                        arg_list = true;
-                        break;
-
-                case 'H':
-                        arg_transport = BUS_TRANSPORT_REMOTE;
-                        arg_host = optarg;
-                        break;
-
-                case 'M':
-                        arg_transport = BUS_TRANSPORT_MACHINE;
-                        arg_host = optarg;
-                        break;
-
-                case 'q':
-                        arg_quiet = true;
-                        break;
-
-                case ARG_VERBOSE:
-                        arg_verbose = true;
-                        break;
-
-                case ARG_EXPECT_REPLY:
-                        r = parse_boolean(optarg);
-                        if (r < 0) {
-                                log_error("Failed to parse --expect-reply= parameter.");
-                                return r;
-                        }
-
-                        arg_expect_reply = !!r;
-                        break;
-
-
-                case ARG_AUTO_START:
-                        r = parse_boolean(optarg);
-                        if (r < 0) {
-                                log_error("Failed to parse --auto-start= parameter.");
-                                return r;
-                        }
-
-                        arg_auto_start = !!r;
-                        break;
-
-
-                case ARG_ALLOW_INTERACTIVE_AUTHORIZATION:
-                        r = parse_boolean(optarg);
-                        if (r < 0) {
-                                log_error("Failed to parse --allow-interactive-authorization= parameter.");
-                                return r;
-                        }
-
-                        arg_allow_interactive_authorization = !!r;
-                        break;
-
-                case ARG_TIMEOUT:
-                        r = parse_sec(optarg, &arg_timeout);
-                        if (r < 0) {
-                                log_error("Failed to parse --timeout= parameter.");
-                                return r;
-                        }
-
-                        break;
-
-                case ARG_AUGMENT_CREDS:
-                        r = parse_boolean(optarg);
-                        if (r < 0) {
-                                log_error("Failed to parse --augment-creds= parameter.");
-                                return r;
-                        }
-
-                        arg_augment_creds = !!r;
-                        break;
-
-                case '?':
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unhandled option");
-                }
-
-        return 1;
-}
-
-static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
-        assert(bus);
-
-        if (optind >= argc ||
-            streq(argv[optind], "list"))
-                return list_bus_names(bus, argv + optind);
-
-        if (streq(argv[optind], "monitor"))
-                return monitor(bus, argv + optind, message_dump);
-
-        if (streq(argv[optind], "capture"))
-                return capture(bus, argv + optind);
-
-        if (streq(argv[optind], "status"))
-                return status(bus, argv + optind);
-
-        if (streq(argv[optind], "tree"))
-                return tree(bus, argv + optind);
-
-        if (streq(argv[optind], "introspect"))
-                return introspect(bus, argv + optind);
-
-        if (streq(argv[optind], "call"))
-                return call(bus, argv + optind);
-
-        if (streq(argv[optind], "get-property"))
-                return get_property(bus, argv + optind);
-
-        if (streq(argv[optind], "set-property"))
-                return set_property(bus, argv + optind);
-
-        if (streq(argv[optind], "help"))
-                return help();
-
-        log_error("Unknown command '%s'", argv[optind]);
-        return -EINVAL;
-}
-
-int main(int argc, char *argv[]) {
-        sd_bus *bus = NULL;
-        int r;
-
-        log_parse_environment();
-        log_open();
-
-        r = parse_argv(argc, argv);
-        if (r <= 0)
-                goto finish;
-
-        r = sd_bus_new(&bus);
-        if (r < 0) {
-                log_error_errno(r, "Failed to allocate bus: %m");
-                goto finish;
-        }
-
-        if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) {
-
-                r = sd_bus_set_monitor(bus, true);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to set monitor mode: %m");
-                        goto finish;
-                }
-
-                r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to enable credentials: %m");
-                        goto finish;
-                }
-
-                r = sd_bus_negotiate_timestamp(bus, true);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to enable timestamps: %m");
-                        goto finish;
-                }
-
-                r = sd_bus_negotiate_fds(bus, true);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to enable fds: %m");
-                        goto finish;
-                }
-        }
-
-        r = sd_bus_set_bus_client(bus, true);
-        if (r < 0) {
-                log_error_errno(r, "Failed to set bus client: %m");
-                goto finish;
-        }
-
-        if (arg_address)
-                r = sd_bus_set_address(bus, arg_address);
-        else {
-                switch (arg_transport) {
-
-                case BUS_TRANSPORT_LOCAL:
-                        if (arg_user) {
-                                bus->is_user = true;
-                                r = bus_set_address_user(bus);
-                        } else {
-                                bus->is_system = true;
-                                r = bus_set_address_system(bus);
-                        }
-                        break;
-
-                case BUS_TRANSPORT_REMOTE:
-                        r = bus_set_address_system_remote(bus, arg_host);
-                        break;
-
-                case BUS_TRANSPORT_MACHINE:
-                        r = bus_set_address_system_machine(bus, arg_host);
-                        break;
-
-                default:
-                        assert_not_reached("Hmm, unknown transport type.");
-                }
-        }
-        if (r < 0) {
-                log_error_errno(r, "Failed to set address: %m");
-                goto finish;
-        }
-
-        r = sd_bus_start(bus);
-        if (r < 0) {
-                log_error_errno(r, "Failed to connect to bus: %m");
-                goto finish;
-        }
-
-        r = busctl_main(bus, argc, argv);
-
-finish:
-        sd_bus_flush_close_unref(bus);
-        pager_close();
-
-        strv_free(arg_matches);
-
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
index e809942278fca6dfe8d66094217acb8450d275b4..2f065c265784ddd1a1ced84879c8b1e28a8b2c3e 100644 (file)
@@ -588,6 +588,8 @@ static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
                 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
         }
 
+        b->is_local = true;
+
         return 0;
 }
 
@@ -655,6 +657,8 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
 
         freeaddrinfo(result);
 
+        b->is_local = false;
+
         return 0;
 }
 
@@ -737,6 +741,9 @@ static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
 
         b->exec_path = path;
         b->exec_argv = argv;
+
+        b->is_local = false;
+
         return 0;
 
 fail:
@@ -780,6 +787,8 @@ static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
         b->kernel = path;
         path = NULL;
 
+        b->is_local = true;
+
         return 0;
 }
 
@@ -838,6 +847,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
         b->sockaddr.un.sun_family = AF_UNIX;
         strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
         b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
+        b->is_local = false;
 
         return 0;
 }
@@ -898,6 +908,8 @@ static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid
         if (r < 0)
                 return r;
 
+        b->is_local = false;
+
         return 0;
 }
 
@@ -1179,6 +1191,7 @@ _public_ int sd_bus_open(sd_bus **ret) {
         /* We don't know whether the bus is trusted or not, so better
          * be safe, and authenticate everything */
         b->trusted = false;
+        b->is_local = false;
         b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
         b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
 
@@ -1227,6 +1240,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
         b->trusted = false;
         b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
         b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
+        b->is_local = true;
 
         r = sd_bus_start(b);
         if (r < 0)
@@ -1293,6 +1307,7 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
         /* We don't do any per-method access control on the user
          * bus. */
         b->trusted = true;
+        b->is_local = true;
 
         r = sd_bus_start(b);
         if (r < 0)
@@ -1364,6 +1379,7 @@ _public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
         bus->bus_client = true;
         bus->trusted = false;
         bus->is_system = true;
+        bus->is_local = false;
 
         r = sd_bus_start(bus);
         if (r < 0)
@@ -1413,6 +1429,7 @@ _public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
         bus->bus_client = true;
         bus->trusted = false;
         bus->is_system = true;
+        bus->is_local = false;
 
         r = sd_bus_start(bus);
         if (r < 0)
index 233a21a5230b4e44f2e863acf784eea1af10b23c..0b33ab7a3a7623e943f0cd402e1023d60b0be693 100644 (file)
@@ -525,8 +525,6 @@ int main(int argc, char *argv[]) {
         void *p;
         int r, q;
 
-        zero(c);
-
         c.automatic_integer_property = 4711;
         assert_se(c.automatic_string_property = strdup("dudeldu"));
 
index 4beb61f05a8a127bad7c18f7db7bc6e8f9d58594..06c61675113d16dcf5f3a9d302b6d48a59a31475 100644 (file)
@@ -17,7 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sd-bus.h>
+#include "sd-bus.h"
 
 #include "macro.h"
 
diff --git a/src/libsystemd/sd-bus/test-bus-vtable-cc.cc b/src/libsystemd/sd-bus/test-bus-vtable-cc.cc
new file mode 120000 (symlink)
index 0000000..abee398
--- /dev/null
@@ -0,0 +1 @@
+test-bus-vtable.c
\ No newline at end of file
diff --git a/src/libsystemd/sd-bus/test-bus-vtable.c b/src/libsystemd/sd-bus/test-bus-vtable.c
new file mode 100644 (file)
index 0000000..fd9ad81
--- /dev/null
@@ -0,0 +1,81 @@
+#include <stdbool.h>
+#include <stddef.h>
+
+/* We use system assert.h here, because we don't want to keep macro.h and log.h C++ compatible */
+#undef NDEBUG
+#include <assert.h>
+#include <errno.h>
+
+#include "sd-bus-vtable.h"
+
+#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
+
+struct context {
+        bool quit;
+        char *something;
+        char *automatic_string_property;
+        uint32_t automatic_integer_property;
+};
+
+static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+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) {
+        return 1;
+}
+
+static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+static const sd_bus_vtable vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("AlterSomething", "s", "s", handler, 0),
+        SD_BUS_METHOD("Exit", "", "", handler, 0),
+        SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0),
+        SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0),
+        SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
+        SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something),
+                        SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
+        SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL,
+                                 offsetof(struct context, automatic_string_property), 0),
+        SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL,
+                                 offsetof(struct context, automatic_integer_property), 0),
+        SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
+        SD_BUS_SIGNAL("DummySignal", "b", 0),
+        SD_BUS_SIGNAL("DummySignal2", "so", 0),
+        SD_BUS_VTABLE_END
+};
+
+static void test_vtable(void) {
+        sd_bus *bus = NULL;
+        struct context c = {};
+        int r;
+
+        assert(sd_bus_new(&bus) >= 0);
+
+        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", vtable, &c) >= 0);
+        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", vtable, &c) >= 0);
+
+        assert(sd_bus_set_address(bus, DEFAULT_BUS_PATH) >= 0);
+        r = sd_bus_start(bus);
+        assert(r == 0 ||     /* success */
+               r == -ENOENT  /* dbus is inactive */ );
+
+        sd_bus_unref(bus);
+}
+
+int main(int argc, char **argv) {
+        test_vtable();
+
+        return 0;
+}
index 86f8935a14e8d1f0d536a557cb7c876eceba2d0a..ebb8b2d1608d0066e54d3a2bdce6eb251820090c 100644 (file)
@@ -631,10 +631,8 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c
         if (!dir) {
                 if (errno == ENOENT)
                         return 0;
-                else {
-                        log_error("sd-device-enumerator: could not open tags directory %s: %m", path);
-                        return -errno;
-                }
+                else
+                        return log_error_errno(errno, "sd-device-enumerator: could not open tags directory %s: %m", path);
         }
 
         /* TODO: filter away subsystems? */
@@ -758,10 +756,8 @@ static int parent_crawl_children(sd_device_enumerator *enumerator, const char *p
         int r = 0;
 
         dir = opendir(path);
-        if (!dir) {
-                log_debug("sd-device-enumerate: could not open parent directory %s: %m", path);
-                return -errno;
-        }
+        if (!dir)
+                return log_debug_errno(errno, "sd-device-enumerate: could not open parent directory %s: %m", path);
 
         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
                 _cleanup_free_ char *child = NULL;
index 9082d377f4d12a9f84157d45efb3718e23539c5b..b4cd676c12a5b4f3bc6b0d2fe8c46811f22e391b 100644 (file)
@@ -778,12 +778,12 @@ int device_rename(sd_device *device, const char *name) {
 
         r = sd_device_get_property_value(device, "INTERFACE", &interface);
         if (r >= 0) {
-                r = device_add_property_internal(device, "INTERFACE", name);
+                /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
+                r = device_add_property_internal(device, "INTERFACE_OLD", interface);
                 if (r < 0)
                         return r;
 
-                /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
-                r = device_add_property_internal(device, "INTERFACE_OLD", interface);
+                r = device_add_property_internal(device, "INTERFACE", name);
                 if (r < 0)
                         return r;
         } else if (r != -ENOENT)
index 04ead29338bbe88298ac888370b9dd8fddd12cc2..ab36aa2e32e0076e10997f53a7fd9a58e12116b1 100644 (file)
@@ -195,8 +195,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
                                         /* this is not a valid device */
                                         return -ENODEV;
 
-                                log_debug("sd-device: %s does not have an uevent file: %m", syspath);
-                                return -errno;
+                                return log_debug_errno(errno, "sd-device: %s does not have an uevent file: %m", syspath);
                         }
                 } else {
                         /* everything else just needs to be a directory */
@@ -325,6 +324,10 @@ _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *s
         if (access(syspath, F_OK) >= 0)
                 return sd_device_new_from_syspath(ret, syspath);
 
+        syspath = strjoina("/sys/firmware/", subsystem, "/", sysname);
+        if (access(syspath, F_OK) >= 0)
+                return sd_device_new_from_syspath(ret, syspath);
+
         return -ENODEV;
 }
 
@@ -1892,6 +1895,7 @@ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr,
                 r = device_add_sysattr_value(device, sysattr, value);
                 if (r < 0)
                         return r;
+                value = NULL;
 
                 return -ENXIO;
         }
index c0e5e06a18459392d9f099ea099c436217609b97..8425378f3438f299c1657f83597fd66cb6aba18c 100644 (file)
@@ -17,6 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/wait.h>
+
 #include "sd-event.h"
 
 #include "fd-util.h"
index cc89f2de2e19d145174bd8faa51f1433b40e6e7d..b1f6c5305fcf75929bc05abd29eb1d058900b1ce 100644 (file)
@@ -289,7 +289,7 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) {
 
         assert_return(ret, -EINVAL);
 
-        r = dev_urandom(&t, sizeof(t));
+        r = acquire_random_bytes(&t, sizeof t, true);
         if (r < 0)
                 return r;
 
index d2cfbdf5b0aa8f5a74dbcee047efbcde56a2f182..5fb7fd99d50970fe653104b5fe94795a611ddcd7 100644 (file)
  */
 
 _public_ int sd_pid_get_session(pid_t pid, char **session) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(session, -EINVAL);
 
-        return cg_pid_get_session(pid, session);
+        r = cg_pid_get_session(pid, session);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(unit, -EINVAL);
 
-        return cg_pid_get_unit(pid, unit);
+        r = cg_pid_get_unit(pid, unit);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(unit, -EINVAL);
 
-        return cg_pid_get_user_unit(pid, unit);
+        r = cg_pid_get_user_unit(pid, unit);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(name, -EINVAL);
 
-        return cg_pid_get_machine_name(pid, name);
+        r = cg_pid_get_machine_name(pid, name);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(slice, -EINVAL);
 
-        return cg_pid_get_slice(pid, slice);
+        r = cg_pid_get_slice(pid, slice);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(slice, -EINVAL);
 
-        return cg_pid_get_user_slice(pid, slice);
+        r = cg_pid_get_user_slice(pid, slice);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
+        int r;
 
         assert_return(pid >= 0, -EINVAL);
         assert_return(uid, -EINVAL);
 
-        return cg_pid_get_owner_uid(pid, uid);
+        r = cg_pid_get_owner_uid(pid, uid);
+        return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r;
 }
 
 _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
@@ -279,7 +293,7 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) {
                         return -ENOMEM;
 
         }
-        if (r < 0) {
+        else if (r < 0) {
                 free(s);
                 return r;
         }
@@ -687,7 +701,7 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
 
         r = parse_env_file(p, NEWLINE,
                            "SESSIONS", &s,
-                           "ACTIVE_SESSIONS", &t,
+                           "UIDS", &t,
                            NULL);
         if (r == -ENOENT)
                 return -ENXIO;
@@ -723,7 +737,7 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
 
                                 r = parse_uid(k, b + i);
                                 if (r < 0)
-                                        continue;
+                                        return r;
 
                                 i++;
                         }
@@ -784,11 +798,27 @@ _public_ int sd_seat_can_graphical(const char *seat) {
 }
 
 _public_ int sd_get_seats(char ***seats) {
-        return get_files_in_directory("/run/systemd/seats/", seats);
+        int r;
+
+        r = get_files_in_directory("/run/systemd/seats/", seats);
+        if (r == -ENOENT) {
+                if (seats)
+                        *seats = NULL;
+                return 0;
+        }
+        return r;
 }
 
 _public_ int sd_get_sessions(char ***sessions) {
-        return get_files_in_directory("/run/systemd/sessions/", sessions);
+        int r;
+
+        r = get_files_in_directory("/run/systemd/sessions/", sessions);
+        if (r == -ENOENT) {
+                if (sessions)
+                        *sessions = NULL;
+                return 0;
+        }
+        return r;
 }
 
 _public_ int sd_get_uids(uid_t **users) {
@@ -799,8 +829,14 @@ _public_ int sd_get_uids(uid_t **users) {
         _cleanup_free_ uid_t *l = NULL;
 
         d = opendir("/run/systemd/users/");
-        if (!d)
+        if (!d) {
+                if (errno == ENOENT) {
+                        if (users)
+                                *users = NULL;
+                        return 0;
+                }
                 return -errno;
+        }
 
         FOREACH_DIRENT_ALL(de, d, return -errno) {
                 int k;
@@ -842,12 +878,16 @@ _public_ int sd_get_uids(uid_t **users) {
 }
 
 _public_ int sd_get_machine_names(char ***machines) {
-        char **l = NULL, **a, **b;
+        _cleanup_strv_free_ char **l = NULL;
+        char **a, **b;
         int r;
 
-        assert_return(machines, -EINVAL);
-
         r = get_files_in_directory("/run/systemd/machines/", &l);
+        if (r == -ENOENT) {
+                if (machines)
+                        *machines = NULL;
+                return 0;
+        }
         if (r < 0)
                 return r;
 
@@ -855,7 +895,7 @@ _public_ int sd_get_machine_names(char ***machines) {
                 r = 0;
 
                 /* Filter out the unit: symlinks */
-                for (a = l, b = l; *a; a++) {
+                for (a = b = l; *a; a++) {
                         if (startswith(*a, "unit:") || !machine_name_is_valid(*a))
                                 free(*a);
                         else {
@@ -868,7 +908,10 @@ _public_ int sd_get_machine_names(char ***machines) {
                 *b = NULL;
         }
 
-        *machines = l;
+        if (machines) {
+                *machines = l;
+                l = NULL;
+        }
         return r;
 }
 
index 9de33d85dbd1dce83e167df759601e5be809171a..b618b79b2812bec13fb710273690034b0be488e5 100644 (file)
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "format-util.h"
+#include "log.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
 
+static char* format_uids(char **buf, uid_t* uids, int count) {
+        int pos = 0, k, inc;
+        size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1;
+
+        assert_se(*buf = malloc(size));
+
+        for (k = 0; k < count; k++) {
+                sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc);
+                pos += inc;
+        }
+
+        assert_se(pos < (ssize_t)size);
+        (*buf)[pos] = '\0';
+
+        return *buf;
+}
+
 static void test_login(void) {
         _cleanup_close_pair_ int pair[2] = { -1, -1 };
-        _cleanup_free_ char *pp = NULL, *qq = NULL;
+        _cleanup_free_ char *pp = NULL, *qq = NULL,
+                *display_session = NULL, *cgroup = NULL,
+                *display = NULL, *remote_user = NULL, *remote_host = NULL,
+                *type = NULL, *class = NULL, *state = NULL, *state2 = NULL,
+                *seat = NULL, *session = NULL,
+                *unit = NULL, *user_unit = NULL, *slice = NULL;
         int r, k;
         uid_t u, u2;
-        char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session, *cgroup;
-        char *session;
-        char *state;
-        char *session2;
-        char *t;
-        char **seats, **sessions, **machines;
-        uid_t *uids;
-        unsigned n;
-        struct pollfd pollfd;
-        sd_login_monitor *m = NULL;
+        char *t, **seats, **sessions;
 
-        assert_se(sd_pid_get_session(0, &session) == 0);
-        printf("session = %s\n", session);
-
-        assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
-        printf("user = "UID_FMT"\n", u2);
+        r = sd_pid_get_unit(0, &unit);
+        assert_se(r >= 0 || r == -ENODATA);
+        log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit));
 
-        assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
-        printf("cgroup = %s\n", cgroup);
-        free(cgroup);
+        r = sd_pid_get_user_unit(0, &user_unit);
+        assert_se(r >= 0 || r == -ENODATA);
+        log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit));
 
-        display_session = NULL;
-        r = sd_uid_get_display(u2, &display_session);
+        r = sd_pid_get_slice(0, &slice);
         assert_se(r >= 0 || r == -ENODATA);
-        printf("user's display session = %s\n", strna(display_session));
-        free(display_session);
+        log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice));
 
-        assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
-        sd_peer_get_session(pair[0], &pp);
-        sd_peer_get_session(pair[1], &qq);
-        assert_se(streq_ptr(pp, qq));
+        r = sd_pid_get_session(0, &session);
+        if (r < 0) {
+                log_warning_errno(r, "sd_pid_get_session(0, …): %m");
+                if (r == -ENODATA)
+                        log_info("Seems we are not running in a session, skipping some tests.");
+        } else {
+                log_info("sd_pid_get_session(0, …) → \"%s\"", session);
 
-        r = sd_uid_get_sessions(u2, false, &sessions);
-        assert_se(r >= 0);
-        assert_se(r == (int) strv_length(sessions));
-        assert_se(t = strv_join(sessions, ", "));
-        strv_free(sessions);
-        printf("sessions = %s\n", t);
-        free(t);
+                assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
+                log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2);
 
-        assert_se(r == sd_uid_get_sessions(u2, false, NULL));
+                assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
+                log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup);
 
-        r = sd_uid_get_seats(u2, false, &seats);
-        assert_se(r >= 0);
-        assert_se(r == (int) strv_length(seats));
-        assert_se(t = strv_join(seats, ", "));
-        strv_free(seats);
-        printf("seats = %s\n", t);
-        free(t);
+                r = sd_uid_get_display(u2, &display_session);
+                assert_se(r >= 0 || r == -ENODATA);
+                log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"",
+                         u2, strnull(display_session));
 
-        assert_se(r == sd_uid_get_seats(u2, false, NULL));
+                assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
+                sd_peer_get_session(pair[0], &pp);
+                sd_peer_get_session(pair[1], &qq);
+                assert_se(streq_ptr(pp, qq));
 
-        r = sd_session_is_active(session);
-        assert_se(r >= 0);
-        printf("active = %s\n", yes_no(r));
+                r = sd_uid_get_sessions(u2, false, &sessions);
+                assert_se(r >= 0);
+                assert_se(r == (int) strv_length(sessions));
+                assert_se(t = strv_join(sessions, " "));
+                strv_free(sessions);
+                log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
+                free(t);
 
-        r = sd_session_is_remote(session);
-        assert_se(r >= 0);
-        printf("remote = %s\n", yes_no(r));
+                assert_se(r == sd_uid_get_sessions(u2, false, NULL));
 
-        r = sd_session_get_state(session, &state);
-        assert_se(r >= 0);
-        printf("state = %s\n", state);
-        free(state);
+                r = sd_uid_get_seats(u2, false, &seats);
+                assert_se(r >= 0);
+                assert_se(r == (int) strv_length(seats));
+                assert_se(t = strv_join(seats, " "));
+                strv_free(seats);
+                log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
+                free(t);
 
-        assert_se(sd_session_get_uid(session, &u) >= 0);
-        printf("uid = "UID_FMT"\n", u);
-        assert_se(u == u2);
+                assert_se(r == sd_uid_get_seats(u2, false, NULL));
+        }
 
-        assert_se(sd_session_get_type(session, &type) >= 0);
-        printf("type = %s\n", type);
-        free(type);
+        if (session) {
+                r = sd_session_is_active(session);
+                assert_se(r >= 0);
+                log_info("sd_session_is_active(\"%s\") → %s", session, yes_no(r));
 
-        assert_se(sd_session_get_class(session, &class) >= 0);
-        printf("class = %s\n", class);
-        free(class);
+                r = sd_session_is_remote(session);
+                assert_se(r >= 0);
+                log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r));
 
-        display = NULL;
-        r = sd_session_get_display(session, &display);
-        assert_se(r >= 0 || r == -ENODATA);
-        printf("display = %s\n", strna(display));
-        free(display);
+                r = sd_session_get_state(session, &state);
+                assert_se(r >= 0);
+                log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state);
 
-        remote_user = NULL;
-        r = sd_session_get_remote_user(session, &remote_user);
-        assert_se(r >= 0 || r == -ENODATA);
-        printf("remote_user = %s\n", strna(remote_user));
-        free(remote_user);
+                assert_se(sd_session_get_uid(session, &u) >= 0);
+                log_info("sd_session_get_uid(\"%s\") → "UID_FMT, session, u);
+                assert_se(u == u2);
 
-        remote_host = NULL;
-        r = sd_session_get_remote_host(session, &remote_host);
-        assert_se(r >= 0 || r == -ENODATA);
-        printf("remote_host = %s\n", strna(remote_host));
-        free(remote_host);
+                assert_se(sd_session_get_type(session, &type) >= 0);
+                log_info("sd_session_get_type(\"%s\") → \"%s\"", session, type);
 
-        assert_se(sd_session_get_seat(session, &seat) >= 0);
-        printf("seat = %s\n", seat);
+                assert_se(sd_session_get_class(session, &class) >= 0);
+                log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class);
 
-        r = sd_seat_can_multi_session(seat);
-        assert_se(r >= 0);
-        printf("can do multi session = %s\n", yes_no(r));
+                r = sd_session_get_display(session, &display);
+                assert_se(r >= 0 || r == -ENODATA);
+                log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display));
 
-        r = sd_seat_can_tty(seat);
-        assert_se(r >= 0);
-        printf("can do tty = %s\n", yes_no(r));
+                r = sd_session_get_remote_user(session, &remote_user);
+                assert_se(r >= 0 || r == -ENODATA);
+                log_info("sd_session_get_remote_user(\"%s\") → \"%s\"",
+                         session, strna(remote_user));
 
-        r = sd_seat_can_graphical(seat);
-        assert_se(r >= 0);
-        printf("can do graphical = %s\n", yes_no(r));
+                r = sd_session_get_remote_host(session, &remote_host);
+                assert_se(r >= 0 || r == -ENODATA);
+                log_info("sd_session_get_remote_host(\"%s\") → \"%s\"",
+                         session, strna(remote_host));
 
-        assert_se(sd_uid_get_state(u, &state) >= 0);
-        printf("state = %s\n", state);
+                r = sd_session_get_seat(session, &seat);
+                if (r >= 0) {
+                        assert_se(seat);
 
-        assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);
+                        log_info("sd_session_get_display(\"%s\") → \"%s\"", session, seat);
 
-        k = sd_uid_is_on_seat(u, 1, seat);
-        assert_se(k >= 0);
-        assert_se(!!r == !!r);
+                        r = sd_seat_can_multi_session(seat);
+                        assert_se(r >= 0);
+                        log_info("sd_session_can_multi_seat(\"%s\") → %s", seat, yes_no(r));
 
-        assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
-        printf("session2 = %s\n", session2);
-        printf("uid2 = "UID_FMT"\n", u2);
+                        r = sd_seat_can_tty(seat);
+                        assert_se(r >= 0);
+                        log_info("sd_session_can_tty(\"%s\") → %s", seat, yes_no(r));
 
-        r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
-        assert_se(r >= 0);
-        printf("n_sessions = %i\n", r);
-        assert_se(r == (int) strv_length(sessions));
-        assert_se(t = strv_join(sessions, ", "));
-        strv_free(sessions);
-        printf("sessions = %s\n", t);
-        free(t);
-        printf("uids =");
-        for (k = 0; k < (int) n; k++)
-                printf(" "UID_FMT, uids[k]);
-        printf("\n");
-        free(uids);
+                        r = sd_seat_can_graphical(seat);
+                        assert_se(r >= 0);
+                        log_info("sd_session_can_graphical(\"%s\") → %s", seat, yes_no(r));
+                } else {
+                        log_info_errno(r, "sd_session_get_display(\"%s\"): %m", session);
+                        assert_se(r == -ENODATA);
+                }
 
-        assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);
+                assert_se(sd_uid_get_state(u, &state2) >= 0);
+                log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2);
+        }
+
+        if (seat) {
+                _cleanup_free_ char *session2 = NULL, *buf = NULL;
+                _cleanup_free_ uid_t *uids = NULL;
+                unsigned n;
+
+                assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);
+
+                k = sd_uid_is_on_seat(u, 1, seat);
+                assert_se(k >= 0);
+                assert_se(!!k == !!r);
 
-        free(session);
-        free(state);
-        free(session2);
-        free(seat);
+                assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
+                log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2);
+
+                r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
+                assert_se(r >= 0);
+                assert_se(r == (int) strv_length(sessions));
+                assert_se(t = strv_join(sessions, " "));
+                strv_free(sessions);
+                log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}",
+                         seat, r, t, n, format_uids(&buf, uids, n));
+                free(t);
+
+                assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);
+        }
 
         r = sd_get_seats(&seats);
         assert_se(r >= 0);
         assert_se(r == (int) strv_length(seats));
         assert_se(t = strv_join(seats, ", "));
         strv_free(seats);
-        printf("n_seats = %i\n", r);
-        printf("seats = %s\n", t);
-        free(t);
+        log_info("sd_get_seats(…) → [%i] \"%s\"", r, t);
+        t = mfree(t);
 
         assert_se(sd_get_seats(NULL) == r);
 
         r = sd_seat_get_active(NULL, &t, NULL);
-        assert_se(r >= 0);
-        printf("active session on current seat = %s\n", t);
+        assert_se(IN_SET(r, 0, -ENODATA));
+        log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t));
         free(t);
 
         r = sd_get_sessions(&sessions);
@@ -199,40 +225,48 @@ static void test_login(void) {
         assert_se(r == (int) strv_length(sessions));
         assert_se(t = strv_join(sessions, ", "));
         strv_free(sessions);
-        printf("n_sessions = %i\n", r);
-        printf("sessions = %s\n", t);
+        log_info("sd_get_sessions(…) → [%i] \"%s\"", r, t);
         free(t);
 
         assert_se(sd_get_sessions(NULL) == r);
 
-        r = sd_get_uids(&uids);
-        assert_se(r >= 0);
+        {
+                _cleanup_free_ uid_t *uids = NULL;
+                _cleanup_free_ char *buf = NULL;
+
+                r = sd_get_uids(&uids);
+                assert_se(r >= 0);
+                log_info("sd_get_uids(…) → [%i] {%s}", r, format_uids(&buf, uids, r));
 
-        printf("uids =");
-        for (k = 0; k < r; k++)
-                printf(" "UID_FMT, uids[k]);
-        printf("\n");
-        free(uids);
+                assert_se(sd_get_uids(NULL) == r);
+        }
 
-        printf("n_uids = %i\n", r);
-        assert_se(sd_get_uids(NULL) == r);
+        {
+                _cleanup_strv_free_ char **machines = NULL;
+                _cleanup_free_ char *buf = NULL;
 
-        r = sd_get_machine_names(&machines);
-        assert_se(r >= 0);
-        assert_se(r == (int) strv_length(machines));
-        assert_se(t = strv_join(machines, ", "));
-        strv_free(machines);
-        printf("n_machines = %i\n", r);
-        printf("machines = %s\n", t);
-        free(t);
+                r = sd_get_machine_names(&machines);
+                assert_se(r >= 0);
+                assert_se(r == (int) strv_length(machines));
+                assert_se(buf = strv_join(machines, " "));
+                log_info("sd_get_machines(…) → [%i] \"%s\"", r, buf);
+
+                assert_se(sd_get_machine_names(NULL) == r);
+        }
+}
+
+static void test_monitor(void) {
+        sd_login_monitor *m = NULL;
+        unsigned n;
+        int r;
 
         r = sd_login_monitor_new("session", &m);
         assert_se(r >= 0);
 
         for (n = 0; n < 5; n++) {
+                struct pollfd pollfd = {};
                 usec_t timeout, nw;
 
-                zero(pollfd);
                 assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0);
                 assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0);
 
@@ -258,7 +292,12 @@ int main(int argc, char* argv[]) {
         log_parse_environment();
         log_open();
 
+        log_info("/* Information printed is from the live system */");
+
         test_login();
 
+        if (streq_ptr(argv[1], "-m"))
+                test_monitor();
+
         return 0;
 }
index 654a22fe3b5c74e1418747930f41def282809a2e..e8c8abac2ae352efe29623c0610a5e56686943a7 100644 (file)
@@ -104,7 +104,8 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
         assert_return(m->hdr->nlmsg_type == RTM_GETLINK  ||
                       m->hdr->nlmsg_type == RTM_GETADDR  ||
                       m->hdr->nlmsg_type == RTM_GETROUTE ||
-                      m->hdr->nlmsg_type == RTM_GETNEIGH,
+                      m->hdr->nlmsg_type == RTM_GETNEIGH ||
+                      m->hdr->nlmsg_type == RTM_GETADDRLABEL ,
                       -EINVAL);
 
         SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
index ff0e99558ee0e8103dfa442b09c646e508e8674f..923f7dd10c9b1af413e26c9181afb98bbabba62b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/veth.h>
 #include <linux/if_bridge.h>
 #include <linux/if_addr.h>
+#include <linux/if_addrlabel.h>
 #include <linux/if.h>
 #include <linux/ip.h>
 #include <linux/if_link.h>
@@ -170,6 +171,9 @@ static const NLType rtnl_link_info_data_vxlan_types[] = {
         [IFLA_VXLAN_REMCSUM_RX]        = { .type = NETLINK_TYPE_U8 },
         [IFLA_VXLAN_GBP]               = { .type = NETLINK_TYPE_FLAG },
         [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
+        [IFLA_VXLAN_COLLECT_METADATA]  = { .type = NETLINK_TYPE_U8 },
+        [IFLA_VXLAN_LABEL]             = { .type = NETLINK_TYPE_U32 },
+        [IFLA_VXLAN_GPE]               = { .type = NETLINK_TYPE_FLAG },
 };
 
 static const NLType rtnl_bond_arp_target_types[] = {
@@ -283,6 +287,19 @@ static const NLType rtnl_link_info_data_vrf_types[] = {
         [IFLA_VRF_TABLE]                 = { .type = NETLINK_TYPE_U32 },
 };
 
+static const NLType rtnl_link_info_data_geneve_types[] = {
+        [IFLA_GENEVE_ID]                = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GENEVE_TTL]               = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_TOS]               = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_PORT]              = { .type = NETLINK_TYPE_U16 },
+        [IFLA_GENEVE_REMOTE]            = { .type = NETLINK_TYPE_IN_ADDR },
+        [IFLA_GENEVE_REMOTE6]           = { .type = NETLINK_TYPE_IN_ADDR },
+        [IFLA_GENEVE_UDP_CSUM]          = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_LABEL]             = { .type = NETLINK_TYPE_U32 },
+};
+
 /* these strings must match the .kind entries in the kernel */
 static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
@@ -305,6 +322,7 @@ static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
         [NL_UNION_LINK_INFO_DATA_VRF] = "vrf",
         [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan",
+        [NL_UNION_LINK_INFO_DATA_GENEVE] = "geneve",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
@@ -346,6 +364,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
                                                        .types = rtnl_link_info_data_ip6tnl_types },
         [NL_UNION_LINK_INFO_DATA_VRF] =              { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types),
                                                        .types = rtnl_link_info_data_vrf_types },
+        [NL_UNION_LINK_INFO_DATA_GENEVE] =           { .count = ELEMENTSOF(rtnl_link_info_data_geneve_types),
+                                                       .types = rtnl_link_info_data_geneve_types },
 };
 
 static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
@@ -567,22 +587,35 @@ static const NLTypeSystem rtnl_neigh_type_system = {
         .types = rtnl_neigh_types,
 };
 
+static const NLType rtnl_addrlabel_types[] = {
+        [IFAL_ADDRESS]         = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
+        [IFAL_LABEL]           = { .type = NETLINK_TYPE_U32 },
+};
+
+static const NLTypeSystem rtnl_addrlabel_type_system = {
+        .count = ELEMENTSOF(rtnl_addrlabel_types),
+        .types = rtnl_addrlabel_types,
+};
+
 static const NLType rtnl_types[] = {
-        [NLMSG_DONE]   = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
-        [NLMSG_ERROR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
-        [RTM_NEWLINK]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
-        [RTM_DELLINK]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
-        [RTM_GETLINK]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
-        [RTM_SETLINK]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
-        [RTM_NEWADDR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
-        [RTM_DELADDR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
-        [RTM_GETADDR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
-        [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
-        [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
-        [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
-        [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
-        [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
-        [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+        [NLMSG_DONE]       = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
+        [NLMSG_ERROR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
+        [RTM_NEWLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+        [RTM_DELLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+        [RTM_GETLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+        [RTM_SETLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+        [RTM_NEWADDR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
+        [RTM_DELADDR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
+        [RTM_GETADDR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
+        [RTM_NEWROUTE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+        [RTM_DELROUTE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+        [RTM_GETROUTE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+        [RTM_NEWNEIGH]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+        [RTM_DELNEIGH]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+        [RTM_GETNEIGH]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+        [RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
+        [RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
+        [RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
 };
 
 const NLTypeSystem type_system_root = {
index 42e96173de84dd3c8b1082439bba9e71c05852ff..ae65c1d8e4fbe83d6977aac9d028a48a7f30f971 100644 (file)
@@ -88,6 +88,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
         NL_UNION_LINK_INFO_DATA_VRF,
         NL_UNION_LINK_INFO_DATA_VCAN,
+        NL_UNION_LINK_INFO_DATA_GENEVE,
         _NL_UNION_LINK_INFO_DATA_MAX,
         _NL_UNION_LINK_INFO_DATA_INVALID = -1
 } NLUnionLinkInfoData;
index 73b9ac0258cacd955045b7743223dbb8681ab256..6b660b7dbf3621a234d8322f20dea1e2181ea9b9 100644 (file)
@@ -116,51 +116,6 @@ int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_netlink_mess
         return 0;
 }
 
-bool rtnl_message_type_is_neigh(uint16_t type) {
-        switch (type) {
-                case RTM_NEWNEIGH:
-                case RTM_GETNEIGH:
-                case RTM_DELNEIGH:
-                        return true;
-                default:
-                        return false;
-        }
-}
-
-bool rtnl_message_type_is_route(uint16_t type) {
-        switch (type) {
-                case RTM_NEWROUTE:
-                case RTM_GETROUTE:
-                case RTM_DELROUTE:
-                        return true;
-                default:
-                        return false;
-        }
-}
-
-bool rtnl_message_type_is_link(uint16_t type) {
-        switch (type) {
-                case RTM_NEWLINK:
-                case RTM_SETLINK:
-                case RTM_GETLINK:
-                case RTM_DELLINK:
-                        return true;
-                default:
-                        return false;
-        }
-}
-
-bool rtnl_message_type_is_addr(uint16_t type) {
-        switch (type) {
-                case RTM_NEWADDR:
-                case RTM_GETADDR:
-                case RTM_DELADDR:
-                        return true;
-                default:
-                        return false;
-        }
-}
-
 int rtnl_log_parse_error(int r) {
         return log_error_errno(r, "Failed to parse netlink message: %m");
 }
index f49bf4eaa6567f38359bee23743092c0c3061645..215af124063baa6fb67b88fa1cd146390f5f90ec 100644 (file)
@@ -27,10 +27,25 @@ int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_netlink_mess
 uint32_t rtnl_message_get_serial(sd_netlink_message *m);
 void rtnl_message_seal(sd_netlink_message *m);
 
-bool rtnl_message_type_is_link(uint16_t type);
-bool rtnl_message_type_is_addr(uint16_t type);
-bool rtnl_message_type_is_route(uint16_t type);
-bool rtnl_message_type_is_neigh(uint16_t type);
+static inline bool rtnl_message_type_is_neigh(uint16_t type) {
+        return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH);
+}
+
+static inline bool rtnl_message_type_is_route(uint16_t type) {
+        return IN_SET(type, RTM_NEWROUTE, RTM_GETROUTE, RTM_DELROUTE);
+}
+
+static inline bool rtnl_message_type_is_link(uint16_t type) {
+        return IN_SET(type, RTM_NEWLINK, RTM_SETLINK, RTM_GETLINK, RTM_DELLINK);
+}
+
+static inline bool rtnl_message_type_is_addr(uint16_t type) {
+        return IN_SET(type, RTM_NEWADDR, RTM_GETADDR, RTM_DELADDR);
+}
+
+static inline bool rtnl_message_type_is_addrlabel(uint16_t type) {
+        return IN_SET(type, RTM_NEWADDRLABEL, RTM_DELADDRLABEL, RTM_GETADDRLABEL);
+}
 
 int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
 int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu);
index b543b5f20cbe09c95290f2ddee5ec1a6a63e57e7..12c51ffe2e6728a5126a25fa75b7f9b847701ee8 100644 (file)
@@ -18,6 +18,7 @@
 ***/
 
 #include <netinet/in.h>
+#include <linux/if_addrlabel.h>
 #include <stdbool.h>
 #include <unistd.h>
 
@@ -700,3 +701,56 @@ int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) {
 
         return -EOPNOTSUPP;
 }
+
+int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family) {
+        struct ifaddrlblmsg *addrlabel;
+        int r;
+
+        assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = message_new(rtnl, ret, nlmsg_type);
+        if (r < 0)
+                return r;
+
+        if (nlmsg_type == RTM_NEWADDRLABEL)
+                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+
+        addrlabel = NLMSG_DATA((*ret)->hdr);
+
+        addrlabel->ifal_family = ifal_family;
+        addrlabel->ifal_index = ifindex;
+
+        return 0;
+}
+
+int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
+        struct ifaddrlblmsg *addrlabel;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
+
+        addrlabel = NLMSG_DATA(m->hdr);
+
+        if (prefixlen > 128)
+                return -ERANGE;
+
+        addrlabel->ifal_prefixlen = prefixlen;
+
+        return 0;
+}
+
+int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) {
+        struct ifaddrlblmsg *addrlabel;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
+
+        addrlabel = NLMSG_DATA(m->hdr);
+
+        *prefixlen = addrlabel->ifal_prefixlen;
+
+        return 0;
+}
index a40329d732834a6d7b4042092bf4ce441ec7ea62..8287694c498637cafe4cc1f6cbed7c926375046d 100644 (file)
@@ -681,7 +681,7 @@ retry:
 
         udev_device = udev_device_new_from_nulstr(udev_monitor->udev, &buf.raw[bufpos], buflen - bufpos);
         if (!udev_device) {
-                log_debug("could not create device: %m");
+                log_debug_errno(errno, "could not create device: %m");
                 return NULL;
         }
 
index d8e13288b025ca533dd67fb168e729d40b778db7..5f2225f402a5943577a20ceb3cb18f8c13af15e7 100644 (file)
@@ -103,82 +103,6 @@ _public_ struct udev *udev_new(void) {
         }
         udev->refcount = 1;
 
-        f = fopen("/etc/udev/udev.conf", "re");
-        if (f != NULL) {
-                char line[UTIL_LINE_SIZE];
-                unsigned line_nr = 0;
-
-                while (fgets(line, sizeof(line), f)) {
-                        size_t len;
-                        char *key;
-                        char *val;
-
-                        line_nr++;
-
-                        /* find key */
-                        key = line;
-                        while (isspace(key[0]))
-                                key++;
-
-                        /* comment or empty line */
-                        if (key[0] == '#' || key[0] == '\0')
-                                continue;
-
-                        /* split key/value */
-                        val = strchr(key, '=');
-                        if (val == NULL) {
-                                log_debug("/etc/udev/udev.conf:%u: missing assignment,  skipping line.", line_nr);
-                                continue;
-                        }
-                        val[0] = '\0';
-                        val++;
-
-                        /* find value */
-                        while (isspace(val[0]))
-                                val++;
-
-                        /* terminate key */
-                        len = strlen(key);
-                        if (len == 0)
-                                continue;
-                        while (isspace(key[len-1]))
-                                len--;
-                        key[len] = '\0';
-
-                        /* terminate value */
-                        len = strlen(val);
-                        if (len == 0)
-                                continue;
-                        while (isspace(val[len-1]))
-                                len--;
-                        val[len] = '\0';
-
-                        if (len == 0)
-                                continue;
-
-                        /* unquote */
-                        if (val[0] == '"' || val[0] == '\'') {
-                                if (len == 1 || val[len-1] != val[0]) {
-                                        log_debug("/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.", line_nr);
-                                        continue;
-                                }
-                                val[len-1] = '\0';
-                                val++;
-                        }
-
-                        if (streq(key, "udev_log")) {
-                                int prio;
-
-                                prio = util_log_priority(val);
-                                if (prio < 0)
-                                        log_debug("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.", line_nr, val);
-                                else
-                                        log_set_max_level(prio);
-                                continue;
-                        }
-                }
-        }
-
         return udev;
 }
 
index 770c92209ec0ead5e0e615bb2ca5926f81c7f8dc..1becae45fdc65e316663c0e2ec85bccfa2dc4841 100644 (file)
@@ -12,6 +12,6 @@ includedir=@includedir@
 
 Name: libudev
 Description: Library to access udev device information
-Version: @VERSION@
+Version: @PACKAGE_VERSION@
 Libs: -L${libdir} -ludev
 Cflags: -I${includedir}
diff --git a/src/libudev/meson.build b/src/libudev/meson.build
new file mode 100644 (file)
index 0000000..1378f9a
--- /dev/null
@@ -0,0 +1,41 @@
+libudev_sources = files('''
+        libudev-private.h
+        libudev-device-internal.h
+        libudev.c
+        libudev-list.c
+        libudev-util.c
+        libudev-device.c
+        libudev-device-private.c
+        libudev-enumerate.c
+        libudev-monitor.c
+        libudev-queue.c
+        libudev-hwdb.c
+'''.split())
+
+############################################################
+
+libudev_sym = 'libudev.sym'
+libudev_sym_path = '@0@/@1@'.format(meson.current_source_dir(), libudev_sym)
+libudev = shared_library(
+        'udev',
+        libudev_sources,
+        version : '1.6.6',
+        include_directories : includes,
+        link_args : ['-shared',
+                     '-Wl,--version-script=' + libudev_sym_path],
+        link_with : [libbasic,
+                     libsystemd_internal],
+        dependencies : [threads],
+        link_depends : libudev_sym,
+        install : true,
+        install_dir : rootlibdir)
+
+install_headers('libudev.h')
+libudev_h_path = '@0@/libudev.h'.format(meson.current_source_dir())
+
+libudev_pc = configure_file(
+        input : 'libudev.pc.in',
+        output : 'libudev.pc',
+        configuration : substs)
+install_data(libudev_pc,
+             install_dir : pkgconfiglibdir)
index da72bee4a92261c503db6a0293340e1a3ef53bd1..105d9b0ee4c86d9afbf97065d0e66ca4bc44c804 100644 (file)
@@ -361,8 +361,9 @@ int x11_write_data(Context *c) {
 
         fchmod(fileno(f), 0644);
 
-        fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n"
-              "# manually too freely.\n"
+        fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n"
+              "# probably wise not to edit this file manually. Use localectl(1) to\n"
+              "# instruct systemd-localed to update it.\n"
               "Section \"InputClass\"\n"
               "        Identifier \"system-keyboard\"\n"
               "        MatchIsKeyboard \"on\"\n", f);
index 1cb049e74af4596e9227e3dd48c62662f49905fc..b4798d674c76119b0f2cfe3fa38d7e8dd24ce570 100644 (file)
@@ -436,7 +436,10 @@ static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char
         const char *fmt;
 
         fmt = strjoina("libxkbcommon: ", format);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
         log_internalv(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, fmt, args);
+#pragma GCC diagnostic pop
 }
 
 #define LOAD_SYMBOL(symbol, dl, name)                                   \
diff --git a/src/locale/meson.build b/src/locale/meson.build
new file mode 100644 (file)
index 0000000..d7dd113
--- /dev/null
@@ -0,0 +1,42 @@
+systemd_localed_sources = files('''
+        localed.c
+        keymap-util.c
+        keymap-util.h
+'''.split())
+
+localectl_sources = files('localectl.c')
+
+if conf.get('ENABLE_LOCALED', false)
+        install_data('org.freedesktop.locale1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.locale1.service',
+                     install_dir : dbussystemservicedir)
+
+        custom_target(
+                'org.freedesktop.locale1.policy',
+                input : 'org.freedesktop.locale1.policy.in',
+                output : 'org.freedesktop.locale1.policy',
+                command : intltool_command,
+                install : install_polkit,
+                install_dir : polkitpolicydir)
+endif
+
+# If you know a way that allows the same variables to be used
+# in sources list and concatenated to a string for test_env,
+# let me know.
+kbd_model_map = join_paths(meson.current_source_dir(),  'kbd-model-map')
+language_fallback_map = join_paths(meson.current_source_dir(), 'language-fallback-map')
+
+if conf.get('ENABLE_LOCALED', false)
+        install_data('kbd-model-map',
+                     'language-fallback-map',
+                     install_dir : pkgdatadir)
+endif
+
+tests += [
+        [['src/locale/test-keymap-util.c',
+          'src/locale/keymap-util.c',
+          'src/locale/keymap-util.h'],
+         [libshared],
+         [libdl]],
+]
index e2855b50f7c4b7bbc2c22f0158c1bc55eb6baa32..394a80f1f8ffce7050093b0233d4945d5fb60f30 100644 (file)
@@ -7,12 +7,7 @@
 
 ACTION=="remove", GOTO="power_switch_end"
 
-SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="acpi", TAG+="power-switch"
-SUBSYSTEM=="input", KERNEL=="event*", KERNELS=="thinkpad_acpi", TAG+="power-switch"
-SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="twl4030_pwrbutton", TAG+="power-switch"
-SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="tps65217_pwr_but", TAG+="power-switch"
-SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="* WMI hotkeys", TAG+="power-switch"
-SUBSYSTEM=="input", KERNEL=="event*", \
-  SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", ATTRS{keys}=="*,116|116,*|116|*,116,*", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_SWITCH}=="1", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_KEY}=="1", TAG+="power-switch"
 
 LABEL="power_switch_end"
index 7dea5c08597ac549ffb32000e0df151427db92d3..1862e8983c5a4664bfea99f4873c8f05a3bfe773 100644 (file)
@@ -907,6 +907,8 @@ static int show_session(int argc, char *argv[], void *userdata) {
         bool properties, new_line = false;
         sd_bus *bus = userdata;
         int r, i;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *path = NULL;
 
         assert(bus);
         assert(argv);
@@ -916,20 +918,28 @@ static int show_session(int argc, char *argv[], void *userdata) {
         pager_open(arg_no_pager, false);
 
         if (argc <= 1) {
-                /* If not argument is specified inspect the manager
-                 * itself */
+                const char *session, *p = "/org/freedesktop/login1/session/self";
+
                 if (properties)
+                        /* If no argument is specified inspect the manager itself */
                         return show_properties(bus, "/org/freedesktop/login1", &new_line);
 
                 /* And in the pretty case, show data of the calling session */
-                return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
+                session = getenv("XDG_SESSION_ID");
+                if (session) {
+                        r = get_session_path(bus, session, &error, &path);
+                        if (r < 0) {
+                                log_error("Failed to get session path: %s", bus_error_message(&error, r));
+                                return r;
+                        }
+                        p = path;
+                }
+
+                return print_session_status_info(bus, p, &new_line);
         }
 
         for (i = 1; i < argc; i++) {
-                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_free_ char *path = NULL;
-
-                r = get_session_path(bus, argv[1], &error, &path);
+                r = get_session_path(bus, argv[i], &error, &path);
                 if (r < 0) {
                         log_error("Failed to get session path: %s", bus_error_message(&error, r));
                         return r;
@@ -1074,12 +1084,11 @@ static int activate(int argc, char *argv[], void *userdata) {
         polkit_agent_open_if_enabled();
 
         if (argc < 2) {
-                /* No argument? Let's convert this into the empty
-                 * session name, which the calls will then resolve to
-                 * the caller's session. */
+                /* No argument? Let's either use $XDG_SESSION_ID (if specified), or an empty
+                 * session name, in which case logind will try to guess our session. */
 
                 short_argv[0] = argv[0];
-                short_argv[1] = (char*) "";
+                short_argv[1] = getenv("XDG_SESSION_ID") ?: (char*) "";
                 short_argv[2] = NULL;
 
                 argv = short_argv;
@@ -1155,8 +1164,11 @@ static int enable_linger(int argc, char *argv[], void *userdata) {
         b = streq(argv[0], "enable-linger");
 
         if (argc < 2) {
+                /* No argument? Let's either use $XDG_SESSION_ID (if specified), or an empty
+                 * session name, in which case logind will try to guess our session. */
+
                 short_argv[0] = argv[0];
-                short_argv[1] = (char*) "";
+                short_argv[1] = getenv("XDG_SESSION_ID") ?: (char*) "";
                 short_argv[2] = NULL;
                 argv = short_argv;
                 argc = 2;
@@ -1386,8 +1398,10 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --kill-who=WHO        Who to send signal to\n"
                "  -s --signal=SIGNAL       Which signal to send\n"
                "  -n --lines=INTEGER       Number of journal entries to show\n"
-               "  -o --output=STRING       Change journal output mode (short, short-monotonic,\n"
-               "                           verbose, export, json, json-pretty, json-sse, cat)\n\n"
+               "  -o --output=STRING       Change journal output mode (short, short-precise,\n"
+               "                             short-iso, short-iso-precise, short-full,\n"
+               "                             short-monotonic, short-unix, verbose, export,\n"
+               "                             json, json-pretty, json-sse, cat)\n"
                "Session Commands:\n"
                "  list-sessions            List sessions\n"
                "  session-status [ID...]   Show session status\n"
index d739af8ea2c3f7c023a9455bbca318b9afa99384..e53dd63c29756e79088cf83c70f9dd361ffd2bbf 100644 (file)
 #include "string-util.h"
 #include "util.h"
 
+#define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d))
+
+#define ULONG_BITS (sizeof(unsigned long)*8)
+
+static bool bitset_get(const unsigned long *bits, unsigned i) {
+        return (bits[i / ULONG_BITS] >> (i % ULONG_BITS)) & 1UL;
+}
+
+static void bitset_put(unsigned long *bits, unsigned i) {
+        bits[i / ULONG_BITS] |= (unsigned long) 1 << (i % ULONG_BITS);
+}
+
 Button* button_new(Manager *m, const char *name) {
         Button *b;
 
@@ -231,6 +243,95 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
         return 0;
 }
 
+static int button_suitable(Button *b) {
+        unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1];
+
+        assert(b);
+        assert(b->fd);
+
+        if (ioctl(b->fd, EVIOCGBIT(EV_SYN, sizeof(types)), types) < 0)
+                return -errno;
+
+        if (bitset_get(types, EV_KEY)) {
+                unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1];
+
+                if (ioctl(b->fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys) < 0)
+                        return -errno;
+
+                if (bitset_get(keys, KEY_POWER) ||
+                    bitset_get(keys, KEY_POWER2) ||
+                    bitset_get(keys, KEY_SLEEP) ||
+                    bitset_get(keys, KEY_SUSPEND))
+                        return true;
+        }
+
+        if (bitset_get(types, EV_SW)) {
+                unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1];
+
+                if (ioctl(b->fd, EVIOCGBIT(EV_SW, sizeof(switches)), switches) < 0)
+                        return -errno;
+
+                if (bitset_get(switches, SW_LID) ||
+                    bitset_get(switches, SW_DOCK))
+                        return true;
+        }
+
+        return false;
+}
+
+static int button_set_mask(Button *b) {
+        unsigned long
+                types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {},
+                keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {},
+                switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
+        struct input_mask mask;
+
+        assert(b);
+        assert(b->fd >= 0);
+
+        bitset_put(types, EV_KEY);
+        bitset_put(types, EV_SW);
+
+        mask = (struct input_mask) {
+                .type = EV_SYN,
+                .codes_size = sizeof(types),
+                .codes_ptr = PTR_TO_UINT64(types),
+        };
+
+        if (ioctl(b->fd, EVIOCSMASK, &mask) < 0)
+                /* Log only at debug level if the kernel doesn't do EVIOCSMASK yet */
+                return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING,
+                                      errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", b->name);
+
+        bitset_put(keys, KEY_POWER);
+        bitset_put(keys, KEY_POWER2);
+        bitset_put(keys, KEY_SLEEP);
+        bitset_put(keys, KEY_SUSPEND);
+
+        mask = (struct input_mask) {
+                .type = EV_KEY,
+                .codes_size = sizeof(keys),
+                .codes_ptr = PTR_TO_UINT64(keys),
+        };
+
+        if (ioctl(b->fd, EVIOCSMASK, &mask) < 0)
+                return log_warning_errno(errno, "Failed to set EV_KEY event mask on /dev/input/%s: %m", b->name);
+
+        bitset_put(switches, SW_LID);
+        bitset_put(switches, SW_DOCK);
+
+        mask = (struct input_mask) {
+                .type = EV_SW,
+                .codes_size = sizeof(switches),
+                .codes_ptr = PTR_TO_UINT64(switches),
+        };
+
+        if (ioctl(b->fd, EVIOCSMASK, &mask) < 0)
+                return log_warning_errno(errno, "Failed to set EV_SW event mask on /dev/input/%s: %m", b->name);
+
+        return 0;
+}
+
 int button_open(Button *b) {
         char *p, name[256];
         int r;
@@ -243,13 +344,23 @@ int button_open(Button *b) {
 
         b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
         if (b->fd < 0)
-                return log_warning_errno(errno, "Failed to open %s: %m", b->name);
+                return log_warning_errno(errno, "Failed to open %s: %m", p);
+
+        r = button_suitable(b);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to determine whether input device is relevant to us: %m");
+        if (r == 0) {
+                log_debug("Device %s does not expose keys or switches relevant to us, ignoring.", p);
+                return -EADDRNOTAVAIL;
+        }
 
         if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
                 r = log_error_errno(errno, "Failed to get input name: %m");
                 goto fail;
         }
 
+        (void) button_set_mask(b);
+
         r = sd_event_add_io(b->manager->event, &b->io_event_source, b->fd, EPOLLIN, button_dispatch, b);
         if (r < 0) {
                 log_error_errno(r, "Failed to add button event: %m");
@@ -266,7 +377,7 @@ fail:
 }
 
 int button_check_switches(Button *b) {
-        uint8_t switches[SW_MAX/8+1] = {};
+        unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
         assert(b);
 
         if (b->fd < 0)
@@ -275,8 +386,8 @@ int button_check_switches(Button *b) {
         if (ioctl(b->fd, EVIOCGSW(sizeof(switches)), switches) < 0)
                 return -errno;
 
-        b->lid_closed = (switches[SW_LID/8] >> (SW_LID % 8)) & 1;
-        b->docked = (switches[SW_DOCK/8] >> (SW_DOCK % 8)) & 1;
+        b->lid_closed = bitset_get(switches, SW_LID);
+        b->docked = bitset_get(switches, SW_DOCK);
 
         if (b->lid_closed)
                 button_install_check_event_source(b);
index eff5a4a36f35fe5a808838aa91f9d00cb436fa05..ebe1d68634027dd475820a69a56db862484c42e1 100644 (file)
@@ -269,7 +269,11 @@ int manager_process_button_device(Manager *m, struct udev_device *d) {
                         sn = "seat0";
 
                 button_set_seat(b, sn);
-                button_open(b);
+
+                r = button_open(b);
+                if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error
+                            * opening the device?) let's close the button again. */
+                        button_free(b);
         }
 
         return 0;
index c6be596af31fe3f760c369b430788937444ca26c..c9b7d998189ecbbc27a492b5300142d82222c9d3 100644 (file)
@@ -65,6 +65,9 @@ int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const ch
                         return r;
 
                 r = sd_bus_creds_get_session(creds, &name);
+                if (r == -ENXIO)
+                        return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
+                                                 "Caller does not belong to any known session");
                 if (r < 0)
                         return r;
         }
index 5ca42b1ca2ae2c4d14cc4f73f23e25d181b3112e..1e6f3837382fe163fed58bbeda901abdda364d91 100644 (file)
@@ -347,7 +347,7 @@ InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
         assert(m);
 
         HASHMAP_FOREACH(i, m->inhibitors, j)
-                if (i->mode == mm)
+                if (i->mode == mm && i->started)
                         what |= i->what;
 
         return what;
@@ -388,6 +388,9 @@ bool manager_is_inhibited(
         assert(w > 0 && w < _INHIBIT_WHAT_MAX);
 
         HASHMAP_FOREACH(i, m->inhibitors, j) {
+                if (!i->started)
+                        continue;
+
                 if (!(i->what & w))
                         continue;
 
index 22dea5db1f959961cec4ec7309c154dfd294be74..22e5349a67ca0a7e17ae29def9cd1af7949d3e4b 100644 (file)
@@ -396,7 +396,7 @@ static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_e
         if (uid != 0 && (force || uid != s->user->uid))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
 
-        r = session_set_controller(s, sd_bus_message_get_sender(message), force);
+        r = session_set_controller(s, sd_bus_message_get_sender(message), force, true);
         if (r < 0)
                 return r;
 
@@ -444,14 +444,23 @@ static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_er
                  * equivalent). */
                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
 
-        r = session_device_new(s, dev, &sd);
+        r = session_device_new(s, dev, true, &sd);
         if (r < 0)
                 return r;
 
+        r = session_device_save(sd);
+        if (r < 0)
+                goto error;
+
         r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
         if (r < 0)
-                session_device_free(sd);
+                goto error;
+
+        session_save(s);
+        return 0;
 
+error:
+        session_device_free(sd);
         return r;
 }
 
@@ -478,6 +487,8 @@ static int method_release_device(sd_bus_message *message, void *userdata, sd_bus
                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
 
         session_device_free(sd);
+        session_save(s);
+
         return sd_bus_reply_method_return(message, NULL);
 }
 
index 4055a23277391abaee3588fae11b08aa91b5ec42..05af2045d289c79c6f446d0aa7b55b358e1f14ee 100644 (file)
@@ -30,6 +30,8 @@
 #include "fd-util.h"
 #include "logind-session-device.h"
 #include "missing.h"
+#include "parse-util.h"
+#include "sd-daemon.h"
 #include "util.h"
 
 enum SessionDeviceNotifications {
@@ -206,7 +208,10 @@ static int session_device_start(SessionDevice *sd) {
                 r = session_device_open(sd, true);
                 if (r < 0)
                         return r;
-                close_nointr(sd->fd);
+                /* For evdev devices, the file descriptor might be left
+                 * uninitialized. This might happen while resuming into a
+                 * session and logind has been restarted right before. */
+                safe_close(sd->fd);
                 sd->fd = r;
                 break;
         case DEVICE_TYPE_UNKNOWN:
@@ -341,7 +346,7 @@ err_dev:
         return r;
 }
 
-int session_device_new(Session *s, dev_t dev, SessionDevice **out) {
+int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **out) {
         SessionDevice *sd;
         int r;
 
@@ -370,22 +375,24 @@ int session_device_new(Session *s, dev_t dev, SessionDevice **out) {
                 goto error;
         }
 
-        /* Open the device for the first time. We need a valid fd to pass back
-         * to the caller. If the session is not active, this _might_ immediately
-         * revoke access and thus invalidate the fd. But this is still needed
-         * to pass a valid fd back. */
-        sd->active = session_is_active(s);
-        r = session_device_open(sd, sd->active);
-        if (r < 0) {
-                /* EINVAL _may_ mean a master is active; retry inactive */
-                if (sd->active && r == -EINVAL) {
-                        sd->active = false;
-                        r = session_device_open(sd, false);
+        if (open_device) {
+                /* Open the device for the first time. We need a valid fd to pass back
+                 * to the caller. If the session is not active, this _might_ immediately
+                 * revoke access and thus invalidate the fd. But this is still needed
+                 * to pass a valid fd back. */
+                sd->active = session_is_active(s);
+                r = session_device_open(sd, sd->active);
+                if (r < 0) {
+                        /* EINVAL _may_ mean a master is active; retry inactive */
+                        if (sd->active && r == -EINVAL) {
+                                sd->active = false;
+                                r = session_device_open(sd, false);
+                        }
+                        if (r < 0)
+                                goto error;
                 }
-                if (r < 0)
-                        goto error;
+                sd->fd = r;
         }
-        sd->fd = r;
 
         LIST_PREPEND(sd_by_device, sd->device->session_devices, sd);
 
@@ -435,15 +442,16 @@ void session_device_complete_pause(SessionDevice *sd) {
 void session_device_resume_all(Session *s) {
         SessionDevice *sd;
         Iterator i;
-        int r;
 
         assert(s);
 
         HASHMAP_FOREACH(sd, s->devices, i) {
                 if (!sd->active) {
-                        r = session_device_start(sd);
-                        if (!r)
-                                session_device_notify(sd, SESSION_DEVICE_RESUME);
+                        if (session_device_start(sd) < 0)
+                                continue;
+                        if (session_device_save(sd) < 0)
+                                continue;
+                        session_device_notify(sd, SESSION_DEVICE_RESUME);
                 }
         }
 }
@@ -478,3 +486,36 @@ unsigned int session_device_try_pause_all(Session *s) {
 
         return num_pending;
 }
+
+int session_device_save(SessionDevice *sd) {
+        _cleanup_free_ char *state = NULL;
+        int r;
+
+        assert(sd);
+
+        /* Store device fd in PID1. It will send it back to us on
+         * restart so revocation will continue to work. To make things
+         * simple, send fds for all type of devices even if they don't
+         * support the revocation mechanism so we don't have to handle
+         * them differently later.
+         *
+         * Note: for device supporting revocation, PID1 will drop a
+         * stored fd automatically if the corresponding device is
+         * revoked. */
+        r = asprintf(&state, "FDSTORE=1\n"
+                             "FDNAME=session-%s", sd->session->id);
+        if (r < 0)
+                return -ENOMEM;
+
+        return sd_pid_notify_with_fds(0, false, state, &sd->fd, 1);
+}
+
+void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
+        assert(fd > 0);
+        assert(sd);
+        assert(sd->fd < 0);
+        assert(!sd->active);
+
+        sd->fd = fd;
+        sd->active = active;
+}
index 7c8503583fe19660ff70476b2f23f23dcf101a4f..83aef1e18c951da82b35f554df2cc5f637b0c923 100644 (file)
@@ -44,10 +44,13 @@ struct SessionDevice {
         LIST_FIELDS(struct SessionDevice, sd_by_device);
 };
 
-int session_device_new(Session *s, dev_t dev, SessionDevice **out);
+int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **out);
 void session_device_free(SessionDevice *sd);
 void session_device_complete_pause(SessionDevice *sd);
 
 void session_device_resume_all(Session *s);
 void session_device_pause_all(Session *s);
 unsigned int session_device_try_pause_all(Session *s);
+
+int session_device_save(SessionDevice *sd);
+void session_device_attach_fd(SessionDevice *sd, int fd, bool active);
index 4a168906d6f8f70391289ba9de7fbc11189490a4..42dfecaffbd47d135523a7c5f73fb03048a351f6 100644 (file)
@@ -152,6 +152,18 @@ void session_set_user(Session *s, User *u) {
         LIST_PREPEND(sessions_by_user, u->sessions, s);
 }
 
+static void session_save_devices(Session *s, FILE *f) {
+        SessionDevice *sd;
+        Iterator i;
+
+        if (!hashmap_isempty(s->devices)) {
+                fprintf(f, "DEVICES=");
+                HASHMAP_FOREACH(sd, s->devices, i)
+                        fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev));
+                fprintf(f, "\n");
+        }
+}
+
 int session_save(Session *s) {
         _cleanup_free_ char *temp_path = NULL;
         _cleanup_fclose_ FILE *f = NULL;
@@ -281,8 +293,10 @@ int session_save(Session *s) {
                         s->timestamp.realtime,
                         s->timestamp.monotonic);
 
-        if (s->controller)
+        if (s->controller) {
                 fprintf(f, "CONTROLLER=%s\n", s->controller);
+                session_save_devices(s, f);
+        }
 
         r = fflush_and_check(f);
         if (r < 0)
@@ -304,6 +318,43 @@ fail:
         return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
 }
 
+static int session_load_devices(Session *s, const char *devices) {
+        const char *p;
+        int r = 0;
+
+        assert(s);
+
+        for (p = devices;;) {
+                _cleanup_free_ char *word = NULL;
+                SessionDevice *sd;
+                dev_t dev;
+                int k;
+
+                k = extract_first_word(&p, &word, NULL, 0);
+                if (k == 0)
+                        break;
+                if (k < 0) {
+                        r = k;
+                        break;
+                }
+
+                k = parse_dev(word, &dev);
+                if (k < 0) {
+                        r = k;
+                        continue;
+                }
+
+                /* The file descriptors for loaded devices will be reattached later. */
+                k = session_device_new(s, dev, false, &sd);
+                if (k < 0)
+                        r = k;
+        }
+
+        if (r < 0)
+                log_error_errno(r, "Loading session devices for session %s failed: %m", s->id);
+
+        return r;
+}
 
 int session_load(Session *s) {
         _cleanup_free_ char *remote = NULL,
@@ -317,7 +368,9 @@ int session_load(Session *s) {
                 *uid = NULL,
                 *realtime = NULL,
                 *monotonic = NULL,
-                *controller = NULL;
+                *controller = NULL,
+                *active = NULL,
+                *devices = NULL;
 
         int k, r;
 
@@ -345,6 +398,8 @@ int session_load(Session *s) {
                            "REALTIME",       &realtime,
                            "MONOTONIC",      &monotonic,
                            "CONTROLLER",     &controller,
+                           "ACTIVE",         &active,
+                           "DEVICES",        &devices,
                            NULL);
 
         if (r < 0)
@@ -447,10 +502,17 @@ int session_load(Session *s) {
         if (monotonic)
                 timestamp_deserialize(monotonic, &s->timestamp.monotonic);
 
+        if (active) {
+                k = parse_boolean(active);
+                if (k >= 0)
+                        s->was_active = k;
+        }
+
         if (controller) {
-                if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
-                        session_set_controller(s, controller, false);
-                else
+                if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
+                        session_set_controller(s, controller, false, false);
+                        session_load_devices(s, devices);
+                } else
                         session_restore_vt(s);
         }
 
@@ -1170,7 +1232,7 @@ static int on_bus_track(sd_bus_track *track, void *userdata) {
         return 0;
 }
 
-int session_set_controller(Session *s, const char *sender, bool force) {
+int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
         _cleanup_free_ char *name = NULL;
         int r;
 
@@ -1202,11 +1264,14 @@ int session_set_controller(Session *s, const char *sender, bool force) {
          * Note that we reset the VT on ReleaseControl() and if the controller
          * exits.
          * If logind crashes/restarts, we restore the controller during restart
-         * or reset the VT in case it crashed/exited, too. */
-        r = session_prepare_vt(s);
-        if (r < 0) {
-                s->track = sd_bus_track_unref(s->track);
-                return r;
+         * (without preparing the VT since the controller has probably overridden
+         * VT state by now) or reset the VT in case it crashed/exited, too. */
+        if (prepare) {
+                r = session_prepare_vt(s);
+                if (r < 0) {
+                        s->track = sd_bus_track_unref(s->track);
+                        return r;
+                }
         }
 
         session_release_controller(s, true);
index ffb7cd2d4176ef174025e06bfd85cba2184b651c..12b9d86f55f9a565ca26ba925eedc5ca4eac1a2c 100644 (file)
@@ -111,6 +111,8 @@ struct Session {
         bool started:1;
         bool stopping:1;
 
+        bool was_active:1;
+
         sd_bus_message *create_message;
 
         sd_event_source *timer_event_source;
@@ -176,7 +178,7 @@ void session_restore_vt(Session *s);
 void session_leave_vt(Session *s);
 
 bool session_is_controller(Session *s, const char *sender);
-int session_set_controller(Session *s, const char *sender, bool force);
+int session_set_controller(Session *s, const char *sender, bool force, bool prepare);
 void session_drop_controller(Session *s);
 
 int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error);
index 19bae294a4a22aee0ff51ae0569cf19c50b3e709..fb70972b80906022f320b643e53520ecad96f7f2 100644 (file)
@@ -409,10 +409,71 @@ static int manager_enumerate_users(Manager *m) {
         return r;
 }
 
+static int manager_attach_fds(Manager *m) {
+        _cleanup_strv_free_ char **fdnames = NULL;
+        int n, i, fd;
+
+        /* Upon restart, PID1 will send us back all fds of session devices
+         * that we previously opened. Each file descriptor is associated
+         * with a given session. The session ids are passed through FDNAMES. */
+
+        n = sd_listen_fds_with_names(true, &fdnames);
+        if (n <= 0)
+                return n;
+
+        for (i = 0; i < n; i++) {
+                struct stat st;
+                SessionDevice *sd;
+                Session *s;
+                char *id;
+
+                fd = SD_LISTEN_FDS_START + i;
+
+                id = startswith(fdnames[i], "session-");
+                if (!id)
+                        continue;
+
+                s = hashmap_get(m->sessions, id);
+                if (!s) {
+                        /* If the session doesn't exist anymore, the associated session
+                         * device attached to this fd doesn't either. Let's simply close
+                         * this fd. */
+                        log_debug("Failed to attach fd for unknown session: %s", id);
+                        close_nointr(fd);
+                        continue;
+                }
+
+                if (fstat(fd, &st) < 0) {
+                        /* The device is allowed to go away at a random point, in which
+                         * case fstat failing is expected. */
+                        log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
+                        close_nointr(fd);
+                        continue;
+                }
+
+                sd = hashmap_get(s->devices, &st.st_rdev);
+                if (!sd) {
+                        /* Weird we got an fd for a session device which wasn't
+                        * recorded in the session state file... */
+                        log_warning("Got fd for missing session device [%u:%u] in session %s",
+                                    major(st.st_rdev), minor(st.st_rdev), s->id);
+                        close_nointr(fd);
+                        continue;
+                }
+
+                log_debug("Attaching fd to session device [%u:%u] for session %s",
+                          major(st.st_rdev), minor(st.st_rdev), s->id);
+
+                session_device_attach_fd(sd, fd, s->was_active);
+        }
+
+        return 0;
+}
+
 static int manager_enumerate_sessions(Manager *m) {
         _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
-        int r = 0;
+        int r = 0, k;
 
         assert(m);
 
@@ -427,7 +488,6 @@ static int manager_enumerate_sessions(Manager *m) {
 
         FOREACH_DIRENT(de, d, return -errno) {
                 struct Session *s;
-                int k;
 
                 if (!dirent_is_file(de))
                         continue;
@@ -441,7 +501,6 @@ static int manager_enumerate_sessions(Manager *m) {
                 k = manager_add_session(m, de->d_name, &s);
                 if (k < 0) {
                         log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
-
                         r = k;
                         continue;
                 }
@@ -453,6 +512,12 @@ static int manager_enumerate_sessions(Manager *m) {
                         r = k;
         }
 
+        /* We might be restarted and PID1 could have sent us back the
+         * session device fds we previously saved. */
+        k = manager_attach_fds(m);
+        if (k < 0)
+                log_warning_errno(k, "Failed to reattach session device fds: %m");
+
         return r;
 }
 
@@ -1004,10 +1069,10 @@ static int manager_parse_config_file(Manager *m) {
         assert(m);
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
-                                 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
-                                 "Login\0",
-                                 config_item_perf_lookup, logind_gperf_lookup,
-                                 false, m);
+                                        CONF_PATHS_NULSTR("systemd/logind.conf.d"),
+                                        "Login\0",
+                                        config_item_perf_lookup, logind_gperf_lookup,
+                                        false, m);
 }
 
 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
diff --git a/src/login/meson.build b/src/login/meson.build
new file mode 100644 (file)
index 0000000..26bdbec
--- /dev/null
@@ -0,0 +1,104 @@
+systemd_logind_sources = files('''
+        logind.c
+        logind.h
+'''.split())
+
+logind_gperf_c = custom_target(
+        'logind_gperf.c',
+        input : 'logind-gperf.gperf',
+        output : 'logind-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+systemd_logind_sources += [logind_gperf_c]
+
+
+liblogind_core_sources = files('''
+        logind-core.c
+        logind-device.c
+        logind-device.h
+        logind-button.c
+        logind-button.h
+        logind-action.c
+        logind-action.h
+        logind-seat.c
+        logind-seat.h
+        logind-session.c
+        logind-session.h
+        logind-session-device.c
+        logind-session-device.h
+        logind-user.c
+        logind-user.h
+        logind-inhibit.c
+        logind-inhibit.h
+        logind-dbus.c
+        logind-session-dbus.c
+        logind-seat-dbus.c
+        logind-user-dbus.c
+        logind-utmp.c
+        logind-acl.h
+'''.split())
+
+logind_acl_c = files('logind-acl.c')
+if conf.get('HAVE_ACL', false)
+        liblogind_core_sources += logind_acl_c
+endif
+
+liblogind_core = static_library(
+        'logind-core',
+        liblogind_core_sources,
+        include_directories : includes,
+        dependencies : [libacl])
+
+loginctl_sources = files('''
+        loginctl.c
+        sysfs-show.h
+        sysfs-show.c
+'''.split())
+
+if conf.get('ENABLE_LOGIND', false)
+        logind_conf = configure_file(
+                input : 'logind.conf.in',
+                output : 'logind.conf',
+                configuration : substs)
+        install_data(logind_conf,
+                     install_dir : pkgsysconfdir)
+
+        pam_systemd_sym = 'src/login/pam_systemd.sym'
+        pam_systemd_c = files('pam_systemd.c')
+
+        install_data('org.freedesktop.login1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.login1.service',
+                     install_dir : dbussystemservicedir)
+
+        custom_target(
+                'org.freedesktop.login1.policy',
+                input : 'org.freedesktop.login1.policy.in',
+                output : 'org.freedesktop.login1.policy',
+                command : intltool_command,
+                install : install_polkit,
+                install_dir : polkitpolicydir)
+
+        install_data('70-power-switch.rules',
+                     '70-uaccess.rules',
+                     install_dir : udevrulesdir)
+
+        foreach file : ['71-seat.rules',
+                        '73-seat-late.rules']
+                gen = configure_file(
+                        input : file + '.in',
+                        output : file,
+                        configuration : substs)
+                install_data(gen,
+                             install_dir : udevrulesdir)
+        endforeach
+
+        custom_target(
+                'systemd-user',
+                input : 'systemd-user.m4',
+                output: 'systemd-user',
+                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                capture : true,
+                install : pamconfdir != 'no',
+                install_dir : pamconfdir)
+endif
index 2f69e2c7b74b5edb641a1efa279ae7890a140f51..18e0e348965a3ee02b4ce1bded6a15a9b59a5925 100644 (file)
@@ -17,6 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/file.h>
 #include <sys/mount.h>
 
 #include "alloc-util.h"
index 28384286fb7b2bc69af6800ed1b49d02118cf6c5..a385e6819bcf5f80b9e238bdfc78023c6d1afb45 100644 (file)
@@ -340,6 +340,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
                         printf("No machines.\n");
         }
 
+        r = 0;
 out:
         clean_machine_info(machines, n_machines);
         return r;
@@ -2693,9 +2694,10 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --mkdir                  Create directory before bind mounting, if missing\n"
                "  -n --lines=INTEGER          Number of journal entries to show\n"
                "     --max-addresses=INTEGER  Number of internet addresses to show at most\n"
-               "  -o --output=STRING          Change journal output mode (short,\n"
-               "                              short-monotonic, verbose, export, json,\n"
-               "                              json-pretty, json-sse, cat)\n"
+               "  -o --output=STRING          Change journal output mode (short, short-precise,\n"
+               "                               short-iso, short-iso-precise, short-full,\n"
+               "                               short-monotonic, short-unix, verbose, export,\n"
+               "                               json, json-pretty, json-sse, cat)\n"
                "     --verify=MODE            Verification mode for downloaded images (no,\n"
                "                              checksum, signature)\n"
                "     --force                  Download image even if already exists\n\n"
diff --git a/src/machine/meson.build b/src/machine/meson.build
new file mode 100644 (file)
index 0000000..1a08133
--- /dev/null
@@ -0,0 +1,45 @@
+systemd_machined_sources = files('''
+        machined.c
+        machined.h
+'''.split())
+
+libmachine_core_sources = files('''
+        machine.c
+        machine.h
+        machined-dbus.c
+        machine-dbus.c
+        machine-dbus.h
+        image-dbus.c
+        image-dbus.h
+        operation.c
+        operation.h
+'''.split())
+
+libmachine_core = static_library(
+        'machine-core',
+        libmachine_core_sources,
+        include_directories : includes,
+        dependencies : [threads])
+
+if conf.get('ENABLE_MACHINED', false)
+        install_data('org.freedesktop.machine1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.machine1.service',
+                     install_dir : dbussystemservicedir)
+
+        custom_target(
+                'org.freedesktop.machine1.policy',
+                input : 'org.freedesktop.machine1.policy.in',
+                output : 'org.freedesktop.machine1.policy',
+                command : intltool_command,
+                install : install_polkit,
+                install_dir : polkitpolicydir)
+endif
+
+tests += [
+        [['src/machine/test-machine-tables.c'],
+         [libmachine_core,
+          libshared],
+         [threads],
+         'ENABLE_MACHINED'],
+]
index f7d5310f44395a0d5b181df94b4ac9f8ecb7a781..9b2d13dde1bacb1596cbefd39e00a851b422636f 100644 (file)
@@ -17,6 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/wait.h>
+
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "operation.h"
index b709166aa9104f85841618bc8a97243a67f3e9d4..ed6578d54021f88b5c1d1a06b73467c56b383496 100644 (file)
 #include "bus-error.h"
 #include "bus-unit-util.h"
 #include "bus-util.h"
+#include "dirent-util.h"
 #include "escape.h"
+#include "fd-util.h"
+#include "fileio.h"
 #include "fstab-util.h"
 #include "pager.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "spawn-polkit-agent.h"
+#include "stat-util.h"
 #include "strv.h"
 #include "udev-util.h"
 #include "unit-name.h"
@@ -77,7 +81,9 @@ static void polkit_agent_open_if_enabled(void) {
 }
 
 static void help(void) {
-        printf("%s [OPTIONS...] WHAT [WHERE]\n\n"
+        printf("systemd-mount [OPTIONS...] WHAT [WHERE]\n"
+               "systemd-mount [OPTIONS...] --list\n"
+               "%s [OPTIONS...] %sWHAT|WHERE...\n\n"
                "Establish a mount or auto-mount point transiently.\n\n"
                "  -h --help                       Show this help\n"
                "     --version                    Show package version\n"
@@ -100,8 +106,9 @@ static void help(void) {
                "                                  Set automount unit property\n"
                "     --bind-device                Bind automount unit to device\n"
                "     --list                       List mountable block devices\n"
-               "  -u --umount                     Unmount mount points\n"
-               , program_invocation_short_name);
+               "  -u --umount                     Unmount mount points\n",
+               program_invocation_short_name,
+               streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount ");
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -297,6 +304,21 @@ static int parse_argv(int argc, char *argv[]) {
                         log_error("Listing devices only supported locally.");
                         return -EOPNOTSUPP;
                 }
+        } else if (arg_action == ACTION_UMOUNT) {
+                if (optind >= argc) {
+                        log_error("At least one argument required.");
+                        return -EINVAL;
+                }
+
+                if (arg_transport != BUS_TRANSPORT_LOCAL) {
+                        int i;
+
+                        for (i = optind; i < argc; i++)
+                                if (!path_is_absolute(argv[i]) ) {
+                                        log_error("Only absolute path is supported: %s", argv[i]);
+                                        return -EINVAL;
+                                }
+                }
         } else {
                 if (optind >= argc) {
                         log_error("At least one argument required.");
@@ -308,14 +330,58 @@ static int parse_argv(int argc, char *argv[]) {
                         return -EINVAL;
                 }
 
-                arg_mount_what = fstab_node_to_udev_node(argv[optind]);
-                if (!arg_mount_what)
-                        return log_oom();
+                if (arg_transport == BUS_TRANSPORT_LOCAL) {
+                        _cleanup_free_ char *u = NULL, *p = NULL;
 
-                if (argc > optind+1) {
-                        r = path_make_absolute_cwd(argv[optind+1], &arg_mount_where);
+                        u = fstab_node_to_udev_node(argv[optind]);
+                        if (!u)
+                                return log_oom();
+
+                        r = path_make_absolute_cwd(u, &p);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to make path absolute: %m");
+
+                        arg_mount_what = canonicalize_file_name(p);
+                        if (!arg_mount_what)
+                                return log_error_errno(errno, "Failed to canonicalize path: %m");
+
+                } else {
+                        arg_mount_what = strdup(argv[optind+1]);
+                        if (!arg_mount_what)
+                                return log_oom();
+
+                        path_kill_slashes(arg_mount_what);
+
+                        if (!path_is_absolute(arg_mount_what)) {
+                                log_error("Only absolute path is supported: %s", arg_mount_what);
+                                return -EINVAL;
+                        }
+                }
+
+                if (argc > optind+1) {
+                        if (arg_transport == BUS_TRANSPORT_LOCAL) {
+                                _cleanup_free_ char *p = NULL;
+
+                                r = path_make_absolute_cwd(argv[optind+1], &p);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to make path absolute: %m");
+
+                                arg_mount_where = canonicalize_file_name(p);
+                                if (!arg_mount_where)
+                                        return log_error_errno(errno, "Failed to canonicalize path: %m");
+
+                        } else {
+                                arg_mount_where = strdup(argv[optind+1]);
+                                if (!arg_mount_where)
+                                        return log_oom();
+
+                                path_kill_slashes(arg_mount_where);
+
+                                if (!path_is_absolute(arg_mount_where)) {
+                                        log_error("Only absolute path is supported: %s", arg_mount_where);
+                                        return -EINVAL;
+                                }
+                        }
                 } else
                         arg_discover = true;
 
@@ -619,9 +685,127 @@ static int start_transient_automount(
         return 0;
 }
 
+static int find_mount_points(const char *what, char ***list) {
+        _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+        _cleanup_strv_free_ char **l = NULL;
+        size_t bufsize = 0, n = 0;
+
+        assert(what);
+        assert(list);
+
+        /* Returns all mount points obtained from /proc/self/mountinfo in *list,
+         * and the number of mount points as return value. */
+
+        proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+        if (!proc_self_mountinfo)
+                return log_error_errno(errno, "Can't open /proc/self/mountinfo: %m");
+
+        for (;;) {
+                _cleanup_free_ char *path = NULL, *where = NULL, *dev = NULL;
+                int r;
+
+                r = fscanf(proc_self_mountinfo,
+                           "%*s "       /* (1) mount id */
+                           "%*s "       /* (2) parent id */
+                           "%*s "       /* (3) major:minor */
+                           "%*s "       /* (4) root */
+                           "%ms "       /* (5) mount point */
+                           "%*s"        /* (6) mount options */
+                           "%*[^-]"     /* (7) optional fields */
+                           "- "         /* (8) separator */
+                           "%*s "       /* (9) file system type */
+                           "%ms"        /* (10) mount source */
+                           "%*s"        /* (11) mount options 2 */
+                           "%*[^\n]",   /* some rubbish at the end */
+                           &path, &dev);
+                if (r != 2) {
+                        if (r == EOF)
+                                break;
+
+                        continue;
+                }
+
+                if (!streq(what, dev))
+                        continue;
+
+                r = cunescape(path, UNESCAPE_RELAX, &where);
+                if (r < 0)
+                        continue;
+
+                /* one extra slot is needed for the terminating NULL */
+                if (!GREEDY_REALLOC(l, bufsize, n + 2))
+                        return log_oom();
+
+                l[n++] = where;
+                where = NULL;
+        }
+
+        if (!GREEDY_REALLOC(l, bufsize, n + 1))
+                return log_oom();
+
+        l[n] = NULL;
+        *list = l;
+        l = NULL; /* avoid freeing */
+
+        return n;
+}
+
+static int find_loop_device(const char *backing_file, char **loop_dev) {
+        _cleanup_closedir_ DIR *d = NULL;
+        struct dirent *de;
+        _cleanup_free_ char *l = NULL;
+
+        assert(backing_file);
+        assert(loop_dev);
+
+        d = opendir("/sys/devices/virtual/block");
+        if (!d)
+                return -errno;
+
+        FOREACH_DIRENT(de, d, return -errno) {
+                _cleanup_free_ char *sys = NULL, *fname = NULL;
+                int r;
+
+                dirent_ensure_type(d, de);
+
+                if (de->d_type != DT_DIR)
+                        continue;
+
+                if (!startswith(de->d_name, "loop"))
+                        continue;
+
+                sys = strjoin("/sys/devices/virtual/block/", de->d_name, "/loop/backing_file");
+                if (!sys)
+                        return -ENOMEM;
+
+                r = read_one_line_file(sys, &fname);
+                if (r < 0) {
+                        log_debug_errno(r, "Failed to read %s, ignoring: %m", sys);
+                        continue;
+                }
+
+                if (files_same(fname, backing_file, 0) <= 0)
+                        continue;
+
+                l = strjoin("/dev/", de->d_name);
+                if (!l)
+                        return -ENOMEM;
+
+                break;
+        }
+
+        if (!l)
+                return -ENXIO;
+
+        *loop_dev = l;
+        l = NULL; /* avoid freeing */
+
+        return 0;
+}
+
 static int stop_mount(
                 sd_bus *bus,
-                char **argv,
+                const char *where,
                 const char *suffix) {
 
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
@@ -636,9 +820,9 @@ static int stop_mount(
                         return log_error_errno(r, "Could not watch jobs: %m");
         }
 
-        r = unit_name_from_path(arg_mount_where, suffix, &mount_unit);
+        r = unit_name_from_path(where, suffix, &mount_unit);
         if (r < 0)
-                return log_error_errno(r, "Failed to make mount unit name: %m");
+                return log_error_errno(r, "Failed to make mount unit name from path %s: %m", where);
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -680,28 +864,162 @@ static int stop_mount(
         if (!arg_quiet)
                 log_info("Stopped unit %s%s%s for mount point: %s%s%s",
                          ansi_highlight(), mount_unit, ansi_normal(),
-                         ansi_highlight(), arg_mount_where, ansi_normal());
+                         ansi_highlight(), where, ansi_normal());
 
         return 0;
 }
 
 static int stop_mounts(
                 sd_bus *bus,
-                char **argv) {
+                const char *where) {
 
         int r;
 
-        r = stop_mount(bus, argv + optind, ".mount");
+        if (path_equal(where, "/")) {
+                log_error("Refusing to operate on root directory: %s", where);
+                return -EINVAL;
+        }
+
+        if (!path_is_safe(where)) {
+                log_error("Path contains unsafe components: %s", where);
+                return -EINVAL;
+        }
+
+        r = stop_mount(bus, where, ".mount");
         if (r < 0)
                 return r;
 
-        r = stop_mount(bus, argv + optind, ".automount");
+        r = stop_mount(bus, where, ".automount");
         if (r < 0)
                 return r;
 
         return 0;
 }
 
+static int umount_by_device(sd_bus *bus, const char *what) {
+        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+        _cleanup_udev_unref_ struct udev *udev = NULL;
+        _cleanup_strv_free_ char **list = NULL;
+        struct stat st;
+        const char *v;
+        char **l;
+        int r, r2 = 0;
+
+        assert(what);
+
+        if (stat(what, &st) < 0)
+                return log_error_errno(errno, "Can't stat %s: %m", what);
+
+        if (!S_ISBLK(st.st_mode)) {
+                log_error("Not a block device: %s", what);
+                return -ENOTBLK;
+        }
+
+        udev = udev_new();
+        if (!udev)
+                return log_oom();
+
+        d = udev_device_new_from_devnum(udev, 'b', st.st_rdev);
+        if (!d)
+                return log_oom();
+
+        v = udev_device_get_property_value(d, "ID_FS_USAGE");
+        if (!streq_ptr(v, "filesystem")) {
+                log_error("%s does not contain a known file system.", what);
+                return -EINVAL;
+        }
+
+        v = udev_device_get_property_value(d, "SYSTEMD_MOUNT_WHERE");
+        if (!isempty(v))
+                r2 = stop_mounts(bus, v);
+
+        r = find_mount_points(what, &list);
+        if (r < 0)
+                return r;
+
+        for (l = list; *l; l++) {
+                r = stop_mounts(bus, *l);
+                if (r < 0)
+                        r2 = r;
+        }
+
+        return r2;
+}
+
+static int umount_loop(sd_bus *bus, const char *backing_file) {
+        _cleanup_free_ char *loop_dev = NULL;
+        int r;
+
+        assert(backing_file);
+
+        r = find_loop_device(backing_file, &loop_dev);
+        if (r < 0)
+                return log_error_errno(r, r == -ENXIO ? "File %s is not mounted." : "Can't get loop device for %s: %m", backing_file);
+
+        return umount_by_device(bus, loop_dev);
+}
+
+static int action_umount(
+                sd_bus *bus,
+                int argc,
+                char **argv) {
+
+        int i, r, r2 = 0;
+
+        if (arg_transport != BUS_TRANSPORT_LOCAL) {
+                for (i = optind; i < argc; i++) {
+                        _cleanup_free_ char *p = NULL;
+
+                        p = strdup(argv[i]);
+                        if (!p)
+                                return log_oom();
+
+                        path_kill_slashes(p);
+
+                        r = stop_mounts(bus, p);
+                        if (r < 0)
+                                r2 = r;
+                }
+                return r2;
+        }
+
+        for (i = optind; i < argc; i++) {
+                _cleanup_free_ char *u = NULL, *a = NULL, *p = NULL;
+                struct stat st;
+
+                u = fstab_node_to_udev_node(argv[i]);
+                if (!u)
+                        return log_oom();
+
+                r = path_make_absolute_cwd(u, &a);
+                if (r < 0) {
+                        r2 = log_error_errno(r, "Failed to make path absolute: %m");
+                        continue;
+                }
+
+                p = canonicalize_file_name(a);
+
+                if (stat(p, &st) < 0)
+                        return log_error_errno(errno, "Can't stat %s: %m", p);
+
+                if (S_ISBLK(st.st_mode))
+                        r = umount_by_device(bus, p);
+                else if (S_ISREG(st.st_mode))
+                        r = umount_loop(bus, p);
+                else if (S_ISDIR(st.st_mode))
+                        r = stop_mounts(bus, p);
+                else {
+                        log_error("Invalid file type: %s", p);
+                        r = -EINVAL;
+                }
+
+                if (r < 0)
+                        r2 = r;
+        }
+
+        return r2;
+}
+
 static int acquire_mount_type(struct udev_device *d) {
         const char *v;
 
@@ -789,6 +1107,8 @@ static int acquire_mount_where(struct udev_device *d) {
                 }
 
                 escaped = xescape(name, "\\");
+                if (!escaped)
+                        return log_oom();
                 if (!filename_is_valid(escaped))
                         return 0;
 
@@ -803,6 +1123,32 @@ static int acquire_mount_where(struct udev_device *d) {
         return 1;
 }
 
+static int acquire_mount_where_for_loop_dev(const char *loop_dev) {
+        _cleanup_strv_free_ char **list = NULL;
+        int r;
+
+        if (arg_mount_where)
+                return 0;
+
+        r = find_mount_points(loop_dev, &list);
+        if (r < 0)
+                return r;
+        else if (r == 0) {
+                log_error("Can't find mount point of %s. It is expected that %s is already mounted on a place.", loop_dev, loop_dev);
+                return -EINVAL;
+        } else if (r >= 2) {
+                log_error("%s is mounted on %d places. It is expected that %s is mounted on a place.", loop_dev, r, loop_dev);
+                return -EINVAL;
+        }
+
+        arg_mount_where = strdup(list[0]);
+        if (!arg_mount_where)
+                return log_oom();
+
+        log_debug("Discovered where=%s", arg_mount_where);
+        return 1;
+}
+
 static int acquire_description(struct udev_device *d) {
         const char *model, *label;
 
@@ -874,27 +1220,97 @@ static int acquire_removable(struct udev_device *d) {
         return 1;
 }
 
-static int discover_device(void) {
+static int discover_loop_backing_file(void) {
         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
         _cleanup_udev_unref_ struct udev *udev = NULL;
+        _cleanup_free_ char *loop_dev = NULL;
         struct stat st;
         const char *v;
         int r;
 
-        if (!arg_discover)
+        r = find_loop_device(arg_mount_what, &loop_dev);
+        if (r < 0 && r != -ENXIO)
+                return log_error_errno(errno, "Can't get loop device for %s: %m", arg_mount_what);
+
+        if (r == -ENXIO) {
+                _cleanup_free_ char *escaped = NULL;
+
+                if (arg_mount_where)
+                        return 0;
+
+                escaped = xescape(basename(arg_mount_what), "\\");
+                if (!escaped)
+                        return log_oom();
+                if (!filename_is_valid(escaped)) {
+                        log_error("Escaped name %s is not a valid filename.", escaped);
+                        return -EINVAL;
+                }
+
+                arg_mount_where = strjoin("/run/media/system/", escaped);
+                if (!arg_mount_where)
+                        return log_oom();
+
+                log_debug("Discovered where=%s", arg_mount_where);
                 return 0;
+        }
+
+        if (stat(loop_dev, &st) < 0)
+                return log_error_errno(errno, "Can't stat %s: %m", loop_dev);
 
-        if (!is_device_path(arg_mount_what)) {
-                log_error("Discovery only supported for block devices, don't know what to do.");
+        if (!S_ISBLK(st.st_mode)) {
+                log_error("Invalid file type: %s", loop_dev);
                 return -EINVAL;
         }
 
+        udev = udev_new();
+        if (!udev)
+                return log_oom();
+
+        d = udev_device_new_from_devnum(udev, 'b', st.st_rdev);
+        if (!d)
+                return log_oom();
+
+        v = udev_device_get_property_value(d, "ID_FS_USAGE");
+        if (!streq_ptr(v, "filesystem")) {
+                log_error("%s does not contain a known file system.", arg_mount_what);
+                return -EINVAL;
+        }
+
+        r = acquire_mount_type(d);
+        if (r < 0)
+                return r;
+
+        r = acquire_mount_options(d);
+        if (r < 0)
+                return r;
+
+        r = acquire_mount_where_for_loop_dev(loop_dev);
+        if (r < 0)
+                return r;
+
+        r = acquire_description(d);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+static int discover_device(void) {
+        _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+        _cleanup_udev_unref_ struct udev *udev = NULL;
+        struct stat st;
+        const char *v;
+        int r;
+
         if (stat(arg_mount_what, &st) < 0)
                 return log_error_errno(errno, "Can't stat %s: %m", arg_mount_what);
 
+        if (S_ISREG(st.st_mode))
+                return discover_loop_backing_file();
+
         if (!S_ISBLK(st.st_mode)) {
-                log_error("Path %s is not a block device, don't know what to do.", arg_mount_what);
-                return -ENOTBLK;
+                log_error("Invalid file type: %s", arg_mount_what);
+                return -EINVAL;
         }
 
         udev = udev_new();
@@ -907,7 +1323,7 @@ static int discover_device(void) {
 
         v = udev_device_get_property_value(d, "ID_FS_USAGE");
         if (!streq_ptr(v, "filesystem")) {
-                log_error("%s does not contain a file system.", arg_mount_what);
+                log_error("%s does not contain a known file system.", arg_mount_what);
                 return -EINVAL;
         }
 
@@ -1130,17 +1546,35 @@ int main(int argc, char* argv[]) {
                 goto finish;
         }
 
-        r = discover_device();
-        if (r < 0)
+        r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
+        if (r < 0) {
+                log_error_errno(r, "Failed to create bus connection: %m");
+                goto finish;
+        }
+
+        if (arg_action == ACTION_UMOUNT) {
+                r = action_umount(bus, argc, argv);
+                goto finish;
+        }
+
+        if (!path_is_safe(arg_mount_what)) {
+                log_error("Path contains unsafe components: %s", arg_mount_what);
+                r = -EINVAL;
                 goto finish;
+        }
+
+        if (arg_discover) {
+                r = discover_device();
+                if (r < 0)
+                        goto finish;
+        }
+
         if (!arg_mount_where) {
                 log_error("Can't figure out where to mount %s.", arg_mount_what);
                 r = -EINVAL;
                 goto finish;
         }
 
-        path_kill_slashes(arg_mount_where);
-
         if (path_equal(arg_mount_where, "/")) {
                 log_error("Refusing to operate on root directory.");
                 r = -EINVAL;
@@ -1148,7 +1582,7 @@ int main(int argc, char* argv[]) {
         }
 
         if (!path_is_safe(arg_mount_where)) {
-                log_error("Path is contains unsafe components.");
+                log_error("Path contains unsafe components: %s", arg_mount_where);
                 r = -EINVAL;
                 goto finish;
         }
@@ -1171,12 +1605,6 @@ int main(int argc, char* argv[]) {
                 }
         }
 
-        r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
-        if (r < 0) {
-                log_error_errno(r, "Failed to create bus connection: %m");
-                goto finish;
-        }
-
         switch (arg_action) {
 
         case ACTION_MOUNT:
@@ -1188,10 +1616,6 @@ int main(int argc, char* argv[]) {
                 r = start_transient_automount(bus, argv + optind);
                 break;
 
-        case ACTION_UMOUNT:
-                r = stop_mounts(bus, argv + optind);
-                break;
-
         default:
                 assert_not_reached("Unexpected action.");
         }
diff --git a/src/network/meson.build b/src/network/meson.build
new file mode 100644 (file)
index 0000000..35ecd86
--- /dev/null
@@ -0,0 +1,150 @@
+sources = files('''
+        netdev/bond.c
+        netdev/bond.h
+        netdev/bridge.c
+        netdev/bridge.h
+        netdev/dummy.c
+        netdev/dummy.h
+        netdev/ipvlan.c
+        netdev/ipvlan.h
+        netdev/macvlan.c
+        netdev/macvlan.h
+        netdev/netdev.c
+        netdev/netdev.h
+        netdev/tunnel.c
+        netdev/tunnel.h
+        netdev/tuntap.c
+        netdev/tuntap.h
+        netdev/vcan.c
+        netdev/vcan.h
+        netdev/veth.c
+        netdev/veth.h
+        netdev/vlan.c
+        netdev/vlan.h
+        netdev/vrf.c
+        netdev/vrf.h
+        netdev/vxlan.c
+        netdev/vxlan.h
+        netdev/geneve.c
+        netdev/geneve.h
+        networkd-address-label.c
+        networkd-address-label.h
+        networkd-address-pool.c
+        networkd-address-pool.h
+        networkd-address.c
+        networkd-address.h
+        networkd-brvlan.c
+        networkd-brvlan.h
+        networkd-conf.c
+        networkd-conf.h
+        networkd-dhcp4.c
+        networkd-dhcp6.c
+        networkd-fdb.c
+        networkd-fdb.h
+        networkd-ipv4ll.c
+        networkd-ipv6-proxy-ndp.c
+        networkd-ipv6-proxy-ndp.h
+        networkd-link-bus.c
+        networkd-link.c
+        networkd-link.h
+        networkd-lldp-tx.c
+        networkd-lldp-tx.h
+        networkd-manager-bus.c
+        networkd-manager.c
+        networkd-manager.h
+        networkd-ndisc.c
+        networkd-ndisc.h
+        networkd-radv.c
+        networkd-radv.h
+        networkd-network-bus.c
+        networkd-network.c
+        networkd-network.h
+        networkd-route.c
+        networkd-route.h
+        networkd-util.c
+        networkd-util.h
+'''.split())
+
+systemd_networkd_sources = files('networkd.c')
+
+systemd_networkd_wait_online_sources = files('''
+        wait-online/link.c
+        wait-online/link.h
+        wait-online/manager.c
+        wait-online/manager.h
+        wait-online/wait-online.c
+'''.split()) + network_internal_h
+
+networkctl_sources = files('networkctl.c')
+
+network_include_dir = include_directories('.')
+
+if conf.get('ENABLE_NETWORKD', false)
+        networkd_gperf_c = custom_target(
+                'networkd-gperf.c',
+                input : 'networkd-gperf.gperf',
+                output : 'networkd-gperf.c',
+                command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+        networkd_network_gperf_c = custom_target(
+                'networkd-network-gperf.c',
+                input : 'networkd-network-gperf.gperf',
+                output : 'networkd-network-gperf.c',
+                command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+        netdev_gperf_c = custom_target(
+                'netdev-gperf.c',
+                input : 'netdev/netdev-gperf.gperf',
+                output : 'netdev-gperf.c',
+                command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+        libnetworkd_core = static_library(
+                'networkd-core',
+                sources,
+                network_internal_h,
+                networkd_gperf_c,
+                networkd_network_gperf_c,
+                netdev_gperf_c,
+                include_directories : includes,
+                link_with : [libshared])
+
+        install_data('org.freedesktop.network1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.network1.service',
+                     install_dir : dbussystemservicedir)
+        if install_polkit
+                install_data('systemd-networkd.rules',
+                             install_dir : polkitrulesdir)
+        endif
+        if install_polkit_pkla
+                install_data('systemd-networkd.pkla',
+                             install_dir : polkitpkladir)
+        endif
+
+        tests += [
+    [['src/network/test-networkd-conf.c'],
+     [libnetworkd_core,
+      libsystemd_network,
+      libudev],
+     []],
+
+    [['src/network/test-network.c'],
+     [libnetworkd_core,
+      libudev_internal,
+      libsystemd_network,
+      libshared],
+     [threads]],
+
+    [['src/network/test-network-tables.c',
+      'src/network/test-network-tables.c',
+      test_tables_h],
+     [libnetworkd_core,
+      libudev_internal,
+      libudev_core,
+      libsystemd_network,
+      libshared],
+     [threads],
+     '', '', [],
+     [network_include_dir] + libudev_core_includes],
+  ]
+endif
index 9fdcb55376ce4af96b2f799f5f418d3677f6b5a6..cf6c591f8bfcd209dcca0c1c8a7f054178265d2d 100644 (file)
@@ -24,6 +24,7 @@
 #include "netlink-util.h"
 #include "netdev/bridge.h"
 #include "networkd-manager.h"
+#include "vlan-util.h"
 
 /* callback for brige netdev's parameter set */
 static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
@@ -102,7 +103,7 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_PRIORITY attribute: %m");
         }
 
-        if (b->default_pvid > 0) {
+        if (b->default_pvid != VLANID_INVALID) {
                 r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_DEFAULT_PVID, b->default_pvid);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m");
@@ -160,6 +161,7 @@ static void bridge_init(NetDev *n) {
         b->mcast_snooping = -1;
         b->vlan_filtering = -1;
         b->stp = -1;
+        b->default_pvid = VLANID_INVALID;
         b->forward_delay = USEC_INFINITY;
 }
 
diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c
new file mode 100644 (file)
index 0000000..e71ea58
--- /dev/null
@@ -0,0 +1,315 @@
+/***
+    This file is part of systemd.
+
+    Copyright 2017 Susant Sahani
+
+    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 <net/if.h>
+
+#include "alloc-util.h"
+#include "conf-parser.h"
+#include "extract-word.h"
+#include "geneve.h"
+#include "parse-util.h"
+#include "sd-netlink.h"
+#include "string-util.h"
+#include "strv.h"
+#include "missing.h"
+#include "networkd-manager.h"
+
+#define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
+#define DEFAULT_GENEVE_DESTINATION_PORT 6081
+
+/* callback for geneve netdev's created without a backing Link */
+static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+        _cleanup_netdev_unref_ NetDev *netdev = userdata;
+        int r;
+
+        assert(netdev->state != _NETDEV_STATE_INVALID);
+
+        r = sd_netlink_message_get_errno(m);
+        if (r == -EEXIST)
+                log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters");
+        else if (r < 0) {
+                log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m");
+                netdev_drop(netdev);
+
+                return 1;
+        }
+
+        log_netdev_debug(netdev, "Geneve created");
+
+        return 1;
+}
+
+static int netdev_geneve_create(NetDev *netdev) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        Geneve *v;
+        int r;
+
+        assert(netdev);
+
+        v = GENEVE(netdev);
+
+        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m");
+
+        r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");
+
+        if (netdev->mac) {
+                r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
+        }
+
+        if (netdev->mtu) {
+                r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
+        }
+
+        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        if (v->id <= GENEVE_VID_MAX) {
+                r = sd_netlink_message_append_u32(m, IFLA_GENEVE_ID, v->id);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_ID attribute: %m");
+        }
+
+        if (!in_addr_is_null(v->remote_family, &v->remote)) {
+
+                if (v->remote_family == AF_INET)
+                        r = sd_netlink_message_append_in_addr(m, IFLA_GENEVE_REMOTE, &v->remote.in);
+                else
+                        r = sd_netlink_message_append_in6_addr(m, IFLA_GENEVE_REMOTE6, &v->remote.in6);
+
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_GROUP attribute: %m");
+
+        }
+
+        if (v->ttl) {
+                r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
+        }
+
+        r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TOS, v->tos);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TOS attribute: %m");
+
+        r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_CSUM, v->udpcsum);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
+
+        r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
+
+        r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
+
+        if (v->dest_port != DEFAULT_GENEVE_DESTINATION_PORT) {
+                r = sd_netlink_message_append_u16(m, IFLA_GENEVE_PORT, htobe16(v->dest_port));
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_PORT attribute: %m");
+        }
+
+        if (v->flow_label > 0) {
+                r = sd_netlink_message_append_u32(m, IFLA_GENEVE_LABEL, htobe32(v->flow_label));
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(m);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        r = sd_netlink_message_close_container(m);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+        r = sd_netlink_call_async(netdev->manager->rtnl, m, geneve_netdev_create_handler, netdev, 0, NULL);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
+
+        netdev_ref(netdev);
+
+        netdev->state = NETDEV_STATE_CREATING;
+
+        log_netdev_debug(netdev, "Creating");
+
+
+        return r;
+}
+
+int config_parse_geneve_vni(const char *unit,
+                           const char *filename,
+                           unsigned line,
+                           const char *section,
+                           unsigned section_line,
+                           const char *lvalue,
+                           int ltype,
+                           const char *rvalue,
+                           void *data,
+                           void *userdata) {
+        Geneve *v = userdata;
+        uint32_t f;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou32(rvalue, &f);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve VNI '%s'.", rvalue);
+                return 0;
+        }
+
+        if (f > GENEVE_VID_MAX){
+                log_syntax(unit, LOG_ERR, filename, line, r, "Geneve VNI out is of range '%s'.", rvalue);
+                return 0;
+        }
+
+        v->id = f;
+
+        return 0;
+}
+
+int config_parse_geneve_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) {
+        Geneve *v = userdata;
+        union in_addr_union *addr = data, buffer;
+        int r, f;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = in_addr_from_string_auto(rvalue, &f, &buffer);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        r = in_addr_is_multicast(f, &buffer);
+        if (r > 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        v->remote_family = f;
+        *addr = buffer;
+
+        return 0;
+}
+
+int config_parse_geneve_flow_label(const char *unit,
+                                   const char *filename,
+                                   unsigned line,
+                                   const char *section,
+                                   unsigned section_line,
+                                   const char *lvalue,
+                                   int ltype,
+                                   const char *rvalue,
+                                   void *data,
+                                   void *userdata) {
+        Geneve *v = userdata;
+        uint32_t f;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou32(rvalue, &f);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve flow label '%s'.", rvalue);
+                return 0;
+        }
+
+        if (f & ~GENEVE_FLOW_LABEL_MAX_MASK) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue);
+                return 0;
+        }
+
+        v->flow_label = f;
+
+        return 0;
+}
+
+static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
+        Geneve *v = GENEVE(netdev);
+
+        assert(netdev);
+        assert(v);
+        assert(filename);
+
+        if (v->ttl == 0) {
+                log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename);
+                return -EINVAL;
+        }
+
+        return 0;
+}
+
+static void geneve_init(NetDev *netdev) {
+        Geneve *v;
+
+        assert(netdev);
+
+        v = GENEVE(netdev);
+
+        assert(v);
+
+        v->id = GENEVE_VID_MAX + 1;
+        v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
+        v->udpcsum = false;
+        v->udp6zerocsumtx = false;
+        v->udp6zerocsumrx = false;
+}
+
+const NetDevVTable geneve_vtable = {
+        .object_size = sizeof(Geneve),
+        .init = geneve_init,
+        .sections = "Match\0NetDev\0GENEVE\0",
+        .create = netdev_geneve_create,
+        .create_type = NETDEV_CREATE_INDEPENDENT,
+        .config_verify = netdev_geneve_verify,
+};
diff --git a/src/network/netdev/geneve.h b/src/network/netdev/geneve.h
new file mode 100644 (file)
index 0000000..bde28ba
--- /dev/null
@@ -0,0 +1,85 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2017 Susant Sahani
+
+  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/>.
+***/
+
+typedef struct Geneve Geneve;
+
+#include "in-addr-util.h"
+#include "netdev.h"
+#include "networkd-link.h"
+#include "networkd-network.h"
+
+#define GENEVE_VID_MAX (1u << 24) - 1
+
+struct Geneve {
+        NetDev meta;
+
+        uint32_t id;
+        uint32_t flow_label;
+
+        int remote_family;
+
+        uint8_t tos;
+        uint8_t ttl;
+
+        uint16_t dest_port;
+
+        bool udpcsum;
+        bool udp6zerocsumtx;
+        bool udp6zerocsumrx;
+
+        union in_addr_union remote;
+};
+
+DEFINE_NETDEV_CAST(GENEVE, Geneve);
+extern const NetDevVTable geneve_vtable;
+
+int config_parse_geneve_vni(const char *unit,
+                            const char *filename,
+                            unsigned line,
+                            const char *section,
+                            unsigned section_line,
+                            const char *lvalue,
+                            int ltype,
+                            const char *rvalue,
+                            void *data,
+                            void *userdata);
+
+int config_parse_geneve_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_geneve_flow_label(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);
index e19fa9817e288fff92481d76fccd8fbbc458c9fa..8b235a485799826afcc6fe2db1b3c5172e8c9fdf 100644 (file)
@@ -4,6 +4,7 @@
 #include "network-internal.h"
 #include "netdev/bond.h"
 #include "netdev/bridge.h"
+#include "netdev/geneve.h"
 #include "netdev/ipvlan.h"
 #include "netdev/macvlan.h"
 #include "netdev/tunnel.h"
@@ -36,6 +37,10 @@ NetDev.Kind,                 config_parse_netdev_kind,             0,
 NetDev.MTUBytes,             config_parse_iec_size,                0,                             offsetof(NetDev, mtu)
 NetDev.MACAddress,           config_parse_hwaddr,                  0,                             offsetof(NetDev, mac)
 VLAN.Id,                     config_parse_vlanid,                  0,                             offsetof(VLan, id)
+VLAN.GVRP,                   config_parse_tristate,                0,                             offsetof(VLan, gvrp)
+VLAN.MVRP,                   config_parse_tristate,                0,                             offsetof(VLan, mvrp)
+VLAN.LooseBinding,           config_parse_tristate,                0,                             offsetof(VLan, loose_binding)
+VLAN.ReorderHeader,          config_parse_tristate,                0,                             offsetof(VLan, reorder_hdr)
 MACVLAN.Mode,                config_parse_macvlan_mode,            0,                             offsetof(MacVlan, mode)
 MACVTAP.Mode,                config_parse_macvlan_mode,            0,                             offsetof(MacVlan, mode)
 IPVLAN.Mode,                 config_parse_ipvlan_mode,             0,                             offsetof(IPVlan, mode)
@@ -77,7 +82,17 @@ VXLAN.FDBAgeingSec,          config_parse_sec,                     0,
 VXLAN.GroupPolicyExtension,  config_parse_bool,                    0,                             offsetof(VxLan, group_policy)
 VXLAN.MaximumFDBEntries,     config_parse_unsigned,                0,                             offsetof(VxLan, max_fdb)
 VXLAN.PortRange,             config_parse_port_range,              0,                             0
-VXLAN.DestinationPort,       config_parse_destination_port,        0,                             offsetof(VxLan, dest_port)
+VXLAN.DestinationPort,       config_parse_ip_port,                 0,                             offsetof(VxLan, dest_port)
+VXLAN.FlowLabel,             config_parse_flow_label,              0,                             0
+GENEVE.Id,                   config_parse_geneve_vni,              0,                             offsetof(Geneve, id)
+GENEVE.Remote,               config_parse_geneve_address,          0,                             offsetof(Geneve, remote)
+GENEVE.TOS,                  config_parse_uint8,                   0,                             offsetof(Geneve, tos)
+GENEVE.TTL,                  config_parse_uint8,                   0,                             offsetof(Geneve, ttl)
+GENEVE.UDPChecksum,          config_parse_bool,                    0,                             offsetof(Geneve, udpcsum)
+GENEVE.UDP6ZeroCheckSumRx,   config_parse_bool,                    0,                             offsetof(Geneve, udp6zerocsumrx)
+GENEVE.UDP6ZeroCheckSumTx,   config_parse_bool,                    0,                             offsetof(Geneve, udp6zerocsumtx)
+GENEVE.DestinationPort,      config_parse_ip_port,                 0,                             offsetof(Geneve, dest_port)
+GENEVE.FlowLabel,            config_parse_geneve_flow_label,       0,                             0
 Tun.OneQueue,                config_parse_bool,                    0,                             offsetof(TunTap, one_queue)
 Tun.MultiQueue,              config_parse_bool,                    0,                             offsetof(TunTap, multi_queue)
 Tun.PacketInfo,              config_parse_bool,                    0,                             offsetof(TunTap, packet_info)
@@ -113,7 +128,7 @@ Bridge.MaxAgeSec,            config_parse_sec,                     0,
 Bridge.AgeingTimeSec,        config_parse_sec,                     0,                             offsetof(Bridge, ageing_time)
 Bridge.ForwardDelaySec,      config_parse_sec,                     0,                             offsetof(Bridge, forward_delay)
 Bridge.Priority,             config_parse_uint16,                  0,                             offsetof(Bridge, priority)
-Bridge.DefaultPVID,          config_parse_vlanid,                  0,                             offsetof(Bridge, default_pvid)
+Bridge.DefaultPVID,          config_parse_default_port_vlanid,     0,                             offsetof(Bridge, default_pvid)
 Bridge.MulticastQuerier,     config_parse_tristate,                0,                             offsetof(Bridge, mcast_querier)
 Bridge.MulticastSnooping,    config_parse_tristate,                0,                             offsetof(Bridge, mcast_snooping)
 Bridge.VLANFiltering,        config_parse_tristate,                0,                             offsetof(Bridge, vlan_filtering)
index 9b9e83d9db4242751532c1a9e0ba1cb7c8c054ae..43884581caf81ab9ae7099ce4aeb2967bc21b6b1 100644 (file)
@@ -28,6 +28,7 @@
 #include "network-internal.h"
 #include "netdev/netdev.h"
 #include "networkd-manager.h"
+#include "networkd-link.h"
 #include "siphash24.h"
 #include "stat-util.h"
 #include "string-table.h"
@@ -35,6 +36,7 @@
 
 #include "netdev/bridge.h"
 #include "netdev/bond.h"
+#include "netdev/geneve.h"
 #include "netdev/vlan.h"
 #include "netdev/macvlan.h"
 #include "netdev/ipvlan.h"
@@ -69,6 +71,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
         [NETDEV_KIND_VRF] = &vrf_vtable,
         [NETDEV_KIND_VCAN] = &vcan_vtable,
+        [NETDEV_KIND_GENEVE] = &geneve_vtable,
 };
 
 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -94,6 +97,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_IP6TNL] = "ip6tnl",
         [NETDEV_KIND_VRF] = "vrf",
         [NETDEV_KIND_VCAN] = "vcan",
+        [NETDEV_KIND_GENEVE] = "geneve",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -218,6 +222,13 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h
         assert(link);
         assert(callback);
 
+        if (link->flags & IFF_UP) {
+                log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname);
+                r = link_down(link);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not bring link down: %m");
+        }
+
         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m");
index 37c74312132bc0948b52c690c16ea9f377bb5533..a961e2ac3b44189c0cabca88f00213798432e662 100644 (file)
@@ -57,6 +57,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_TAP,
         NETDEV_KIND_VRF,
         NETDEV_KIND_VCAN,
+        NETDEV_KIND_GENEVE,
         _NETDEV_KIND_MAX,
         _NETDEV_KIND_INVALID = -1
 } NetDevKind;
index 28c061fa4f90effb7c9858349918a3a0ebeaee02..6f41633eade74da08b9f4c0cbd71010b8a1b4ff5 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <linux/if_vlan.h>
 #include <net/if.h>
 
 #include "netdev/vlan.h"
 #include "vlan-util.h"
 
 static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) {
+        struct ifla_vlan_flags flags = {};
         VLan *v;
         int r;
 
@@ -38,6 +40,30 @@ static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlin
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m");
 
+        if (v->gvrp != -1) {
+                flags.mask |= VLAN_FLAG_GVRP;
+                SET_FLAG(flags.flags, VLAN_FLAG_GVRP, v->gvrp);
+        }
+
+        if (v->mvrp != -1) {
+                flags.mask |= VLAN_FLAG_MVRP;
+                SET_FLAG(flags.flags, VLAN_FLAG_MVRP, v->mvrp);
+        }
+
+        if (v->reorder_hdr != -1) {
+                flags.mask |= VLAN_FLAG_REORDER_HDR;
+                SET_FLAG(flags.flags, VLAN_FLAG_REORDER_HDR, v->reorder_hdr);
+        }
+
+        if (v->loose_binding != -1) {
+                flags.mask |= VLAN_FLAG_LOOSE_BINDING;
+                SET_FLAG(flags.flags, VLAN_FLAG_LOOSE_BINDING, v->loose_binding);
+        }
+
+        r = sd_netlink_message_append_data(req, IFLA_VLAN_FLAGS, &flags, sizeof(struct ifla_vlan_flags));
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_FLAGS attribute: %m");
+
         return 0;
 }
 
@@ -66,6 +92,10 @@ static void vlan_init(NetDev *netdev) {
         assert(v);
 
         v->id = VLANID_INVALID;
+        v->gvrp = -1;
+        v->mvrp = -1;
+        v->loose_binding = -1;
+        v->reorder_hdr = -1;
 }
 
 const NetDevVTable vlan_vtable = {
index fade899997d0d190d0cdae78549405b5930b737b..780d61262a2fc858ed64f5777c170797c0e623b2 100644 (file)
@@ -27,6 +27,11 @@ struct VLan {
         NetDev meta;
 
         uint16_t id;
+
+        int gvrp;
+        int mvrp;
+        int loose_binding;
+        int reorder_hdr;
 };
 
 DEFINE_NETDEV_CAST(VLAN, VLan);
index b677b000fd978547893b481fd8ff0cca95484385..b5b7aec2c07af4e3af5cca6bfed51cf3bf0f2a16 100644 (file)
@@ -157,6 +157,10 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m");
         }
 
+        r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LABEL, htobe32(v->flow_label));
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LABEL attribute: %m");
+
         if (v->group_policy) {
                 r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GBP);
                 if (r < 0)
@@ -267,18 +271,18 @@ int config_parse_port_range(const char *unit,
         return 0;
 }
 
-int config_parse_destination_port(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_flow_label(const char *unit,
+                            const char *filename,
+                            unsigned line,
+                            const char *section,
+                            unsigned section_line,
+                            const char *lvalue,
+                            int ltype,
+                            const char *rvalue,
+                            void *data,
+                            void *userdata) {
         VxLan *v = userdata;
-        uint16_t port;
+        unsigned f;
         int r;
 
         assert(filename);
@@ -286,13 +290,19 @@ int config_parse_destination_port(const char *unit,
         assert(rvalue);
         assert(data);
 
-        r = parse_ip_port(rvalue, &port);
+        r = safe_atou(rvalue, &f);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN flow label '%s'.", rvalue);
+                return 0;
+        }
+
+        if (f & ~VXLAN_FLOW_LABEL_MAX_MASK) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "VXLAN flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue);
                 return 0;
         }
 
-        v->dest_port = port;
+        v->flow_label = f;
 
         return 0;
 }
index dca58e7fe69321499deea6ccf9c005ab6c17bd68..1eeda022a2043882bbd133a46f2a991cfca8b817 100644 (file)
@@ -25,6 +25,7 @@ typedef struct VxLan VxLan;
 #include "netdev/netdev.h"
 
 #define VXLAN_VID_MAX (1u << 24) - 1
+#define VXLAN_FLOW_LABEL_MAX_MASK 0xFFFFFU
 
 struct VxLan {
         NetDev meta;
@@ -40,6 +41,7 @@ struct VxLan {
         unsigned tos;
         unsigned ttl;
         unsigned max_fdb;
+        unsigned flow_label;
 
         uint16_t dest_port;
 
@@ -84,13 +86,13 @@ int config_parse_port_range(const char *unit,
                             void *data,
                             void *userdata);
 
-int config_parse_destination_port(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_flow_label(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);
index 6f7f41bf7d2c5e8f98249b013308e92936e39662..54d54c8fd5939263dbe367e777bc7e9b3a14fca5 100644 (file)
@@ -18,6 +18,7 @@
 ***/
 
 #include <getopt.h>
+#include <linux/if_addrlabel.h>
 #include <net/if.h>
 #include <stdbool.h>
 
@@ -35,6 +36,7 @@
 #include "hwdb-util.h"
 #include "local-addresses.h"
 #include "locale-util.h"
+#include "macro.h"
 #include "netlink-util.h"
 #include "pager.h"
 #include "parse-util.h"
@@ -569,6 +571,76 @@ static int dump_addresses(
         return 0;
 }
 
+static int dump_address_labels(sd_netlink *rtnl) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        sd_netlink_message *m;
+        int r;
+
+        assert(rtnl);
+
+        r = sd_rtnl_message_new_addrlabel(rtnl, &req, RTM_GETADDRLABEL, 0, AF_INET6);
+        if (r < 0)
+                return log_error_errno(r, "Could not allocate RTM_GETADDRLABEL message: %m");
+
+        r = sd_netlink_message_request_dump(req, true);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_call(rtnl, req, 0, &reply);
+        if (r < 0)
+                return r;
+
+        printf("%10s/%s %30s\n", "Prefix", "Prefixlen", "Label");
+
+        for (m = reply; m; m = sd_netlink_message_next(m)) {
+                _cleanup_free_ char *pretty = NULL;
+                union in_addr_union prefix = {};
+                uint8_t prefixlen;
+                uint32_t label;
+
+                r = sd_netlink_message_get_errno(m);
+                if (r < 0) {
+                        log_error_errno(r, "got error: %m");
+                        continue;
+                }
+
+                r = sd_netlink_message_read_u32(m, IFAL_LABEL, &label);
+                if (r < 0 && r != -ENODATA) {
+                        log_error_errno(r, "Could not read IFAL_LABEL, ignoring: %m");
+                        continue;
+                }
+
+                r = sd_netlink_message_read_in6_addr(m, IFAL_ADDRESS, &prefix.in6);
+                if (r < 0)
+                        continue;
+
+                r = in_addr_to_string(AF_INET6, &prefix, &pretty);
+                if (r < 0)
+                        continue;
+
+                r = sd_rtnl_message_addrlabel_get_prefixlen(m, &prefixlen);
+                if (r < 0)
+                        continue;
+
+                printf("%10s/%-5u %30u\n", pretty, prefixlen, label);
+        }
+
+        return 0;
+}
+
+static int list_address_labels(int argc, char *argv[], void *userdata) {
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        int r;
+
+        r = sd_netlink_open(&rtnl);
+        if (r < 0)
+                return log_error_errno(r, "Failed to connect to netlink: %m");
+
+        dump_address_labels(rtnl);
+
+        return 0;
+}
+
 static int open_lldp_neighbors(int ifindex, FILE **ret) {
         _cleanup_free_ char *p = NULL;
         FILE *f;
@@ -1043,6 +1115,7 @@ static void help(void) {
                "  list [LINK...]        List links\n"
                "  status [LINK...]      Show link status\n"
                "  lldp [LINK...]        Show LLDP neighbors\n"
+               "  label                 Show current address label entries in the kernel\n"
                , program_invocation_short_name);
 }
 
@@ -1107,6 +1180,7 @@ static int networkctl_main(int argc, char *argv[]) {
                 { "list",   VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links       },
                 { "status", VERB_ANY, VERB_ANY, 0,            link_status      },
                 { "lldp",   VERB_ANY, VERB_ANY, 0,            link_lldp_status },
+                { "label",  VERB_ANY, VERB_ANY, 0,            list_address_labels},
                 {}
         };
 
diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c
new file mode 100644 (file)
index 0000000..b89995e
--- /dev/null
@@ -0,0 +1,223 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2017 Susant Sahani
+
+  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 <net/if.h>
+#include <linux/if_addrlabel.h>
+
+#include "alloc-util.h"
+#include "conf-parser.h"
+#include "networkd-address-label.h"
+#include "netlink-util.h"
+#include "networkd-manager.h"
+#include "parse-util.h"
+#include "socket-util.h"
+
+int address_label_new(AddressLabel **ret) {
+        _cleanup_address_label_free_ AddressLabel *addrlabel = NULL;
+
+        addrlabel = new0(AddressLabel, 1);
+        if (!addrlabel)
+                return -ENOMEM;
+
+        *ret = addrlabel;
+        addrlabel = NULL;
+
+        return 0;
+}
+
+void address_label_free(AddressLabel *label) {
+        if (!label)
+                return;
+
+        if (label->network) {
+                LIST_REMOVE(labels, label->network->address_labels, label);
+                assert(label->network->n_address_labels > 0);
+                label->network->n_address_labels--;
+
+                if (label->section) {
+                        hashmap_remove(label->network->address_labels_by_section, label->section);
+                        network_config_section_free(label->section);
+                }
+        }
+
+        free(label);
+}
+
+static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
+        _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
+        _cleanup_address_label_free_ AddressLabel *label = NULL;
+        int r;
+
+        assert(network);
+        assert(ret);
+        assert(!!filename == (section_line > 0));
+
+        r = network_config_section_new(filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        label = hashmap_get(network->address_labels_by_section, n);
+        if (label) {
+                *ret = label;
+                label = NULL;
+
+                return 0;
+        }
+
+        r = address_label_new(&label);
+        if (r < 0)
+                return r;
+
+        label->section = n;
+        n = NULL;
+
+        r = hashmap_put(network->address_labels_by_section, label->section, label);
+        if (r < 0)
+                return r;
+
+        label->network = network;
+        LIST_APPEND(labels, network->address_labels, label);
+        network->n_address_labels++;
+
+        *ret = label;
+        label = NULL;
+
+        return 0;
+}
+
+int address_label_configure(
+                AddressLabel *label,
+                Link *link,
+                sd_netlink_message_handler_t callback,
+                bool update) {
+
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(label);
+        assert(link);
+        assert(link->ifindex > 0);
+        assert(link->manager);
+        assert(link->manager->rtnl);
+
+        r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL,
+                                          link->ifindex, AF_INET6);
+        if (r < 0)
+                return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
+
+        r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen);
+        if (r < 0)
+                return log_error_errno(r, "Could not set prefixlen: %m");
+
+        r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label);
+        if (r < 0)
+                return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m");
+
+        r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6);
+        if (r < 0)
+                return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
+
+        r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return 0;
+}
+
+int config_parse_address_label_prefix(const char *unit,
+                                      const char *filename,
+                                      unsigned line,
+                                      const char *section,
+                                      unsigned section_line,
+                                      const char *lvalue,
+                                      int ltype,
+                                      const char *rvalue,
+                                      void *data,
+                                      void *userdata) {
+
+        _cleanup_address_label_free_ AddressLabel *n = NULL;
+        Network *network = userdata;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = address_label_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        n = NULL;
+
+        return 0;
+}
+
+int config_parse_address_label(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_address_label_free_ AddressLabel *n = NULL;
+        Network *network = userdata;
+        uint32_t k;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = address_label_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        r = safe_atou32(rvalue, &k);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (k == 0xffffffffUL) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Adress label is invalid, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        n->label = k;
+        n = NULL;
+
+        return 0;
+}
diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h
new file mode 100644 (file)
index 0000000..8724ea8
--- /dev/null
@@ -0,0 +1,58 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2017 Susant Sahani
+
+  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 <inttypes.h>
+#include <stdbool.h>
+
+#include "in-addr-util.h"
+
+typedef struct AddressLabel AddressLabel;
+
+#include "networkd-link.h"
+#include "networkd-network.h"
+
+typedef struct Network Network;
+typedef struct Link Link;
+typedef struct NetworkConfigSection NetworkConfigSection;
+
+struct AddressLabel {
+        Network *network;
+        Link *link;
+        NetworkConfigSection *section;
+
+        unsigned char prefixlen;
+        uint32_t label;
+
+        union in_addr_union in_addr;
+
+        LIST_FIELDS(AddressLabel, labels);
+};
+
+int address_label_new(AddressLabel **ret);
+void address_label_free(AddressLabel *label);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(AddressLabel*, address_label_free);
+#define _cleanup_address_label_free_ _cleanup_(address_label_freep)
+
+int address_label_configure(AddressLabel *address, Link *link, sd_netlink_message_handler_t callback, bool update);
+
+int config_parse_address_label(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_address_label_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
index 2e6c763aba46cfb62c37dc2dfb33c9c264fe6ef9..d66b3a288f26cd8e2e1926cc16c64e2e978c2953 100644 (file)
@@ -932,3 +932,251 @@ bool address_is_ready(const Address *a) {
 
         return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
 }
+
+int config_parse_router_preference(const char *unit,
+                                   const char *filename,
+                                   unsigned line,
+                                   const char *section,
+                                   unsigned section_line,
+                                   const char *lvalue,
+                                   int ltype,
+                                   const char *rvalue,
+                                   void *data,
+                                   void *userdata) {
+        Network *network = userdata;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "high"))
+                network->router_preference = SD_NDISC_PREFERENCE_HIGH;
+        else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
+                network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
+        else if (streq(rvalue, "low"))
+                network->router_preference = SD_NDISC_PREFERENCE_LOW;
+        else
+                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue);
+
+        return 0;
+}
+
+void prefix_free(Prefix *prefix) {
+        if (!prefix)
+                return;
+
+        if (prefix->network) {
+                LIST_REMOVE(prefixes, prefix->network->static_prefixes, prefix);
+                assert(prefix->network->n_static_prefixes > 0);
+                prefix->network->n_static_prefixes--;
+
+                if (prefix->section)
+                        hashmap_remove(prefix->network->prefixes_by_section,
+                                       prefix->section);
+        }
+
+        prefix->radv_prefix = sd_radv_prefix_unref(prefix->radv_prefix);
+
+        free(prefix);
+}
+
+int prefix_new(Prefix **ret) {
+        Prefix *prefix = NULL;
+
+        prefix = new0(Prefix, 1);
+        if (!prefix)
+                return -ENOMEM;
+
+        if (sd_radv_prefix_new(&prefix->radv_prefix) < 0)
+                return -ENOMEM;
+
+        *ret = prefix;
+        prefix = NULL;
+
+        return 0;
+}
+
+int prefix_new_static(Network *network, const char *filename,
+                      unsigned section_line, Prefix **ret) {
+        _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
+        _cleanup_prefix_free_ Prefix *prefix = NULL;
+        int r;
+
+        assert(network);
+        assert(ret);
+        assert(!!filename == (section_line > 0));
+
+        if (filename) {
+                r = network_config_section_new(filename, section_line, &n);
+                if (r < 0)
+                        return r;
+
+                if (section_line) {
+                        prefix = hashmap_get(network->prefixes_by_section, n);
+                        if (prefix) {
+                                *ret = prefix;
+                                prefix = NULL;
+
+                                return 0;
+                        }
+                }
+        }
+
+        r = prefix_new(&prefix);
+        if (r < 0)
+                return r;
+
+        if (filename) {
+                prefix->section = n;
+                n = NULL;
+
+                r = hashmap_put(network->prefixes_by_section, prefix->section,
+                                prefix);
+                if (r < 0)
+                        return r;
+        }
+
+        prefix->network = network;
+        LIST_APPEND(prefixes, network->static_prefixes, prefix);
+        network->n_static_prefixes++;
+
+        *ret = prefix;
+        prefix = NULL;
+
+        return 0;
+}
+
+int config_parse_prefix(const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = userdata;
+        _cleanup_prefix_free_ Prefix *p = NULL;
+        uint8_t prefixlen = 64;
+        union in_addr_union in6addr;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return r;
+
+        r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Prefix is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        if (sd_radv_prefix_set_prefix(p->radv_prefix, &in6addr.in6, prefixlen) < 0)
+                return -EADDRNOTAVAIL;
+
+        log_syntax(unit, LOG_INFO, filename, line, r, "Found prefix %s", rvalue);
+
+        p = NULL;
+
+        return 0;
+}
+
+int config_parse_prefix_flags(const char *unit,
+                              const char *filename,
+                              unsigned line,
+                              const char *section,
+                              unsigned section_line,
+                              const char *lvalue,
+                              int ltype,
+                              const char *rvalue,
+                              void *data,
+                              void *userdata) {
+        Network *network = userdata;
+        _cleanup_prefix_free_ Prefix *p = NULL;
+        int r, val;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return r;
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        val = r;
+
+        if (streq(lvalue, "OnLink"))
+                r = sd_radv_prefix_set_onlink(p->radv_prefix, val);
+        else if (streq(lvalue, "AddressAutoconfiguration"))
+                r = sd_radv_prefix_set_address_autoconfiguration(p->radv_prefix, val);
+        if (r < 0)
+                return r;
+
+        p = NULL;
+
+        return 0;
+}
+
+int config_parse_prefix_lifetime(const char *unit,
+                                 const char *filename,
+                                 unsigned line,
+                                 const char *section,
+                                 unsigned section_line,
+                                 const char *lvalue,
+                                 int ltype,
+                                 const char *rvalue,
+                                 void *data,
+                                 void *userdata) {
+        Network *network = userdata;
+        _cleanup_prefix_free_ Prefix *p = NULL;
+        usec_t usec;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return r;
+
+        r = parse_sec(rvalue, &usec);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Lifetime is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        /* a value of 0xffffffff represents infinity */
+        if (streq(lvalue, "PreferredLifetimeSec"))
+                r = sd_radv_prefix_set_preferred_lifetime(p->radv_prefix,
+                                                          DIV_ROUND_UP(usec, USEC_PER_SEC));
+        else if (streq(lvalue, "ValidLifetimeSec"))
+                r = sd_radv_prefix_set_valid_lifetime(p->radv_prefix,
+                                                      DIV_ROUND_UP(usec, USEC_PER_SEC));
+        if (r < 0)
+                return r;
+
+        p = NULL;
+
+        return 0;
+};
index 71a07ea7a337ff7435b32ee30785c9d94b898e79..065328482ef647f2abd5fc968beb9012fc912b98 100644 (file)
@@ -25,6 +25,7 @@
 #include "in-addr-util.h"
 
 typedef struct Address Address;
+typedef struct Prefix Prefix;
 
 #include "networkd-link.h"
 #include "networkd-network.h"
@@ -35,6 +36,15 @@ typedef struct Network Network;
 typedef struct Link Link;
 typedef struct NetworkConfigSection NetworkConfigSection;
 
+struct Prefix {
+        Network *network;
+        NetworkConfigSection *section;
+
+        sd_radv_prefix *radv_prefix;
+
+        LIST_FIELDS(Prefix, prefixes);
+};
+
 struct Address {
         Network *network;
         NetworkConfigSection *section;
@@ -79,8 +89,20 @@ bool address_is_ready(const Address *a);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
 #define _cleanup_address_free_ _cleanup_(address_freep)
 
+int prefix_new(Prefix **ret);
+void prefix_free(Prefix *prefix);
+int prefix_new_static(Network *network, const char *filename, unsigned section,
+                      Prefix **ret);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Prefix*, prefix_free);
+#define _cleanup_prefix_free_ _cleanup_(prefix_freep)
+
 int config_parse_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_broadcast(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_label(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_lifetime(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_address_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_router_preference(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_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_prefix_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_prefix_lifetime(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);
index aaa27f311d39ce24e5ed0df326b1cef3574fdb0a..e28e018116044e1cadc7feb79ad5ca03d85f9a65 100644 (file)
@@ -32,10 +32,10 @@ int manager_parse_config_file(Manager *m) {
         assert(m);
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/networkd.conf",
-                                 CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
-                                 "DHCP\0",
-                                 config_item_perf_lookup, networkd_gperf_lookup,
-                                 false, m);
+                                        CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
+                                        "DHCP\0",
+                                        config_item_perf_lookup, networkd_gperf_lookup,
+                                        false, m);
 }
 
 static const char* const duid_type_table[_DUID_TYPE_MAX] = {
index c5c5b95c8fef3115607acde635d8edc8175c8c45..9229b5753c7a867e3223bd3c620e7b3afe9e3458 100644 (file)
@@ -52,8 +52,21 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
         return 1;
 }
 
+static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
+        assert(route);
+        assert(self_addr);
+
+        if (in_addr_is_localhost(AF_INET, &route->dst) ||
+            (self_addr->s_addr && route->dst.in.s_addr == self_addr->s_addr))
+                return RT_SCOPE_HOST;
+        else if (in4_addr_is_null(&route->gw.in))
+                return RT_SCOPE_LINK;
+        else
+                return RT_SCOPE_UNIVERSE;
+}
+
 static int link_set_dhcp_routes(Link *link) {
-        struct in_addr gateway;
+        struct in_addr gateway, address;
         _cleanup_free_ sd_dhcp_route **static_routes = NULL;
         int r, n, i;
 
@@ -64,19 +77,18 @@ static int link_set_dhcp_routes(Link *link) {
         if (!link->network->dhcp_use_routes)
                 return 0;
 
+        r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
+
         r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
         if (r < 0 && r != -ENODATA)
                 return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
 
         if (r >= 0) {
-                struct in_addr address;
                 _cleanup_route_free_ Route *route = NULL;
                 _cleanup_route_free_ Route *route_gw = NULL;
 
-                r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
-
                 r = route_new(&route);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not allocate route: %m");
@@ -141,6 +153,7 @@ static int link_set_dhcp_routes(Link *link) {
                 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
                 route->priority = link->network->dhcp_route_metric;
                 route->table = link->network->dhcp_route_table;
+                route->scope = route_scope_from_address(route, &address);
 
                 r = route_configure(route, link, dhcp4_route_handler);
                 if (r < 0)
index 7ba05dbec30d51467e14c0d625bc4d231a51cc85..d2b10107b8360b8185b9c80efaf5cb30bfd26ecb 100644 (file)
@@ -109,7 +109,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void
 
         link->ipv4ll_address = true;
 
-        if (link->ipv4ll_route == true)
+        if (link->ipv4ll_route)
                 link_check_ready(link);
 
         return 1;
@@ -179,12 +179,22 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
 
         switch(event) {
                 case SD_IPV4LL_EVENT_STOP:
+                        r = ipv4ll_address_lost(link);
+                        if (r < 0) {
+                                link_enter_failed(link);
+                                return;
+                        }
+                        break;
                 case SD_IPV4LL_EVENT_CONFLICT:
                         r = ipv4ll_address_lost(link);
                         if (r < 0) {
                                 link_enter_failed(link);
                                 return;
                         }
+
+                        r = sd_ipv4ll_restart(ll);
+                        if (r < 0)
+                                log_link_warning(link, "Could not acquire IPv4 link-local address");
                         break;
                 case SD_IPV4LL_EVENT_BIND:
                         r = ipv4ll_address_claimed(ll, link);
index 11c1cd92686cd80c6db0da7a9c74d42d7a28f674..00790c0c135b68fa035b9ee9f352b0282c2b1f76 100644 (file)
@@ -38,6 +38,9 @@ static bool ipv6_proxy_ndp_is_needed(Link *link) {
         if (!link->network)
                 return false;
 
+        if (link->network->ipv6_proxy_ndp != -1)
+                return link->network->ipv6_proxy_ndp;
+
         if (link->network->n_ipv6_proxy_ndp_addresses == 0)
                 return false;
 
index 0c1229336b87c8d4b8db7e106ef504e2d68f0af1..4c57fa1793894455eeff66929c4614dfb9dad899 100644 (file)
@@ -32,6 +32,7 @@
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
 #include "networkd-ndisc.h"
+#include "networkd-radv.h"
 #include "set.h"
 #include "socket-util.h"
 #include "stdio-util.h"
@@ -119,6 +120,15 @@ static bool link_ipv6_enabled(Link *link) {
         return link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network);
 }
 
+static bool link_radv_enabled(Link *link) {
+        assert(link);
+
+        if (!link_ipv6ll_enabled(link))
+                return false;
+
+        return link->network->router_prefix_delegation;
+}
+
 static bool link_lldp_rx_enabled(Link *link) {
         assert(link);
 
@@ -131,7 +141,10 @@ static bool link_lldp_rx_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (link->network->bridge)
+        /* LLDP should be handled on bridge slaves as those have a direct
+         * connection to their peers not on the bridge master. Linux doesn't
+         * even (by default) forward lldp packets to the bridge master.*/
+        if (streq_ptr("bridge", link->kind))
                 return false;
 
         return link->network->lldp_mode != LLDP_MODE_NO;
@@ -521,6 +534,7 @@ static void link_free(Link *link) {
         sd_ipv4ll_unref(link->ipv4ll);
         sd_dhcp6_client_unref(link->dhcp6_client);
         sd_ndisc_unref(link->ndisc);
+        sd_radv_unref(link->radv);
 
         if (link->manager)
                 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
@@ -640,6 +654,12 @@ static int link_stop_clients(Link *link) {
                         r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
         }
 
+        if (link->radv) {
+                k = sd_radv_stop(link->radv);
+                if (k < 0)
+                        r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
+        }
+
         link_lldp_emit_stop(link);
         return r;
 }
@@ -853,6 +873,35 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
         return 1;
 }
 
+static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+        _cleanup_link_unref_ Link *link = userdata;
+        int r;
+
+        assert(rtnl);
+        assert(m);
+        assert(link);
+        assert(link->ifname);
+        assert(link->link_messages > 0);
+
+        link->link_messages--;
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0 && r != -EEXIST)
+                log_link_warning_errno(link, r, "could not set address label: %m");
+        else if (r >= 0)
+                manager_rtnl_process_address(rtnl, m, link->manager);
+
+        if (link->link_messages == 0) {
+                log_link_debug(link, "Addresses label set");
+                link_enter_set_routes(link);
+        }
+
+        return 1;
+}
+
 static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
         _cleanup_free_ struct in_addr *addresses = NULL;
         size_t n_addresses = 0, n_allocated = 0;
@@ -965,6 +1014,7 @@ static int link_set_bridge_fdb(Link *link) {
 }
 
 static int link_enter_set_addresses(Link *link) {
+        AddressLabel *label;
         Address *ad;
         int r;
 
@@ -989,6 +1039,17 @@ static int link_enter_set_addresses(Link *link) {
                 link->link_messages++;
         }
 
+        LIST_FOREACH(labels, label, link->network->address_labels) {
+                r = address_label_configure(label, link, address_label_handler, false);
+                if (r < 0) {
+                        log_link_warning_errno(link, r, "Could not set address label: %m");
+                        link_enter_failed(link);
+                        return r;
+                }
+
+                link->link_messages++;
+        }
+
         /* now that we can figure out a default address for the dhcp server,
            start it */
         if (link_dhcp4_server_enabled(link)) {
@@ -1325,6 +1386,11 @@ static int link_set_bridge(Link *link) {
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
         }
+        if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
+                r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
+        }
 
         r = sd_netlink_message_close_container(req);
         if (r < 0)
@@ -1508,6 +1574,17 @@ static int link_acquire_ipv6_conf(Link *link) {
                         return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
         }
 
+        if (link_radv_enabled(link)) {
+                assert(link->radv);
+                assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
+
+                log_link_debug(link, "Starting IPv6 Router Advertisements");
+
+                r = sd_radv_start(link->radv);
+                if (r < 0 && r != -EBUSY)
+                        return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");
+        }
+
         return 0;
 }
 
@@ -1598,7 +1675,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
         return 1;
 }
 
-static int link_up(Link *link) {
+int link_up(Link *link) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         uint8_t ipv6ll_mode;
         int r;
@@ -1719,7 +1796,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
         return 1;
 }
 
-static int link_down(Link *link) {
+int link_down(Link *link) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -2058,6 +2135,12 @@ static int link_joined(Link *link) {
                         log_link_error_errno(link, r, "Could not set bridge vlan: %m");
         }
 
+        /* Skip setting up addresses until it gets carrier,
+           or it would try to set addresses twice,
+           which is bad for non-idempotent steps. */
+        if (!link_has_carrier(link))
+                return 0;
+
         return link_enter_set_addresses(link);
 }
 
@@ -2366,7 +2449,7 @@ static int link_drop_foreign_config(Link *link) {
 }
 
 static int link_drop_config(Link *link) {
-        Address *address;
+        Address *address, *pool_address;
         Route *route;
         Iterator i;
         int r;
@@ -2379,6 +2462,15 @@ static int link_drop_config(Link *link) {
                 r = address_remove(address, link, link_address_remove_handler);
                 if (r < 0)
                         return r;
+
+                /* If this address came from an address pool, clean up the pool */
+                LIST_FOREACH(addresses, pool_address, link->pool_addresses) {
+                        if (address_equal(address, pool_address)) {
+                                LIST_REMOVE(addresses, link->pool_addresses, pool_address);
+                                address_free(pool_address);
+                                break;
+                        }
+                }
         }
 
         SET_FOREACH(route, link->routes, i) {
@@ -2516,6 +2608,12 @@ static int link_configure(Link *link) {
                         return r;
         }
 
+        if (link_radv_enabled(link)) {
+                r = radv_configure(link);
+                if (r < 0)
+                        return r;
+        }
+
         if (link_lldp_rx_enabled(link)) {
                 r = sd_lldp_new(&link->lldp);
                 if (r < 0)
@@ -2962,6 +3060,8 @@ static int link_carrier_lost(Link *link) {
                 return r;
         }
 
+        (void) sd_dhcp_server_stop(link->dhcp_server);
+
         r = link_drop_config(link);
         if (r < 0)
                 return r;
@@ -3052,6 +3152,12 @@ int link_update(Link *link, sd_netlink_message *m) {
                                 return r;
                         }
                 }
+
+                if (link->radv) {
+                        r = sd_radv_set_mtu(link->radv, link->mtu);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "Could not set MTU for Router Advertisement: %m");
+                }
         }
 
         /* The kernel may broadcast NEWLINK messages without the MAC address
@@ -3120,6 +3226,12 @@ int link_update(Link *link, sd_netlink_message *m) {
                                 if (r < 0)
                                         return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
                         }
+
+                        if (link->radv) {
+                                r = sd_radv_set_mac(link->radv, &link->mac);
+                                if (r < 0)
+                                        return log_link_warning_errno(link, r, "Could not update MAC for Router Advertisement: %m");
+                        }
                 }
         }
 
@@ -3220,6 +3332,7 @@ int link_save(Link *link) {
                 sd_dhcp6_lease *dhcp6_lease = NULL;
                 const char *dhcp_domainname = NULL;
                 char **dhcp6_domains = NULL;
+                char **dhcp_domains = NULL;
                 unsigned j;
 
                 if (link->dhcp6_client) {
@@ -3329,13 +3442,16 @@ int link_save(Link *link) {
                 fputc('\n', f);
 
                 if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
-                        if (link->dhcp_lease)
+                        if (link->dhcp_lease) {
                                 (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
+                                (void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
+                        }
                         if (dhcp6_lease)
                                 (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
                 }
 
                 fputs("DOMAINS=", f);
+                space = false;
                 fputstrv(f, link->network->search_domains, NULL, &space);
 
                 if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
@@ -3343,6 +3459,8 @@ int link_save(Link *link) {
 
                         if (dhcp_domainname)
                                 fputs_with_space(f, dhcp_domainname, NULL, &space);
+                        if (dhcp_domains)
+                                fputstrv(f, dhcp_domains, NULL, &space);
                         if (dhcp6_domains)
                                 fputstrv(f, dhcp6_domains, NULL, &space);
 
@@ -3353,13 +3471,16 @@ int link_save(Link *link) {
                 fputc('\n', f);
 
                 fputs("ROUTE_DOMAINS=", f);
-                fputstrv(f, link->network->route_domains, NULL, NULL);
+                space = false;
+                fputstrv(f, link->network->route_domains, NULL, &space);
 
                 if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
                         NDiscDNSSL *dd;
 
                         if (dhcp_domainname)
                                 fputs_with_space(f, dhcp_domainname, NULL, &space);
+                        if (dhcp_domains)
+                                fputstrv(f, dhcp_domains, NULL, &space);
                         if (dhcp6_domains)
                                 fputstrv(f, dhcp6_domains, NULL, &space);
 
index e6190fbe576409ff5b59018889ae38d7ad5e60e0..6479f4a2e54f9908b2864a1dc360e1c28d31c52a 100644 (file)
@@ -28,6 +28,7 @@
 #include "sd-ipv4ll.h"
 #include "sd-lldp.h"
 #include "sd-ndisc.h"
+#include "sd-radv.h"
 #include "sd-netlink.h"
 
 #include "list.h"
@@ -117,6 +118,8 @@ typedef struct Link {
         Set *ndisc_rdnss;
         Set *ndisc_dnssl;
 
+        sd_radv *radv;
+
         sd_dhcp6_client *dhcp6_client;
         bool rtnl_extended_attrs;
 
@@ -138,6 +141,9 @@ int link_get(Manager *m, int ifindex, Link **ret);
 int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
 void link_drop(Link *link);
 
+int link_up(Link *link);
+int link_down(Link *link);
+
 int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
 int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
 
index ea1c320809f9f23a8fb8f08037a406a66cf5e108..5f10b4f993af8c1cb235c3e1dbd9a821fd1ec8c2 100644 (file)
@@ -961,15 +961,20 @@ static int manager_save(Manager *m) {
 
                 if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
                         const char *domainname;
+                        char **domains = NULL;
 
+                        OrderedSet *target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? search_domains : route_domains;
                         r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
                         if (r >= 0) {
+                                r = ordered_set_put_strdup(target_domains, domainname);
+                                if (r < 0)
+                                        return r;
+                        } else if (r != -ENODATA)
+                                return r;
 
-                                if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES)
-                                        r = ordered_set_put_strdup(search_domains, domainname);
-                                else
-                                        r = ordered_set_put_strdup(route_domains, domainname);
-
+                        r = sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains);
+                        if (r >= 0) {
+                                r = ordered_set_put_strdupv(target_domains, domains);
                                 if (r < 0)
                                         return r;
                         } else if (r != -ENODATA)
index 4fd5d8ae70312fcaa49d578a3e85ed653ebe66fa..d52b511bb55c5996cf058cae04ec7b00a9845597 100644 (file)
@@ -27,6 +27,7 @@
 
 #define NDISC_DNSSL_MAX 64U
 #define NDISC_RDNSS_MAX 64U
+#define NDISC_PREFIX_LFT_MIN 7200U
 
 static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
         _cleanup_link_unref_ Link *link = userdata;
@@ -152,13 +153,21 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
 
 static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
         _cleanup_address_free_ Address *address = NULL;
-        uint32_t lifetime_valid, lifetime_preferred;
+        Address *existing_address;
+        uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
+        usec_t time_now;
         unsigned prefixlen;
         int r;
 
         assert(link);
         assert(rt);
 
+        r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
+                return;
+        }
+
         r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
         if (r < 0) {
                 log_link_error_errno(link, r, "Failed to get prefix length: %m");
@@ -207,7 +216,24 @@ static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *
         address->prefixlen = prefixlen;
         address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
         address->cinfo.ifa_prefered = lifetime_preferred;
-        address->cinfo.ifa_valid = lifetime_valid;
+
+        /* see RFC4862 section 5.5.3.e */
+        r = address_get(link, address->family, &address->in_addr, address->prefixlen, &existing_address);
+        if (r > 0) {
+                lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
+                if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
+                        address->cinfo.ifa_valid = lifetime_valid;
+                else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
+                        address->cinfo.ifa_valid = lifetime_remaining;
+                else
+                        address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
+        } else if (lifetime_valid > 0)
+                address->cinfo.ifa_valid = lifetime_valid;
+        else
+                return; /* see RFC4862 section 5.5.3.d */
+
+        if (address->cinfo.ifa_valid == 0)
+                return;
 
         r = address_configure(address, link, ndisc_netlink_handler, true);
         if (r < 0) {
index 68052ba54439840b2bac6dc3a8b20db51d160653..a2d38501a533ba390b62fea1038fd559b4b8ae32 100644 (file)
@@ -63,6 +63,7 @@ Network.IPv6AcceptRA,                   config_parse_tristate,
 Network.IPv6AcceptRouterAdvertisements, config_parse_tristate,                          0,                             offsetof(Network, ipv6_accept_ra)
 Network.IPv6DuplicateAddressDetection,  config_parse_int,                               0,                             offsetof(Network, ipv6_dad_transmits)
 Network.IPv6HopLimit,                   config_parse_int,                               0,                             offsetof(Network, ipv6_hop_limit)
+Network.IPv6ProxyNDP,                   config_parse_tristate,                          0,                             offsetof(Network, ipv6_proxy_ndp)
 Network.ActiveSlave,                    config_parse_bool,                              0,                             offsetof(Network, active_slave)
 Network.PrimarySlave,                   config_parse_bool,                              0,                             offsetof(Network, primary_slave)
 Network.IPv4ProxyARP,                   config_parse_tristate,                          0,                             offsetof(Network, proxy_arp)
@@ -79,6 +80,8 @@ Address.DuplicateAddressDetection,      config_parse_address_flags,
 Address.ManageTemporaryAddress,         config_parse_address_flags,                     0,                             0
 Address.PrefixRoute,                    config_parse_address_flags,                     0,                             0
 Address.AutoJoin,                       config_parse_address_flags,                     0,                             0
+IPv6AddressLabel.Prefix,                config_parse_address_label_prefix,              0,                             0
+IPv6AddressLabel.Label,                 config_parse_address_label,                     0,                             0
 Route.Gateway,                          config_parse_gateway,                           0,                             0
 Route.Destination,                      config_parse_destination,                       0,                             0
 Route.Source,                           config_parse_destination,                       0,                             0
@@ -86,6 +89,9 @@ Route.Metric,                           config_parse_route_priority,
 Route.Scope,                            config_parse_route_scope,                       0,                             0
 Route.PreferredSource,                  config_parse_preferred_src,                     0,                             0
 Route.Table,                            config_parse_route_table,                       0,                             0
+Route.GatewayOnlink,                    config_parse_gateway_onlink,                    0,                             0
+Route.IPv6Preference,                   config_parse_ipv6_route_preference,             0,                             0
+Route.Protocol,                         config_parse_route_protocol,                    0,                             0
 DHCP.ClientIdentifier,                  config_parse_dhcp_client_identifier,            0,                             offsetof(Network, dhcp_client_identifier)
 DHCP.UseDNS,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
 DHCP.UseNTP,                            config_parse_bool,                              0,                             offsetof(Network, dhcp_use_ntp)
@@ -119,17 +125,28 @@ DHCPServer.EmitTimezone,                config_parse_bool,
 DHCPServer.Timezone,                    config_parse_timezone,                          0,                             offsetof(Network, dhcp_server_timezone)
 DHCPServer.PoolOffset,                  config_parse_uint32,                            0,                             offsetof(Network, dhcp_server_pool_offset)
 DHCPServer.PoolSize,                    config_parse_uint32,                            0,                             offsetof(Network, dhcp_server_pool_size)
-Bridge.Cost,                            config_parse_unsigned,                          0,                             offsetof(Network, cost)
+Bridge.Cost,                            config_parse_uint32,                            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)
+Bridge.Priority,                        config_parse_bridge_port_priority,              0,                             offsetof(Network, priority)
 BridgeFDB.MACAddress,                   config_parse_fdb_hwaddr,                        0,                             0
 BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,                       0,                             0
 BridgeVLAN.PVID,                        config_parse_brvlan_pvid,                       0,                             0
 BridgeVLAN.VLAN,                        config_parse_brvlan_vlan,                       0,                             0
 BridgeVLAN.EgressUntagged,              config_parse_brvlan_untagged,                   0,                             0
+Network.IPv6PrefixDelegation,           config_parse_bool,                              0,                             offsetof(Network, router_prefix_delegation)
+IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec,                               0,                             offsetof(Network, router_lifetime_usec)
+IPv6PrefixDelegation.Managed,           config_parse_bool,                              0,                             offsetof(Network, router_managed)
+IPv6PrefixDelegation.OtherInformation,  config_parse_bool,                              0,                             offsetof(Network, router_other_information)
+IPv6PrefixDelegation.RouterPreference,  config_parse_router_preference,                 0,                             0
+IPv6Prefix.Prefix,                      config_parse_prefix,                            0,                             0
+IPv6Prefix.OnLink,                      config_parse_prefix_flags,                      0,                             0
+IPv6Prefix.AddressAutoconfiguration,    config_parse_prefix_flags,                      0,                             0
+IPv6Prefix.ValidLifetimeSec,            config_parse_prefix_lifetime,                   0,                             0
+IPv6Prefix.PreferredLifetimeSec,        config_parse_prefix_lifetime,                   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_use_dns)
index ab372568de819e1d711fbc97712a54e3966e0173..6f2ae66d403ebc8bd30a4f41b5cd97933101315b 100644 (file)
@@ -114,6 +114,8 @@ static int network_load_one(Manager *manager, const char *filename) {
         LIST_HEAD_INIT(network->static_routes);
         LIST_HEAD_INIT(network->static_fdb_entries);
         LIST_HEAD_INIT(network->ipv6_proxy_ndp_addresses);
+        LIST_HEAD_INIT(network->address_labels);
+        LIST_HEAD_INIT(network->static_prefixes);
 
         network->stacked_netdevs = hashmap_new(&string_hash_ops);
         if (!network->stacked_netdevs)
@@ -131,6 +133,14 @@ static int network_load_one(Manager *manager, const char *filename) {
         if (!network->fdb_entries_by_section)
                 return log_oom();
 
+        network->address_labels_by_section = hashmap_new(&network_config_hash_ops);
+        if (!network->address_labels_by_section)
+                log_oom();
+
+        network->prefixes_by_section = hashmap_new(&network_config_hash_ops);
+        if (!network->prefixes_by_section)
+                return log_oom();
+
         network->filename = strdup(filename);
         if (!network->filename)
                 return log_oom();
@@ -165,6 +175,7 @@ static int network_load_one(Manager *manager, const char *filename) {
         network->use_bpdu = true;
         network->allow_port_to_be_root = true;
         network->unicast_flood = true;
+        network->priority = LINK_BRIDGE_PORT_PRIORITY_INVALID;
 
         network->lldp_mode = LLDP_MODE_ROUTERS_ONLY;
 
@@ -178,6 +189,7 @@ static int network_load_one(Manager *manager, const char *filename) {
         network->ipv6_accept_ra = -1;
         network->ipv6_dad_transmits = -1;
         network->ipv6_hop_limit = -1;
+        network->ipv6_proxy_ndp = -1;
         network->duid.type = _DUID_TYPE_INVALID;
         network->proxy_arp = -1;
         network->arp = -1;
@@ -191,6 +203,7 @@ static int network_load_one(Manager *manager, const char *filename) {
                               "Link\0"
                               "Network\0"
                               "Address\0"
+                              "IPv6AddressLabel\0"
                               "Route\0"
                               "DHCP\0"
                               "DHCPv4\0" /* compat */
@@ -199,7 +212,9 @@ static int network_load_one(Manager *manager, const char *filename) {
                               "IPv6NDPProxyAddress\0"
                               "Bridge\0"
                               "BridgeFDB\0"
-                              "BridgeVLAN\0",
+                              "BridgeVLAN\0"
+                              "IPv6PrefixDelegation\0"
+                              "IPv6Prefix\0",
                               config_item_perf_lookup, network_network_gperf_lookup,
                               false, network);
         if (r < 0)
@@ -270,6 +285,8 @@ void network_free(Network *network) {
         Address *address;
         FdbEntry *fdb_entry;
         IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
+        AddressLabel *label;
+        Prefix *prefix;
         Iterator i;
 
         if (!network)
@@ -317,9 +334,17 @@ void network_free(Network *network) {
         while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
                 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
 
+        while ((label = network->address_labels))
+                address_label_free(label);
+
+        while ((prefix = network->static_prefixes))
+                prefix_free(prefix);
+
         hashmap_free(network->addresses_by_section);
         hashmap_free(network->routes_by_section);
         hashmap_free(network->fdb_entries_by_section);
+        hashmap_free(network->address_labels_by_section);
+        hashmap_free(network->prefixes_by_section);
 
         if (network->manager) {
                 if (network->manager->networks)
@@ -428,7 +453,7 @@ int network_apply(Network *network, Link *link) {
         if (network->ipv4ll_route) {
                 Route *route;
 
-                r = route_new_static(network, "Network", 0, &route);
+                r = route_new_static(network, NULL, 0, &route);
                 if (r < 0)
                         return r;
 
index 4ce066a76463b16091eba7786b27cec7884bb5fa..b31921947dc551818b190a457cfb87fa410dab53 100644 (file)
@@ -28,6 +28,7 @@
 #include "resolve-util.h"
 
 #include "networkd-address.h"
+#include "networkd-address-label.h"
 #include "networkd-brvlan.h"
 #include "networkd-fdb.h"
 #include "networkd-lldp-tx.h"
@@ -157,13 +158,21 @@ struct Network {
         AddressFamilyBoolean link_local;
         bool ipv4ll_route;
 
+        /* IPv6 prefix delegation support */
+        bool router_prefix_delegation;
+        usec_t router_lifetime_usec;
+        uint8_t router_preference;
+        bool router_managed;
+        bool router_other_information;
+
         /* Bridge Support */
         bool use_bpdu;
         bool hairpin;
         bool fast_leave;
         bool allow_port_to_be_root;
         bool unicast_flood;
-        unsigned cost;
+        uint32_t cost;
+        uint16_t priority;
 
         bool use_br_vlan;
         uint16_t pvid;
@@ -176,6 +185,7 @@ struct Network {
         int ipv6_accept_ra;
         int ipv6_dad_transmits;
         int ipv6_hop_limit;
+        int ipv6_proxy_ndp;
         int proxy_arp;
 
         bool ipv6_accept_ra_use_dns;
@@ -201,15 +211,21 @@ struct Network {
         LIST_HEAD(Route, static_routes);
         LIST_HEAD(FdbEntry, static_fdb_entries);
         LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
+        LIST_HEAD(AddressLabel, address_labels);
+        LIST_HEAD(Prefix, static_prefixes);
 
         unsigned n_static_addresses;
         unsigned n_static_routes;
         unsigned n_static_fdb_entries;
         unsigned n_ipv6_proxy_ndp_addresses;
+        unsigned n_address_labels;
+        unsigned n_static_prefixes;
 
         Hashmap *addresses_by_section;
         Hashmap *routes_by_section;
         Hashmap *fdb_entries_by_section;
+        Hashmap *address_labels_by_section;
+        Hashmap *prefixes_by_section;
 
         struct in_addr_data *dns;
         unsigned n_dns;
diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c
new file mode 100644 (file)
index 0000000..af9e116
--- /dev/null
@@ -0,0 +1,79 @@
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2017 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (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 <netinet/icmp6.h>
+#include <arpa/inet.h>
+
+#include "networkd-address.h"
+#include "networkd-radv.h"
+#include "sd-radv.h"
+
+int radv_configure(Link *link) {
+        int r;
+        Prefix *p;
+
+        assert(link);
+        assert(link->network);
+
+        r = sd_radv_new(&link->radv);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_attach_event(link->radv, NULL, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_set_mac(link->radv, &link->mac);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_set_ifindex(link->radv, link->ifindex);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_set_managed_information(link->radv, link->network->router_managed);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_set_other_information(link->radv, link->network->router_other_information);
+        if (r < 0)
+                return r;
+
+        /* a value of 0xffffffff represents infinity, 0x0 means this host is
+           not a router */
+        r = sd_radv_set_router_lifetime(link->radv,
+                                        DIV_ROUND_UP(link->network->router_lifetime_usec, USEC_PER_SEC));
+        if (r < 0)
+                return r;
+
+        if (link->network->router_lifetime_usec > 0) {
+                r = sd_radv_set_preference(link->radv,
+                                           link->network->router_preference);
+                if (r < 0)
+                        return r;
+        }
+
+        LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
+                r = sd_radv_add_prefix(link->radv, p->radv_prefix);
+                if (r != -EEXIST && r < 0)
+                        return r;
+        }
+
+        return 0;
+}
diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h
new file mode 100644 (file)
index 0000000..a186b11
--- /dev/null
@@ -0,0 +1,24 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2017 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (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 "networkd-link.h"
+
+int radv_configure(Link *link);
index 570083f1803b626a017ef900c2bdaf709eab21f5..e5d61ce8cc6452560a42816758b0f4a74de5b36e 100644 (file)
@@ -17,6 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <linux/icmpv6.h>
+
 #include "alloc-util.h"
 #include "conf-parser.h"
 #include "in-addr-util.h"
@@ -228,7 +230,7 @@ int route_get(Link *link,
               unsigned char dst_prefixlen,
               unsigned char tos,
               uint32_t priority,
-              unsigned char table,
+              uint32_t table,
               Route **ret) {
 
         Route route, *existing;
@@ -270,7 +272,7 @@ static int route_add_internal(
                 unsigned char dst_prefixlen,
                 unsigned char tos,
                 uint32_t priority,
-                unsigned char table,
+                uint32_t table,
                 Route **ret) {
 
         _cleanup_route_free_ Route *route = NULL;
@@ -316,7 +318,7 @@ int route_add_foreign(
                 unsigned char dst_prefixlen,
                 unsigned char tos,
                 uint32_t priority,
-                unsigned char table,
+                uint32_t table,
                 Route **ret) {
 
         return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret);
@@ -329,7 +331,7 @@ int route_add(
               unsigned char dst_prefixlen,
               unsigned char tos,
               uint32_t priority,
-              unsigned char table,
+              uint32_t table,
               Route **ret) {
 
         Route *route;
@@ -755,10 +757,9 @@ int config_parse_destination(const char *unit,
 
         Network *network = userdata;
         _cleanup_route_free_ Route *n = NULL;
-        const char *address, *e;
         union in_addr_union buffer;
         unsigned char prefixlen;
-        int r, f;
+        int r;
 
         assert(filename);
         assert(section);
@@ -770,45 +771,20 @@ int config_parse_destination(const char *unit,
         if (r < 0)
                 return r;
 
-        /* Destination|Source=address/prefixlen */
-
-        /* address */
-        e = strchr(rvalue, '/');
-        if (e)
-                address = strndupa(rvalue, e - rvalue);
-        else
-                address = rvalue;
-
-        r = in_addr_from_string_auto(address, &f, &buffer);
+        r = in_addr_prefix_from_string(rvalue, AF_INET, &buffer, &prefixlen);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r, "Destination is invalid, ignoring assignment: %s", address);
-                return 0;
-        }
-
-        if (f != AF_INET && f != AF_INET6) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown address family, ignoring assignment: %s", address);
-                return 0;
-        }
-
-        /* prefixlen */
-        if (e) {
-                r = safe_atou8(e + 1, &prefixlen);
+                r = in_addr_prefix_from_string(rvalue, AF_INET6, &buffer, &prefixlen);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Route destination prefix length is invalid, ignoring assignment: %s", e + 1);
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Route %s= prefix is invalid, ignoring assignment: %s",
+                                   lvalue, rvalue);
                         return 0;
                 }
-        } else {
-                switch (f) {
-                        case AF_INET:
-                                prefixlen = 32;
-                                break;
-                        case AF_INET6:
-                                prefixlen = 128;
-                                break;
-                }
-        }
 
-        n->family = f;
+                n->family = AF_INET6;
+        } else
+                n->family = AF_INET;
+
         if (streq(lvalue, "Destination")) {
                 n->dst = buffer;
                 n->dst_prefixlen = prefixlen;
@@ -939,3 +915,111 @@ int config_parse_route_table(const char *unit,
 
         return 0;
 }
+
+int config_parse_gateway_onlink(const char *unit,
+                                const char *filename,
+                                unsigned line,
+                                const char *section,
+                                unsigned section_line,
+                                const char *lvalue,
+                                int ltype,
+                                const char *rvalue,
+                                void *data,
+                                void *userdata) {
+        Network *network = userdata;
+        _cleanup_route_free_ Route *n = NULL;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Could not parse gateway onlink \"%s\", ignoring assignment: %m", rvalue);
+                return 0;
+        }
+
+        SET_FLAG(n->flags, RTNH_F_ONLINK, r);
+        n = NULL;
+
+        return 0;
+}
+
+int config_parse_ipv6_route_preference(const char *unit,
+                                       const char *filename,
+                                       unsigned line,
+                                       const char *section,
+                                       unsigned section_line,
+                                       const char *lvalue,
+                                       int ltype,
+                                       const char *rvalue,
+                                       void *data,
+                                       void *userdata) {
+        Network *network = userdata;
+        _cleanup_route_free_ Route *n = NULL;
+        int r;
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        if (streq(rvalue, "low"))
+                n->pref = ICMPV6_ROUTER_PREF_LOW;
+        else if (streq(rvalue, "medium"))
+                n->pref = ICMPV6_ROUTER_PREF_MEDIUM;
+        else if (streq(rvalue, "high"))
+                n->pref = ICMPV6_ROUTER_PREF_HIGH;
+        else {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route preference: %s", rvalue);
+                return 0;
+        }
+
+        n = NULL;
+
+        return 0;
+}
+
+int config_parse_route_protocol(const char *unit,
+                                const char *filename,
+                                unsigned line,
+                                const char *section,
+                                unsigned section_line,
+                                const char *lvalue,
+                                int ltype,
+                                const char *rvalue,
+                                void *data,
+                                void *userdata) {
+        Network *network = userdata;
+        _cleanup_route_free_ Route *n = NULL;
+        int r;
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        if (streq(rvalue, "kernel"))
+                n->protocol = RTPROT_KERNEL;
+        else if (streq(rvalue, "boot"))
+                n->protocol = RTPROT_BOOT;
+        else if (streq(rvalue, "static"))
+                n->protocol = RTPROT_STATIC;
+        else {
+                r = safe_atou8(rvalue , &n->protocol);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+        }
+
+        n = NULL;
+
+        return 0;
+}
index 4ebfa0f0bdcf77586031b40e53e8c3abeee7fe18..3f389489da921a782a568fda7ba1d38bf218badc 100644 (file)
@@ -59,9 +59,9 @@ void route_free(Route *route);
 int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
 int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback);
 
-int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
-int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
-int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
+int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
+int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
+int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
 int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
 
 int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
@@ -75,3 +75,6 @@ int config_parse_destination(const char *unit, const char *filename, unsigned li
 int config_parse_route_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_route_scope(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_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_gateway_onlink(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_ipv6_route_preference(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_route_protocol(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/meson.build b/src/nspawn/meson.build
new file mode 100644 (file)
index 0000000..b6ac600
--- /dev/null
@@ -0,0 +1,40 @@
+systemd_nspawn_sources = files('''
+        nspawn.c
+        nspawn-settings.c
+        nspawn-settings.h
+        nspawn-mount.c
+        nspawn-mount.h
+        nspawn-network.c
+        nspawn-network.h
+        nspawn-expose-ports.c
+        nspawn-expose-ports.h
+        nspawn-cgroup.c
+        nspawn-cgroup.h
+        nspawn-seccomp.c
+        nspawn-seccomp.h
+        nspawn-register.c
+        nspawn-register.h
+        nspawn-setuid.c
+        nspawn-setuid.h
+        nspawn-stub-pid1.c
+        nspawn-stub-pid1.h
+        nspawn-patch-uid.c
+        nspawn-patch-uid.h
+'''.split())
+
+nspawn_gperf_c = custom_target(
+        'nspawn-gperf.c',
+        input : 'nspawn-gperf.gperf',
+        output : 'nspawn-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+systemd_nspawn_sources += [nspawn_gperf_c]
+
+tests += [
+        [['src/nspawn/test-patch-uid.c',
+          'src/nspawn/nspawn-patch-uid.c',
+          'src/nspawn/nspawn-patch-uid.h'],
+         [libshared],
+         [libacl],
+         '', 'manual'],
+]
index d749756437c5f867d121ebd5e4c9b5c7389ffdf2..fd565c09cdff77b5081600a0c366b6a4f36e5c78 100644 (file)
@@ -49,7 +49,7 @@ static int chown_cgroup_path(const char *path, uid_t uid_shift) {
                        "cgroup.subtree_control")
                 if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0)
                         log_full_errno(errno == ENOENT ? LOG_DEBUG :  LOG_WARNING, errno,
-                                       "Failed to chown() cgroup file %s, ignoring: %m", fn);
+                                       "Failed to chown \"%s/%s\", ignoring: %m", path, fn);
 
         return 0;
 }
index d27699412070ea153ddc13b2bfd781422a06f488..ac7290732e58fdb1b0208d240ad58f9aa7e81a1a 100644 (file)
@@ -552,7 +552,7 @@ int mount_all(const char *dest,
                 { NULL,                  "/proc/sysrq-trigger", NULL,    NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,             MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },                          /* ... then, make it r/o */
 
                 /* outer child mounts */
-                { "tmpfs",               "/tmp",                "tmpfs", "mode=1777", MS_STRICTATIME,                                            MOUNT_FATAL },
+                { "tmpfs",               "/tmp",                "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,                                            MOUNT_FATAL },
                 { "tmpfs",               "/sys",                "tmpfs", "mode=755",  MS_NOSUID|MS_NOEXEC|MS_NODEV,                              MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
                 { "sysfs",               "/sys",                "sysfs", NULL,        MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,                    MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO },    /* skipped if above was mounted */
                 { "sysfs",               "/sys",                "sysfs", NULL,                  MS_NOSUID|MS_NOEXEC|MS_NODEV,                    MOUNT_FATAL },                          /* skipped if above was mounted */
index 428cc04de05d4d10bfcadc836d1fe605f301db33..aa61aaaa79d858da0b98d696ce12f33129c5b229 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/veth.h>
 #include <net/if.h>
+#include <sys/file.h>
 
 #include "libudev.h"
 #include "sd-id128.h"
index e3ab39faea4450171d23eaea5b469313b55ff5e5..5b0faf809c622c8c6a25685f7febbfd0c44e9d1a 100644 (file)
 #include "strv.h"
 #include "util.h"
 
+static int append_machine_properties(
+                sd_bus_message *m,
+                CustomMount *mounts,
+                unsigned n_mounts,
+                int kill_signal,
+                char **properties) {
+
+        unsigned j;
+        int r;
+
+        assert(m);
+
+        r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in
+         * sync regardless if we are run with or without the --keep-unit switch. */
+        r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
+                                  /* Allow the container to
+                                   * access and create the API
+                                   * device nodes, so that
+                                   * PrivateDevices= in the
+                                   * container can work
+                                   * fine */
+                                  "/dev/net/tun", "rwm",
+                                  /* Allow the container
+                                   * access to ptys. However,
+                                   * do not permit the
+                                   * container to ever create
+                                   * these device nodes. */
+                                  "char-pts", "rw");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        for (j = 0; j < n_mounts; j++) {
+                CustomMount *cm = mounts + j;
+
+                if (cm->type != CUSTOM_MOUNT_BIND)
+                        continue;
+
+                r = is_device_node(cm->source);
+                if (r == -ENOENT) {
+                        /* The bind source might only appear as the image is put together, hence don't complain */
+                        log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
+                        continue;
+                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to stat %s: %m", cm->source);
+
+                if (r) {
+                        r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
+                                                  cm->source, cm->read_only ? "r" : "rw");
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to append message arguments: %m");
+                }
+        }
+
+        if (kill_signal != 0) {
+                r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        return 0;
+}
+
 int register_machine(
                 const char *machine_name,
                 pid_t pid,
@@ -68,7 +139,6 @@ int register_machine(
                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
         } else {
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-                unsigned j;
 
                 r = sd_bus_message_new_method_call(
                                 bus,
@@ -103,63 +173,14 @@ int register_machine(
                                 return bus_log_create_error(r);
                 }
 
-                r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                /* If you make changes here, also make sure to update
-                 * systemd-nspawn@.service, to keep the device
-                 * policies in sync regardless if we are run with or
-                 * without the --keep-unit switch. */
-                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
-                                          /* Allow the container to
-                                           * access and create the API
-                                           * device nodes, so that
-                                           * PrivateDevices= in the
-                                           * container can work
-                                           * fine */
-                                          "/dev/net/tun", "rwm",
-                                          /* Allow the container
-                                           * access to ptys. However,
-                                           * do not permit the
-                                           * container to ever create
-                                           * these device nodes. */
-                                          "char-pts", "rw");
+                r = append_machine_properties(
+                                m,
+                                mounts,
+                                n_mounts,
+                                kill_signal,
+                                properties);
                 if (r < 0)
-                        return bus_log_create_error(r);
-
-                for (j = 0; j < n_mounts; j++) {
-                        CustomMount *cm = mounts + j;
-
-                        if (cm->type != CUSTOM_MOUNT_BIND)
-                                continue;
-
-                        r = is_device_node(cm->source);
-                        if (r == -ENOENT) {
-                                /* The bind source might only appear as the image is put together, hence don't complain */
-                                log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
-                                continue;
-                        }
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to stat %s: %m", cm->source);
-
-                        if (r) {
-                                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
-                                        cm->source, cm->read_only ? "r" : "rw");
-                                if (r < 0)
-                                        return log_error_errno(r, "Failed to append message arguments: %m");
-                        }
-                }
-
-                if (kill_signal != 0) {
-                        r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
-                        r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
+                        return r;
 
                 r = bus_append_unit_property_assignment_many(m, properties);
                 if (r < 0)
@@ -229,3 +250,104 @@ int terminate_machine(pid_t pid) {
 
         return 0;
 }
+
+int allocate_scope(
+                const char *machine_name,
+                pid_t pid,
+                const char *slice,
+                CustomMount *mounts,
+                unsigned n_mounts,
+                int kill_signal,
+                char **properties) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
+        _cleanup_free_ char *scope = NULL;
+        const char *description, *object;
+        int r;
+
+        r = sd_bus_default_system(&bus);
+        if (r < 0)
+                return log_error_errno(r, "Failed to open system bus: %m");
+
+        r = bus_wait_for_jobs_new(bus, &w);
+        if (r < 0)
+                return log_error_errno(r, "Could not watch job: %m");
+
+        r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope);
+        if (r < 0)
+                return log_error_errno(r, "Failed to mangle scope name: %m");
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &m,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "StartTransientUnit");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(m, "ss", scope, "fail");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* Properties */
+        r = sd_bus_message_open_container(m, 'a', "(sv)");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        description = strjoina("Container ", machine_name);
+
+        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
+                                  "PIDs", "au", 1, pid,
+                                  "Description", "s", description,
+                                  "Delegate", "b", 1,
+                                  "Slice", "s", isempty(slice) ? "machine.slice" : slice);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = append_machine_properties(
+                        m,
+                        mounts,
+                        n_mounts,
+                        kill_signal,
+                        properties);
+        if (r < 0)
+                return r;
+
+        r = bus_append_unit_property_assignment_many(m, properties);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_close_container(m);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* No auxiliary units */
+        r = sd_bus_message_append(
+                        m,
+                        "a(sa(sv))",
+                        0);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_call(bus, m, 0, &error, &reply);
+        if (r < 0) {
+                log_error("Failed to allocate scope: %s", bus_error_message(&error, r));
+                return r;
+        }
+
+        r = sd_bus_message_read(reply, "o", &object);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = bus_wait_for_jobs_one(w, object, false);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
index 304c5a485b2fbfb1fa8960691d82bb10b470e6d6..6694b3f6b1b10e71173a5dab2323980011987800 100644 (file)
@@ -27,3 +27,5 @@
 
 int register_machine(const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, bool keep_unit, const char *service);
 int terminate_machine(pid_t pid);
+
+int allocate_scope(const char *machine_name, pid_t pid, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties);
index 7f2a53a2451a25a0bf384a0eede1873030dbccbe..0c48434db8e78ad4b9206fa24fba789411d92956 100644 (file)
@@ -18,9 +18,9 @@
 ***/
 
 #include <sys/reboot.h>
-#include <sys/unistd.h>
 #include <sys/wait.h>
 #include <sys/prctl.h>
+#include <unistd.h>
 
 #include "fd-util.h"
 #include "log.h"
@@ -188,7 +188,16 @@ int stub_pid1(sd_id128_t uuid) {
                 else
                         assert_not_reached("Got unexpected signal");
 
-                /* (void) kill_and_sigcont(pid, SIGTERM); */
+                r = kill_and_sigcont(pid, SIGTERM);
+
+                /* Let's send a SIGHUP after the SIGTERM, as shells tend to ignore SIGTERM but do react to SIGHUP. We
+                 * do it strictly in this order, so that the SIGTERM is dispatched first, and SIGHUP second for those
+                 * processes which handle both. That's because services tend to bind configuration reload or something
+                 * else to SIGHUP. */
+
+                if (r != -ESRCH)
+                        (void) kill(pid, SIGHUP);
+
                 quit_usec = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC;
         }
 
index 1fc0501c2e70eb590cc8f67ee4d0596486b08813..8a5fedd4b0b9aeebd79a82e05158d32ece6cc8a9 100644 (file)
@@ -18,7 +18,7 @@
 ***/
 
 #ifdef HAVE_BLKID
-#include <blkid/blkid.h>
+#include <blkid.h>
 #endif
 #include <errno.h>
 #include <getopt.h>
@@ -389,12 +389,10 @@ static void parse_mount_settings_env(void) {
         if (r < 0) {
                 log_warning_errno(r, "Failed to parse SYSTEMD_NSPAWN_API_VFS_WRITABLE from environment, ignoring.");
                 return;
-        } else if (r > 0)
-                arg_mount_settings &= ~MOUNT_APPLY_APIVFS_RO;
-        else
-                arg_mount_settings |= MOUNT_APPLY_APIVFS_RO;
+        }
 
-        arg_mount_settings &= ~MOUNT_APPLY_APIVFS_NETNS;
+        SET_FLAG(arg_mount_settings, MOUNT_APPLY_APIVFS_RO, r == 0);
+        SET_FLAG(arg_mount_settings, MOUNT_APPLY_APIVFS_NETNS, false);
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -1085,8 +1083,8 @@ static int parse_argv(int argc, char *argv[]) {
         if (arg_userns_mode == USER_NAMESPACE_PICK)
                 arg_userns_chown = true;
 
-        if (arg_keep_unit && cg_pid_get_owner_uid(0, NULL) >= 0) {
-                log_error("--keep-unit may not be used when invoked from a user session.");
+        if (arg_keep_unit && arg_register && cg_pid_get_owner_uid(0, NULL) >= 0) {
+                log_error("--keep-unit --register=yes may not be used when invoked from a user session.");
                 return -EINVAL;
         }
 
@@ -1158,6 +1156,10 @@ static int parse_argv(int argc, char *argv[]) {
 
         arg_caps_retain = (arg_caps_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus;
 
+        r = cg_unified_flush();
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m");
+
         e = getenv("SYSTEMD_NSPAWN_CONTAINER_SERVICE");
         if (e)
                 arg_container_service_name = e;
@@ -1321,17 +1323,32 @@ static int setup_timezone(const char *dest) {
         return 0;
 }
 
-static int resolved_running(void) {
+static int resolved_listening(void) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_free_ char *dns_stub_listener_mode = NULL;
         int r;
 
-        /* Check if resolved is running */
+        /* Check if resolved is listening */
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
                 return r;
 
-        return bus_name_has_owner(bus, "org.freedesktop.resolve1", NULL);
+        r = bus_name_has_owner(bus, "org.freedesktop.resolve1", NULL);
+        if (r <= 0)
+                return r;
+
+        r = sd_bus_get_property_string(bus,
+                                       "org.freedesktop.resolve1",
+                                       "/org/freedesktop/resolve1",
+                                       "org.freedesktop.resolve1.Manager",
+                                       "DNSStubListener",
+                                       NULL,
+                                       &dns_stub_listener_mode);
+        if (r < 0)
+                return r;
+
+        return STR_IN_SET(dns_stub_listener_mode, "udp", "yes");
 }
 
 static int setup_resolv_conf(const char *dest) {
@@ -1358,7 +1375,7 @@ static int setup_resolv_conf(const char *dest) {
         }
 
         if (access("/usr/lib/systemd/resolv.conf", F_OK) >= 0 &&
-            resolved_running() > 0) {
+            resolved_listening() > 0) {
 
                 /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the
                  * container, so that the container can use the host's resolver. Given that network namespacing is
@@ -2012,7 +2029,7 @@ static int determine_names(void) {
                         if (r < 0)
                                 return log_error_errno(r, "Failed to find image for machine '%s': %m", arg_machine);
                         if (r == 0) {
-                                log_error("No image for machine '%s': %m", arg_machine);
+                                log_error("No image for machine '%s'.", arg_machine);
                                 return -ENOENT;
                         }
 
@@ -3370,7 +3387,19 @@ static int run(int master,
                                 arg_container_service_name);
                 if (r < 0)
                         return r;
-        }
+        } else if (!arg_keep_unit) {
+                r = allocate_scope(
+                                arg_machine,
+                                *pid,
+                                arg_slice,
+                                arg_custom_mounts, arg_n_custom_mounts,
+                                arg_kill_signal,
+                                arg_property);
+                if (r < 0)
+                        return r;
+
+        } else if (arg_slice || arg_property)
+                log_notice("Machine and scope registration turned off, --slice= and --property= settings will have no effect.");
 
         r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
         if (r < 0)
@@ -3530,10 +3559,6 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
-        r = cg_unified_flush();
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m");
-
         /* Make sure rename_process() in the stub init process can work */
         saved_argv = argv;
         saved_argc = argc;
index d155625e111fc7c04172124e90d072e7365d33f9..ec059d95865a2970a21dbe5b0405b94b803b1341 100644 (file)
@@ -17,7 +17,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dlfcn.h>
 #include <errno.h>
 #include <netdb.h>
 #include <nss.h>
@@ -39,20 +38,6 @@ NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
 
 #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
 
-typedef void (*voidfunc_t)(void);
-
-static voidfunc_t find_fallback(const char *module, const char *symbol) {
-        void *dl;
-
-        /* Try to find a fallback NSS module symbol */
-
-        dl = dlopen(module, RTLD_LAZY|RTLD_NODELETE);
-        if (!dl)
-                return NULL;
-
-        return dlsym(dl, symbol);
-}
-
 static bool bus_error_shall_fallback(sd_bus_error *e) {
         return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
                sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
@@ -151,7 +136,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fallback;
+                goto fail;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -179,13 +164,14 @@ enum nss_status _nss_resolve_gethostbyname4_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error))
-                        goto fallback;
+                /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails,
+                   allowing falling back to other nss modules. Treat all other error conditions as
+                   NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this
+                   case so that the nsswitch.conf configuration can distuingish such executed but
+                   negative replies from complete failure to talk to resolved). */
+                if (!bus_error_shall_fallback(&error))
+                        ret = NSS_STATUS_NOTFOUND;
 
-                /* Treat all other error conditions as NOTFOUND, and fail. This includes DNSSEC errors and
-                   suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf configuration can distuingish
-                   such executed but negative replies from complete failure to talk to resolved. */
-                ret = NSS_STATUS_NOTFOUND;
                 goto fail;
         }
 
@@ -286,17 +272,6 @@ enum nss_status _nss_resolve_gethostbyname4_r(
 
         return NSS_STATUS_SUCCESS;
 
-fallback:
-        {
-                _nss_gethostbyname4_r_t fallback;
-
-                fallback = (_nss_gethostbyname4_r_t)
-                        find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
-
-                if (fallback)
-                        return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
-        }
-
 fail:
         *errnop = -r;
         *h_errnop = NO_RECOVERY;
@@ -339,7 +314,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fallback;
+                goto fail;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -367,10 +342,9 @@ enum nss_status _nss_resolve_gethostbyname3_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error))
-                        goto fallback;
+                if (!bus_error_shall_fallback(&error))
+                        ret = NSS_STATUS_NOTFOUND;
 
-                ret = NSS_STATUS_NOTFOUND;
                 goto fail;
         }
 
@@ -484,16 +458,6 @@ enum nss_status _nss_resolve_gethostbyname3_r(
 
         return NSS_STATUS_SUCCESS;
 
-fallback:
-        {
-                _nss_gethostbyname3_r_t fallback;
-
-                fallback = (_nss_gethostbyname3_r_t)
-                        find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
-                if (fallback)
-                        return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
-        }
-
 fail:
         *errnop = -r;
         *h_errnop = NO_RECOVERY;
@@ -540,7 +504,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         r = sd_bus_open_system(&bus);
         if (r < 0)
-                goto fallback;
+                goto fail;
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -576,10 +540,9 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                         return NSS_STATUS_NOTFOUND;
                 }
 
-                if (bus_error_shall_fallback(&error))
-                        goto fallback;
+                if (!bus_error_shall_fallback(&error))
+                        ret = NSS_STATUS_NOTFOUND;
 
-                ret = NSS_STATUS_NOTFOUND;
                 goto fail;
         }
 
@@ -674,17 +637,6 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         return NSS_STATUS_SUCCESS;
 
-fallback:
-        {
-                _nss_gethostbyaddr2_r_t fallback;
-
-                fallback = (_nss_gethostbyaddr2_r_t)
-                        find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");
-
-                if (fallback)
-                        return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
-        }
-
 fail:
         *errnop = -r;
         *h_errnop = NO_RECOVERY;
index b704ca3b4b6bfd0e5841a75d0d581aec82d8e9cd..db3bf5bd21e5ab18f503bbdc6c92024ce084c21b 100644 (file)
 #include "string-util.h"
 #include "util.h"
 
-#ifndef RC_LOCAL_SCRIPT_PATH_START
-#define RC_LOCAL_SCRIPT_PATH_START "/etc/rc.d/rc.local"
-#endif
-
-#ifndef RC_LOCAL_SCRIPT_PATH_STOP
-#define RC_LOCAL_SCRIPT_PATH_STOP "/sbin/halt.local"
-#endif
-
 static const char *arg_dest = "/tmp";
 
 static int add_symlink(const char *service, const char *where) {
diff --git a/src/resolve/dns_type-to-name.awk b/src/resolve/dns_type-to-name.awk
new file mode 100644 (file)
index 0000000..badb182
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN{
+        print "const char *dns_type_to_string(int type) {\n\tswitch(type) {"
+}
+{
+        printf "        case DNS_TYPE_%s: return ", $1;
+        sub(/_/, "-");
+        printf "\"%s\";\n", $1
+}
+END{
+        print "        default: return NULL;\n\t}\n}\n"
+}
diff --git a/src/resolve/generate-dns_type-gperf.py b/src/resolve/generate-dns_type-gperf.py
new file mode 100755 (executable)
index 0000000..8a0b43c
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+"""Generate %-from-name.gperf from %-list.txt
+"""
+
+import sys
+
+name, prefix, input = sys.argv[1:]
+
+print("""\
+struct {}_name {{ const char* name; int id; }};
+%null-strings
+%%""".format(name))
+
+for line in open(input):
+    line = line.rstrip()
+    s = line.replace('_', '-')
+    print("{}, {}{}".format(s, prefix, line))
diff --git a/src/resolve/generate-dns_type-list.sed b/src/resolve/generate-dns_type-list.sed
new file mode 100644 (file)
index 0000000..b7bc30f
--- /dev/null
@@ -0,0 +1 @@
+s/.* DNS_TYPE_(\w+).*/\1/p
diff --git a/src/resolve/meson.build b/src/resolve/meson.build
new file mode 100644 (file)
index 0000000..fe22878
--- /dev/null
@@ -0,0 +1,187 @@
+basic_dns_sources = files('''
+        resolved-dns-dnssec.c
+        resolved-dns-dnssec.h
+        resolved-dns-packet.c
+        resolved-dns-packet.h
+        resolved-dns-rr.c
+        resolved-dns-rr.h
+        resolved-dns-answer.c
+        resolved-dns-answer.h
+        resolved-dns-question.c
+        resolved-dns-question.h
+        dns-type.c
+'''.split())
+
+dns_type_h = files('dns-type.h')[0]
+
+systemd_resolved_only_sources = files('''
+        resolved.c
+        resolved-manager.c
+        resolved-manager.h
+        resolved-conf.c
+        resolved-conf.h
+        resolved-resolv-conf.c
+        resolved-resolv-conf.h
+        resolved-bus.c
+        resolved-bus.h
+        resolved-link.h
+        resolved-link.c
+        resolved-link-bus.c
+        resolved-link-bus.h
+        resolved-llmnr.h
+        resolved-llmnr.c
+        resolved-mdns.h
+        resolved-mdns.c
+        resolved-def.h
+        resolved-dns-query.h
+        resolved-dns-query.c
+        resolved-dns-synthesize.h
+        resolved-dns-synthesize.c
+        resolved-dns-transaction.h
+        resolved-dns-transaction.c
+        resolved-dns-scope.h
+        resolved-dns-scope.c
+        resolved-dns-server.h
+        resolved-dns-server.c
+        resolved-dns-search-domain.h
+        resolved-dns-search-domain.c
+        resolved-dns-cache.h
+        resolved-dns-cache.c
+        resolved-dns-zone.h
+        resolved-dns-zone.c
+        resolved-dns-stream.h
+        resolved-dns-stream.c
+        resolved-dns-trust-anchor.h
+        resolved-dns-trust-anchor.c
+        resolved-dns-stub.h
+        resolved-dns-stub.c
+        resolved-etc-hosts.h
+        resolved-etc-hosts.c
+'''.split())
+
+systemd_resolve_only_sources = files('resolve-tool.c')
+
+############################################################
+
+dns_type_list_txt = custom_target(
+        'dns_type-list.txt',
+        input : ['generate-dns_type-list.sed', dns_type_h],
+        output : 'dns_type-list.txt',
+        command : [sed, '-n', '-r', '-f', '@INPUT0@', '@INPUT1@'],
+        capture : true)
+
+generate_dns_type_gperf = find_program('generate-dns_type-gperf.py')
+
+dns_type_headers = [dns_type_h]
+foreach item : [['dns_type', dns_type_list_txt, 'dns_type', 'DNS_TYPE_']]
+
+        fname = '@0@-from-name.gperf'.format(item[0])
+        gperf_file = custom_target(
+                fname,
+                input : item[1],
+                output : fname,
+                command : [generate_dns_type_gperf, item[2], item[3], '@INPUT@'],
+                capture : true)
+
+        fname = '@0@-from-name.h'.format(item[0])
+        target1 = custom_target(
+                fname,
+                input : gperf_file,
+                output : fname,
+                command : [gperf,
+                           '-L', 'ANSI-C', '-t', '--ignore-case',
+                           '-N', 'lookup_@0@'.format(item[2]),
+                           '-H', 'hash_@0@_name'.format(item[2]),
+                           '-p', '-C',
+                           '@INPUT@'],
+                capture : true)
+
+        fname = '@0@-to-name.h'.format(item[0])
+        awkscript = '@0@-to-name.awk'.format(item[0])
+        target2 = custom_target(
+                fname,
+                input : [awkscript, item[1]],
+                output : fname,
+                command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+                capture : true)
+
+        dns_type_headers += [target1, target2]
+endforeach
+
+resolved_gperf_c = custom_target(
+        'resolved_gperf.c',
+        input : 'resolved-gperf.gperf',
+        output : 'resolved-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+systemd_resolved_sources = (basic_dns_sources +
+                            [resolved_gperf_c] +
+                            systemd_resolved_only_sources +
+                            dns_type_headers)
+
+systemd_resolve_sources = (basic_dns_sources +
+                           systemd_resolve_only_sources +
+                           dns_type_headers)
+
+if conf.get('ENABLE_RESOLVED', false)
+        install_data('org.freedesktop.resolve1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.resolve1.service',
+                     install_dir : dbussystemservicedir)
+
+        resolved_conf = configure_file(
+                input : 'resolved.conf.in',
+                output : 'resolved.conf',
+                configuration : substs)
+        install_data(resolved_conf,
+                     install_dir : pkgsysconfdir)
+
+        install_data('resolv.conf',
+                     install_dir : rootlibexecdir)
+endif
+
+tests += [
+        [['src/resolve/test-resolve-tables.c',
+          basic_dns_sources,
+          dns_type_headers,
+          'src/shared/test-tables.h'],
+         [],
+         [libgcrypt,
+          libgpg_error,
+          libm],
+         'ENABLE_RESOLVED'],
+
+        [['src/resolve/test-dns-packet.c',
+          basic_dns_sources,
+          dns_type_headers],
+         [],
+         [libgcrypt,
+          libgpg_error,
+          libm],
+         'ENABLE_RESOLVED'],
+
+        [['src/resolve/test-resolved-packet.c',
+          basic_dns_sources,
+          dns_type_headers],
+         [],
+         [libgcrypt,
+          libgpg_error,
+          libm],
+         'ENABLE_RESOLVED'],
+
+        [['src/resolve/test-dnssec.c',
+          basic_dns_sources,
+          dns_type_headers],
+         [],
+         [libgcrypt,
+          libgpg_error,
+          libm],
+         'ENABLE_RESOLVED'],
+
+        [['src/resolve/test-dnssec-complex.c',
+          'src/resolve/dns-type.c',
+          dns_type_headers],
+         [],
+         [],
+         'ENABLE_RESOLVED', 'manual'],
+]
index 32537ce6e8acb6db5f24fb7de931ee5bb44148df..c62058917fca9231de45c32fb807a8175c6f0f9c 100644 (file)
@@ -114,8 +114,8 @@ static void print_source(uint64_t flags, usec_t rtt) {
                        flags & SD_RESOLVED_DNS ? " DNS" :"",
                        flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
                        flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
-                       flags & SD_RESOLVED_MDNS_IPV4 ? "mDNS/IPv4" : "",
-                       flags & SD_RESOLVED_MDNS_IPV6 ? "mDNS/IPv6" : "");
+                       flags & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "",
+                       flags & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : "");
 
         assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
 
index 2c501093882635e605af5e2857fcc3bcc34dcabc..5aa23485761ec9821889e03d096e055f596ec291 100644 (file)
@@ -345,10 +345,10 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
                 return r;
 
         r = dns_question_new_address(&question_idna, family, hostname, true);
-        if (r < 0)
+        if (r < 0 && r != -EALREADY)
                 return r;
 
-        r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags);
+        r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags);
         if (r < 0)
                 return r;
 
@@ -1450,6 +1450,8 @@ static int bus_property_get_ntas(
         return sd_bus_message_close_container(reply);
 }
 
+static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
+
 static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = userdata;
         DnsScope *s;
@@ -1577,6 +1579,7 @@ static const sd_bus_vtable resolve_vtable[] = {
         SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
         SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
         SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
+        SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
 
         SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
index abf3263178b8e7868b6f97ff78057d9ee4c6970b..75636e0e5647816d53d8841fd7f16eaecf61fa44 100644 (file)
@@ -233,10 +233,10 @@ int manager_parse_config_file(Manager *m) {
         assert(m);
 
         r = config_parse_many_nulstr(PKGSYSCONFDIR "/resolved.conf",
-                              CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
-                              "Resolve\0",
-                              config_item_perf_lookup, resolved_gperf_lookup,
-                              false, m);
+                                     CONF_PATHS_NULSTR("systemd/resolved.conf.d"),
+                                     "Resolve\0",
+                                     config_item_perf_lookup, resolved_gperf_lookup,
+                                     false, m);
         if (r < 0)
                 return r;
 
@@ -246,6 +246,12 @@ int manager_parse_config_file(Manager *m) {
                         return r;
         }
 
+#ifndef HAVE_GCRYPT
+        if (m->dnssec_mode != DNSSEC_NO) {
+                log_warning("DNSSEC option cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.");
+                m->dnssec_mode = DNSSEC_NO;
+        }
+#endif
         return 0;
 
 }
index 652970284ed666ba09ce75f8e2aa50c0da63557f..49a04615d4e128228fada224a7505685d066d57f 100644 (file)
@@ -28,6 +28,9 @@
 
 #define EDNS0_OPT_DO (1<<15)
 
+#define DNS_PACKET_SIZE_START 512u
+assert_cc(DNS_PACKET_SIZE_START > DNS_PACKET_HEADER_SIZE)
+
 typedef struct DnsPacketRewinder {
         DnsPacket *packet;
         size_t saved_rindex;
@@ -41,19 +44,28 @@ static void rewind_dns_packet(DnsPacketRewinder *rewinder) {
 #define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0)
 #define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while (0)
 
-int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
+int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize) {
         DnsPacket *p;
         size_t a;
 
         assert(ret);
 
-        if (mtu <= UDP_PACKET_HEADER_SIZE)
+        /* The caller may not check what is going to be truly allocated, so do not allow to
+         * allocate a DNS packet bigger than DNS_PACKET_SIZE_MAX.
+         */
+        if (min_alloc_dsize > DNS_PACKET_SIZE_MAX) {
+                log_error("Requested packet data size too big: %zu", min_alloc_dsize);
+                return -EFBIG;
+        }
+
+        /* When dns_packet_new() is called with min_alloc_dsize == 0, allocate more than the
+         * absolute minimum (which is the dns packet header size), to avoid
+         * resizing immediately again after appending the first data to the packet.
+         */
+        if (min_alloc_dsize < DNS_PACKET_HEADER_SIZE)
                 a = DNS_PACKET_SIZE_START;
         else
-                a = mtu - UDP_PACKET_HEADER_SIZE;
-
-        if (a < DNS_PACKET_HEADER_SIZE)
-                a = DNS_PACKET_HEADER_SIZE;
+                a = min_alloc_dsize;
 
         /* round up to next page size */
         a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
@@ -127,13 +139,13 @@ void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool trun
         }
 }
 
-int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
+int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled) {
         DnsPacket *p;
         int r;
 
         assert(ret);
 
-        r = dns_packet_new(&p, protocol, mtu);
+        r = dns_packet_new(&p, protocol, min_alloc_dsize);
         if (r < 0)
                 return r;
 
@@ -2269,6 +2281,9 @@ int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
         if (r < 0)
                 return r;
 
+        if (!p->question)
+                return 0;
+
         if (p->question->n_keys != 1)
                 return 0;
 
index 2c92392e4d78ee93dfcb5cceeb4e672a0f4dbc8b..a65d6d38cf972c88530f8a40f16967bc24727320 100644 (file)
@@ -58,15 +58,13 @@ struct DnsPacketHeader {
 /* 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
    be the absolute maximum. */
-#define DNS_PACKET_SIZE_MAX 0xFFFF
+#define DNS_PACKET_SIZE_MAX 0xFFFFu
 
 /* RFC 1035 say 512 is the maximum, for classic unicast DNS */
-#define DNS_PACKET_UNICAST_SIZE_MAX 512
+#define DNS_PACKET_UNICAST_SIZE_MAX 512u
 
 /* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */
-#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096
-
-#define DNS_PACKET_SIZE_START 512
+#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096u
 
 struct DnsPacket {
         int n_ref;
@@ -185,8 +183,8 @@ static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) {
                 (unsigned) DNS_PACKET_ARCOUNT(p);
 }
 
-int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu);
-int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled);
+int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize);
+int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled);
 
 void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated);
 
index c8b502d1cd7fc22cdf121ab42a3bfb464c7140e5..24f3e8e351f0a2f78deed1f46e77be5d5dc13702 100644 (file)
@@ -309,8 +309,14 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
                 r = dns_name_apply_idna(name, &buf);
                 if (r < 0)
                         return r;
-
-                name = buf;
+                if (r > 0 && !streq(name, buf))
+                        name = buf;
+                else
+                        /* We did not manage to create convert the idna name, or it's
+                         * the same as the original name. We assume the caller already
+                         * created an uncoverted question, so let's not repeat work
+                         * unnecessarily. */
+                        return -EALREADY;
         }
 
         q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
@@ -422,8 +428,8 @@ int dns_question_new_service(
                         r = dns_name_apply_idna(domain, &buf);
                         if (r < 0)
                                 return r;
-
-                        domain = buf;
+                        if (r > 0)
+                                domain = buf;
                 }
 
                 r = dns_service_join(service, type, domain, &joined);
index 5498f7b9cbdcd0f985f626a9652a64b16383b857..b3d37525f475688863e6cada63af436ebc9a4631 100644 (file)
@@ -17,7 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sd-messages.h>
+#include "sd-messages.h"
 
 #include "alloc-util.h"
 #include "resolved-dns-server.h"
@@ -304,7 +304,10 @@ void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLeve
         if (s->max_rtt < rtt) {
                 s->max_rtt = rtt;
                 s->resend_timeout = CLAMP(s->max_rtt * 2, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
-        }
+        } else if (s->resend_timeout > rtt)
+                /* If we received the packet faster than the resend_timeout, bias
+                 * the resend_timeout back to the rtt. */
+                s->resend_timeout = CLAMP((2 * s->resend_timeout + rtt) / 3, DNS_TIMEOUT_MIN_USEC, DNS_TIMEOUT_MAX_USEC);
 }
 
 void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level, usec_t usec) {
@@ -716,9 +719,9 @@ DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
                 return s;
 
         if (s)
-                log_info("Switching to %s DNS server %s.",
-                         dns_server_type_to_string(s->type),
-                         dns_server_string(s));
+                log_debug("Switching to %s DNS server %s.",
+                          dns_server_type_to_string(s->type),
+                          dns_server_string(s));
 
         dns_server_unref(m->current_dns_server);
         m->current_dns_server = dns_server_ref(s);
index ff2ad9c1de4fc54b9cd92ad28be839d0d70fb9c1..3075f62b5e26fe09009cb23bbfefaaa2a09bd25e 100644 (file)
@@ -17,7 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sd-messages.h>
+#include "sd-messages.h"
 
 #include "af-list.h"
 #include "alloc-util.h"
index 7e9f9e5a2075d5dd22edb1533771e29b2f3bc8ee..dda98750632c496733d1349170f30027f3f9828e 100644 (file)
@@ -17,7 +17,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sd-messages.h>
+#include "sd-messages.h"
 
 #include "alloc-util.h"
 #include "conf-files.h"
index 446f85cdf41afb2aa650e6ac3811e6e685626450..5153563b9993bff3ebf09732d776456370f46f7f 100644 (file)
@@ -18,6 +18,7 @@ Resolve.DNS,             config_parse_dns_servers,            DNS_SERVER_SYSTEM,
 Resolve.FallbackDNS,     config_parse_dns_servers,            DNS_SERVER_FALLBACK, 0
 Resolve.Domains,         config_parse_search_domains,         0,                   0
 Resolve.LLMNR,           config_parse_resolve_support,        0,                   offsetof(Manager, llmnr_support)
+Resolve.MulticastDNS,    config_parse_resolve_support,        0,                   offsetof(Manager, mdns_support)
 Resolve.DNSSEC,          config_parse_dnssec_mode,            0,                   offsetof(Manager, dnssec_mode)
 Resolve.Cache,           config_parse_bool,                   0,                   offsetof(Manager, enable_cache)
 Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0,                   offsetof(Manager, dns_stub_listener_mode)
index 3f7f9035cfdcd55af8613cb37bd6b587e628bad2..61a3f2036253c3e59b6c198e28d112185686d096 100644 (file)
@@ -28,6 +28,8 @@
 #include "mkdir.h"
 #include "parse-util.h"
 #include "resolved-link.h"
+#include "resolved-llmnr.h"
+#include "resolved-mdns.h"
 #include "string-util.h"
 #include "strv.h"
 
@@ -311,6 +313,12 @@ void link_set_dnssec_mode(Link *l, DnssecMode mode) {
 
         assert(l);
 
+#ifndef HAVE_GCRYPT
+        if (mode == DNSSEC_YES || mode == DNSSEC_ALLOW_DOWNGRADE)
+                log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.");
+        return;
+#endif
+
         if (l->dnssec_mode == mode)
                 return;
 
@@ -523,10 +531,25 @@ static void link_read_settings(Link *l) {
 }
 
 int link_update(Link *l) {
+        int r;
+
         assert(l);
 
         link_read_settings(l);
         link_load_user(l);
+
+        if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
+                r = manager_llmnr_start(l->manager);
+                if (r < 0)
+                        return r;
+        }
+
+        if (l->mdns_support != RESOLVE_SUPPORT_NO) {
+                r = manager_mdns_start(l->manager);
+                if (r < 0)
+                        return r;
+        }
+
         link_allocate_scopes(l);
         link_add_rrs(l, false);
 
@@ -539,7 +562,7 @@ bool link_relevant(Link *l, int family, bool local_multicast) {
 
         assert(l);
 
-        /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
+        /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
          * beat, can do multicast and has at least one link-local (or better) IP address.
          *
          * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
@@ -552,9 +575,6 @@ bool link_relevant(Link *l, int family, bool local_multicast) {
                 return false;
 
         if (local_multicast) {
-                if (l->flags & IFF_POINTOPOINT)
-                        return false;
-
                 if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
                         return false;
         }
@@ -594,7 +614,7 @@ DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
                 return s;
 
         if (s)
-                log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
+                log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
 
         dns_server_unref(l->current_dns_server);
         l->current_dns_server = dns_server_ref(s);
index 3516af58ee6d1e3d02cd51e854d25d9dfb0b32f6..29396e997356149728a3c30552a24f5ed7f8fa9b 100644 (file)
@@ -77,7 +77,7 @@ int manager_llmnr_start(Manager *m) {
         return 0;
 
 eaddrinuse:
-        log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
+        log_warning("Another LLMNR responder prohibits binding the socket to the same port. Turning off LLMNR support.");
         m->llmnr_support = RESOLVE_SUPPORT_NO;
         manager_llmnr_stop(m);
 
@@ -136,56 +136,75 @@ int manager_llmnr_ipv4_udp_fd(Manager *m) {
 
         m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (m->llmnr_ipv4_udp_fd < 0)
-                return -errno;
+                return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m");
 
         /* 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;
+                r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_TTL: %m");
                 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;
+                r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m");
                 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;
+                r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set IP_MTU_DISCOVER: %m");
                 goto fail;
         }
 
+        /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
         r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
         if (r < 0) {
-                r = -errno;
-                goto fail;
+                if (errno != EADDRINUSE) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
+                        goto fail;
+                }
+
+                log_warning("LLMNR-IPv4(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
+
+                /* try again with SO_REUSEADDR */
+                r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
+
+                r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m");
+                        goto fail;
+                }
+        } else {
+                /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
+                r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m");
+                        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);
@@ -216,55 +235,74 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
 
         m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (m->llmnr_ipv6_udp_fd < 0)
-                return -errno;
+                return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m");
 
         r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m");
                 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;
+                r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_HOPS: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_LOOP: %m");
                 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;
+                r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m");
                 goto fail;
         }
 
+        /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
         r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
         if (r < 0) {
-                r = -errno;
-                goto fail;
+                if (errno != EADDRINUSE) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
+                        goto fail;
+                }
+
+                log_warning("LLMNR-IPv6(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
+
+                /* try again with SO_REUSEADDR */
+                r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
+
+                r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m");
+                        goto fail;
+                }
+        } else {
+                /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
+                r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m");
+                        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);
@@ -338,49 +376,68 @@ int manager_llmnr_ipv4_tcp_fd(Manager *m) {
 
         m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (m->llmnr_ipv4_tcp_fd < 0)
-                return -errno;
+                return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m");
 
         /* 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;
+                r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m");
                 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;
+                r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set IP_MTU_DISCOVER: %m");
                 goto fail;
         }
 
+        /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
         r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
         if (r < 0) {
-                r = -errno;
-                goto fail;
+                if (errno != EADDRINUSE) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
+                        goto fail;
+                }
+
+                log_warning("LLMNR-IPv4(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
+
+                /* try again with SO_REUSEADDR */
+                r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
+
+                r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m");
+                        goto fail;
+                }
+        } else {
+                /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
+                r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
         }
 
         r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to listen the stream: %m");
                 goto fail;
         }
 
@@ -412,48 +469,67 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) {
 
         m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (m->llmnr_ipv6_tcp_fd < 0)
-                return -errno;
+                return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m");
 
         /* 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;
+                r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m");
                 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;
+                r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m");
                 goto fail;
         }
 
         r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m");
                 goto fail;
         }
 
+        /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */
         r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
         if (r < 0) {
-                r = -errno;
-                goto fail;
+                if (errno != EADDRINUSE) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
+                        goto fail;
+                }
+
+                log_warning("LLMNR-IPv6(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers.");
+
+                /* try again with SO_REUSEADDR */
+                r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
+
+                r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m");
+                        goto fail;
+                }
+        } else {
+                /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */
+                r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
         }
 
         r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to listen the stream: %m");
                 goto fail;
         }
 
index c4e4409fe38e5e43a76369ad626fc9ef36e7d7f1..b6620875eae334001b392be1bcfa42049d54e782 100644 (file)
 #include <poll.h>
 #include <sys/ioctl.h>
 
+#ifdef HAVE_LIBIDN2
+#include <idn2.h>
+#endif
+
 #include "af-list.h"
 #include "alloc-util.h"
 #include "dirent-util.h"
@@ -324,9 +328,14 @@ static int manager_network_monitor_listen(Manager *m) {
 
 static int determine_hostname(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) {
         _cleanup_free_ char *h = NULL, *n = NULL;
+#if defined(HAVE_LIBIDN2)
+        _cleanup_free_ char *utf8 = NULL;
+#elif defined(HAVE_LIBIDN)
+        int k;
+#endif
         char label[DNS_LABEL_MAX];
-        const char *p;
-        int r, k;
+        const char *p, *decoded;
+        int r;
 
         assert(full_hostname);
         assert(llmnr_hostname);
@@ -339,7 +348,7 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
                 return log_debug_errno(r, "Can't determine system hostname: %m");
 
         p = h;
-        r = dns_label_unescape(&p, label, sizeof(label));
+        r = dns_label_unescape(&p, label, sizeof label);
         if (r < 0)
                 return log_error_errno(r, "Failed to unescape host name: %m");
         if (r == 0) {
@@ -347,7 +356,16 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
                 return -EINVAL;
         }
 
-        k = dns_label_undo_idna(label, r, label, sizeof(label));
+#if defined(HAVE_LIBIDN2)
+        r = idn2_to_unicode_8z8z(label, &utf8, 0);
+        if (r != IDN2_OK)
+                return log_error("Failed to undo IDNA: %s", idn2_strerror(r));
+        assert(utf8_is_valid(utf8));
+
+        r = strlen(utf8);
+        decoded = utf8;
+#elif defined(HAVE_LIBIDN)
+        k = dns_label_undo_idna(label, r, label, sizeof label);
         if (k < 0)
                 return log_error_errno(k, "Failed to undo IDNA: %m");
         if (k > 0)
@@ -357,8 +375,12 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
                 log_error("System hostname is not UTF-8 clean.");
                 return -EINVAL;
         }
+        decoded = label;
+#else
+        decoded = label; /* no decoding */
+#endif
 
-        r = dns_label_escape_new(label, r, &n);
+        r = dns_label_escape_new(decoded, r, &n);
         if (r < 0)
                 return log_error_errno(r, "Failed to escape host name: %m");
 
@@ -561,7 +583,7 @@ int manager_new(Manager **ret) {
 
         r = manager_parse_config_file(m);
         if (r < 0)
-                return r;
+                log_warning_errno(r, "Failed to parse configuration file: %m");
 
         r = sd_event_default(&m->event);
         if (r < 0)
@@ -612,14 +634,6 @@ int manager_start(Manager *m) {
         if (r < 0)
                 return r;
 
-        r = manager_llmnr_start(m);
-        if (r < 0)
-                return r;
-
-        r = manager_mdns_start(m);
-        if (r < 0)
-                return r;
-
         return 0;
 }
 
index c40e8f75f0e30bcc2c9327509e8aec9bf8b5c22d..415dc1a5328f900fd66d01665da8488fc45fabe6 100644 (file)
@@ -60,7 +60,7 @@ int manager_mdns_start(Manager *m) {
         return 0;
 
 eaddrinuse:
-        log_warning("There appears to be another mDNS responder running. Turning off mDNS support.");
+        log_warning("Another mDNS responder prohibits binding the socket to the same port. Turning off mDNS support.");
         m->mdns_support = RESOLVE_SUPPORT_NO;
         manager_mdns_stop(m);
 
@@ -217,55 +217,75 @@ int manager_mdns_ipv4_fd(Manager *m) {
 
         m->mdns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (m->mdns_ipv4_fd < 0)
-                return -errno;
+                return log_error_errno(errno, "mDNS-IPv4: Failed to create socket: %m");
 
         r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_TTL: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MULTICAST_TTL: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
-                goto fail;
-        }
-
-        r = setsockopt(m->mdns_ipv4_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-        if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MULTICAST_LOOP: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_PKTINFO: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_RECVTTL: %m");
                 goto fail;
         }
 
         /* Disable Don't-Fragment bit in the IP header */
         r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MTU_DISCOVER: %m");
                 goto fail;
         }
 
+        /* See the section 15.1 of RFC6762 */
+        /* first try to bind without SO_REUSEADDR to detect another mDNS responder */
         r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in));
         if (r < 0) {
-                r = -errno;
-                goto fail;
+                if (errno != EADDRINUSE) {
+                        r = log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m");
+                        goto fail;
+                }
+
+                log_warning("mDNS-IPv4: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers.");
+
+                /* try again with SO_REUSEADDR */
+                r = setsockopt(m->mdns_ipv4_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
+
+                r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in));
+                if (r < 0) {
+                        r = log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m");
+                        goto fail;
+                }
+        } else {
+                /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */
+                r = setsockopt(m->mdns_ipv4_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
         }
 
         r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, m->mdns_ipv4_fd, EPOLLIN, on_mdns_packet, m);
@@ -294,55 +314,75 @@ int manager_mdns_ipv6_fd(Manager *m) {
 
         m->mdns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (m->mdns_ipv6_fd < 0)
-                return -errno;
+                return log_error_errno(errno, "mDNS-IPv6: Failed to create socket: %m");
 
         r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_UNICAST_HOPS: %m");
                 goto fail;
         }
 
         /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
         r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_MULTICAST_HOPS: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_MULTICAST_LOOP: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
-                goto fail;
-        }
-
-        r = setsockopt(m->mdns_ipv6_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-        if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_V6ONLY: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_RECVPKTINFO: %m");
                 goto fail;
         }
 
         r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
         if (r < 0) {
-                r = -errno;
+                r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_RECVHOPLIMIT: %m");
                 goto fail;
         }
 
+        /* See the section 15.1 of RFC6762 */
+        /* first try to bind without SO_REUSEADDR to detect another mDNS responder */
         r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6));
         if (r < 0) {
-                r = -errno;
-                goto fail;
+                if (errno != EADDRINUSE) {
+                        r = log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m");
+                        goto fail;
+                }
+
+                log_warning("mDNS-IPv6: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers.");
+
+                /* try again with SO_REUSEADDR */
+                r = setsockopt(m->mdns_ipv6_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
+
+                r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6));
+                if (r < 0) {
+                        r = log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m");
+                        goto fail;
+                }
+        } else {
+                /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */
+                r = setsockopt(m->mdns_ipv6_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+                if (r < 0) {
+                        r = log_error_errno(errno, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m");
+                        goto fail;
+                }
         }
 
         r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLIN, on_mdns_packet, m);
index 60afa151e3121c180d3c944364da783f29c6001b..e6b20620e2c631125aab95bbffd45d71000f407b 100644 (file)
@@ -16,6 +16,7 @@
 #FallbackDNS=@DNS_SERVERS@
 #Domains=
 #LLMNR=yes
+#MulticastDNS=yes
 #DNSSEC=@DEFAULT_DNSSEC_MODE@
 #Cache=yes
 #DNSStubListener=udp
index 3d7074af11fc841aebbb722e7433a9105a6778c6..090b2fac23bb4dad6551c5a3622b9a597f880821 100644 (file)
@@ -218,7 +218,7 @@ int main(int argc, char* argv[]) {
         test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
         test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
 
-#ifdef HAVE_LIBIDN
+#if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN)
         /* Unsigned A with IDNA conversion necessary */
         test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
         test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);
diff --git a/src/resolve/test-resolved-packet.c b/src/resolve/test-resolved-packet.c
new file mode 100644 (file)
index 0000000..1b00412
--- /dev/null
@@ -0,0 +1,48 @@
+/***
+  This file is part of systemd
+
+  Copyright 2017 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 "log.h"
+#include "resolved-dns-packet.h"
+
+static void test_dns_packet_new(void) {
+        size_t i;
+         _cleanup_(dns_packet_unrefp) DnsPacket *p2 = NULL;
+
+        for (i = 0; i <= DNS_PACKET_SIZE_MAX; i++) {
+                _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+
+                assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, i) == 0);
+
+                log_debug("dns_packet_new: %zu → %zu", i, p->allocated);
+                assert_se(p->allocated >= MIN(DNS_PACKET_SIZE_MAX, i));
+        }
+
+        assert_se(dns_packet_new(&p2, DNS_PROTOCOL_DNS, DNS_PACKET_SIZE_MAX + 1) == -EFBIG);
+}
+
+int main(int argc, char **argv) {
+
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
+        test_dns_packet_new();
+
+        return 0;
+}
index 127cbe44e38744bfd85e9f648724a9bb3de7d3de..903a1878611a3064bd7f5f7b2d276031f6d56fe6 100644 (file)
@@ -51,6 +51,9 @@ static const BaseFilesystem table[] = {
         { "usr",   0755, NULL,                         NULL },
         { "var",   0755, NULL,                         NULL },
         { "etc",   0755, NULL,                         NULL },
+        { "proc",  0755, NULL,                         NULL, true },
+        { "sys",   0755, NULL,                         NULL, true },
+        { "dev",   0755, NULL,                         NULL, true },
 #if defined(__i386__) || defined(__x86_64__)
         { "lib64",    0, "usr/lib/x86_64-linux-gnu\0"
                          "usr/lib64\0",                "ld-linux-x86-64.so.2" },
@@ -117,6 +120,8 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
 
                         if (!table[i].ignore_failure)
                                 return -errno;
+
+                        continue;
                 }
 
                 if (uid != UID_INVALID || gid != UID_INVALID) {
index aae69f6da5f4079e38dab09f0b9e8466fccbb4a9..5cbe663fa87be28d9bf26bbde8a20a17703e1db9 100644 (file)
@@ -266,7 +266,8 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                               "StandardInput", "StandardOutput", "StandardError",
                               "Description", "Slice", "Type", "WorkingDirectory",
                               "RootDirectory", "SyslogIdentifier", "ProtectSystem",
-                              "ProtectHome", "SELinuxContext", "Restart", "RootImage"))
+                              "ProtectHome", "SELinuxContext", "Restart", "RootImage",
+                              "NotifyAccess"))
                 r = sd_bus_message_append(m, "v", "s", eq);
 
         else if (streq(field, "SyslogLevel")) {
@@ -389,6 +390,33 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
 
                 r = sd_bus_message_append(m, "v", "i", (int32_t) n);
 
+        } else if (streq(field, "FileDescriptorStoreMax")) {
+                unsigned u;
+
+                r = safe_atou(eq, &u);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse file descriptor store limit: %s", eq);
+
+                r = sd_bus_message_append(m, "v", "u", (uint32_t) u);
+
+        } else if (streq(field, "IOSchedulingClass")) {
+                int c;
+
+                c = ioprio_class_from_string(eq);
+                if (c < 0)
+                        return log_error_errno(r, "Failed to parse IO scheduling class: %s", eq);
+
+                r = sd_bus_message_append(m, "v", "i", (int32_t) c);
+
+        } else if (streq(field, "IOSchedulingPriority")) {
+                int q;
+
+                r = ioprio_parse_priority(eq, &q);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse IO scheduling priority: %s", eq);
+
+                r = sd_bus_message_append(m, "v", "i", (int32_t) q);
+
         } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
                 const char *p;
 
@@ -860,7 +888,7 @@ static void log_job_error_with_service_result(const char* service, const char *r
 
         assert(service);
 
-        service_shell_quoted = shell_maybe_quote(service);
+        service_shell_quoted = shell_maybe_quote(service, ESCAPE_BACKSLASH);
 
         if (extra_args) {
                 _cleanup_free_ char *t;
index 8ddfb584ea5c39ca152688446fd992c0e37d9cb2..207b5e66fccca00a7104bd385eaa3aef1b9cb8f0 100644 (file)
@@ -725,13 +725,12 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
                         return r;
 
                 if (all || !isempty(s)) {
-                        _cleanup_free_ char *escaped = NULL;
+                        bool good;
 
-                        escaped = xescape(s, "\n");
-                        if (!escaped)
-                                return -ENOMEM;
-
-                        print_property(name, "%s", escaped);
+                        /* This property has a single value, so we need to take
+                         * care not to print a new line, everything else is OK. */
+                        good = !strchr(s, '\n');
+                        print_property(name, "%s", good ? s : "[unprintable]");
                 }
 
                 return 1;
@@ -852,16 +851,16 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
                                 return r;
 
                         while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
-                                _cleanup_free_ char *escaped = NULL;
+                                bool good;
 
                                 if (first && !value)
                                         printf("%s=", name);
 
-                                escaped = xescape(str, "\n ");
-                                if (!escaped)
-                                        return -ENOMEM;
+                                /* This property has multiple space-seperated values, so
+                                 * neither spaces not newlines can be allowed in a value. */
+                                good = str[strcspn(str, " \n")] == '\0';
 
-                                printf("%s%s", first ? "" : " ", escaped);
+                                printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
 
                                 first = false;
                         }
index 8765cf2f49d4997e06b4ab044c1c355eefbe7580..436130edea665e4f1159b782ecc7558387fd1e59 100644 (file)
@@ -24,8 +24,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <systemd/sd-bus.h>
-
 #include "alloc-util.h"
 #include "bus-error.h"
 #include "bus-util.h"
index 736f0f34c88ff528a730c7566a07110e2b6b7b42..1764f76744578f25c75572208d4feace1a08eca6 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
-#include <systemd/sd-bus.h>
+#include "sd-bus.h"
 
 #include "logs-show.h"
 #include "output-mode.h"
index 0b77d2c22dc3ce8f16d0f4fa63f52880e5fdc88d..1af74c61f00bd76c197f06570ab2e259e3ffeeef 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -52,6 +53,7 @@
 #include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "user-util.h"
 #include "util.h"
 #include "virt.h"
 
@@ -138,6 +140,60 @@ static int condition_test_kernel_command_line(Condition *c) {
         return false;
 }
 
+static int condition_test_user(Condition *c) {
+        uid_t id;
+        int r;
+        _cleanup_free_ char *username = NULL;
+        const char *u;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_USER);
+
+        r = parse_uid(c->parameter, &id);
+        if (r >= 0)
+                return id == getuid() || id == geteuid();
+
+        if (streq("@system", c->parameter))
+                return getuid() <= SYSTEM_UID_MAX || geteuid() <= SYSTEM_UID_MAX;
+
+        username = getusername_malloc();
+        if (!username)
+                return -ENOMEM;
+
+        if (streq(username, c->parameter))
+                return 1;
+
+        if (getpid() == 1)
+                return streq(c->parameter, "root");
+
+        u = c->parameter;
+        r = get_user_creds(&u, &id, NULL, NULL, NULL);
+        if (r < 0)
+                return 0;
+
+        return id == getuid() || id == geteuid();
+}
+
+static int condition_test_group(Condition *c) {
+        gid_t id;
+        int r;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_GROUP);
+
+        r = parse_gid(c->parameter, &id);
+        if (r >= 0)
+                return in_gid(id);
+
+        /* Avoid any NSS lookups if we are PID1 */
+        if (getpid() == 1)
+                return streq(c->parameter, "root");
+
+        return in_group(c->parameter) > 0;
+}
+
 static int condition_test_virtualization(Condition *c) {
         int b, v;
 
@@ -235,7 +291,7 @@ static int condition_test_security(Condition *c) {
         assert(c->type == CONDITION_SECURITY);
 
         if (streq(c->parameter, "selinux"))
-                return mac_selinux_have();
+                return mac_selinux_use();
         if (streq(c->parameter, "smack"))
                 return mac_smack_use();
         if (streq(c->parameter, "apparmor"))
@@ -475,6 +531,8 @@ int condition_test(Condition *c) {
                 [CONDITION_ARCHITECTURE] = condition_test_architecture,
                 [CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
                 [CONDITION_FIRST_BOOT] = condition_test_first_boot,
+                [CONDITION_USER] = condition_test_user,
+                [CONDITION_GROUP] = condition_test_group,
                 [CONDITION_NULL] = condition_test_null,
         };
 
@@ -538,6 +596,8 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
         [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
         [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
+        [CONDITION_USER] = "ConditionUser",
+        [CONDITION_GROUP] = "ConditionGroup",
         [CONDITION_NULL] = "ConditionNull"
 };
 
@@ -562,6 +622,8 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
         [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
         [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
+        [CONDITION_USER] = "AssertUser",
+        [CONDITION_GROUP] = "AssertGroup",
         [CONDITION_NULL] = "AssertNull"
 };
 
index bdda04b7702b0a593cf606a9a401a28bd35165e8..d0b592bc433d43e4d04df89f89d36e173759da8c 100644 (file)
@@ -49,6 +49,9 @@ typedef enum ConditionType {
 
         CONDITION_NULL,
 
+        CONDITION_USER,
+        CONDITION_GROUP,
+
         _CONDITION_TYPE_MAX,
         _CONDITION_TYPE_INVALID = -1
 } ConditionType;
index 265ac83dc0b88170f86762ff931ff88eb547390b..e08402e3d22ea54e785c8d4bac71f490d9e8a797 100644 (file)
@@ -506,6 +506,7 @@ int config_parse_many(
 
 DEFINE_PARSER(int, int, safe_atoi);
 DEFINE_PARSER(long, long, safe_atoli);
+DEFINE_PARSER(uint8, uint8_t, safe_atou8);
 DEFINE_PARSER(uint16, uint16_t, safe_atou16);
 DEFINE_PARSER(uint32, uint32_t, safe_atou32);
 DEFINE_PARSER(uint64, uint64_t, safe_atou64);
@@ -614,6 +615,7 @@ int config_parse_bool(const char* unit,
 
         int k;
         bool *b = data;
+        bool fatal = ltype;
 
         assert(filename);
         assert(lvalue);
@@ -622,8 +624,10 @@ int config_parse_bool(const char* unit,
 
         k = parse_boolean(rvalue);
         if (k < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, k,
+                           "Failed to parse boolean value%s: %s",
+                           fatal ? "" : ", ignoring", rvalue);
+                return fatal ? -ENOEXEC : 0;
         }
 
         *b = !!k;
@@ -714,6 +718,7 @@ int config_parse_path(
                 void *userdata) {
 
         char **s = data, *n;
+        bool fatal = ltype;
 
         assert(filename);
         assert(lvalue);
@@ -722,12 +727,14 @@ int config_parse_path(
 
         if (!utf8_is_valid(rvalue)) {
                 log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
-                return 0;
+                return fatal ? -ENOEXEC : 0;
         }
 
         if (!path_is_absolute(rvalue)) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue);
-                return 0;
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "Not an absolute path%s: %s",
+                           fatal ? "" : ", ignoring", rvalue);
+                return fatal ? -ENOEXEC : 0;
         }
 
         n = strdup(rvalue);
@@ -792,7 +799,7 @@ int config_parse_strv(const char *unit,
                 }
 
                 if (!utf8_is_valid(word)) {
-                        log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
+                        log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word);
                         free(word);
                         continue;
                 }
@@ -959,3 +966,40 @@ int config_parse_ifname(
 
         return 0;
 }
+
+int config_parse_ip_port(
+                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) {
+
+        uint16_t *s = data;
+        uint16_t port;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                *s = 0;
+                return 0;
+        }
+
+        r = parse_ip_port(rvalue, &port);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse port '%s'.", rvalue);
+                return 0;
+        }
+
+        *s = port;
+
+        return 0;
+}
index 26ff3df16f26cc0f43495809d9e9d1bc69f8fd1c..ce1113485d5915797bacdcad8f25e1e5da4d2cd2 100644 (file)
@@ -119,6 +119,7 @@ int config_parse_many(
 int config_parse_int(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_unsigned(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_long(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_uint8(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_uint16(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_uint32(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_uint64(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);
@@ -139,6 +140,7 @@ int config_parse_log_level(const char *unit, const char *filename, unsigned line
 int config_parse_signal(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_personality(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_ifname(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_ip_port(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);
 
 #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg)                \
         int function(const char *unit,                                  \
index 39e724c51a7b9ea563b37cef44b28188e3ab03d7..505a83f54f8f829b5a9599b89ba924f11263a7ed 100644 (file)
@@ -20,7 +20,6 @@
 #ifdef HAVE_LIBCRYPTSETUP
 #include <libcryptsetup.h>
 #endif
-#include <linux/dm-ioctl.h>
 #include <sys/mount.h>
 
 #include "architecture.h"
@@ -32,6 +31,7 @@
 #include "fs-util.h"
 #include "gpt.h"
 #include "hexdecoct.h"
+#include "linux-3.13/dm-ioctl.h"
 #include "mount-util.h"
 #include "path-util.h"
 #include "stat-util.h"
@@ -42,7 +42,7 @@
 #include "udev-util.h"
 #include "xattr-util.h"
 
-static int probe_filesystem(const char *node, char **ret_fstype) {
+_unused_ static int probe_filesystem(const char *node, char **ret_fstype) {
 #ifdef HAVE_BLKID
         _cleanup_blkid_free_probe_ blkid_probe b = NULL;
         const char *fstype;
@@ -301,7 +301,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
                 _cleanup_udev_device_unref_ struct udev_device *q;
                 unsigned long long pflags;
                 blkid_partition pp;
-                const char *node;
+                const char *node, *sysname;
                 dev_t qn;
                 int nr;
 
@@ -316,6 +316,12 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
                 if (st.st_rdev == qn)
                         continue;
 
+                /* Filter out weird MMC RPMB partitions, which cannot reasonably be read, see
+                 * https://github.com/systemd/systemd/issues/5806 */
+                sysname = udev_device_get_sysname(q);
+                if (sysname && startswith(sysname, "mmcblk") && endswith(sysname, "rpmb"))
+                        continue;
+
                 node = udev_device_get_devnode(q);
                 if (!node)
                         continue;
@@ -951,7 +957,7 @@ int dissected_image_decrypt(
          *
          *      = 0           → There was nothing to decrypt
          *      > 0           → Decrypted successfully
-         *      -ENOKEY       → There's some to decrypt but no key was supplied
+         *      -ENOKEY       → There's something to decrypt but no key was supplied
          *      -EKEYREJECTED → Passed key was not correct
          */
 
index 33debadb153ae9f867b60eb8f70c9b4faf2dee2a..12c4d65dd3f66f82311ee4d977d272b43a860ed6 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
 
-#ifdef HAVE_LIBIDN
-#include <idna.h>
-#include <stringprep.h>
+#if defined(HAVE_LIBIDN2)
+#  include <idn2.h>
+#elif defined(HAVE_LIBIDN)
+#  include <idna.h>
+#  include <stringprep.h>
 #endif
 
 #include <endian.h>
@@ -299,8 +301,8 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) {
         return r;
 }
 
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
 #ifdef HAVE_LIBIDN
+int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
         _cleanup_free_ uint32_t *input = NULL;
         size_t input_size, l;
         const char *p;
@@ -348,13 +350,9 @@ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded
                 decoded[l] = 0;
 
         return (int) l;
-#else
-        return 0;
-#endif
 }
 
 int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
-#ifdef HAVE_LIBIDN
         size_t input_size, output_size;
         _cleanup_free_ uint32_t *input = NULL;
         _cleanup_free_ char *result = NULL;
@@ -399,10 +397,8 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
                 decoded[w] = 0;
 
         return w;
-#else
-        return 0;
-#endif
 }
+#endif
 
 int dns_name_concat(const char *a, const char *b, char **_ret) {
         _cleanup_free_ char *ret = NULL;
@@ -1274,6 +1270,26 @@ int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
 }
 
 int dns_name_apply_idna(const char *name, char **ret) {
+        /* Return negative on error, 0 if not implemented, positive on success. */
+
+#if defined(HAVE_LIBIDN2)
+        int r;
+
+        assert(name);
+        assert(ret);
+
+        r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) ret,
+                           IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
+        if (r == IDN2_OK)
+                return 1; /* *ret has been written */
+        log_debug("idn2_lookup_u8(\"%s\") failed: %s", name, idn2_strerror(r));
+        if (r == IDN2_2HYPHEN)
+                /* The name has two hypens — forbidden by IDNA2008 in some cases */
+                return 0;
+        if (IN_SET(r, IDN2_TOO_BIG_DOMAIN, IDN2_TOO_BIG_LABEL))
+                return -ENOSPC;
+        return -EINVAL;
+#elif defined(HAVE_LIBIDN)
         _cleanup_free_ char *buf = NULL;
         size_t n = 0, allocated = 0;
         bool first = true;
@@ -1309,7 +1325,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
                 else
                         buf[n++] = '.';
 
-                n +=r;
+                n += r;
         }
 
         if (n > DNS_HOSTNAME_MAX)
@@ -1322,7 +1338,10 @@ int dns_name_apply_idna(const char *name, char **ret) {
         *ret = buf;
         buf = NULL;
 
-        return (int) n;
+        return 1;
+#else
+        return 0;
+#endif
 }
 
 int dns_name_is_valid_or_address(const char *name) {
index 03f160369cbb692064bf20bc966756fe6e8c83fb..fca025def01a785c4dae8c7cd7641c7ad2d894aa 100644 (file)
@@ -51,8 +51,10 @@ static inline int dns_name_parent(const char **name) {
         return dns_label_unescape(name, NULL, DNS_LABEL_MAX);
 }
 
+#if defined(HAVE_LIBIDN)
 int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
 int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
+#endif
 
 int dns_name_concat(const char *a, const char *b, char **ret);
 
index 8631a5a5d9fa4a0eff51a6ac81d25a6b84b93f8f..8229e6b1834402b4cbfe6026eb30cda4640935c1 100644 (file)
@@ -269,6 +269,7 @@ int efi_set_variable(
         _cleanup_close_ int fd = -1;
 
         assert(name);
+        assert(value);
 
         if (asprintf(&p,
                      "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
index c3106f1ae913d5cbc780a5c82a7bc3e13ce2b250..ec2e868ca8ebae2cde906252a5e9ba42e1c6283b 100644 (file)
 #include "strv.h"
 #include "util.h"
 
-bool fstab_is_mount_point(const char *mount) {
+int fstab_has_fstype(const char *fstype) {
         _cleanup_endmntent_ FILE *f = NULL;
         struct mntent *m;
 
         f = setmntent("/etc/fstab", "re");
         if (!f)
-                return false;
+                return errno == ENOENT ? false : -errno;
 
-        while ((m = getmntent(f)))
-                if (path_equal(m->mnt_dir, mount))
+        for (;;) {
+                errno = 0;
+                m = getmntent(f);
+                if (!m)
+                        return errno != 0 ? -errno : false;
+
+                if (streq(m->mnt_type, fstype))
                         return true;
+        }
+        return false;
+}
+
+int fstab_is_mount_point(const char *mount) {
+        _cleanup_endmntent_ FILE *f = NULL;
+        struct mntent *m;
 
+        f = setmntent("/etc/fstab", "re");
+        if (!f)
+                return errno == ENOENT ? false : -errno;
+
+        for (;;) {
+                errno = 0;
+                m = getmntent(f);
+                if (!m)
+                        return errno != 0 ? -errno : false;
+
+                if (path_equal(m->mnt_dir, mount))
+                        return true;
+        }
         return false;
 }
 
index 679f6902f79c3d41a75466d52125682e3414433d..bbf04413513baacc7c27d61a4abf0c89170fbe58 100644 (file)
@@ -24,7 +24,8 @@
 
 #include "macro.h"
 
-bool fstab_is_mount_point(const char *mount);
+int fstab_is_mount_point(const char *mount);
+int fstab_has_fstype(const char *fstype);
 
 int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered);
 
index 9a069b2f97e1c00ba16964423b831331ea5cbb7d..6a78ebbda793178a206b88533e72c0e3373d1710 100644 (file)
@@ -167,12 +167,13 @@ int generator_write_timeouts(
         usec_t u;
         int r;
 
-        r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0",
+        r = fstab_filter_options(opts, "comment=systemd.device-timeout\0"
+                                       "x-systemd.device-timeout\0",
                                  NULL, &timeout, filtered);
         if (r <= 0)
                 return r;
 
-        r = parse_sec(timeout, &u);
+        r = parse_sec_fix_0(timeout, &u);
         if (r < 0) {
                 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
                 return 0;
@@ -188,10 +189,49 @@ int generator_write_timeouts(
 
         return write_drop_in_format(dir, unit, 50, "device-timeout",
                                     "# Automatically generated by %s\n\n"
-                                    "[Unit]\nJobTimeoutSec=%s",
+                                    "[Unit]\nJobRunningTimeoutSec=%s",
                                     program_invocation_short_name, timeout);
 }
 
+int generator_write_device_deps(
+                const char *dir,
+                const char *what,
+                const char *where,
+                const char *opts) {
+
+        /* fstab records that specify _netdev option should apply the network
+         * ordering on the actual device depending on network connection. If we
+         * are not mounting real device (NFS, CIFS), we rely on _netdev effect
+         * on the mount unit itself. */
+
+        _cleanup_free_ char *node = NULL, *unit = NULL;
+        int r;
+
+        if (!fstab_test_option(opts, "_netdev\0"))
+                return 0;
+
+        node = fstab_node_to_udev_node(what);
+        if (!node)
+                return log_oom();
+
+        /* Nothing to apply dependencies to. */
+        if (!is_device_path(node))
+                return 0;
+
+        r = unit_name_from_path(node, ".device", &unit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to make unit name from path: %m");
+
+        /* See mount_add_default_dependencies for explanation why we create such
+         * dependencies. */
+        return write_drop_in_format(dir, unit, 50, "netdev-dependencies",
+                                    "# Automatically generated by %s\n\n"
+                                    "[Unit]\n"
+                                    "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n"
+                                    "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n",
+                                    program_invocation_short_name);
+}
+
 int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
         _cleanup_free_ char *unit = NULL;
         int r;
index a6017c1b76a1970d78903a79d4ce5190eb9d8786..825d934c8e9977651b977b464407cfb312fa96d2 100644 (file)
@@ -35,6 +35,12 @@ int generator_write_timeouts(
         const char *opts,
         char **filtered);
 
+int generator_write_device_deps(
+                const char *dir,
+                const char *what,
+                const char *where,
+                const char *opts);
+
 int generator_write_initrd_root_device_deps(
         const char *dir,
         const char *what);
index 58c8e852b2cce5b36f15f765a79879dce2a6cb3c..d0a291b819b6714bc97c1a0217749a9d9184c69c 100644 (file)
@@ -422,7 +422,7 @@ static bool chroot_symlinks_same(const char *root, const char *wd, const char *a
 
         a = strjoina(path_is_absolute(a) ? root : wd, "/", a);
         b = strjoina(path_is_absolute(b) ? root : wd, "/", b);
-        return path_equal_or_files_same(a, b);
+        return path_equal_or_files_same(a, b, 0);
 }
 
 static int create_symlink(
@@ -3045,7 +3045,7 @@ int unit_file_get_list(
                         if (errno == ENOENT)
                                 continue;
                         if (IN_SET(errno, ENOTDIR, EACCES)) {
-                                log_debug("Failed to open \"%s\": %m", *i);
+                                log_debug_errno(errno, "Failed to open \"%s\": %m", *i);
                                 continue;
                         }
 
diff --git a/src/shared/linux-3.13/dm-ioctl.h b/src/shared/linux-3.13/dm-ioctl.h
new file mode 100644 (file)
index 0000000..c8a4302
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
+ * Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef _LINUX_DM_IOCTL_V4_H
+#define _LINUX_DM_IOCTL_V4_H
+
+#include <linux/types.h>
+
+#define DM_DIR "mapper"                /* Slashes not supported */
+#define DM_CONTROL_NODE "control"
+#define DM_MAX_TYPE_NAME 16
+#define DM_NAME_LEN 128
+#define DM_UUID_LEN 129
+
+/*
+ * A traditional ioctl interface for the device mapper.
+ *
+ * Each device can have two tables associated with it, an
+ * 'active' table which is the one currently used by io passing
+ * through the device, and an 'inactive' one which is a table
+ * that is being prepared as a replacement for the 'active' one.
+ *
+ * DM_VERSION:
+ * Just get the version information for the ioctl interface.
+ *
+ * DM_REMOVE_ALL:
+ * Remove all dm devices, destroy all tables.  Only really used
+ * for debug.
+ *
+ * DM_LIST_DEVICES:
+ * Get a list of all the dm device names.
+ *
+ * DM_DEV_CREATE:
+ * Create a new device, neither the 'active' or 'inactive' table
+ * slots will be filled.  The device will be in suspended state
+ * after creation, however any io to the device will get errored
+ * since it will be out-of-bounds.
+ *
+ * DM_DEV_REMOVE:
+ * Remove a device, destroy any tables.
+ *
+ * DM_DEV_RENAME:
+ * Rename a device or set its uuid if none was previously supplied.
+ *
+ * DM_SUSPEND:
+ * This performs both suspend and resume, depending which flag is
+ * passed in.
+ * Suspend: This command will not return until all pending io to
+ * the device has completed.  Further io will be deferred until
+ * the device is resumed.
+ * Resume: It is no longer an error to issue this command on an
+ * unsuspended device.  If a table is present in the 'inactive'
+ * slot, it will be moved to the active slot, then the old table
+ * from the active slot will be _destroyed_.  Finally the device
+ * is resumed.
+ *
+ * DM_DEV_STATUS:
+ * Retrieves the status for the table in the 'active' slot.
+ *
+ * DM_DEV_WAIT:
+ * Wait for a significant event to occur to the device.  This
+ * could either be caused by an event triggered by one of the
+ * targets of the table in the 'active' slot, or a table change.
+ *
+ * DM_TABLE_LOAD:
+ * Load a table into the 'inactive' slot for the device.  The
+ * device does _not_ need to be suspended prior to this command.
+ *
+ * DM_TABLE_CLEAR:
+ * Destroy any table in the 'inactive' slot (ie. abort).
+ *
+ * DM_TABLE_DEPS:
+ * Return a set of device dependencies for the 'active' table.
+ *
+ * DM_TABLE_STATUS:
+ * Return the targets status for the 'active' table.
+ *
+ * DM_TARGET_MSG:
+ * Pass a message string to the target at a specific offset of a device.
+ *
+ * DM_DEV_SET_GEOMETRY:
+ * Set the geometry of a device by passing in a string in this format:
+ *
+ * "cylinders heads sectors_per_track start_sector"
+ *
+ * Beware that CHS geometry is nearly obsolete and only provided
+ * for compatibility with dm devices that can be booted by a PC
+ * BIOS.  See struct hd_geometry for range limits.  Also note that
+ * the geometry is erased if the device size changes.
+ */
+
+/*
+ * All ioctl arguments consist of a single chunk of memory, with
+ * this structure at the start.  If a uuid is specified any
+ * lookup (eg. for a DM_INFO) will be done on that, *not* the
+ * name.
+ */
+struct dm_ioctl {
+       /*
+        * The version number is made up of three parts:
+        * major - no backward or forward compatibility,
+        * minor - only backwards compatible,
+        * patch - both backwards and forwards compatible.
+        *
+        * All clients of the ioctl interface should fill in the
+        * version number of the interface that they were
+        * compiled with.
+        *
+        * All recognised ioctl commands (ie. those that don't
+        * return -ENOTTY) fill out this field, even if the
+        * command failed.
+        */
+       __u32 version[3];       /* in/out */
+       __u32 data_size;        /* total size of data passed in
+                                * including this struct */
+
+       __u32 data_start;       /* offset to start of data
+                                * relative to start of this struct */
+
+       __u32 target_count;     /* in/out */
+       __s32 open_count;       /* out */
+       __u32 flags;            /* in/out */
+
+       /*
+        * event_nr holds either the event number (input and output) or the
+        * udev cookie value (input only).
+        * The DM_DEV_WAIT ioctl takes an event number as input.
+        * The DM_SUSPEND, DM_DEV_REMOVE and DM_DEV_RENAME ioctls
+        * use the field as a cookie to return in the DM_COOKIE
+        * variable with the uevents they issue.
+        * For output, the ioctls return the event number, not the cookie.
+        */
+       __u32 event_nr;         /* in/out */
+       __u32 padding;
+
+       __u64 dev;              /* in/out */
+
+       char name[DM_NAME_LEN]; /* device name */
+       char uuid[DM_UUID_LEN]; /* unique identifier for
+                                * the block device */
+       char data[7];           /* padding or data */
+};
+
+/*
+ * Used to specify tables.  These structures appear after the
+ * dm_ioctl.
+ */
+struct dm_target_spec {
+       __u64 sector_start;
+       __u64 length;
+       __s32 status;           /* used when reading from kernel only */
+
+       /*
+        * Location of the next dm_target_spec.
+        * - When specifying targets on a DM_TABLE_LOAD command, this value is
+        *   the number of bytes from the start of the "current" dm_target_spec
+        *   to the start of the "next" dm_target_spec.
+        * - When retrieving targets on a DM_TABLE_STATUS command, this value
+        *   is the number of bytes from the start of the first dm_target_spec
+        *   (that follows the dm_ioctl struct) to the start of the "next"
+        *   dm_target_spec.
+        */
+       __u32 next;
+
+       char target_type[DM_MAX_TYPE_NAME];
+
+       /*
+        * Parameter string starts immediately after this object.
+        * Be careful to add padding after string to ensure correct
+        * alignment of subsequent dm_target_spec.
+        */
+};
+
+/*
+ * Used to retrieve the target dependencies.
+ */
+struct dm_target_deps {
+       __u32 count;    /* Array size */
+       __u32 padding;  /* unused */
+       __u64 dev[0];   /* out */
+};
+
+/*
+ * Used to get a list of all dm devices.
+ */
+struct dm_name_list {
+       __u64 dev;
+       __u32 next;             /* offset to the next record from
+                                  the _start_ of this */
+       char name[0];
+};
+
+/*
+ * Used to retrieve the target versions
+ */
+struct dm_target_versions {
+        __u32 next;
+        __u32 version[3];
+
+        char name[0];
+};
+
+/*
+ * Used to pass message to a target
+ */
+struct dm_target_msg {
+       __u64 sector;   /* Device sector */
+
+       char message[0];
+};
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to dm-ioctl.c:lookup_ioctl()
+ */
+enum {
+       /* Top level cmds */
+       DM_VERSION_CMD = 0,
+       DM_REMOVE_ALL_CMD,
+       DM_LIST_DEVICES_CMD,
+
+       /* device level cmds */
+       DM_DEV_CREATE_CMD,
+       DM_DEV_REMOVE_CMD,
+       DM_DEV_RENAME_CMD,
+       DM_DEV_SUSPEND_CMD,
+       DM_DEV_STATUS_CMD,
+       DM_DEV_WAIT_CMD,
+
+       /* Table level cmds */
+       DM_TABLE_LOAD_CMD,
+       DM_TABLE_CLEAR_CMD,
+       DM_TABLE_DEPS_CMD,
+       DM_TABLE_STATUS_CMD,
+
+       /* Added later */
+       DM_LIST_VERSIONS_CMD,
+       DM_TARGET_MSG_CMD,
+       DM_DEV_SET_GEOMETRY_CMD
+};
+
+#define DM_IOCTL 0xfd
+
+#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
+#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
+#define DM_LIST_DEVICES  _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
+
+#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
+#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
+#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
+#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
+#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
+#define DM_DEV_WAIT      _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
+
+#define DM_TABLE_LOAD    _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
+#define DM_TABLE_CLEAR   _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
+#define DM_TABLE_DEPS    _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
+#define DM_TABLE_STATUS  _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
+
+#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
+
+#define DM_TARGET_MSG   _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
+#define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
+
+#define DM_VERSION_MAJOR       4
+#define DM_VERSION_MINOR       27
+#define DM_VERSION_PATCHLEVEL  0
+#define DM_VERSION_EXTRA       "-ioctl (2013-10-30)"
+
+/* Status bits */
+#define DM_READONLY_FLAG       (1 << 0) /* In/Out */
+#define DM_SUSPEND_FLAG                (1 << 1) /* In/Out */
+#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG   (1 << 4) /* In */
+
+/*
+ * Flags that indicate whether a table is present in either of
+ * the two table slots that a device has.
+ */
+#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
+#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
+
+/*
+ * Indicates that the buffer passed in wasn't big enough for the
+ * results.
+ */
+#define DM_BUFFER_FULL_FLAG    (1 << 8) /* Out */
+
+/*
+ * This flag is now ignored.
+ */
+#define DM_SKIP_BDGET_FLAG     (1 << 9) /* In */
+
+/*
+ * Set this to avoid attempting to freeze any filesystem when suspending.
+ */
+#define DM_SKIP_LOCKFS_FLAG    (1 << 10) /* In */
+
+/*
+ * Set this to suspend without flushing queued ios.
+ * Also disables flushing uncommitted changes in the thin target before
+ * generating statistics for DM_TABLE_STATUS and DM_DEV_WAIT.
+ */
+#define DM_NOFLUSH_FLAG                (1 << 11) /* In */
+
+/*
+ * If set, any table information returned will relate to the inactive
+ * table instead of the live one.  Always check DM_INACTIVE_PRESENT_FLAG
+ * is set before using the data returned.
+ */
+#define DM_QUERY_INACTIVE_TABLE_FLAG   (1 << 12) /* In */
+
+/*
+ * If set, a uevent was generated for which the caller may need to wait.
+ */
+#define DM_UEVENT_GENERATED_FLAG       (1 << 13) /* Out */
+
+/*
+ * If set, rename changes the uuid not the name.  Only permitted
+ * if no uuid was previously supplied: an existing uuid cannot be changed.
+ */
+#define DM_UUID_FLAG                   (1 << 14) /* In */
+
+/*
+ * If set, all buffers are wiped after use. Use when sending
+ * or requesting sensitive data such as an encryption key.
+ */
+#define DM_SECURE_DATA_FLAG            (1 << 15) /* In */
+
+/*
+ * If set, a message generated output data.
+ */
+#define DM_DATA_OUT_FLAG               (1 << 16) /* Out */
+
+/*
+ * If set with DM_DEV_REMOVE or DM_REMOVE_ALL this indicates that if
+ * the device cannot be removed immediately because it is still in use
+ * it should instead be scheduled for removal when it gets closed.
+ *
+ * On return from DM_DEV_REMOVE, DM_DEV_STATUS or other ioctls, this
+ * flag indicates that the device is scheduled to be removed when it
+ * gets closed.
+ */
+#define DM_DEFERRED_REMOVE             (1 << 17) /* In/Out */
+
+#endif                         /* _LINUX_DM_IOCTL_H */
index 72c43e80cb197f45e8bcde8e2b23de74f8481210..02ae4265c6b5ef0b67b02e89c2ec875d278db268 100644 (file)
@@ -264,6 +264,8 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou
                 }
 
         } else {
+                char usec[7];
+
                 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
                 t = (time_t) (x / USEC_PER_SEC);
 
@@ -275,9 +277,19 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou
 
                 case OUTPUT_SHORT_ISO:
                         if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)) <= 0) {
-                                log_error("Failed for format ISO time");
+                                log_error("Failed to format ISO time");
+                                return -EINVAL;
+                        }
+                        break;
+
+                case OUTPUT_SHORT_ISO_PRECISE:
+                        /* No usec in strftime, so we leave space and copy over */
+                        if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.xxxxxx%z", gettime_r(&t, &tm)) <= 0) {
+                                log_error("Failed to format ISO-precise time");
                                 return -EINVAL;
                         }
+                        xsprintf(usec, "%06"PRI_USEC, x % USEC_PER_SEC);
+                        memcpy(buf + 20, usec, 6);
                         break;
 
                 case OUTPUT_SHORT:
@@ -473,6 +485,7 @@ static int output_verbose(
         _cleanup_free_ char *cursor = NULL;
         uint64_t realtime = 0;
         char ts[FORMAT_TIMESTAMP_MAX + 7];
+        const char *timestamp;
         int r;
 
         assert(f);
@@ -508,10 +521,10 @@ static int output_verbose(
         if (r < 0)
                 return log_error_errno(r, "Failed to get cursor: %m");
 
+        timestamp = flags & OUTPUT_UTC ? format_timestamp_us_utc(ts, sizeof ts, realtime)
+                                       : format_timestamp_us(ts, sizeof ts, realtime);
         fprintf(f, "%s [%s]\n",
-                flags & OUTPUT_UTC ?
-                format_timestamp_us_utc(ts, sizeof(ts), realtime) :
-                format_timestamp_us(ts, sizeof(ts), realtime),
+                timestamp ?: "(no timestamp)",
                 cursor);
 
         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
@@ -949,6 +962,7 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(
 
         [OUTPUT_SHORT] = output_short,
         [OUTPUT_SHORT_ISO] = output_short,
+        [OUTPUT_SHORT_ISO_PRECISE] = output_short,
         [OUTPUT_SHORT_PRECISE] = output_short,
         [OUTPUT_SHORT_MONOTONIC] = output_short,
         [OUTPUT_SHORT_UNIX] = output_short,
@@ -977,7 +991,6 @@ int output_journal(
                 n_columns = columns();
 
         ret = output_funcs[mode](f, j, mode, n_columns, flags);
-        fflush(stdout);
 
         if (ellipsized && ret > 0)
                 *ellipsized = true;
diff --git a/src/shared/meson.build b/src/shared/meson.build
new file mode 100644 (file)
index 0000000..2eaef11
--- /dev/null
@@ -0,0 +1,158 @@
+shared_sources = '''
+        acl-util.h
+        acpi-fpdt.c
+        acpi-fpdt.h
+        apparmor-util.c
+        apparmor-util.h
+        ask-password-api.c
+        ask-password-api.h
+        base-filesystem.c
+        base-filesystem.h
+        boot-timestamps.c
+        boot-timestamps.h
+        bus-unit-util.c
+        bus-unit-util.h
+        bus-util.c
+        bus-util.h
+        cgroup-show.c
+        cgroup-show.h
+        clean-ipc.c
+        clean-ipc.h
+        condition.c
+        condition.h
+        conf-parser.c
+        conf-parser.h
+        dev-setup.c
+        dev-setup.h
+        dissect-image.c
+        dissect-image.h
+        dns-domain.c
+        dns-domain.h
+        dropin.c
+        dropin.h
+        efivars.c
+        efivars.h
+        fdset.c
+        fdset.h
+        firewall-util.h
+        fstab-util.c
+        fstab-util.h
+        gcrypt-util.c
+        gcrypt-util.h
+        generator.c
+        generator.h
+        gpt.h
+        ima-util.c
+        ima-util.h
+        import-util.c
+        import-util.h
+        initreq.h
+        install.c
+        install.h
+        install-printf.c
+        install-printf.h
+        journal-util.c
+        journal-util.h
+        logs-show.c
+        logs-show.h
+        loop-util.c
+        loop-util.h
+        machine-image.c
+        machine-image.h
+        machine-pool.c
+        machine-pool.h
+        nsflags.c
+        nsflags.h
+        output-mode.c
+        output-mode.h
+        pager.c
+        pager.h
+        path-lookup.c
+        path-lookup.h
+        ptyfwd.c
+        ptyfwd.h
+        resolve-util.c
+        resolve-util.h
+        seccomp-util.h
+        sleep-config.c
+        sleep-config.h
+        spawn-ask-password-agent.c
+        spawn-ask-password-agent.h
+        spawn-polkit-agent.c
+        spawn-polkit-agent.h
+        specifier.c
+        specifier.h
+        switch-root.c
+        switch-root.h
+        sysctl-util.c
+        sysctl-util.h
+        tests.c
+        tests.h
+        udev-util.h
+        udev-util.c
+        uid-range.c
+        uid-range.h
+        utmp-wtmp.h
+        vlan-util.c
+        vlan-util.h
+        volatile-util.c
+        volatile-util.h
+        watchdog.c
+        watchdog.h
+'''.split()
+
+test_tables_h = files('test-tables.h')
+shared_sources += [test_tables_h]
+
+if conf.get('HAVE_ACL', false)
+        shared_sources += ['acl-util.c']
+endif
+
+if conf.get('HAVE_UTMP', false)
+        shared_sources += ['utmp-wtmp.c']
+endif
+
+if conf.get('HAVE_SECCOMP', false)
+        shared_sources += ['seccomp-util.c']
+endif
+
+if conf.get('HAVE_LIBIPTC', false)
+        shared_sources += ['firewall-util.c']
+endif
+
+libshared_name = 'systemd-shared-@0@'.format(meson.project_version())
+
+libshared_deps = [threads,
+                  librt,
+                  libcap,
+                  libacl,
+                  libcryptsetup,
+                  libgcrypt,
+                  libiptc,
+                  libseccomp,
+                  libselinux,
+                  libidn,
+                  libxz,
+                  liblz4,
+                  libblkid]
+
+libshared = shared_library(
+        libshared_name,
+        shared_sources,
+        basic_sources,
+        journal_internal_sources,
+        libsystemd_internal_sources,
+        libudev_sources,
+        include_directories : includes,
+        link_args : ['-shared'],
+        c_args : ['-fvisibility=default'],
+        dependencies : libshared_deps,
+        install : true,
+        install_dir : rootlibexecdir)
+
+libshared_static = static_library(
+        libshared_name,
+        shared_sources,
+        basic_sources,
+        include_directories : includes,
+        dependencies : libshared_deps)
index 67d8208ad2d88bc762d4f0c754e61b70cfa15bcc..29dcba9f6b82cd6a6d52d539ccaaf059826ec53c 100644 (file)
@@ -24,6 +24,7 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
         [OUTPUT_SHORT] = "short",
         [OUTPUT_SHORT_FULL] = "short-full",
         [OUTPUT_SHORT_ISO] = "short-iso",
+        [OUTPUT_SHORT_ISO_PRECISE] = "short-iso-precise",
         [OUTPUT_SHORT_PRECISE] = "short-precise",
         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
         [OUTPUT_SHORT_UNIX] = "short-unix",
index ff29dafcb57970eecb5ecd95db25348170d54312..2a1bfd98d087c60b62be33ec4015a291b59fde4a 100644 (file)
@@ -25,6 +25,7 @@ typedef enum OutputMode {
         OUTPUT_SHORT,
         OUTPUT_SHORT_FULL,
         OUTPUT_SHORT_ISO,
+        OUTPUT_SHORT_ISO_PRECISE,
         OUTPUT_SHORT_PRECISE,
         OUTPUT_SHORT_MONOTONIC,
         OUTPUT_SHORT_UNIX,
index f00ba9e1e79f133c4446052bdad1f127ed4f9a1e..4d7b02c63c4ae08b9001472a3bcbd54c838d7bab 100644 (file)
@@ -53,6 +53,11 @@ noreturn static void pager_fallback(void) {
         _exit(EXIT_SUCCESS);
 }
 
+static int stored_stdout = -1;
+static int stored_stderr = -1;
+static bool stdout_redirected = false;
+static bool stderr_redirected = false;
+
 int pager_open(bool no_pager, bool jump_to_end) {
         _cleanup_close_pair_ int fd[2] = { -1, -1 };
         const char *pager;
@@ -147,10 +152,19 @@ int pager_open(bool no_pager, bool jump_to_end) {
         }
 
         /* Return in the parent */
-        if (dup2(fd[1], STDOUT_FILENO) < 0)
+        stored_stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 3);
+        if (dup2(fd[1], STDOUT_FILENO) < 0) {
+                stored_stdout = safe_close(stored_stdout);
                 return log_error_errno(errno, "Failed to duplicate pager pipe: %m");
-        if (dup2(fd[1], STDERR_FILENO) < 0)
+        }
+        stdout_redirected = true;
+
+        stored_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3);
+        if (dup2(fd[1], STDERR_FILENO) < 0) {
+                stored_stderr = safe_close(stored_stderr);
                 return log_error_errno(errno, "Failed to duplicate pager pipe: %m");
+        }
+        stderr_redirected = true;
 
         return 1;
 }
@@ -161,8 +175,17 @@ void pager_close(void) {
                 return;
 
         /* Inform pager that we are done */
-        stdout = safe_fclose(stdout);
-        stderr = safe_fclose(stderr);
+        (void) fflush(stdout);
+        if (stdout_redirected)
+                if (stored_stdout < 0 || dup2(stored_stdout, STDOUT_FILENO) < 0)
+                        (void) close(STDOUT_FILENO);
+        stored_stdout = safe_close(stored_stdout);
+        (void) fflush(stderr);
+        if (stderr_redirected)
+                if (stored_stderr < 0 || dup2(stored_stderr, STDERR_FILENO) < 0)
+                        (void) close(STDERR_FILENO);
+        stored_stderr = safe_close(stored_stderr);
+        stdout_redirected = stderr_redirected = false;
 
         (void) kill(pager_pid, SIGCONT);
         (void) wait_for_terminate(pager_pid, NULL);
index 2631856563c5daebfb415e2c241221eb1d84aed1..36843d4bf585c510f43d0b77207f9aeedcb05b63 100644 (file)
@@ -792,37 +792,10 @@ int seccomp_restrict_namespaces(unsigned long retain) {
 
         SECCOMP_FOREACH_LOCAL_ARCH(arch) {
                 _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
-                int clone_reversed_order = -1;
                 unsigned i;
 
                 log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
 
-                switch (arch) {
-
-                case SCMP_ARCH_X86_64:
-                case SCMP_ARCH_X86:
-                case SCMP_ARCH_X32:
-                case SCMP_ARCH_PPC64:
-                case SCMP_ARCH_PPC64LE:
-                        clone_reversed_order = 0;
-                        break;
-
-                case SCMP_ARCH_S390:
-                case SCMP_ARCH_S390X:
-                        /* On s390/s390x the first two parameters to clone are switched */
-                        clone_reversed_order = 1;
-                        break;
-
-                /* Please add more definitions here, if you port systemd to other architectures! */
-
-#if SECCOMP_RESTRICT_NAMESPACES_BROKEN
-#  warning "Consider adding the right clone() syscall definitions here!"
-#endif
-                }
-
-                if (clone_reversed_order < 0) /* we don't know the right order, let's ignore this arch... */
-                        continue;
-
                 r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
                 if (r < 0)
                         return r;
@@ -871,7 +844,8 @@ int seccomp_restrict_namespaces(unsigned long retain) {
                                 break;
                         }
 
-                        if (clone_reversed_order == 0)
+                        /* On s390/s390x the first two parameters to clone are switched */
+                        if (!IN_SET(arch, SCMP_ARCH_S390, SCMP_ARCH_S390X))
                                 r = seccomp_rule_add_exact(
                                                 seccomp,
                                                 SCMP_ACT_ERRNO(EPERM),
@@ -966,16 +940,16 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
                 case SCMP_ARCH_X32:
                 case SCMP_ARCH_ARM:
                 case SCMP_ARCH_AARCH64:
+                case SCMP_ARCH_PPC64:
+                case SCMP_ARCH_PPC64LE:
                         /* These we know we support (i.e. are the ones that do not use socketcall()) */
                         supported = true;
                         break;
 
-                case SCMP_ARCH_X86:
                 case SCMP_ARCH_S390:
                 case SCMP_ARCH_S390X:
                 case SCMP_ARCH_PPC:
-                case SCMP_ARCH_PPC64:
-                case SCMP_ARCH_PPC64LE:
+                case SCMP_ARCH_X86:
                 default:
                         /* These we either know we don't support (i.e. are the ones that do use socketcall()), or we
                          * don't know */
@@ -1186,6 +1160,37 @@ int seccomp_restrict_realtime(void) {
         return 0;
 }
 
+static int add_seccomp_syscall_filter(scmp_filter_ctx seccomp,
+                                      uint32_t arch,
+                                      int nr,
+                                      unsigned int arg_cnt,
+                                      const struct scmp_arg_cmp arg) {
+        int r;
+
+        r = seccomp_rule_add_exact(seccomp, SCMP_ACT_ERRNO(EPERM), nr, arg_cnt, arg);
+        if (r < 0) {
+                _cleanup_free_ char *n = NULL;
+
+                n = seccomp_syscall_resolve_num_arch(arch, nr);
+                log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m",
+                                strna(n),
+                                seccomp_arch_to_string(arch));
+        }
+
+        return r;
+}
+
+/* For known architectures, check that syscalls are indeed defined or not. */
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+assert_cc(SCMP_SYS(shmget) > 0);
+assert_cc(SCMP_SYS(shmat) > 0);
+assert_cc(SCMP_SYS(shmdt) > 0);
+#elif defined(__i386__) || defined(__powerpc64__)
+assert_cc(SCMP_SYS(shmget) < 0);
+assert_cc(SCMP_SYS(shmat) < 0);
+assert_cc(SCMP_SYS(shmdt) < 0);
+#endif
+
 int seccomp_memory_deny_write_execute(void) {
 
         uint32_t arch;
@@ -1202,21 +1207,36 @@ int seccomp_memory_deny_write_execute(void) {
                 case SCMP_ARCH_X86:
                         filter_syscall = SCMP_SYS(mmap2);
                         block_syscall = SCMP_SYS(mmap);
+                        break;
+
+                case SCMP_ARCH_PPC64:
+                case SCMP_ARCH_PPC64LE:
+                        filter_syscall = SCMP_SYS(mmap);
+
+                        /* Note that shmat() isn't available, and the call is multiplexed through ipc().
+                         * We ignore that here, which means there's still a way to get writable/executable
+                         * memory, if an IPC key is mapped like this. That's a pity, but no total loss. */
 
-                        /* Note that shmat() isn't available on i386, where the call is multiplexed through ipc(). We
-                         * ignore that here, which means there's still a way to get writable/executable memory, if an
-                         * IPC key is mapped like this on i386. That's a pity, but no total loss. */
+                        break;
+
+                case SCMP_ARCH_AARCH64:
+                        block_syscall = SCMP_SYS(mmap);
+                        /* fall through */
+
+                case SCMP_ARCH_ARM:
+                        filter_syscall = SCMP_SYS(mmap2); /* arm has only mmap2 */
+                        shmat_syscall = SCMP_SYS(shmat);
                         break;
 
                 case SCMP_ARCH_X86_64:
                 case SCMP_ARCH_X32:
-                        filter_syscall = SCMP_SYS(mmap);
+                        filter_syscall = SCMP_SYS(mmap); /* amd64 and x32 have only mmap */
                         shmat_syscall = SCMP_SYS(shmat);
                         break;
 
                 /* Please add more definitions here, if you port systemd to other architectures! */
 
-#if !defined(__i386__) && !defined(__x86_64__)
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__)
 #warning "Consider adding the right mmap() syscall definitions here!"
 #endif
                 }
@@ -1229,63 +1249,30 @@ int seccomp_memory_deny_write_execute(void) {
                 if (r < 0)
                         return r;
 
-                if (filter_syscall != 0)  {
-                        r = seccomp_rule_add_exact(
-                                        seccomp,
-                                        SCMP_ACT_ERRNO(EPERM),
-                                        filter_syscall,
-                                        1,
-                                        SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE));
-                        if (r < 0) {
-                                _cleanup_free_ char *n = NULL;
-
-                                n = seccomp_syscall_resolve_num_arch(arch, filter_syscall);
-                                log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m",
-                                                strna(n),
-                                                seccomp_arch_to_string(arch));
-                                continue;
-                        }
-                }
+                r = add_seccomp_syscall_filter(seccomp, arch, filter_syscall,
+                                               1,
+                                               SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE));
+                if (r < 0)
+                        continue;
 
                 if (block_syscall != 0) {
-                        r = seccomp_rule_add_exact(
-                                        seccomp,
-                                        SCMP_ACT_ERRNO(EPERM),
-                                        block_syscall,
-                                        0);
-                        if (r < 0) {
-                                _cleanup_free_ char *n = NULL;
-
-                                n = seccomp_syscall_resolve_num_arch(arch, block_syscall);
-                                log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m",
-                                                strna(n),
-                                                seccomp_arch_to_string(arch));
+                        r = add_seccomp_syscall_filter(seccomp, arch, block_syscall, 0, (const struct scmp_arg_cmp){} );
+                        if (r < 0)
                                 continue;
-                        }
                 }
 
-                r = seccomp_rule_add_exact(
-                                seccomp,
-                                SCMP_ACT_ERRNO(EPERM),
-                                SCMP_SYS(mprotect),
-                                1,
-                                SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to add mprotect() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+                r = add_seccomp_syscall_filter(seccomp, arch, SCMP_SYS(mprotect),
+                                               1,
+                                               SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
+                if (r < 0)
                         continue;
-                }
 
                 if (shmat_syscall != 0) {
-                        r = seccomp_rule_add_exact(
-                                        seccomp,
-                                        SCMP_ACT_ERRNO(EPERM),
-                                        SCMP_SYS(shmat),
-                                        1,
-                                        SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC));
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to add shmat() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+                        r = add_seccomp_syscall_filter(seccomp, arch, SCMP_SYS(shmat),
+                                                       1,
+                                                       SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC));
+                        if (r < 0)
                                 continue;
-                        }
                 }
 
                 r = seccomp_load(seccomp);
index b56ac3f7630d329297d5c834184af3af34b488ac..4438e87fa6c55abe5c39595841a27c8ead30171f 100644 (file)
@@ -76,28 +76,6 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist);
 int seccomp_restrict_realtime(void);
 int seccomp_memory_deny_write_execute(void);
 
-#if defined(__i386__) || defined(__s390x__) || defined(__s390__) || defined(__powerpc64__) || defined(__powerpc__) || defined (__mips__)
-/* On these archs, socket() is implemented via the socketcall() syscall multiplexer, and we can't restrict it hence via
- * seccomp */
-#define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
-#else
-#define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
-#endif
-
-/* mmap() blocking is only available on some archs for now */
-#if defined(__x86_64__) || defined(__i386__)
-#define SECCOMP_MEMORY_DENY_WRITE_EXECUTE_BROKEN 0
-#else
-#define SECCOMP_MEMORY_DENY_WRITE_EXECUTE_BROKEN 1
-#endif
-
-/* we don't know the right order of the clone() parameters except for these archs, for now */
-#if defined(__x86_64__) || defined(__i386__) || defined(__s390x__) || defined(__s390__) || defined(__powerpc64__)
-#define SECCOMP_RESTRICT_NAMESPACES_BROKEN 0
-#else
-#define SECCOMP_RESTRICT_NAMESPACES_BROKEN 1
-#endif
-
 extern const uint32_t seccomp_local_archs[];
 
 #define SECCOMP_FOREACH_LOCAL_ARCH(arch) \
index ed31a80c8d036cb178dcca49f756c7ec450181ed..8c1624ff46733d65e8d6af7ada8f86823496405c 100644 (file)
@@ -59,9 +59,9 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {
         };
 
         config_parse_many_nulstr(PKGSYSCONFDIR "/sleep.conf",
-                          CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
-                          "Sleep\0", config_item_table_lookup, items,
-                          false, NULL);
+                                 CONF_PATHS_NULSTR("systemd/sleep.conf.d"),
+                                 "Sleep\0", config_item_table_lookup, items,
+                                 false, NULL);
 
         if (streq(verb, "suspend")) {
                 /* empty by default */
diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c
new file mode 100644 (file)
index 0000000..f708dcf
--- /dev/null
@@ -0,0 +1,56 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2017 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 <string.h>
+
+#include "fileio.h"
+#include "log.h"
+#include "string-util.h"
+#include "udev-util.h"
+
+int udev_parse_config(void) {
+        _cleanup_free_ char *val = NULL;
+        const char *log;
+        size_t n;
+        int r;
+
+        r = parse_env_file("/etc/udev/udev.conf", NEWLINE, "udev_log", &val, NULL);
+        if (r == -ENOENT || !val)
+                return 0;
+        if (r < 0)
+                return r;
+
+        /* unquote */
+        n = strlen(val);
+        if (n >= 2 &&
+            ((val[0] == '"' && val[n-1] == '"') ||
+             (val[0] == '\'' && val[n-1] == '\''))) {
+                val[n - 1] = '\0';
+                log = val + 1;
+        } else
+                log = val;
+
+        /* we set the udev log level here explicitly, this is supposed
+         * to regulate the code in libudev/ and udev/. */
+        r = log_set_max_level_from_string_realm(LOG_REALM_UDEV, log);
+        if (r < 0)
+                log_debug_errno(r, "/etc/udev/udev.conf: failed to set udev log level '%s', ignoring: %m", log);
+
+        return 0;
+}
index ca0889f8a6a52f3a9fe47756fd489152e4c984d2..a415be249e4fe3f8ac3b91619939b8c1f69a49b9 100644 (file)
@@ -42,3 +42,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref);
 #define _cleanup_udev_ctrl_msg_unref_ _cleanup_(udev_ctrl_msg_unrefp)
 #define _cleanup_udev_monitor_unref_ _cleanup_(udev_monitor_unrefp)
 #define _cleanup_udev_list_cleanup_ _cleanup_(udev_list_cleanup)
+
+int udev_parse_config(void);
index 78d66dd3d9d9f54af892582e12690560dba93dce..1edd96fbe77a40b23d5c53166391a2b5c0ca21ae 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "vlan-util.h"
-#include "parse-util.h"
 #include "conf-parser.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "vlan-util.h"
 
 int parse_vlanid(const char *p, uint16_t *ret) {
         uint16_t id;
@@ -35,6 +36,32 @@ int parse_vlanid(const char *p, uint16_t *ret) {
         return 0;
 }
 
+int config_parse_default_port_vlanid(
+                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) {
+        uint16_t *id = data;
+
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "none")) {
+                *id = 0;
+                return 0;
+        }
+
+        return config_parse_vlanid(unit, filename, line, section, section_line,
+                                   lvalue, ltype, rvalue, data, userdata);
+}
+
 int config_parse_vlanid(
                 const char *unit,
                 const char *filename,
index ce6763b3a337234c8e301cc7f47570e2bccabaf3..365ed14d88f862da967fe402f9dd7bedbd281fc0 100644 (file)
@@ -32,4 +32,5 @@ static inline bool vlanid_is_valid(uint16_t id) {
 
 int parse_vlanid(const char *p, uint16_t *ret);
 
+int config_parse_default_port_vlanid(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_vlanid(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);
index ce8efce3d533e9c25bf3a970740f402b1f0054b6..097f8c1a4b32820e1a0a551e8bab9150700548e0 100644 (file)
@@ -115,7 +115,7 @@ int main(int argc, char *argv[]) {
                 in_fd = SD_LISTEN_FDS_START;
                 out_fd = SD_LISTEN_FDS_START;
         } else {
-                log_error("Illegal number of file descriptors passed\n");
+                log_error("Illegal number of file descriptors passed.");
                 goto finish;
         }
 
@@ -190,7 +190,7 @@ int main(int argc, char *argv[]) {
         }
 
         for (;;) {
-                _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL;
+                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
                 int events_a, events_b, fd;
                 uint64_t timeout_a, timeout_b, t;
                 struct timespec _ts, *ts;
@@ -292,7 +292,7 @@ int main(int argc, char *argv[]) {
                         r = ppoll(p, ELEMENTSOF(p), ts, NULL);
                 }
                 if (r < 0) {
-                        log_error("ppoll() failed: %m");
+                        log_error_errno(errno, "ppoll() failed: %m");
                         goto finish;
                 }
         }
diff --git a/src/sulogin-shell/.gitignore b/src/sulogin-shell/.gitignore
new file mode 100644 (file)
index 0000000..01a3155
--- /dev/null
@@ -0,0 +1 @@
+systemd-sulogin-shell
diff --git a/src/sulogin-shell/meson.build b/src/sulogin-shell/meson.build
new file mode 100644 (file)
index 0000000..4ec0d3d
--- /dev/null
@@ -0,0 +1,7 @@
+gen = configure_file(
+        input : 'systemd-sulogin-shell.in',
+        output : 'systemd-sulogin-shell',
+        configuration : substs)
+
+install_data(gen,
+             install_dir : rootlibexecdir)
diff --git a/src/sulogin-shell/systemd-sulogin-shell.in b/src/sulogin-shell/systemd-sulogin-shell.in
new file mode 100755 (executable)
index 0000000..103f841
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ -x /bin/plymouth ]; then
+    /bin/plymouth --wait quit
+fi
+
+echo "You are in $1 mode. After logging in, type \"journalctl -xb\" to view"
+echo "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or ^D to boot"
+echo "into default mode."
+
+@SULOGIN@
+@SYSTEMCTL@ --job-mode=fail --no-block default
index d78e56d777e1e9abb9cd37207a33354a109df39b..83ed9ef9f71e0f134f8a2c08d068389a00521a14 100644 (file)
@@ -47,6 +47,7 @@
 #include "dropin.h"
 #include "efivars.h"
 #include "env-util.h"
+#include "escape.h"
 #include "exit-status.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -1780,6 +1781,7 @@ static int list_dependencies_one(
         STRV_FOREACH(c, deps) {
                 if (strv_contains(*units, *c)) {
                         if (!arg_plain) {
+                                printf("  ");
                                 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
                                 if (r < 0)
                                         return r;
@@ -3190,8 +3192,8 @@ static int start_unit(int argc, char *argv[], void *userdata) {
         return r;
 }
 
+#ifdef ENABLE_LOGIND
 static int logind_set_wall_message(void) {
-#ifdef HAVE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         _cleanup_free_ char *m = NULL;
@@ -3219,15 +3221,14 @@ static int logind_set_wall_message(void) {
 
         if (r < 0)
                 return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
-
-#endif
         return 0;
 }
+#endif
 
 /* Ask systemd-logind, which might grant access to unprivileged users
  * through PolicyKit */
 static int logind_reboot(enum action a) {
-#ifdef HAVE_LOGIND
+#ifdef ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *method, *description;
         sd_bus *bus;
@@ -3290,7 +3291,7 @@ static int logind_reboot(enum action a) {
 }
 
 static int logind_check_inhibitors(enum action a) {
-#ifdef HAVE_LOGIND
+#ifdef ENABLE_LOGIND
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_strv_free_ char **sessions = NULL;
         const char *what, *who, *why, *mode;
@@ -3409,7 +3410,7 @@ static int logind_check_inhibitors(enum action a) {
 }
 
 static int logind_prepare_firmware_setup(void) {
-#ifdef HAVE_LOGIND
+#ifdef ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;
@@ -3817,6 +3818,8 @@ typedef struct UnitStatusInfo {
         bool failed_assert_negate;
         const char *failed_assert;
         const char *failed_assert_parameter;
+        usec_t next_elapse_real;
+        usec_t next_elapse_monotonic;
 
         /* Socket */
         unsigned n_accepted;
@@ -3986,6 +3989,31 @@ static void print_status_info(
         else
                 printf("\n");
 
+        if (endswith(i->id, ".timer")) {
+                char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX],
+                     tstamp2[FORMAT_TIMESTAMP_MAX];
+                char *next_rel_time, *next_time;
+                dual_timestamp nw, next = {i->next_elapse_real,
+                                           i->next_elapse_monotonic};
+                usec_t next_elapse;
+
+                printf("  Trigger: ");
+
+                dual_timestamp_get(&nw);
+                next_elapse = calc_next_elapse(&nw, &next);
+                next_rel_time = format_timestamp_relative(tstamp1,
+                                                          sizeof(tstamp1),
+                                                          next_elapse);
+                next_time = format_timestamp(tstamp2,
+                                             sizeof(tstamp2),
+                                             next_elapse);
+
+                if (next_time && next_rel_time)
+                        printf("%s; %s\n", next_time, next_rel_time);
+                else
+                        printf("n/a\n");
+        }
+
         if (!i->condition_result && i->condition_timestamp > 0) {
                 UnitCondition *c;
                 int n = 0;
@@ -4423,6 +4451,10 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
                         i->tasks_max = u;
                 else if (streq(name, "CPUUsageNSec"))
                         i->cpu_usage_nsec = u;
+                else if (streq(name, "NextElapseUSecMonotonic"))
+                        i->next_elapse_monotonic = u;
+                else if (streq(name, "NextElapseUSecRealtime"))
+                        i->next_elapse_real = u;
 
                 break;
         }
@@ -5573,6 +5605,24 @@ static int reset_failed(int argc, char *argv[], void *userdata) {
         return r;
 }
 
+static int print_variable(const char *s) {
+        const char *sep;
+        _cleanup_free_ char *esc = NULL;
+
+        sep = strchr(s, '=');
+        if (!sep) {
+                log_error("Invalid environment block");
+                return -EUCLEAN;
+        }
+
+        esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX);
+        if (!esc)
+                return log_oom();
+
+        printf("%.*s=%s\n", (int)(sep-s), s, esc);
+        return 0;
+}
+
 static int show_environment(int argc, char *argv[], void *userdata) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -5602,8 +5652,11 @@ static int show_environment(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
-                puts(text);
+        while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
+                r = print_variable(text);
+                if (r < 0)
+                        return r;
+        }
         if (r < 0)
                 return bus_log_parse_error(r);
 
@@ -5654,7 +5707,7 @@ static int switch_root(int argc, char *argv[], void *userdata) {
 
                 /* If the passed init is actually the same as the
                  * systemd binary, then let's suppress it. */
-                if (files_same(root_init_path, root_systemd_path) > 0)
+                if (files_same(root_init_path, root_systemd_path, 0) > 0)
                         init = NULL;
         }
 
@@ -5890,7 +5943,8 @@ static int enable_sysv_units(const char *verb, char **args) {
                 if (!l)
                         return log_oom();
 
-                log_info("Executing: %s", l);
+                if (!arg_quiet)
+                        log_info("Executing: %s", l);
 
                 pid = fork();
                 if (pid < 0)
@@ -5979,6 +6033,34 @@ static int mangle_names(char **original_names, char ***mangled_names) {
         return 0;
 }
 
+static int normalize_filenames(char **names) {
+        char **u;
+        int r;
+
+        STRV_FOREACH(u, names)
+                if (!path_is_absolute(*u)) {
+                        char* normalized_path;
+
+                        if (!isempty(arg_root)) {
+                                log_error("Non-absolute paths are not allowed when --root is used: %s", *u);
+                                return -EINVAL;
+                        }
+
+                        if (!strchr(*u,'/')) {
+                                log_error("Link argument does contain at least one directory separator: %s", *u);
+                                return -EINVAL;
+                        }
+
+                        r = path_make_absolute_cwd(*u, &normalized_path);
+                        if (r < 0)
+                                return r;
+
+                        free_and_replace(*u, normalized_path);
+                }
+
+        return 0;
+}
+
 static int normalize_names(char **names, bool warn_if_path) {
         char **u;
         bool was_path = false;
@@ -6075,6 +6157,12 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
                         return r;
         }
 
+        if (streq(verb, "link")) {
+                r = normalize_filenames(names);
+                if (r < 0)
+                        return r;
+        }
+
         if (install_client_side()) {
                 UnitFileFlags flags;
 
@@ -7001,7 +7089,8 @@ static void systemctl_help(void) {
                "     --root=PATH      Enable unit files in the specified root directory\n"
                "  -n --lines=INTEGER  Number of journal entries to show\n"
                "  -o --output=STRING  Change journal output mode (short, short-precise,\n"
-               "                             short-iso, short-full, short-monotonic, short-unix,\n"
+               "                             short-iso, short-iso-precise, short-full,\n"
+               "                             short-monotonic, short-unix,\n"
                "                             verbose, export, json, json-pretty, json-sse, cat)\n"
                "     --firmware-setup Tell the firmware to show the setup menu on next boot\n"
                "     --plain          Print unit dependencies as a list instead of a tree\n\n"
@@ -8245,12 +8334,14 @@ static int halt_now(enum action a) {
         switch (a) {
 
         case ACTION_HALT:
-                log_info("Halting.");
+                if (!arg_quiet)
+                        log_info("Halting.");
                 (void) reboot(RB_HALT_SYSTEM);
                 return -errno;
 
         case ACTION_POWEROFF:
-                log_info("Powering off.");
+                if (!arg_quiet)
+                        log_info("Powering off.");
                 (void) reboot(RB_POWER_OFF);
                 return -errno;
 
@@ -8259,16 +8350,18 @@ static int halt_now(enum action a) {
                 _cleanup_free_ char *param = NULL;
 
                 r = read_one_line_file("/run/systemd/reboot-param", &param);
-                if (r < 0)
+                if (r < 0 && r != -ENOENT)
                         log_warning_errno(r, "Failed to read reboot parameter file: %m");
 
                 if (!isempty(param)) {
-                        log_info("Rebooting with argument '%s'.", param);
+                        if (!arg_quiet)
+                                log_info("Rebooting with argument '%s'.", param);
                         (void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
                         log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
                 }
 
-                log_info("Rebooting.");
+                if (!arg_quiet)
+                        log_info("Rebooting.");
                 (void) reboot(RB_AUTOBOOT);
                 return -errno;
         }
@@ -8280,7 +8373,7 @@ static int halt_now(enum action a) {
 
 static int logind_schedule_shutdown(void) {
 
-#ifdef HAVE_LOGIND
+#ifdef ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         char date[FORMAT_TIMESTAMP_MAX];
         const char *action;
@@ -8329,7 +8422,8 @@ static int logind_schedule_shutdown(void) {
         if (r < 0)
                 return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
 
-        log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
+        if (!arg_quiet)
+                log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
         return 0;
 #else
         log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
@@ -8408,7 +8502,7 @@ static int runlevel_main(void) {
 }
 
 static int logind_cancel_shutdown(void) {
-#ifdef HAVE_LOGIND
+#ifdef ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
         int r;
@@ -8457,7 +8551,9 @@ int main(int argc, char*argv[]) {
                 goto finish;
 
         if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
-                log_info("Running in chroot, ignoring request.");
+
+                if (!arg_quiet)
+                        log_info("Running in chroot, ignoring request.");
                 r = 0;
                 goto finish;
         }
index 3bb886be75959100f12c32e62f067927bbe070c0..97c3943861c9d195cf01f17330f0221a1f069e1e 100644 (file)
@@ -22,8 +22,8 @@
 
 /* This is a private header; never even think of including this directly! */
 
-#if __INCLUDE_LEVEL__ <= 1
-#error "Do not include _sd-common.h directly; it is a private header."
+#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1
+#  error "Do not include _sd-common.h directly; it is a private header."
 #endif
 
 #ifndef _sd_printf_
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
new file mode 100644 (file)
index 0000000..debbd46
--- /dev/null
@@ -0,0 +1,59 @@
+_systemd_headers = '''
+        sd-bus.h
+        sd-bus-protocol.h
+        sd-bus-vtable.h
+        sd-daemon.h
+        sd-event.h
+        sd-id128.h
+        sd-journal.h
+        sd-login.h
+        sd-messages.h
+'''.split()
+
+# https://github.com/mesonbuild/meson/issues/1633
+systemd_headers = files(_systemd_headers)
+
+#  sd-device.h
+#  sd-hwdb.h
+#  sd-dhcp6-client.h
+#  sd-dhcp6-lease.h
+#  sd-dhcp-client.h
+#  sd-dhcp-lease.h
+#  sd-dhcp-server.h
+#  sd-ipv4acd.h
+#  sd-ipv4ll.h
+#  sd-lldp.h
+#  sd-ndisc.h
+#  sd-netlink.h
+#  sd-network.h
+#  sd-path.h
+#  sd-resolve.h
+#  sd-utf8.h
+
+install_headers(
+        systemd_headers,
+        '_sd-common.h',
+        subdir : 'systemd')
+
+
+############################################################
+
+opts = [['c'],
+        ['c', '-ansi'],
+        ['c', '-std=iso9899:1990']]
+
+cxx = find_program('c++', required : false)
+if cxx.found()
+        opts += [['c++']]
+endif
+
+foreach header : _systemd_headers
+        foreach opt : opts
+                name = ''.join([header, ':'] + opt)
+                test('cc-' + name,
+                     check_compilation_sh,
+                     args : cc.cmd_array() + ['-c', '-x'] + opt +
+                            ['-Werror', '-include',
+                             join_paths(meson.current_source_dir(), header)])
+        endforeach
+endforeach
index 3563a2b126bffc3d9662dea4d18ec4688f5966c8..1e82cae0381f44f084421281ed134cdfa9c993c6 100644 (file)
@@ -131,6 +131,7 @@ struct sd_bus_vtable {
                         .member = _member,                              \
                         .signature = _signature,                        \
                         .get = _get,                                    \
+                        .set = NULL,                                    \
                         .offset = _offset,                              \
                     },                                                  \
                 },                                                      \
@@ -154,6 +155,9 @@ struct sd_bus_vtable {
 #define SD_BUS_VTABLE_END                                               \
         {                                                               \
                 .type = _SD_BUS_VTABLE_END,                             \
+                .flags = 0,                                             \
+                .x = {                                                  \
+                },                                                      \
         }
 
 _SD_END_DECLARATIONS;
index c47459c9adbb1fff848623f0caccf9eee63ef53a..2b6aeb79896e6fb7b8f6e6315e537cb362a1216c 100644 (file)
@@ -266,6 +266,7 @@ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination);
 int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority);
 
 int sd_bus_message_append(sd_bus_message *m, const char *types, ...);
+int sd_bus_message_appendv(sd_bus_message *m, const char *types, va_list ap);
 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p);
 int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size);
 int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr);
index ffe7f836de0c87d0459c11b1e4013361738002c5..f731fdcbd48cbc79da4029cc5502e861368697bc 100644 (file)
@@ -76,6 +76,7 @@ enum {
         SD_DHCP_OPTION_FQDN                        = 81,
         SD_DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
         SD_DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
+        SD_DHCP_OPTION_DOMAIN_SEARCH_LIST          = 119,
         SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,
         SD_DHCP_OPTION_PRIVATE_BASE                = 224,
         SD_DHCP_OPTION_PRIVATE_LAST                = 254,
index 2f565ca825a30ba718ed2572bcc99732526b4d47..7ab99cccd16a803ee0d29cc9f9ce9868f20665ca 100644 (file)
@@ -49,6 +49,7 @@ int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
 int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
 int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
+int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
 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, sd_dhcp_route ***routes);
index cc26b7df553b2499b33bb5530e52477d33025b24..f8cb895660516b839dd8bd39c6ab25a640429321 100644 (file)
@@ -69,7 +69,7 @@ typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
 typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
 typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
 typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
-#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
+#if defined _GNU_SOURCE || _POSIX_C_SOURCE >= 199309L
 typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
 #else
 typedef void* sd_event_child_handler_t;
index 1109ec52e0472f32f0e8e19bcdfa44427ba1510a..5ba92083f4851944c9ab9f98196f36b4dc64ee28 100644 (file)
@@ -47,6 +47,7 @@ int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index);
 int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
 int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed);
 int sd_ipv4ll_is_running(sd_ipv4ll *ll);
+int sd_ipv4ll_restart(sd_ipv4ll *ll);
 int sd_ipv4ll_start(sd_ipv4ll *ll);
 int sd_ipv4ll_stop(sd_ipv4ll *ll);
 sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll);
index 7efa8ebe5ab0384005982d7ed87f98782aa99386..3f5a6673cf54fe41087c7f32cc05c32c3db0b698 100644 (file)
@@ -155,6 +155,10 @@ int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *family);
 int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state);
 int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags);
 
+int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family);
+int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
+int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen);
+
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref);
 
diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h
new file mode 100644 (file)
index 0000000..4cbd80d
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef foosdradvfoo
+#define foosdradvfoo
+
+/***
+  This file is part of systemd.
+
+  Copyright (C) 2017 Intel Corporation. All rights reserved.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (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 <inttypes.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+
+#include "sd-ndisc.h"
+
+#include "sd-event.h"
+
+#include "_sd-common.h"
+
+_SD_BEGIN_DECLARATIONS;
+
+typedef struct sd_radv sd_radv;
+typedef struct sd_radv_prefix sd_radv_prefix;
+
+/* Router Advertisment */
+int sd_radv_new(sd_radv **ret);
+sd_radv *sd_radv_ref(sd_radv *ra);
+sd_radv *sd_radv_unref(sd_radv *ra);
+
+int sd_radv_attach_event(sd_radv *ra, sd_event *event, int64_t priority);
+int sd_radv_detach_event(sd_radv *nd);
+sd_event *sd_radv_get_event(sd_radv *ra);
+
+int sd_radv_start(sd_radv *ra);
+int sd_radv_stop(sd_radv *ra);
+
+int sd_radv_set_ifindex(sd_radv *ra, int interface_index);
+int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr);
+int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu);
+int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit);
+int sd_radv_set_router_lifetime(sd_radv *ra, uint32_t router_lifetime);
+int sd_radv_set_managed_information(sd_radv *ra, int managed);
+int sd_radv_set_other_information(sd_radv *ra, int other);
+int sd_radv_set_preference(sd_radv *ra, unsigned preference);
+int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p);
+
+/* Advertised prefixes */
+int sd_radv_prefix_new(sd_radv_prefix **ret);
+sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *ra);
+sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *ra);
+
+int sd_radv_prefix_set_prefix(sd_radv_prefix *p, struct in6_addr *in6_addr,
+                              unsigned char prefixlen);
+int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink);
+int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p,
+                                                 int address_autoconfiguration);
+int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p,
+                                      uint32_t valid_lifetime);
+int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p,
+                                          uint32_t preferred_lifetime);
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref);
+
+_SD_END_DECLARATIONS;
+
+#endif
index 4a0a49f2bb5af75a5294c77116a49ecb4e9671c5..fbe51a6ed5a67bc46794f25ac7a10fc75cf4a3b1 100644 (file)
@@ -29,6 +29,7 @@
 #include "copy.h"
 #include "def.h"
 #include "fd-util.h"
+#include "fs-util.h"
 #include "fileio-label.h"
 #include "format-util.h"
 #include "hashmap.h"
@@ -292,6 +293,7 @@ static int putgrent_with_members(const struct group *gr, FILE *group) {
         return 0;
 }
 
+#ifdef ENABLE_GSHADOW
 static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
         char **a;
 
@@ -341,6 +343,7 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
 
         return 0;
 }
+#endif
 
 static int sync_rights(FILE *from, FILE *to) {
         struct stat st;
@@ -370,400 +373,424 @@ static int rename_and_apply_smack(const char *temp_path, const char *dest_path)
         return r;
 }
 
-static int write_files(void) {
-
-        _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL;
-        _cleanup_free_ char *passwd_tmp = NULL, *group_tmp = NULL, *shadow_tmp = NULL, *gshadow_tmp = NULL;
-        const char *passwd_path = NULL, *group_path = NULL, *shadow_path = NULL, *gshadow_path = NULL;
-        bool group_changed = false;
+static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char **tmpfile_path) {
+        _cleanup_fclose_ FILE *original = NULL, *passwd = NULL;
+        _cleanup_(unlink_and_freep) char *passwd_tmp = NULL;
         Iterator iterator;
         Item *i;
         int r;
 
-        if (hashmap_size(todo_gids) > 0 || hashmap_size(members) > 0) {
-                _cleanup_fclose_ FILE *original = NULL;
+        if (hashmap_size(todo_uids) == 0)
+                return 0;
 
-                /* First we update the actual group list file */
-                group_path = prefix_roota(arg_root, "/etc/group");
-                r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp);
+        r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
+        if (r < 0)
+                return r;
+
+        original = fopen(passwd_path, "re");
+        if (original) {
+                struct passwd *pw;
+
+                r = sync_rights(original, passwd);
                 if (r < 0)
-                        goto finish;
+                        return r;
 
-                original = fopen(group_path, "re");
-                if (original) {
-                        struct group *gr;
+                errno = 0;
+                while ((pw = fgetpwent(original))) {
 
-                        r = sync_rights(original, group);
-                        if (r < 0)
-                                goto finish;
+                        i = hashmap_get(users, pw->pw_name);
+                        if (i && i->todo_user) {
+                                log_error("%s: User \"%s\" already exists.", passwd_path, pw->pw_name);
+                                return -EEXIST;
+                        }
+
+                        if (hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) {
+                                log_error("%s: Detected collision for UID " UID_FMT ".", passwd_path, pw->pw_uid);
+                                return -EEXIST;
+                        }
 
                         errno = 0;
-                        while ((gr = fgetgrent(original))) {
-                                /* Safety checks against name and GID
-                                 * collisions. Normally, this should
-                                 * be unnecessary, but given that we
-                                 * look at the entries anyway here,
-                                 * let's make an extra verification
-                                 * step that we don't generate
-                                 * duplicate entries. */
-
-                                i = hashmap_get(groups, gr->gr_name);
-                                if (i && i->todo_group) {
-                                        log_error("%s: Group \"%s\" already exists.", group_path, gr->gr_name);
-                                        r = -EEXIST;
-                                        goto finish;
-                                }
+                        if (putpwent(pw, passwd) < 0)
+                                return errno ? -errno : -EIO;
 
-                                if (hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) {
-                                        log_error("%s: Detected collision for GID " GID_FMT ".", group_path, gr->gr_gid);
-                                        r = -EEXIST;
-                                        goto finish;
-                                }
+                        errno = 0;
+                }
+                if (!IN_SET(errno, 0, ENOENT))
+                        return -errno;
 
-                                r = putgrent_with_members(gr, group);
-                                if (r < 0)
-                                        goto finish;
-                                if (r > 0)
-                                        group_changed = true;
+        } else {
+                if (errno != ENOENT)
+                        return -errno;
+                if (fchmod(fileno(passwd), 0644) < 0)
+                        return -errno;
+        }
 
-                                errno = 0;
-                        }
-                        if (!IN_SET(errno, 0, ENOENT)) {
-                                r = -errno;
-                                goto finish;
-                        }
+        HASHMAP_FOREACH(i, todo_uids, iterator) {
+                struct passwd n = {
+                        .pw_name = i->name,
+                        .pw_uid = i->uid,
+                        .pw_gid = i->gid,
+                        .pw_gecos = i->description,
 
-                } else if (errno != ENOENT) {
-                        r = -errno;
-                        goto finish;
-                } else if (fchmod(fileno(group), 0644) < 0) {
-                        r = -errno;
-                        goto finish;
-                }
+                        /* "x" means the password is stored in the shadow file */
+                        .pw_passwd = (char*) "x",
 
-                HASHMAP_FOREACH(i, todo_gids, iterator) {
-                        struct group n = {
-                                .gr_name = i->name,
-                                .gr_gid = i->gid,
-                                .gr_passwd = (char*) "x",
-                        };
+                        /* We default to the root directory as home */
+                        .pw_dir = i->home ? i->home : (char*) "/",
 
-                        r = putgrent_with_members(&n, group);
-                        if (r < 0)
-                                goto finish;
+                        /* Initialize the shell to nologin, with one exception:
+                         * for root we patch in something special */
+                        .pw_shell = i->uid == 0 ? (char*) "/bin/sh" : (char*) "/sbin/nologin",
+                };
 
-                        group_changed = true;
-                }
+                errno = 0;
+                if (putpwent(&n, passwd) != 0)
+                        return errno ? -errno : -EIO;
+        }
 
-                r = fflush_and_check(group);
-                if (r < 0)
-                        goto finish;
+        r = fflush_and_check(passwd);
+        if (r < 0)
+                return r;
 
-                if (original) {
-                        fclose(original);
-                        original = NULL;
-                }
+        *tmpfile = passwd;
+        *tmpfile_path = passwd_tmp;
+        passwd = NULL;
+        passwd_tmp = NULL;
+        return 0;
+}
 
-                /* OK, now also update the shadow file for the group list */
-                gshadow_path = prefix_roota(arg_root, "/etc/gshadow");
-                r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp);
-                if (r < 0)
-                        goto finish;
+static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char **tmpfile_path) {
+        _cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
+        _cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
+        Iterator iterator;
+        long lstchg;
+        Item *i;
+        int r;
 
-                original = fopen(gshadow_path, "re");
-                if (original) {
-                        struct sgrp *sg;
+        if (hashmap_size(todo_uids) == 0)
+                return 0;
 
-                        r = sync_rights(original, gshadow);
-                        if (r < 0)
-                                goto finish;
+        r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
+        if (r < 0)
+                return r;
 
-                        errno = 0;
-                        while ((sg = fgetsgent(original))) {
+        lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
 
-                                i = hashmap_get(groups, sg->sg_namp);
-                                if (i && i->todo_group) {
-                                        log_error("%s: Group \"%s\" already exists.", gshadow_path, sg->sg_namp);
-                                        r = -EEXIST;
-                                        goto finish;
-                                }
+        original = fopen(shadow_path, "re");
+        if (original) {
+                struct spwd *sp;
 
-                                r = putsgent_with_members(sg, gshadow);
-                                if (r < 0)
-                                        goto finish;
-                                if (r > 0)
-                                        group_changed = true;
+                r = sync_rights(original, shadow);
+                if (r < 0)
+                        return r;
 
-                                errno = 0;
-                        }
-                        if (!IN_SET(errno, 0, ENOENT)) {
-                                r = -errno;
-                                goto finish;
-                        }
+                errno = 0;
+                while ((sp = fgetspent(original))) {
 
-                } else if (errno != ENOENT) {
-                        r = -errno;
-                        goto finish;
-                } else if (fchmod(fileno(gshadow), 0000) < 0) {
-                        r = -errno;
-                        goto finish;
-                }
+                        i = hashmap_get(users, sp->sp_namp);
+                        if (i && i->todo_user) {
+                                /* we will update the existing entry */
+                                sp->sp_lstchg = lstchg;
 
-                HASHMAP_FOREACH(i, todo_gids, iterator) {
-                        struct sgrp n = {
-                                .sg_namp = i->name,
-                                .sg_passwd = (char*) "!!",
-                        };
+                                /* only the /etc/shadow stage is left, so we can
+                                 * safely remove the item from the todo set */
+                                i->todo_user = false;
+                                hashmap_remove(todo_uids, UID_TO_PTR(i->uid));
+                        }
 
-                        r = putsgent_with_members(&n, gshadow);
-                        if (r < 0)
-                                goto finish;
+                        errno = 0;
+                        if (putspent(sp, shadow) < 0)
+                                return errno ? -errno : -EIO;
 
-                        group_changed = true;
+                        errno = 0;
                 }
+                if (!IN_SET(errno, 0, ENOENT))
+                        return -errno;
 
-                r = fflush_and_check(gshadow);
-                if (r < 0)
-                        goto finish;
+        } else {
+                if (errno != ENOENT)
+                        return -errno;
+                if (fchmod(fileno(shadow), 0000) < 0)
+                        return -errno;
         }
 
-        if (hashmap_size(todo_uids) > 0) {
-                _cleanup_fclose_ FILE *original = NULL;
-                long lstchg;
-
-                /* First we update the user database itself */
-                passwd_path = prefix_roota(arg_root, "/etc/passwd");
-                r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
-                if (r < 0)
-                        goto finish;
-
-                original = fopen(passwd_path, "re");
-                if (original) {
-                        struct passwd *pw;
+        HASHMAP_FOREACH(i, todo_uids, iterator) {
+                struct spwd n = {
+                        .sp_namp = i->name,
+                        .sp_pwdp = (char*) "!!",
+                        .sp_lstchg = lstchg,
+                        .sp_min = -1,
+                        .sp_max = -1,
+                        .sp_warn = -1,
+                        .sp_inact = -1,
+                        .sp_expire = -1,
+                        .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
+                };
 
-                        r = sync_rights(original, passwd);
-                        if (r < 0)
-                                goto finish;
+                errno = 0;
+                if (putspent(&n, shadow) != 0)
+                        return errno ? -errno : -EIO;
+        }
 
-                        errno = 0;
-                        while ((pw = fgetpwent(original))) {
+        r = fflush_and_check(shadow);
+        if (r < 0)
+                return r;
 
-                                i = hashmap_get(users, pw->pw_name);
-                                if (i && i->todo_user) {
-                                        log_error("%s: User \"%s\" already exists.", passwd_path, pw->pw_name);
-                                        r = -EEXIST;
-                                        goto finish;
-                                }
+        *tmpfile = shadow;
+        *tmpfile_path = shadow_tmp;
+        shadow = NULL;
+        shadow_tmp = NULL;
+        return 0;
+}
 
-                                if (hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) {
-                                        log_error("%s: Detected collision for UID " UID_FMT ".", passwd_path, pw->pw_uid);
-                                        r = -EEXIST;
-                                        goto finish;
-                                }
+static int write_temporary_group(const char *group_path, FILE **tmpfile, char **tmpfile_path) {
+        _cleanup_fclose_ FILE *original = NULL, *group = NULL;
+        _cleanup_(unlink_and_freep) char *group_tmp = NULL;
+        bool group_changed = false;
+        Iterator iterator;
+        Item *i;
+        int r;
 
-                                errno = 0;
-                                if (putpwent(pw, passwd) < 0) {
-                                        r = errno ? -errno : -EIO;
-                                        goto finish;
-                                }
+        if (hashmap_size(todo_gids) == 0 && hashmap_size(members) == 0)
+                return 0;
 
-                                errno = 0;
-                        }
-                        if (!IN_SET(errno, 0, ENOENT)) {
-                                r = -errno;
-                                goto finish;
-                        }
+        r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp);
+        if (r < 0)
+                return r;
 
-                } else if (errno != ENOENT) {
-                        r = -errno;
-                        goto finish;
-                } else if (fchmod(fileno(passwd), 0644) < 0) {
-                        r = -errno;
-                        goto finish;
-                }
+        original = fopen(group_path, "re");
+        if (original) {
+                struct group *gr;
 
-                HASHMAP_FOREACH(i, todo_uids, iterator) {
-                        struct passwd n = {
-                                .pw_name = i->name,
-                                .pw_uid = i->uid,
-                                .pw_gid = i->gid,
-                                .pw_gecos = i->description,
+                r = sync_rights(original, group);
+                if (r < 0)
+                        return r;
 
-                                /* "x" means the password is stored in
-                                 * the shadow file */
-                                .pw_passwd = (char*) "x",
+                errno = 0;
+                while ((gr = fgetgrent(original))) {
+                        /* Safety checks against name and GID collisions. Normally,
+                         * this should be unnecessary, but given that we look at the
+                         * entries anyway here, let's make an extra verification
+                         * step that we don't generate duplicate entries. */
+
+                        i = hashmap_get(groups, gr->gr_name);
+                        if (i && i->todo_group) {
+                                log_error("%s: Group \"%s\" already exists.", group_path, gr->gr_name);
+                                return -EEXIST;
+                        }
 
-                                /* We default to the root directory as home */
-                                .pw_dir = i->home ? i->home : (char*) "/",
+                        if (hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) {
+                                log_error("%s: Detected collision for GID " GID_FMT ".", group_path, gr->gr_gid);
+                                return  -EEXIST;
+                        }
 
-                                /* Initialize the shell to nologin,
-                                 * with one exception: for root we
-                                 * patch in something special */
-                                .pw_shell = i->uid == 0 ? (char*) "/bin/sh" : (char*) "/sbin/nologin",
-                        };
+                        r = putgrent_with_members(gr, group);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                group_changed = true;
 
                         errno = 0;
-                        if (putpwent(&n, passwd) != 0) {
-                                r = errno ? -errno : -EIO;
-                                goto finish;
-                        }
                 }
+                if (!IN_SET(errno, 0, ENOENT))
+                        return -errno;
 
-                r = fflush_and_check(passwd);
-                if (r < 0)
-                        goto finish;
+        } else {
+                if (errno != ENOENT)
+                        return -errno;
+                if (fchmod(fileno(group), 0644) < 0)
+                        return -errno;
+        }
 
-                if (original) {
-                        fclose(original);
-                        original = NULL;
-                }
+        HASHMAP_FOREACH(i, todo_gids, iterator) {
+                struct group n = {
+                        .gr_name = i->name,
+                        .gr_gid = i->gid,
+                        .gr_passwd = (char*) "x",
+                };
 
-                /* The we update the shadow database */
-                shadow_path = prefix_roota(arg_root, "/etc/shadow");
-                r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
+                r = putgrent_with_members(&n, group);
                 if (r < 0)
-                        goto finish;
+                        return r;
 
-                lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
+                group_changed = true;
+        }
 
-                original = fopen(shadow_path, "re");
-                if (original) {
-                        struct spwd *sp;
+        r = fflush_and_check(group);
+        if (r < 0)
+                return r;
 
-                        r = sync_rights(original, shadow);
-                        if (r < 0)
-                                goto finish;
+        if (group_changed) {
+                *tmpfile = group;
+                *tmpfile_path = group_tmp;
+                group = NULL;
+                group_tmp = NULL;
+        }
+        return 0;
+}
 
-                        errno = 0;
-                        while ((sp = fgetspent(original))) {
+static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, char **tmpfile_path) {
+#ifdef ENABLE_GSHADOW
+        _cleanup_fclose_ FILE *original = NULL, *gshadow = NULL;
+        _cleanup_(unlink_and_freep) char *gshadow_tmp = NULL;
+        bool group_changed = false;
+        Iterator iterator;
+        Item *i;
+        int r;
 
-                                i = hashmap_get(users, sp->sp_namp);
-                                if (i && i->todo_user) {
-                                        /* we will update the existing entry */
-                                        sp->sp_lstchg = lstchg;
+        if (hashmap_size(todo_gids) == 0 && hashmap_size(members) == 0)
+                return 0;
 
-                                        /* only the /etc/shadow stage is left, so we can
-                                         * safely remove the item from the todo set */
-                                        i->todo_user = false;
-                                        hashmap_remove(todo_uids, UID_TO_PTR(i->uid));
-                                }
+        r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp);
+        if (r < 0)
+                return r;
 
-                                errno = 0;
-                                if (putspent(sp, shadow) < 0) {
-                                        r = errno ? -errno : -EIO;
-                                        goto finish;
-                                }
+        original = fopen(gshadow_path, "re");
+        if (original) {
+                struct sgrp *sg;
 
-                                errno = 0;
-                        }
-                        if (!IN_SET(errno, 0, ENOENT)) {
-                                r = -errno;
-                                goto finish;
+                r = sync_rights(original, gshadow);
+                if (r < 0)
+                        return r;
+
+                errno = 0;
+                while ((sg = fgetsgent(original))) {
+
+                        i = hashmap_get(groups, sg->sg_namp);
+                        if (i && i->todo_group) {
+                                log_error("%s: Group \"%s\" already exists.", gshadow_path, sg->sg_namp);
+                                return -EEXIST;
                         }
-                } else if (errno != ENOENT) {
-                        r = -errno;
-                        goto finish;
-                } else if (fchmod(fileno(shadow), 0000) < 0) {
-                        r = -errno;
-                        goto finish;
-                }
 
-                HASHMAP_FOREACH(i, todo_uids, iterator) {
-                        struct spwd n = {
-                                .sp_namp = i->name,
-                                .sp_pwdp = (char*) "!!",
-                                .sp_lstchg = lstchg,
-                                .sp_min = -1,
-                                .sp_max = -1,
-                                .sp_warn = -1,
-                                .sp_inact = -1,
-                                .sp_expire = -1,
-                                .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
-                        };
+                        r = putsgent_with_members(sg, gshadow);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                group_changed = true;
 
                         errno = 0;
-                        if (putspent(&n, shadow) != 0) {
-                                r = errno ? -errno : -EIO;
-                                goto finish;
-                        }
                 }
+                if (!IN_SET(errno, 0, ENOENT))
+                        return -errno;
+
+        } else {
+                if (errno != ENOENT)
+                        return -errno;
+                if (fchmod(fileno(gshadow), 0000) < 0)
+                        return -errno;
+        }
+
+        HASHMAP_FOREACH(i, todo_gids, iterator) {
+                struct sgrp n = {
+                        .sg_namp = i->name,
+                        .sg_passwd = (char*) "!!",
+                };
 
-                r = fflush_and_check(shadow);
+                r = putsgent_with_members(&n, gshadow);
                 if (r < 0)
-                        goto finish;
+                        return r;
+
+                group_changed = true;
         }
 
-        /* Make a backup of the old files */
+        r = fflush_and_check(gshadow);
+        if (r < 0)
+                return r;
+
         if (group_changed) {
-                if (group) {
-                        r = make_backup("/etc/group", group_path);
-                        if (r < 0)
-                                goto finish;
-                }
-                if (gshadow) {
-                        r = make_backup("/etc/gshadow", gshadow_path);
-                        if (r < 0)
-                                goto finish;
-                }
+                *tmpfile = gshadow;
+                *tmpfile_path = gshadow_tmp;
+                gshadow = NULL;
+                gshadow_tmp = NULL;
+        }
+        return 0;
+#else
+        return 0;
+#endif
+}
+
+static int write_files(void) {
+        _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL;
+        _cleanup_(unlink_and_freep) char *passwd_tmp = NULL, *group_tmp = NULL, *shadow_tmp = NULL, *gshadow_tmp = NULL;
+        const char *passwd_path = NULL, *group_path = NULL, *shadow_path = NULL, *gshadow_path = NULL;
+        int r;
+
+        passwd_path = prefix_roota(arg_root, "/etc/passwd");
+        shadow_path = prefix_roota(arg_root, "/etc/shadow");
+        group_path = prefix_roota(arg_root, "/etc/group");
+        gshadow_path = prefix_roota(arg_root, "/etc/gshadow");
+
+        r = write_temporary_group(group_path, &group, &group_tmp);
+        if (r < 0)
+                return r;
+
+        r = write_temporary_gshadow(gshadow_path, &gshadow, &gshadow_tmp);
+        if (r < 0)
+                return r;
+
+        r = write_temporary_passwd(passwd_path, &passwd, &passwd_tmp);
+        if (r < 0)
+                return r;
+
+        r = write_temporary_shadow(shadow_path, &shadow, &shadow_tmp);
+        if (r < 0)
+                return r;
+
+        /* Make a backup of the old files */
+        if (group) {
+                r = make_backup("/etc/group", group_path);
+                if (r < 0)
+                        return r;
+        }
+        if (gshadow) {
+                r = make_backup("/etc/gshadow", gshadow_path);
+                if (r < 0)
+                        return r;
         }
 
         if (passwd) {
                 r = make_backup("/etc/passwd", passwd_path);
                 if (r < 0)
-                        goto finish;
+                        return r;
         }
         if (shadow) {
                 r = make_backup("/etc/shadow", shadow_path);
                 if (r < 0)
-                        goto finish;
+                        return r;
         }
 
         /* And make the new files count */
-        if (group_changed) {
-                if (group) {
-                        r = rename_and_apply_smack(group_tmp, group_path);
-                        if (r < 0)
-                                goto finish;
+        if (group) {
+                r = rename_and_apply_smack(group_tmp, group_path);
+                if (r < 0)
+                        return r;
 
-                        group_tmp = mfree(group_tmp);
-                }
-                if (gshadow) {
-                        r = rename_and_apply_smack(gshadow_tmp, gshadow_path);
-                        if (r < 0)
-                                goto finish;
+                group_tmp = mfree(group_tmp);
+        }
+        if (gshadow) {
+                r = rename_and_apply_smack(gshadow_tmp, gshadow_path);
+                if (r < 0)
+                        return r;
 
-                        gshadow_tmp = mfree(gshadow_tmp);
-                }
+                gshadow_tmp = mfree(gshadow_tmp);
         }
 
         if (passwd) {
                 r = rename_and_apply_smack(passwd_tmp, passwd_path);
                 if (r < 0)
-                        goto finish;
+                        return r;
 
                 passwd_tmp = mfree(passwd_tmp);
         }
         if (shadow) {
                 r = rename_and_apply_smack(shadow_tmp, shadow_path);
                 if (r < 0)
-                        goto finish;
+                        return r;
 
                 shadow_tmp = mfree(shadow_tmp);
         }
 
-        r = 0;
-
-finish:
-        if (passwd_tmp)
-                unlink(passwd_tmp);
-        if (shadow_tmp)
-                unlink(shadow_tmp);
-        if (group_tmp)
-                unlink(group_tmp);
-        if (gshadow_tmp)
-                unlink(gshadow_tmp);
-
-        return r;
+        return 0;
 }
 
 static int uid_is_ok(uid_t uid, const char *name) {
index 9fde9b18842dc78a57191f16cb82a89d1e149314..98280784439610596454119a2cd4c4d58967b258 100644 (file)
@@ -389,6 +389,9 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co
                                 r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET);
                                 if (r < 0)
                                         return log_oom();
+                                r = strv_extend(&s->wants, SPECIAL_NETWORK_TARGET);
+                                if (r < 0)
+                                        return log_oom();
                         }
 
                         break;
diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py
new file mode 100755 (executable)
index 0000000..357cce8
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+import sys, re
+
+print('#include <stdio.h>')
+for header in sys.argv[2:]:
+    print('#include "{}"'.format(header.split('/')[-1]))
+
+print('''
+void* functions[] = {''')
+
+for line in open(sys.argv[1]):
+    match = re.search('^ +([a-zA-Z0-9_]+);', line)
+    if match:
+        print('    {},'.format(match.group(1)))
+
+print('''};
+
+int main(void) {
+    unsigned i;
+    for (i = 0; i < sizeof(functions)/sizeof(void*); i++)
+         printf("%p\\n", functions[i]);
+    return 0;
+}''')
diff --git a/src/test/meson.build b/src/test/meson.build
new file mode 100644 (file)
index 0000000..7b493a4
--- /dev/null
@@ -0,0 +1,906 @@
+awkscript = 'test-hashmap-ordered.awk'
+test_hashmap_ordered_c = custom_target(
+        'test-hashmap-ordered.c',
+        input : [awkscript, 'test-hashmap-plain.c'],
+        output : 'test-hashmap-ordered.c',
+        command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
+        capture : true)
+
+test_include_dir = include_directories('.')
+
+path = run_command('sh', ['-c', 'echo "$PATH"']).stdout()
+test_env = environment()
+test_env.set('SYSTEMD_KBD_MODEL_MAP', kbd_model_map)
+test_env.set('SYSTEMD_LANGUAGE_FALLBACK_MAP', language_fallback_map)
+test_env.set('PATH', path)
+test_env.prepend('PATH', meson.build_root())
+
+############################################################
+
+generate_sym_test_py = find_program('generate-sym-test.py')
+
+test_libsystemd_sym_c = custom_target(
+        'test-libsystemd-sym.c',
+        input : [libsystemd_sym_path] + systemd_headers,
+        output : 'test-libsystemd-sym.c',
+        command : [generate_sym_test_py, libsystemd_sym_path] + systemd_headers,
+        capture : true)
+
+test_libudev_sym_c = custom_target(
+        'test-libudev-sym.c',
+        input : [libudev_sym_path, libudev_h_path],
+        output : 'test-libudev-sym.c',
+        command : [generate_sym_test_py, '@INPUT0@', '@INPUT1@'],
+        capture : true)
+
+test_dlopen_c = files('test-dlopen.c')
+
+############################################################
+
+tests += [
+        [['src/test/test-device-nodes.c'],
+         [],
+         []],
+
+        [['src/test/test-engine.c'],
+         [libcore,
+          libudev,
+          libsystemd_internal],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-job-type.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-ns.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid],
+         '', 'manual'],
+
+        [['src/test/test-loopback.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-hostname.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid],
+         '', 'unsafe'],
+
+        [['src/test/test-dns-domain.c'],
+         [libcore,
+          libsystemd_network],
+         []],
+
+        [['src/test/test-boot-timestamps.c'],
+         [],
+         [],
+         'ENABLE_EFI'],
+
+        [['src/test/test-unit-name.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-unit-file.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-utf8.c'],
+         [],
+         []],
+
+        [['src/test/test-capability.c'],
+         [],
+         [libcap]],
+
+        [['src/test/test-async.c'],
+         [],
+         []],
+
+        [['src/test/test-locale-util.c'],
+         [],
+         []],
+
+        [['src/test/test-copy.c'],
+         [libshared_static],
+         []],
+
+        [['src/test/test-sigbus.c'],
+         [],
+         []],
+
+        [['src/test/test-condition.c'],
+         [],
+         []],
+
+        [['src/test/test-fdset.c'],
+         [],
+         []],
+
+        [['src/test/test-fstab-util.c'],
+         [],
+         []],
+
+        [['src/test/test-random-util.c'],
+         [],
+         []],
+
+        [['src/test/test-ratelimit.c'],
+         [],
+         []],
+
+        [['src/test/test-util.c'],
+         [],
+         []],
+
+        [['src/test/test-mount-util.c'],
+         [],
+         []],
+
+        [['src/test/test-exec-util.c'],
+         [],
+         []],
+
+        [['src/test/test-hexdecoct.c'],
+         [],
+         []],
+
+        [['src/test/test-alloc-util.c'],
+         [],
+         []],
+
+        [['src/test/test-xattr-util.c'],
+         [],
+         []],
+
+        [['src/test/test-io-util.c'],
+         [],
+         []],
+
+        [['src/test/test-glob-util.c'],
+         [],
+         []],
+
+        [['src/test/test-fs-util.c'],
+         [],
+         []],
+
+        [['src/test/test-proc-cmdline.c'],
+         [],
+         []],
+
+        [['src/test/test-fd-util.c'],
+         [],
+         []],
+
+        [['src/test/test-web-util.c'],
+         [],
+         []],
+
+        [['src/test/test-cpu-set-util.c'],
+         [],
+         []],
+
+        [['src/test/test-stat-util.c'],
+         [],
+         []],
+
+        [['src/test/test-escape.c'],
+         [],
+         []],
+
+        [['src/test/test-string-util.c'],
+         [],
+         []],
+
+        [['src/test/test-extract-word.c'],
+         [],
+         []],
+
+        [['src/test/test-parse-util.c'],
+         [],
+         []],
+
+        [['src/test/test-user-util.c'],
+         [],
+         []],
+
+        [['src/test/test-hostname-util.c'],
+         [],
+         []],
+
+        [['src/test/test-process-util.c'],
+         [],
+         []],
+
+        [['src/test/test-terminal-util.c'],
+         [],
+         []],
+
+        [['src/test/test-path-lookup.c'],
+         [],
+         []],
+
+        [['src/test/test-uid-range.c'],
+         [],
+         []],
+
+        [['src/test/test-cap-list.c',
+          generated_gperf_headers],
+         [],
+         [libcap]],
+
+        [['src/test/test-socket-util.c'],
+         [],
+         []],
+
+        [['src/test/test-barrier.c'],
+         [],
+         []],
+
+        [['src/test/test-tmpfiles.c'],
+         [],
+         []],
+
+        [['src/test/test-namespace.c'],
+         [libcore,
+          libshared],
+         [threads,
+          libblkid]],
+
+        [['src/test/test-verbs.c'],
+         [],
+         []],
+
+        [['src/test/test-install-root.c'],
+         [],
+         []],
+
+        [['src/test/test-acl-util.c'],
+         [],
+         [],
+         'HAVE_ACL'],
+
+        [['src/test/test-seccomp.c'],
+         [],
+         [libseccomp],
+         'HAVE_SECCOMP'],
+
+        [['src/test/test-rlimit-util.c'],
+         [],
+         []],
+
+        [['src/test/test-ask-password-api.c'],
+         [],
+         [],
+         '', 'manual'],
+
+        [['src/test/test-dissect-image.c'],
+         [],
+         [libblkid],
+         '', 'manual'],
+
+        [['src/test/test-signal-util.c'],
+         [],
+         []],
+
+        [['src/test/test-selinux.c'],
+         [],
+         []],
+
+        [['src/test/test-sizeof.c'],
+         [libbasic],
+         []],
+
+        [['src/test/test-hashmap.c',
+          'src/test/test-hashmap-plain.c',
+          test_hashmap_ordered_c],
+         [],
+         [],
+         '', 'timeout=90'],
+
+        [['src/test/test-set.c'],
+         [],
+         []],
+
+        [['src/test/test-bitmap.c'],
+         [],
+         []],
+
+        [['src/test/test-xml.c'],
+         [],
+         []],
+
+        [['src/test/test-list.c'],
+         [],
+         []],
+
+        [['src/test/test-unaligned.c'],
+         [],
+         []],
+
+        [['src/test/test-tables.c',
+          'src/shared/test-tables.h',
+          'src/journal/journald-server.c',
+          'src/journal/journald-server.h'],
+         [libcore,
+          libjournal_core,
+          libudev_core,
+          libudev_internal,
+          libsystemd_network,
+          libshared],
+         [threads,
+          libseccomp,
+          libmount,
+          libxz,
+          liblz4,
+          libblkid],
+         '', '', [], libudev_core_includes],
+
+        [['src/test/test-prioq.c'],
+         [],
+         []],
+
+        [['src/test/test-fileio.c'],
+         [],
+         []],
+
+        [['src/test/test-time.c'],
+         [],
+         []],
+
+        [['src/test/test-clock.c'],
+         [],
+         []],
+
+        [['src/test/test-architecture.c'],
+         [],
+         []],
+
+        [['src/test/test-log.c'],
+         [],
+         []],
+
+        [['src/test/test-ipcrm.c'],
+         [],
+         [],
+         '', 'unsafe'],
+
+        [['src/test/test-btrfs.c'],
+         [],
+         [],
+         '', 'manual'],
+
+
+        [['src/test/test-firewall-util.c'],
+         [libshared],
+         [],
+         'HAVE_LIBIPTC'],
+
+        [['src/test/test-netlink-manual.c'],
+         [],
+         [libkmod],
+         'HAVE_KMOD', 'manual'],
+
+        [['src/test/test-ellipsize.c'],
+         [],
+         []],
+
+        [['src/test/test-date.c'],
+         [],
+         []],
+
+        [['src/test/test-sleep.c'],
+         [],
+         []],
+
+        [['src/test/test-replace-var.c'],
+         [],
+         []],
+
+        [['src/test/test-calendarspec.c'],
+         [],
+         []],
+
+        [['src/test/test-strip-tab-ansi.c'],
+         [],
+         []],
+
+        [['src/test/test-daemon.c'],
+         [],
+         []],
+
+        [['src/test/test-cgroup.c'],
+         [],
+         [],
+         '', 'manual'],
+
+
+        [['src/test/test-cgroup-mask.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-cgroup-util.c'],
+         [],
+         []],
+
+        [['src/test/test-env-util.c'],
+         [],
+         []],
+
+        [['src/test/test-strbuf.c'],
+         [],
+         []],
+
+        [['src/test/test-strv.c'],
+         [],
+         []],
+
+        [['src/test/test-path-util.c'],
+         [],
+         []],
+
+        [['src/test/test-path.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-execute.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-siphash24.c'],
+         [],
+         []],
+
+        [['src/test/test-strxcpyx.c'],
+         [],
+         []],
+
+        [['src/test/test-install.c'],
+         [libcore,
+          libshared],
+         [],
+         '', 'manual'],
+
+        [['src/test/test-watchdog.c'],
+         [],
+         []],
+
+        [['src/test/test-sched-prio.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid]],
+
+        [['src/test/test-conf-files.c'],
+         [],
+         []],
+
+        [['src/test/test-conf-parser.c'],
+         [],
+         []],
+
+        [['src/test/test-af-list.c',
+          generated_gperf_headers],
+         [],
+         []],
+
+        [['src/test/test-arphrd-list.c',
+          generated_gperf_headers],
+         [],
+         []],
+
+        [['src/test/test-journal-importer.c'],
+         [],
+         []],
+
+        [['src/test/test-libudev.c'],
+         [libshared],
+         []],
+
+        [['src/test/test-udev.c'],
+         [libudev_core,
+          libudev_internal,
+          libsystemd_network,
+          libshared],
+         [threads,
+          librt,
+          libblkid,
+          libkmod,
+          libacl],
+         '', 'manual'],
+
+        [['src/test/test-id128.c'],
+         [],
+         []],
+
+        [['src/test/test-hash.c'],
+         [],
+         []],
+
+        [['src/test/test-nss.c'],
+         [],
+         [libdl],
+         '', 'manual'],
+]
+
+############################################################
+
+# define some tests here, because the link_with deps were not defined earlier
+
+tests += [
+        [['src/journal/test-journal.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-send.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-syslog.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4,
+          libselinux]],
+
+        [['src/journal/test-journal-match.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-enum.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-stream.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-flush.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-init.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-verify.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-journal-interleaving.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-mmap-cache.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4]],
+
+        [['src/journal/test-catalog.c'],
+         [libjournal_core,
+          libshared],
+         [threads,
+          libxz,
+          liblz4],
+         '', '', '-DCATALOG_DIR="@0@"'.format(build_catalog_dir)],
+
+        [['src/journal/test-compress.c'],
+         [libjournal_core,
+          libshared],
+         [liblz4,
+          libxz]],
+
+        [['src/journal/test-compress-benchmark.c'],
+         [libjournal_core,
+          libshared],
+         [liblz4,
+          libxz],
+         '', 'timeout=90'],
+
+        [['src/journal/test-audit-type.c'],
+         [libjournal_core,
+          libshared],
+         [liblz4,
+          libxz]],
+]
+
+############################################################
+
+tests += [
+        [['src/libsystemd/sd-bus/test-bus-marshal.c'],
+         [],
+         [threads,
+          libglib,
+          libgobject,
+          libgio,
+          libdbus]],
+
+        [['src/libsystemd/sd-bus/test-bus-signature.c'],
+         [],
+         [threads]],
+
+        [['src/libsystemd/sd-bus/test-bus-chat.c'],
+         [],
+         [threads]],
+
+        [['src/libsystemd/sd-bus/test-bus-cleanup.c'],
+         [],
+         [threads,
+          libseccomp]],
+
+        [['src/libsystemd/sd-bus/test-bus-error.c'],
+         [libshared_static,
+          libsystemd_internal],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-track.c'],
+         [],
+         [libseccomp]],
+
+        [['src/libsystemd/sd-bus/test-bus-server.c'],
+         [],
+         [threads]],
+
+        [['src/libsystemd/sd-bus/test-bus-objects.c'],
+         [],
+         [threads]],
+
+        [['src/libsystemd/sd-bus/test-bus-vtable.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-gvariant.c'],
+         [],
+         [libglib,
+          libgobject,
+          libgio]],
+
+        [['src/libsystemd/sd-bus/test-bus-creds.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-match.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-kernel.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-kernel-bloom.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-benchmark.c'],
+         [],
+         [threads]],
+
+        [['src/libsystemd/sd-bus/test-bus-zero-copy.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-bus/test-bus-introspect.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-event/test-event.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-netlink/test-netlink.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-netlink/test-local-addresses.c'],
+         [],
+         []],
+
+        [['src/libsystemd/sd-resolve/test-resolve.c'],
+         [],
+         [threads]],
+
+        [['src/libsystemd/sd-login/test-login.c'],
+         [],
+         []],
+]
+
+if cxx.found()
+        tests += [
+                [['src/libsystemd/sd-bus/test-bus-vtable-cc.cc'],
+                 [],
+                 []]
+        ]
+endif
+
+############################################################
+
+tests += [
+        [['src/libsystemd-network/test-dhcp-option.c',
+          'src/libsystemd-network/dhcp-protocol.h',
+          'src/libsystemd-network/dhcp-internal.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-sd-dhcp-lease.c',
+          'src/libsystemd-network/dhcp-lease-internal.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-dhcp-client.c',
+          'src/libsystemd-network/dhcp-protocol.h',
+          'src/libsystemd-network/dhcp-internal.h',
+          'src/systemd/sd-dhcp-client.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-dhcp-server.c'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-ipv4ll.c',
+          'src/libsystemd-network/arp-util.h',
+          'src/systemd/sd-ipv4ll.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-ipv4ll-manual.c',
+          'src/systemd/sd-ipv4ll.h'],
+         [libshared,
+          libsystemd_network],
+         [],
+         '', 'manual'],
+
+        [['src/libsystemd-network/test-acd.c',
+          'src/systemd/sd-ipv4acd.h'],
+         [libshared,
+          libsystemd_network],
+         [],
+         '', 'manual'],
+
+        [['src/libsystemd-network/test-ndisc-rs.c',
+          'src/libsystemd-network/dhcp-identifier.h',
+          'src/libsystemd-network/dhcp-identifier.c',
+          'src/libsystemd-network/icmp6-util.h',
+          'src/systemd/sd-dhcp6-client.h',
+          'src/systemd/sd-ndisc.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-ndisc-ra.c',
+          'src/libsystemd-network/icmp6-util.h',
+          'src/systemd/sd-ndisc.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-dhcp6-client.c',
+          'src/libsystemd-network/dhcp-identifier.h',
+          'src/libsystemd-network/dhcp-identifier.c',
+          'src/libsystemd-network/dhcp6-internal.h',
+          'src/systemd/sd-dhcp6-client.h'],
+         [libshared,
+          libsystemd_network],
+         []],
+
+        [['src/libsystemd-network/test-lldp.c'],
+         [libshared,
+          libsystemd_network],
+         []],
+]
+
+############################################################
+
+tests += [
+        [['src/login/test-login-shared.c'],
+         [],
+         []],
+
+        [['src/login/test-inhibit.c'],
+         [],
+         [],
+         '', 'manual'],
+
+        [['src/login/test-login-tables.c'],
+         [liblogind_core,
+          libshared],
+         [threads]],
+]
index e5ca54c8e7873a169692e3e89f7a6e0d07d463ce..bbaf18b08a2e1064d7ca1793b6b7000e42c8f32e 100644 (file)
@@ -24,7 +24,7 @@
 #include "string-util.h"
 #include "util.h"
 
-_unused_ \
+_unused_
 static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len);
 
 #include "af-from-name.h"
index f90b73aeaf31862e6540bd55c4daf6c65cb088d5..a026ce4ef12d2370aee361d01d33391d7d0282f2 100644 (file)
@@ -193,6 +193,11 @@ int main(int argc, char* argv[]) {
         test_one("*:20..39/5", "*-*-* *:20..35/5:00");
         test_one("00:00:20..40/1", "*-*-* 00:00:20..40");
         test_one("*~03/1,03..05", "*-*~03/1,03..05 00:00:00");
+        /* UNIX timestamps are always UTC */
+        test_one("@1493187147", "2017-04-26 06:12:27 UTC");
+        test_one("@1493187147 UTC", "2017-04-26 06:12:27 UTC");
+        test_one("@0", "1970-01-01 00:00:00 UTC");
+        test_one("@0 UTC", "1970-01-01 00:00:00 UTC");
 
         test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
         test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
index dd985f58634fac1691bf7a25307e2927219ffba7..121345cfd1c72a4a666f812fd3c954ff814af8b8 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include "sd-id128.h"
 
 #include "alloc-util.h"
@@ -34,6 +38,7 @@
 #include "strv.h"
 #include "virt.h"
 #include "util.h"
+#include "user-util.h"
 
 static void test_condition_test_path(void) {
         Condition *condition;
@@ -243,7 +248,7 @@ static void test_condition_test_security(void) {
 
         condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
         assert_se(condition);
-        assert_se(condition_test(condition) != mac_selinux_have());
+        assert_se(condition_test(condition) != mac_selinux_use());
         condition_free(condition);
 
         condition = condition_new(CONDITION_SECURITY, "ima", false, false);
@@ -323,6 +328,150 @@ static void test_condition_test_virtualization(void) {
         }
 }
 
+static void test_condition_test_user(void) {
+        Condition *condition;
+        char* uid;
+        char* username;
+        int r;
+
+        condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=garbage → %i", r);
+        assert_se(r == 0);
+        condition_free(condition);
+
+        assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0);
+        condition = condition_new(CONDITION_USER, uid, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=%s → %i", uid, r);
+        assert_se(r == 0);
+        condition_free(condition);
+        free(uid);
+
+        assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0);
+        condition = condition_new(CONDITION_USER, uid, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=%s → %i", uid, r);
+        assert_se(r > 0);
+        condition_free(condition);
+        free(uid);
+
+        assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0);
+        condition = condition_new(CONDITION_USER, uid, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=%s → %i", uid, r);
+        assert_se(r == 0);
+        condition_free(condition);
+        free(uid);
+
+        username = getusername_malloc();
+        assert_se(username);
+        condition = condition_new(CONDITION_USER, username, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=%s → %i", username, r);
+        assert_se(r > 0);
+        condition_free(condition);
+        free(username);
+
+        username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root");
+        condition = condition_new(CONDITION_USER, username, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=%s → %i", username, r);
+        assert_se(r == 0);
+        condition_free(condition);
+
+        condition = condition_new(CONDITION_USER, "@system", false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionUser=@system → %i", r);
+        if (geteuid() == 0)
+                assert_se(r > 0);
+        else
+                assert_se(r == 0);
+        condition_free(condition);
+}
+
+static void test_condition_test_group(void) {
+        Condition *condition;
+        char* gid;
+        char* groupname;
+        gid_t *gids, max_gid;
+        int ngroups_max, r, i;
+
+        assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF)));
+        condition = condition_new(CONDITION_GROUP, gid, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionGroup=%s → %i", gid, r);
+        assert_se(r == 0);
+        condition_free(condition);
+        free(gid);
+
+        assert_se(0 < asprintf(&gid, "%u", getgid()));
+        condition = condition_new(CONDITION_GROUP, gid, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionGroup=%s → %i", gid, r);
+        assert_se(r > 0);
+        condition_free(condition);
+        free(gid);
+
+        ngroups_max = sysconf(_SC_NGROUPS_MAX);
+        assert(ngroups_max > 0);
+
+        gids = alloca(sizeof(gid_t) * ngroups_max);
+
+        r = getgroups(ngroups_max, gids);
+        assert(r >= 0);
+
+        max_gid = getgid();
+        for (i = 0; i < r; i++) {
+                assert_se(0 < asprintf(&gid, "%u", gids[i]));
+                condition = condition_new(CONDITION_GROUP, gid, false, false);
+                assert_se(condition);
+                r = condition_test(condition);
+                log_info("ConditionGroup=%s → %i", gid, r);
+                assert_se(r > 0);
+                condition_free(condition);
+                free(gid);
+                max_gid = gids[i] > max_gid ? gids[i] : max_gid;
+
+                groupname = gid_to_name(gids[i]);
+                assert_se(groupname);
+                condition = condition_new(CONDITION_GROUP, groupname, false, false);
+                assert_se(condition);
+                r = condition_test(condition);
+                log_info("ConditionGroup=%s → %i", groupname, r);
+                assert_se(r > 0);
+                condition_free(condition);
+                free(groupname);
+                max_gid = gids[i] > max_gid ? gids[i] : max_gid;
+        }
+
+        assert_se(0 < asprintf(&gid, "%u", max_gid+1));
+        condition = condition_new(CONDITION_GROUP, gid, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionGroup=%s → %i", gid, r);
+        assert_se(r == 0);
+        condition_free(condition);
+        free(gid);
+
+        groupname = (char*)(geteuid() == 0 ? NOBODY_GROUP_NAME : "root");
+        condition = condition_new(CONDITION_GROUP, groupname, false, false);
+        assert_se(condition);
+        r = condition_test(condition);
+        log_info("ConditionGroup=%s → %i", groupname, r);
+        assert_se(r == 0);
+        condition_free(condition);
+}
+
 int main(int argc, char *argv[]) {
         log_set_max_level(LOG_DEBUG);
         log_parse_environment();
@@ -336,6 +485,8 @@ int main(int argc, char *argv[]) {
         test_condition_test_null();
         test_condition_test_security();
         test_condition_test_virtualization();
+        test_condition_test_user();
+        test_condition_test_group();
 
         return 0;
 }
index be5d2611f89e8a155bfd21d0fa20b9d47a7caae4..77fcbc0dd3399aca7228d37d90a2a55a7f6a952a 100644 (file)
@@ -109,8 +109,10 @@ static void test_config_parse_path(void) {
         test_config_parse_path_one("/path", "/path");
         test_config_parse_path_one("/path//////////", "/path");
         test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar");
+        test_config_parse_path_one("/path/\xc3\x80", "/path/\xc3\x80");
 
         test_config_parse_path_one("not_absolute/path", NULL);
+        test_config_parse_path_one("/path/\xc3\x7f", NULL);
 }
 
 static void test_config_parse_log_level(void) {
@@ -180,6 +182,8 @@ static void test_config_parse_strv(void) {
         test_config_parse_strv_one("foo", STRV_MAKE("foo"));
         test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo"));
         test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo"));
+        test_config_parse_strv_one("\xc3\x80", STRV_MAKE("\xc3\x80"));
+        test_config_parse_strv_one("\xc3\x7f", STRV_MAKE_EMPTY);
 }
 
 static void test_config_parse_mode(void) {
index b77598c81dd090f579dcd4c929a7c1b13c044135..0e7d44fade9f5d1e03e3d82c7d5642b7e642027c 100644 (file)
 
 static void test_should_pass(const char *p) {
         usec_t t, q;
-        char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *sp;
+        char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
 
+        log_info("Test: %s", p);
         assert_se(parse_timestamp(p, &t) >= 0);
-        format_timestamp_us(buf, sizeof(buf), t);
-        log_info("%s", buf);
-
-        /* Chop off timezone */
-        sp = strrchr(buf, ' ');
-        assert_se(sp);
-        *sp = 0;
+        assert_se(format_timestamp_us(buf, sizeof(buf), t));
+        log_info("\"%s\" → \"%s\"", p, buf);
 
         assert_se(parse_timestamp(buf, &q) >= 0);
         assert_se(q == t);
 
-        format_timestamp_relative(buf_relative, sizeof(buf_relative), t);
+        assert_se(format_timestamp_relative(buf_relative, sizeof(buf_relative), t));
         log_info("%s", strna(buf_relative));
-        assert_se(parse_timestamp(buf, &q) >= 0);
 }
 
 static void test_should_parse(const char *p) {
         usec_t t;
 
+        log_info("Test: %s", p);
         assert_se(parse_timestamp(p, &t) >= 0);
+        log_info("\"%s\" → \"@%" PRI_USEC "\"", p, t);
 }
 
 static void test_should_fail(const char *p) {
         usec_t t;
+        int r;
 
-        assert_se(parse_timestamp(p, &t) < 0);
+        log_info("Test: %s", p);
+        r = parse_timestamp(p, &t);
+        if (r >= 0)
+                log_info("\"%s\" → \"@%" PRI_USEC "\" (unexpected)", p, t);
+        else
+                log_info("parse_timestamp() returns %d (expected)", r);
+        assert_se(r < 0);
 }
 
 static void test_one(const char *p) {
         _cleanup_free_ char *with_utc;
 
-        log_info("Test: %s", p);
         with_utc = strjoin(p, " UTC");
         test_should_pass(p);
         test_should_pass(with_utc);
@@ -68,7 +71,6 @@ static void test_one(const char *p) {
 static void test_one_noutc(const char *p) {
         _cleanup_free_ char *with_utc;
 
-        log_info("Test: %s", p);
         with_utc = strjoin(p, " UTC");
         test_should_pass(p);
         test_should_fail(with_utc);
@@ -85,25 +87,26 @@ int main(int argc, char *argv[]) {
         test_one("2012-12-30 18:42");
         test_one("2012-10-02");
         test_one("Tue 2012-10-02");
-        test_one_noutc("now");
         test_one("yesterday");
         test_one("today");
         test_one("tomorrow");
+        test_one_noutc("now");
         test_one_noutc("+2d");
         test_one_noutc("+2y 4d");
         test_one_noutc("5months ago");
         test_one_noutc("@1395716396");
-        test_should_parse("today UTC");
-        test_should_fail("today UTC UTC");
         test_should_parse("1970-1-1 UTC");
-        test_should_fail("1969-1-1 UTC");
+        test_should_pass("1970-1-1 00:00:01 UTC");
+        test_should_fail("1969-12-31 UTC");
+        test_should_fail("-100y");
+        test_should_fail("today UTC UTC");
 #if SIZEOF_TIME_T == 8
-        test_should_parse("9999-12-30 23:59:59 UTC");
+        test_should_pass("9999-12-30 23:59:59 UTC");
         test_should_fail("9999-12-31 00:00:00 UTC");
         test_should_fail("10000-01-01 00:00:00 UTC");
 #elif SIZEOF_TIME_T == 4
-        test_should_parse("2038-01-19 03:14:07 UTC");
-        test_should_fail( "2038-01-19 03:14:08 UTC");
+        test_should_pass("2038-01-19 03:14:07 UTC");
+        test_should_fail("2038-01-19 03:14:08 UTC");
 #endif
 
         return 0;
diff --git a/src/test/test-dlopen.c b/src/test/test-dlopen.c
new file mode 100644 (file)
index 0000000..9f5343a
--- /dev/null
@@ -0,0 +1,32 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 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 <dlfcn.h>
+#include <stdlib.h>
+
+#include "macro.h"
+
+int main(int argc, char **argv) {
+        void *handle;
+
+        assert_se((handle = dlopen(argv[1], RTLD_NOW)));
+        assert_se(dlclose(handle) == 0);
+
+        return EXIT_SUCCESS;
+}
index a7cd8e4b5131874d62b5535c1afd6d62941d50d9..11cf0b1f0b2459ed543975a6348bf9507eed7594 100644 (file)
@@ -607,24 +607,53 @@ static void test_dns_name_common_suffix(void) {
         test_dns_name_common_suffix_one("FOO.BAR", "tEST.bAR", "BAR");
 }
 
-static void test_dns_name_apply_idna_one(const char *s, const char *result) {
-#ifdef HAVE_LIBIDN
+static void test_dns_name_apply_idna_one(const char *s, int expected, const char *result) {
         _cleanup_free_ char *buf = NULL;
-        assert_se(dns_name_apply_idna(s, &buf) >= 0);
-        assert_se(dns_name_equal(buf, result) > 0);
-#endif
+        int r;
+
+        r = dns_name_apply_idna(s, &buf);
+        log_debug("dns_name_apply_idna: \"%s\" → %d/\"%s\" (expected %d/\"%s\")",
+                  s, r, strnull(buf), expected, strnull(result));
+
+        assert_se(r == expected);
+        if (expected == 1)
+                assert_se(dns_name_equal(buf, result) == 1);
 }
 
 static void test_dns_name_apply_idna(void) {
-        test_dns_name_apply_idna_one("", "");
-        test_dns_name_apply_idna_one("foo", "foo");
-        test_dns_name_apply_idna_one("foo.", "foo");
-        test_dns_name_apply_idna_one("foo.bar", "foo.bar");
-        test_dns_name_apply_idna_one("foo.bar.", "foo.bar");
-        test_dns_name_apply_idna_one("föö", "xn--f-1gaa");
-        test_dns_name_apply_idna_one("föö.", "xn--f-1gaa");
-        test_dns_name_apply_idna_one("föö.bär", "xn--f-1gaa.xn--br-via");
-        test_dns_name_apply_idna_one("föö.bär.", "xn--f-1gaa.xn--br-via");
+#if defined HAVE_LIBIDN2 || defined HAVE_LIBIDN
+        const int ret = 1;
+#else
+        const int ret = 0;
+#endif
+
+        /* IDNA2008 forbids names with hyphens in third and fourth positions
+         * (https://tools.ietf.org/html/rfc5891#section-4.2.3.1).
+         * IDNA2003 does not have this restriction
+         * (https://tools.ietf.org/html/rfc3490#section-5).
+         * This means that when using libidn we will transform and test more
+         * labels. If registrars follow IDNA2008 we'll just be performing a
+         * useless lookup.
+         */
+#if defined HAVE_LIBIDN
+        const int ret2 = 1;
+#else
+        const int ret2 = 0;
+#endif
+
+        test_dns_name_apply_idna_one("", ret, "");
+        test_dns_name_apply_idna_one("foo", ret, "foo");
+        test_dns_name_apply_idna_one("foo.", ret, "foo");
+        test_dns_name_apply_idna_one("foo.bar", ret, "foo.bar");
+        test_dns_name_apply_idna_one("foo.bar.", ret, "foo.bar");
+        test_dns_name_apply_idna_one("föö", ret, "xn--f-1gaa");
+        test_dns_name_apply_idna_one("föö.", ret, "xn--f-1gaa");
+        test_dns_name_apply_idna_one("föö.bär", ret, "xn--f-1gaa.xn--br-via");
+        test_dns_name_apply_idna_one("föö.bär.", ret, "xn--f-1gaa.xn--br-via");
+        test_dns_name_apply_idna_one("xn--f-1gaa.xn--br-via", ret, "xn--f-1gaa.xn--br-via");
+
+        test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", ret2,
+                                     ret2 ? "r3---sn-ab5l6ne7.googlevideo.com" : "");
 }
 
 static void test_dns_name_is_valid_or_address(void) {
@@ -640,6 +669,9 @@ static void test_dns_name_is_valid_or_address(void) {
 }
 
 int main(int argc, char *argv[]) {
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
 
         test_dns_label_unescape();
         test_dns_label_unescape_suffix();
index e5cc2a2df85c2bd191b106fe25b6db6e8d0172a4..3a2492dc6fd569374952185fe6c8d6f3ffc54be8 100644 (file)
@@ -21,6 +21,8 @@
 #include <string.h>
 
 #include "env-util.h"
+#include "fd-util.h"
+#include "fileio.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
@@ -314,6 +316,57 @@ static void test_env_assignment_is_valid(void) {
         assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));
 }
 
+static void test_deserialize_environment(void) {
+        _cleanup_strv_free_ char **env = strv_new("A=1", NULL);
+
+        assert_se(deserialize_environment(&env, "env=test") < 0);
+        assert_se(deserialize_environment(&env, "env=B=2") >= 0);
+
+        assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2")));
+}
+
+static void test_serialize_environment(void) {
+        char fn[] = "/tmp/test-env-util.XXXXXXX";
+        int fd, r;
+        _cleanup_fclose_ FILE *f = NULL;
+
+        _cleanup_strv_free_ char **env = strv_new("A=1",
+                                                  "B=2",
+                                                  "C=ąęółń",
+                                                  "D=D=a\\x0Ab",
+                                                  NULL);
+        _cleanup_strv_free_ char **env2 = NULL;
+
+        fd = mkostemp_safe(fn);
+        assert_se(fd >= 0);
+
+        assert_se(f = fdopen(fd, "r+"));
+
+        assert_se(serialize_environment(f, env) == 0);
+        assert_se(fflush_and_check(f) == 0);
+
+        rewind(f);
+
+        for (;;) {
+                char line[LINE_MAX];
+                const char *l;
+
+                if (!fgets(line, sizeof line, f))
+                        break;
+
+                char_array_0(line);
+                l = strstrip(line);
+
+                r = deserialize_environment(&env2, l);
+                assert_se(r == 1);
+        }
+        assert_se(feof(f));
+
+        assert_se(strv_equal(env, env2));
+
+        unlink(fn);
+}
+
 int main(int argc, char *argv[]) {
         test_strv_env_delete();
         test_strv_env_get();
@@ -330,6 +383,8 @@ int main(int argc, char *argv[]) {
         test_env_name_is_valid();
         test_env_value_is_valid();
         test_env_assignment_is_valid();
+        test_deserialize_environment();
+        test_serialize_environment();
 
         return 0;
 }
index 6cbb8443fe2c682957a5dd98af643f34ffaf780d..d060afaffa7b076d5e61a309924f497ae85a2baf 100644 (file)
@@ -69,6 +69,14 @@ static void test_cunescape(void) {
 
         assert_se(cunescape("\\073", 0, &unescaped) >= 0);
         assert_se(streq_ptr(unescaped, ";"));
+        unescaped = mfree(unescaped);
+
+        assert_se(cunescape("A=A\\\\x0aB", 0, &unescaped) >= 0);
+        assert_se(streq_ptr(unescaped, "A=A\\x0aB"));
+        unescaped = mfree(unescaped);
+
+        assert_se(cunescape("A=A\\\\x0aB", UNESCAPE_RELAX, &unescaped) >= 0);
+        assert_se(streq_ptr(unescaped, "A=A\\x0aB"));
 }
 
 static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
@@ -86,25 +94,52 @@ static void test_shell_escape(void) {
         test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
 }
 
-static void test_shell_maybe_quote_one(const char *s, const char *expected) {
-        _cleanup_free_ char *r;
+static void test_shell_maybe_quote_one(const char *s,
+                                       EscapeStyle style,
+                                       const char *expected) {
+        _cleanup_free_ char *ret = NULL;
 
-        assert_se(r = shell_maybe_quote(s));
-        assert_se(streq(r, expected));
+        assert_se(ret = shell_maybe_quote(s, style));
+        log_debug("[%s] → [%s] (%s)", s, ret, expected);
+        assert_se(streq(ret, expected));
 }
 
 static void test_shell_maybe_quote(void) {
 
-        test_shell_maybe_quote_one("", "");
-        test_shell_maybe_quote_one("\\", "\"\\\\\"");
-        test_shell_maybe_quote_one("\"", "\"\\\"\"");
-        test_shell_maybe_quote_one("foobar", "foobar");
-        test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
-        test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
-        test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
+        test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, "");
+        test_shell_maybe_quote_one("", ESCAPE_POSIX, "");
+        test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\"");
+        test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'");
+        test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\"");
+        test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'");
+        test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar");
+        test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar");
+        test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\"");
+        test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'");
+        test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\"");
+        test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'");
+        test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\"");
+        test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'");
+        test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\"");
+        test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'");
+        test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\"");
+        test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'");
+
+        /* Note that current users disallow control characters, so this "test"
+         * is here merely to establish current behaviour. If control characters
+         * were allowed, they should be quoted, i.e. \001 should become \\001. */
+        test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\"");
+        test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'");
+
+        test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\"");
+        test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'");
 }
 
 int main(int argc, char *argv[]) {
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
         test_cescape();
         test_cunescape();
         test_shell_escape();
index 482b0751b938519509b92e1136d289946b5f0e56..30c92019d910a52d908c5e17e96a5e5179cd8128 100644 (file)
@@ -223,7 +223,7 @@ static int gather_stdout_three(int fd, void *arg) {
         return 0;
 }
 
-const gather_stdout_callback_t const gather_stdout[] = {
+const gather_stdout_callback_t gather_stdout[] = {
         gather_stdout_one,
         gather_stdout_two,
         gather_stdout_three,
index 90540b884bf8ef78df6064d1baf9ac7145e5ddfb..29c8fd613f070866c83a00590dde819628b1fa11 100644 (file)
@@ -233,6 +233,15 @@ static void test_exec_inaccessiblepaths(Manager *m) {
         test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
 }
 
+static void test_exec_inaccessiblepaths_proc(Manager *m) {
+        if (!is_inaccessible_available()) {
+                log_notice("testing without inaccessible, skipping %s", __func__);
+                return;
+        }
+
+        test(m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
+}
+
 static void test_exec_systemcallfilter(Manager *m) {
 #ifdef HAVE_SECCOMP
         if (!is_seccomp_available())
@@ -479,6 +488,7 @@ int main(int argc, char *argv[]) {
                 test_exec_readonlypaths,
                 test_exec_readwritepaths,
                 test_exec_inaccessiblepaths,
+                test_exec_inaccessiblepaths_proc,
                 test_exec_privatenetwork,
                 test_exec_systemcallfilter,
                 test_exec_systemcallerrornumber,
index e774f567e0307f8881fcd11bde724242144a9d4c..9e964a8bbb3c289f2991009a3e3731918ba7b6a2 100644 (file)
@@ -317,8 +317,8 @@ static void test_dot_or_dot_dot(void) {
 
 int main(int argc, char *argv[]) {
         test_unlink_noerrno();
-        test_readlink_and_make_absolute();
         test_get_files_in_directory();
+        test_readlink_and_make_absolute();
         test_var_tmp();
         test_chase_symlinks();
         test_dot_or_dot_dot();
index 9eea3eb608bf36925ccb176dc5dd9cf39088a207..af866e004b9bad6c34e4ff9da9d0fa268a78f119 100644 (file)
 ***/
 
 #include <fcntl.h>
+#include <glob.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "dirent-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "glob-util.h"
 #include "macro.h"
+#include "rm-rf.h"
 
 static void test_glob_exists(void) {
         char name[] = "/tmp/test-glob_exists.XXXXXX";
@@ -43,8 +48,69 @@ static void test_glob_exists(void) {
         assert_se(r == 0);
 }
 
+static void test_glob_no_dot(void) {
+        char template[] = "/tmp/test-glob-util.XXXXXXX";
+        const char *fn;
+
+        _cleanup_globfree_ glob_t g = {
+                .gl_closedir = (void (*)(void *)) closedir,
+                .gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot,
+                .gl_opendir = (void *(*)(const char *)) opendir,
+                .gl_lstat = lstat,
+                .gl_stat = stat,
+        };
+
+        int r;
+
+        assert_se(mkdtemp(template));
+
+        fn = strjoina(template, "/*");
+        r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
+        assert_se(r == GLOB_NOMATCH);
+
+        fn = strjoina(template, "/.*");
+        r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
+        assert_se(r == GLOB_NOMATCH);
+
+        (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
+static void test_safe_glob(void) {
+        char template[] = "/tmp/test-glob-util.XXXXXXX";
+        const char *fn, *fn2, *fname;
+
+        _cleanup_globfree_ glob_t g = {};
+        int r;
+
+        assert_se(mkdtemp(template));
+
+        fn = strjoina(template, "/*");
+        r = safe_glob(fn, 0, &g);
+        assert_se(r == -ENOENT);
+
+        fn2 = strjoina(template, "/.*");
+        r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g);
+        assert_se(r == -ENOENT);
+
+        fname = strjoina(template, "/.foobar");
+        assert_se(touch(fname) == 0);
+
+        r = safe_glob(fn, 0, &g);
+        assert_se(r == -ENOENT);
+
+        r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g);
+        assert_se(r == 0);
+        assert_se(g.gl_pathc == 1);
+        assert_se(streq(g.gl_pathv[0], fname));
+        assert_se(g.gl_pathv[1] == NULL);
+
+        (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
 int main(void) {
         test_glob_exists();
+        test_glob_no_dot();
+        test_safe_glob();
 
         return 0;
 }
index 1972b94cfe89ad617f5b7da153b9d684e2b4127a..02d1cfaee30a3d19e5672571625417683d3b929f 100644 (file)
@@ -17,6 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdio.h>
+
 #include "alloc-util.h"
 #include "log.h"
 #include "string-util.h"
 int main(int argc, char *argv[]) {
         _cleanup_(khash_unrefp) khash *h = NULL, *copy = NULL;
         _cleanup_free_ char *s = NULL;
+        int r;
 
         log_set_max_level(LOG_DEBUG);
 
         assert_se(khash_new(&h, NULL) == -EINVAL);
         assert_se(khash_new(&h, "") == -EINVAL);
-        assert_se(khash_new(&h, "foobar") == -EOPNOTSUPP);
+        r = khash_new(&h, "foobar");
+        if (r == -EAFNOSUPPORT) {
+                puts("khash not supported on this kernel, skipping");
+                return EXIT_TEST_SKIP;
+        }
+        assert_se(r == -EOPNOTSUPP);
 
         assert_se(khash_new(&h, "sha256") >= 0);
         assert_se(khash_get_size(h) == 32);
diff --git a/src/test/test-hashmap-ordered.awk b/src/test/test-hashmap-ordered.awk
new file mode 100644 (file)
index 0000000..10f4386
--- /dev/null
@@ -0,0 +1,11 @@
+BEGIN {
+        print "/* GENERATED FILE */";
+        print "#define ORDERED"
+}
+{
+        if (!match($0, "^#include"))
+                gsub(/hashmap/, "ordered_hashmap");
+        gsub(/HASHMAP/, "ORDERED_HASHMAP");
+        gsub(/Hashmap/, "OrderedHashmap");
+        print
+}
index e8c4c3e550d26fa95c85442356dfb837ff574f70..e5f45206f16a086d5d89585a98948285efd058b0 100644 (file)
@@ -154,11 +154,16 @@ int main(int argc, char *argv[]) {
         assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
         assert_se(sd_id128_equal(id, id2));
 
-        assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0);
-        assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0);
-        assert_se(sd_id128_equal(id, id2));
-        assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), &id2) >= 0);
-        assert_se(!sd_id128_equal(id, id2));
+        r = sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id);
+        if (r == -EAFNOSUPPORT) {
+                log_info("khash not supported on this kernel, skipping sd_id128_get_machine_app_specific() checks");
+        } else {
+                assert_se(r >= 0);
+                assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0);
+                assert_se(sd_id128_equal(id, id2));
+                assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), &id2) >= 0);
+                assert_se(!sd_id128_equal(id, id2));
+        }
 
         /* Query the invocation ID */
         r = sd_id128_get_invocation(&id);
index e28de9b37b44164a6cd54fdc5bdf2c243d363250..0f71c18b650f12bd12774bd38c80c173326fbeed 100644 (file)
@@ -392,7 +392,7 @@ int main(int argc, char *argv[]) {
                         return EXIT_SUCCESS;
 
                 case 'V':
-                        printf("%s\n", VERSION);
+                        printf("%s\n", PACKAGE_VERSION);
                         return EXIT_SUCCESS;
 
                 case 'm':
index ae9e113efba739e2274088137f517a1a571f13b0..626d2c6135b1d23efedaab57816f38211ec73da8 100644 (file)
 #include "log.h"
 #include "util.h"
 
+assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG))
+          == LOG_REALM_SYSTEMD);
+assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_LOCAL7 | LOG_DEBUG))
+          == LOG_REALM_UDEV);
+assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_LOCAL3 | LOG_DEBUG) & LOG_FACMASK)
+          == LOG_LOCAL3);
+assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMASK)
+          == LOG_INFO);
+
 int main(int argc, char* argv[]) {
 
         log_set_target(LOG_TARGET_CONSOLE);
index 7b67337331b926ff7b85d060df77caf02e65c597..c70633a0f3abf77df483186179470e7fd146ca4d 100644 (file)
@@ -27,11 +27,12 @@ int main(int argc, char* argv[]) {
         int r;
 
         log_open();
+        log_set_max_level(LOG_DEBUG);
         log_parse_environment();
 
         r = loopback_setup();
         if (r < 0)
-                log_error("loopback: %m");
+                log_error_errno(r, "loopback: %m");
 
         return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
index b59cb7aa694478c4d3f6e0b34046b193ea68cb3c..57eeb8e40c5c36dbe706ee90dcb597b255d6f335 100644 (file)
@@ -71,9 +71,11 @@ static void* open_handle(const char* dir, const char* module, int flags) {
         const char *path;
         void *handle;
 
-        if (dir)
-                path = strjoina(dir, "/.libs/libnss_", module, ".so.2");
-        else
+        if (dir) {
+                path = strjoina(dir, "/libnss_", module, ".so.2");
+                if (access(path, F_OK) < 0)
+                        path = strjoina(dir, "/.libs/libnss_", module, ".so.2");
+        } else
                 path = strjoina("libnss_", module, ".so.2");
 
         handle = dlopen(path, flags);
@@ -103,7 +105,7 @@ static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) {
                         goto numerical_index;
 
                 if (if_indextoname(it->scopeid, ifname) == NULL) {
-                        log_warning("if_indextoname(%d) failed: %m", it->scopeid);
+                        log_warning_errno(errno, "if_indextoname(%d) failed: %m", it->scopeid);
                 numerical_index:
                         xsprintf(ifname, "%i", it->scopeid);
                 };
index d08014100b6dc847846f418fbc0eb8ae1c5591b1..1b29b2ea87e9b41f1ee103a4aab13d4635273f76 100644 (file)
@@ -395,6 +395,9 @@ static void test_safe_atou16(void) {
 
         r = safe_atou16("junk", &l);
         assert_se(r == -EINVAL);
+
+        r = safe_atou16("123x", &l);
+        assert_se(r == -EINVAL);
 }
 
 static void test_safe_atoi16(void) {
@@ -425,6 +428,70 @@ static void test_safe_atoi16(void) {
 
         r = safe_atoi16("junk", &l);
         assert_se(r == -EINVAL);
+
+        r = safe_atoi16("123x", &l);
+        assert_se(r == -EINVAL);
+}
+
+static void test_safe_atou64(void) {
+        int r;
+        uint64_t l;
+
+        r = safe_atou64("12345", &l);
+        assert_se(r == 0);
+        assert_se(l == 12345);
+
+        r = safe_atou64("  12345", &l);
+        assert_se(r == 0);
+        assert_se(l == 12345);
+
+        r = safe_atou64("18446744073709551617", &l);
+        assert_se(r == -ERANGE);
+
+        r = safe_atou64("-1", &l);
+        assert_se(r == -ERANGE);
+
+        r = safe_atou64("  -1", &l);
+        assert_se(r == -ERANGE);
+
+        r = safe_atou64("junk", &l);
+        assert_se(r == -EINVAL);
+
+        r = safe_atou64("123x", &l);
+        assert_se(r == -EINVAL);
+}
+
+static void test_safe_atoi64(void) {
+        int r;
+        int64_t l;
+
+        r = safe_atoi64("-12345", &l);
+        assert_se(r == 0);
+        assert_se(l == -12345);
+
+        r = safe_atoi64("  -12345", &l);
+        assert_se(r == 0);
+        assert_se(l == -12345);
+
+        r = safe_atoi64("32767", &l);
+        assert_se(r == 0);
+        assert_se(l == 32767);
+
+        r = safe_atoi64("  32767", &l);
+        assert_se(r == 0);
+        assert_se(l == 32767);
+
+        r = safe_atoi64("9223372036854775813", &l);
+        assert_se(r == -ERANGE);
+
+        r = safe_atoi64("-9223372036854775813", &l);
+        assert_se(r == -ERANGE);
+
+        r = safe_atoi64("junk", &l);
+        assert_se(r == -EINVAL);
+
+        r = safe_atoi64("123x", &l);
+        assert_se(r == -EINVAL);
 }
 
 static void test_safe_atod(void) {
@@ -526,6 +593,19 @@ static void test_parse_nice(void) {
         assert_se(parse_nice("+20", &n) == -ERANGE);
 }
 
+static void test_parse_dev(void) {
+        dev_t dev;
+
+        assert_se(parse_dev("0", &dev) == -EINVAL);
+        assert_se(parse_dev("5", &dev) == -EINVAL);
+        assert_se(parse_dev("5:", &dev) == -EINVAL);
+        assert_se(parse_dev(":5", &dev) == -EINVAL);
+#if SIZEOF_DEV_T < 8
+        assert_se(parse_dev("4294967295:4294967295", &dev) == -EINVAL);
+#endif
+        assert_se(parse_dev("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11);
+}
+
 int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
@@ -538,10 +618,13 @@ int main(int argc, char *argv[]) {
         test_safe_atolli();
         test_safe_atou16();
         test_safe_atoi16();
+        test_safe_atou64();
+        test_safe_atoi64();
         test_safe_atod();
         test_parse_percent();
         test_parse_percent_unbounded();
         test_parse_nice();
+        test_parse_dev();
 
         return 0;
 }
index 22df20a1eb9ceaa6dc82be0a0100676501e355e2..e5644246c287ab5b33c6ebe6c14cdce8708aee4d 100644 (file)
@@ -27,6 +27,7 @@
 #include "mount-util.h"
 #include "path-util.h"
 #include "rm-rf.h"
+#include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
@@ -104,6 +105,48 @@ static void test_path(void) {
         assert_se(!path_equal_ptr(NULL, "/a"));
 }
 
+static void test_path_equal_root(void) {
+        /* Nail down the details of how path_equal("/", ...) works. */
+
+        assert_se(path_equal("/", "/"));
+        assert_se(path_equal("/", "//"));
+
+        assert_se(!path_equal("/", "/./"));
+        assert_se(!path_equal("/", "/../"));
+
+        assert_se(!path_equal("/", "/.../"));
+
+        /* Make sure that files_same works as expected. */
+
+        assert_se(files_same("/", "/", 0) > 0);
+        assert_se(files_same("/", "/", AT_SYMLINK_NOFOLLOW) > 0);
+        assert_se(files_same("/", "//", 0) > 0);
+        assert_se(files_same("/", "//", AT_SYMLINK_NOFOLLOW) > 0);
+
+        assert_se(files_same("/", "/./", 0) > 0);
+        assert_se(files_same("/", "/./", AT_SYMLINK_NOFOLLOW) > 0);
+        assert_se(files_same("/", "/../", 0) > 0);
+        assert_se(files_same("/", "/../", AT_SYMLINK_NOFOLLOW) > 0);
+
+        assert_se(files_same("/", "/.../", 0) == -ENOENT);
+        assert_se(files_same("/", "/.../", AT_SYMLINK_NOFOLLOW) == -ENOENT);
+
+        /* The same for path_equal_or_files_same. */
+
+        assert_se(path_equal_or_files_same("/", "/", 0));
+        assert_se(path_equal_or_files_same("/", "/", AT_SYMLINK_NOFOLLOW));
+        assert_se(path_equal_or_files_same("/", "//", 0));
+        assert_se(path_equal_or_files_same("/", "//", AT_SYMLINK_NOFOLLOW));
+
+        assert_se(path_equal_or_files_same("/", "/./", 0));
+        assert_se(path_equal_or_files_same("/", "/./", AT_SYMLINK_NOFOLLOW));
+        assert_se(path_equal_or_files_same("/", "/../", 0));
+        assert_se(path_equal_or_files_same("/", "/../", AT_SYMLINK_NOFOLLOW));
+
+        assert_se(!path_equal_or_files_same("/", "/.../", 0));
+        assert_se(!path_equal_or_files_same("/", "/.../", AT_SYMLINK_NOFOLLOW));
+}
+
 static void test_find_binary(const char *self) {
         char *p;
 
@@ -551,6 +594,7 @@ int main(int argc, char **argv) {
         log_open();
 
         test_path();
+        test_path_equal_root();
         test_find_binary(argv[0]);
         test_prefixes();
         test_path_join();
diff --git a/src/test/test-random-util.c b/src/test/test-random-util.c
new file mode 100644 (file)
index 0000000..50f4da2
--- /dev/null
@@ -0,0 +1,65 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2017 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 "hexdecoct.h"
+#include "random-util.h"
+#include "log.h"
+
+static void test_acquire_random_bytes(bool high_quality_required) {
+        uint8_t buf[16] = {};
+        unsigned i;
+
+        log_info("/* %s */", __func__);
+
+        for (i = 1; i < sizeof buf; i++) {
+                assert_se(acquire_random_bytes(buf, i, high_quality_required) == 0);
+                if (i + 1 < sizeof buf)
+                        assert_se(buf[i] == 0);
+
+                hexdump(stdout, buf, i);
+        }
+}
+
+static void test_pseudorandom_bytes(void) {
+        uint8_t buf[16] = {};
+        unsigned i;
+
+        log_info("/* %s */", __func__);
+
+        for (i = 1; i < sizeof buf; i++) {
+                pseudorandom_bytes(buf, i);
+                if (i + 1 < sizeof buf)
+                        assert_se(buf[i] == 0);
+
+                hexdump(stdout, buf, i);
+        }
+}
+
+int main(int argc, char **argv) {
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
+        test_acquire_random_bytes(false);
+        test_acquire_random_bytes(true);
+
+        test_pseudorandom_bytes();
+
+        return 0;
+}
index 34a1275162d8739aba2d884e56e42ee0f94ab03c..efd145e063a9684475d99a2141dec20b5f32fe2e 100644 (file)
 #include <stdlib.h>
 #include <sys/eventfd.h>
 #include <sys/mman.h>
-#include <unistd.h>
 #include <sys/poll.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "util.h"
 #include "virt.h"
 
+#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__)
+/* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
+ * and we can't restrict it hence via seccomp. */
+#  define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1
+#else
+#  define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
+#endif
+
+
 static void test_seccomp_arch_to_string(void) {
         uint32_t a, b;
         const char *name;
@@ -158,8 +169,6 @@ static void test_restrict_namespace(void) {
         assert_se(streq(s, "cgroup ipc net mnt pid user uts"));
         assert_se(namespace_flag_from_string_many(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
 
-#if SECCOMP_RESTRICT_NAMESPACES_BROKEN == 0
-
         if (!is_seccomp_available())
                 return;
         if (geteuid() != 0)
@@ -218,7 +227,6 @@ static void test_restrict_namespace(void) {
         }
 
         assert_se(wait_for_terminate_and_warn("nsseccomp", pid, true) == EXIT_SUCCESS);
-#endif
 }
 
 static void test_protect_sysctl(void) {
@@ -286,12 +294,12 @@ static void test_restrict_address_families(void) {
                 assert_se(fd >= 0);
                 safe_close(fd);
 
-#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
                 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
                 assert_se(fd >= 0);
                 safe_close(fd);
 #else
-                assert_se(socket(AF_UNIX, SOCK_DGRAM, 0) < 0);
+                assert_se(fd < 0);
                 assert_se(errno == EAFNOSUPPORT);
 #endif
 
@@ -309,19 +317,21 @@ static void test_restrict_address_families(void) {
                 assert_se(fd >= 0);
                 safe_close(fd);
 
-#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
                 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
                 assert_se(fd >= 0);
                 safe_close(fd);
+#else
+                assert_se(fd < 0);
+                assert_se(errno == EAFNOSUPPORT);
+#endif
 
                 fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
+#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN
                 assert_se(fd >= 0);
                 safe_close(fd);
 #else
-                assert_se(socket(AF_UNIX, SOCK_DGRAM, 0) < 0);
-                assert_se(errno == EAFNOSUPPORT);
-
-                assert_se(socket(AF_NETLINK, SOCK_DGRAM, 0) < 0);
+                assert_se(fd < 0);
                 assert_se(errno == EAFNOSUPPORT);
 #endif
 
@@ -369,7 +379,7 @@ static void test_restrict_realtime(void) {
         assert_se(wait_for_terminate_and_warn("realtimeseccomp", pid, true) == EXIT_SUCCESS);
 }
 
-static void test_memory_deny_write_execute(void) {
+static void test_memory_deny_write_execute_mmap(void) {
         pid_t pid;
 
         if (!is_seccomp_available())
@@ -393,14 +403,13 @@ static void test_memory_deny_write_execute(void) {
 
                 assert_se(seccomp_memory_deny_write_execute() >= 0);
 
-#if SECCOMP_MEMORY_DENY_WRITE_EXECUTE_BROKEN
-                p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
-                assert_se(p != MAP_FAILED);
-                assert_se(munmap(p, page_size()) >= 0);
-#else
                 p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
+#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__)
                 assert_se(p == MAP_FAILED);
                 assert_se(errno == EPERM);
+#else /* unknown architectures */
+                assert_se(p != MAP_FAILED);
+                assert_se(munmap(p, page_size()) >= 0);
 #endif
 
                 p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
@@ -410,7 +419,54 @@ static void test_memory_deny_write_execute(void) {
                 _exit(EXIT_SUCCESS);
         }
 
-        assert_se(wait_for_terminate_and_warn("memoryseccomp", pid, true) == EXIT_SUCCESS);
+        assert_se(wait_for_terminate_and_warn("memoryseccomp-mmap", pid, true) == EXIT_SUCCESS);
+}
+
+static void test_memory_deny_write_execute_shmat(void) {
+        int shmid;
+        pid_t pid;
+
+        if (!is_seccomp_available())
+                return;
+        if (geteuid() != 0)
+                return;
+
+        shmid = shmget(IPC_PRIVATE, page_size(), 0);
+        assert_se(shmid >= 0);
+
+        pid = fork();
+        assert_se(pid >= 0);
+
+        if (pid == 0) {
+                void *p;
+
+                p = shmat(shmid, NULL, 0);
+                assert_se(p != MAP_FAILED);
+                assert_se(shmdt(p) == 0);
+
+                p = shmat(shmid, NULL, SHM_EXEC);
+                assert_se(p != MAP_FAILED);
+                assert_se(shmdt(p) == 0);
+
+                assert_se(seccomp_memory_deny_write_execute() >= 0);
+
+                p = shmat(shmid, NULL, SHM_EXEC);
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+                assert_se(p == MAP_FAILED);
+                assert_se(errno == EPERM);
+#else /* __i386__, __powerpc64__, and "unknown" architectures */
+                assert_se(p != MAP_FAILED);
+                assert_se(shmdt(p) == 0);
+#endif
+
+                p = shmat(shmid, NULL, 0);
+                assert_se(p != MAP_FAILED);
+                assert_se(shmdt(p) == 0);
+
+                _exit(EXIT_SUCCESS);
+        }
+
+        assert_se(wait_for_terminate_and_warn("memoryseccomp-shmat", pid, true) == EXIT_SUCCESS);
 }
 
 static void test_restrict_archs(void) {
@@ -509,7 +565,8 @@ int main(int argc, char *argv[]) {
         test_protect_sysctl();
         test_restrict_address_families();
         test_restrict_realtime();
-        test_memory_deny_write_execute();
+        test_memory_deny_write_execute_mmap();
+        test_memory_deny_write_execute_shmat();
         test_restrict_archs();
         test_load_syscall_filter_set_raw();
 
index b676c259134c36926e1b265e8e108f4a5345ad99..190736aa47b26633ad35f4cc8ec687216b96f195 100644 (file)
@@ -35,16 +35,16 @@ static void test_testing(void) {
         b = mac_selinux_use();
         log_info("mac_selinux_use → %s", yes_no(b));
 
-        b = mac_selinux_have();
-        log_info("mac_selinux_have → %s", yes_no(b));
+        b = mac_selinux_use();
+        log_info("mac_selinux_use → %s", yes_no(b));
 
         mac_selinux_retest();
 
         b = mac_selinux_use();
         log_info("mac_selinux_use → %s", yes_no(b));
 
-        b = mac_selinux_have();
-        log_info("mac_selinux_have → %s", yes_no(b));
+        b = mac_selinux_use();
+        log_info("mac_selinux_use → %s", yes_no(b));
 }
 
 static void test_loading(void) {
index 02b8e243086f9f78ee4237e8723ad67bb9bf294c..7a4a8a6636cd3fd84614a1c3123e119856ca62e2 100644 (file)
@@ -22,6 +22,9 @@
 #include "fd-util.h"
 #include "sigbus.h"
 #include "util.h"
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
 
 int main(int argc, char *argv[]) {
         _cleanup_close_ int fd = -1;
@@ -29,6 +32,11 @@ int main(int argc, char *argv[]) {
         void *addr = NULL;
         uint8_t *p;
 
+#ifdef HAVE_VALGRIND_VALGRIND_H
+        if (RUNNING_ON_VALGRIND)
+                return EXIT_TEST_SKIP;
+#endif
+
 #ifdef __SANITIZE_ADDRESS__
         return EXIT_TEST_SKIP;
 #endif
@@ -38,7 +46,7 @@ int main(int argc, char *argv[]) {
 
         assert_se((fd = mkostemp(template, O_RDWR|O_CREAT|O_EXCL)) >= 0);
         assert_se(unlink(template) >= 0);
-        assert_se(fallocate(fd, 0, 0, page_size() * 8) >= 0);
+        assert_se(posix_fallocate(fd, 0, page_size() * 8) >= 0);
 
         p = mmap(NULL, page_size() * 16, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
         assert_se(p != MAP_FAILED);
index 8f99a13772701ca6e3855c98542caf06aee36ade..269adfd18fe8bac5b6f8b44b415d41465166d1d3 100644 (file)
@@ -17,7 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "log.h"
+#include <stdio.h>
+
 #include "time-util.h"
 
 /* Print information about various types. Useful when diagnosing
 #pragma GCC diagnostic ignored "-Wtype-limits"
 
 #define info(t)                                                 \
-        log_info("%s → %zu bits%s", STRINGIFY(t),               \
-                 sizeof(t)*CHAR_BIT,                            \
-                 strstr(STRINGIFY(t), "signed") ? "" :          \
-                 ((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+        printf("%s → %zu bits%s\n", STRINGIFY(t),               \
+               sizeof(t)*CHAR_BIT,                              \
+               strstr(STRINGIFY(t), "signed") ? "" :            \
+               ((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+
+enum Enum {
+        enum_value,
+};
+
+enum BigEnum {
+        big_enum_value = UINT64_C(-1),
+};
 
 int main(void) {
         info(char);
@@ -39,6 +48,8 @@ int main(void) {
         info(unsigned);
         info(long unsigned);
         info(long long unsigned);
+        info(__syscall_ulong_t);
+        info(__syscall_slong_t);
 
         info(float);
         info(double);
@@ -48,6 +59,10 @@ int main(void) {
         info(ssize_t);
         info(time_t);
         info(usec_t);
+        info(__time_t);
+
+        info(enum Enum);
+        info(enum BigEnum);
 
         return 0;
 }
index 3ff2aadea48fe404304e61cbf52047d0a8bfa5d8..8e027ff26cf60a7b8ea3ec1d081baabe634194c1 100644 (file)
@@ -38,8 +38,10 @@ static void test_files_same(void) {
         assert_se(fd >= 0);
         assert_se(symlink(name, name_alias) >= 0);
 
-        assert_se(files_same(name, name));
-        assert_se(files_same(name, name_alias));
+        assert_se(files_same(name, name, 0));
+        assert_se(files_same(name, name, AT_SYMLINK_NOFOLLOW));
+        assert_se(files_same(name, name_alias, 0));
+        assert_se(!files_same(name, name_alias, AT_SYMLINK_NOFOLLOW));
 
         unlink(name);
         unlink(name_alias);
index 9bea7701314c659fafa8e2c7d73a10233fa1c512..d95945f6b01a4b65d37863049607b9074b66dffa 100644 (file)
@@ -51,6 +51,13 @@ static void test_strpcpyf(void) {
 
         assert_se(streq(target, "space left: 25. foobar"));
         assert_se(space_left == 3);
+
+        /* test overflow */
+        s = target;
+        space_left = strpcpyf(&s, 12, "00 left: %i. ", 999);
+        assert_se(streq(target, "00 left: 99"));
+        assert_se(space_left == 0);
+        assert_se(target[12] == '2');
 }
 
 static void test_strpcpyl(void) {
index 911282bf0c096759263e0c7d880bda25dcde73c6..b7a06c7b19c6c90cf6039cdbc950b8c84e43ca5e 100644 (file)
@@ -61,6 +61,19 @@ static void test_parse_sec(void) {
         assert_se(parse_sec(".3 infinity", &u) < 0);
 }
 
+static void test_parse_sec_fix_0(void) {
+        usec_t u;
+
+        assert_se(parse_sec_fix_0("5s", &u) >= 0);
+        assert_se(u == 5 * USEC_PER_SEC);
+        assert_se(parse_sec_fix_0("0s", &u) >= 0);
+        assert_se(u == 0 * USEC_PER_SEC);
+        assert_se(parse_sec_fix_0("0", &u) >= 0);
+        assert_se(u == USEC_INFINITY);
+        assert_se(parse_sec_fix_0(" 0", &u) >= 0);
+        assert_se(u == USEC_INFINITY);
+}
+
 static void test_parse_time(void) {
         usec_t u;
 
@@ -195,16 +208,37 @@ static void test_usec_add(void) {
         assert_se(usec_add(USEC_INFINITY, 2) == USEC_INFINITY);
 }
 
-static void test_usec_sub(void) {
-        assert_se(usec_sub(0, 0) == 0);
-        assert_se(usec_sub(4, 1) == 3);
-        assert_se(usec_sub(4, 4) == 0);
-        assert_se(usec_sub(4, 5) == 0);
-        assert_se(usec_sub(USEC_INFINITY-3, -3) == USEC_INFINITY);
-        assert_se(usec_sub(USEC_INFINITY-3, -3) == USEC_INFINITY);
-        assert_se(usec_sub(USEC_INFINITY-3, -4) == USEC_INFINITY);
-        assert_se(usec_sub(USEC_INFINITY-3, -5) == USEC_INFINITY);
-        assert_se(usec_sub(USEC_INFINITY, 5) == USEC_INFINITY);
+static void test_usec_sub_unsigned(void) {
+        assert_se(usec_sub_unsigned(0, 0) == 0);
+        assert_se(usec_sub_unsigned(0, 2) == 0);
+        assert_se(usec_sub_unsigned(0, USEC_INFINITY) == 0);
+        assert_se(usec_sub_unsigned(1, 0) == 1);
+        assert_se(usec_sub_unsigned(1, 1) == 0);
+        assert_se(usec_sub_unsigned(1, 2) == 0);
+        assert_se(usec_sub_unsigned(1, 3) == 0);
+        assert_se(usec_sub_unsigned(1, USEC_INFINITY) == 0);
+        assert_se(usec_sub_unsigned(USEC_INFINITY-1, 0) == USEC_INFINITY-1);
+        assert_se(usec_sub_unsigned(USEC_INFINITY-1, 1) == USEC_INFINITY-2);
+        assert_se(usec_sub_unsigned(USEC_INFINITY-1, 2) == USEC_INFINITY-3);
+        assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY-2) == 1);
+        assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY-1) == 0);
+        assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY) == 0);
+        assert_se(usec_sub_unsigned(USEC_INFINITY, 0) == USEC_INFINITY);
+        assert_se(usec_sub_unsigned(USEC_INFINITY, 1) == USEC_INFINITY);
+        assert_se(usec_sub_unsigned(USEC_INFINITY, 2) == USEC_INFINITY);
+        assert_se(usec_sub_unsigned(USEC_INFINITY, USEC_INFINITY) == USEC_INFINITY);
+}
+
+static void test_usec_sub_signed(void) {
+        assert_se(usec_sub_signed(0, 0) == 0);
+        assert_se(usec_sub_signed(4, 1) == 3);
+        assert_se(usec_sub_signed(4, 4) == 0);
+        assert_se(usec_sub_signed(4, 5) == 0);
+        assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY);
+        assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY);
+        assert_se(usec_sub_signed(USEC_INFINITY-3, -4) == USEC_INFINITY);
+        assert_se(usec_sub_signed(USEC_INFINITY-3, -5) == USEC_INFINITY);
+        assert_se(usec_sub_signed(USEC_INFINITY, 5) == USEC_INFINITY);
 }
 
 static void test_format_timestamp(void) {
@@ -273,10 +307,93 @@ static void test_format_timestamp_utc(void) {
         test_format_timestamp_utc_one(USEC_INFINITY, NULL);
 }
 
+static void test_dual_timestamp_deserialize(void) {
+        int r;
+        dual_timestamp t;
+
+        r = dual_timestamp_deserialize("1234 5678", &t);
+        assert_se(r == 0);
+        assert_se(t.realtime == 1234);
+        assert_se(t.monotonic == 5678);
+
+        r = dual_timestamp_deserialize("1234x 5678", &t);
+        assert_se(r == -EINVAL);
+
+        r = dual_timestamp_deserialize("1234 5678y", &t);
+        assert_se(r == -EINVAL);
+
+        r = dual_timestamp_deserialize("-1234 5678", &t);
+        assert_se(r == -EINVAL);
+
+        r = dual_timestamp_deserialize("1234 -5678", &t);
+        assert_se(r == -EINVAL);
+
+        /* Check that output wasn't modified. */
+        assert_se(t.realtime == 1234);
+        assert_se(t.monotonic == 5678);
+
+        r = dual_timestamp_deserialize("+123 567", &t);
+        assert_se(r == 0);
+        assert_se(t.realtime == 123);
+        assert_se(t.monotonic == 567);
+
+        /* Check that we get "infinity" on overflow. */
+        r = dual_timestamp_deserialize("18446744073709551617 0", &t);
+        assert_se(r == 0);
+        assert_se(t.realtime == USEC_INFINITY);
+        assert_se(t.monotonic == 0);
+}
+
+static void assert_similar(usec_t a, usec_t b) {
+        usec_t d;
+
+        if (a > b)
+                d = a - b;
+        else
+                d = b - a;
+
+        assert(d < 10*USEC_PER_SEC);
+}
+
+static void test_usec_shift_clock(void) {
+        usec_t rt, mn, bt;
+
+        rt = now(CLOCK_REALTIME);
+        mn = now(CLOCK_MONOTONIC);
+        bt = now(clock_boottime_or_monotonic());
+
+        assert_se(usec_shift_clock(USEC_INFINITY, CLOCK_REALTIME, CLOCK_MONOTONIC) == USEC_INFINITY);
+
+        assert_similar(usec_shift_clock(rt + USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_MONOTONIC), mn + USEC_PER_HOUR);
+        assert_similar(usec_shift_clock(rt + 2*USEC_PER_HOUR, CLOCK_REALTIME, clock_boottime_or_monotonic()), bt + 2*USEC_PER_HOUR);
+        assert_se(usec_shift_clock(rt + 3*USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_REALTIME_ALARM) == rt + 3*USEC_PER_HOUR);
+
+        assert_similar(usec_shift_clock(mn + 4*USEC_PER_HOUR, CLOCK_MONOTONIC, CLOCK_REALTIME_ALARM), rt + 4*USEC_PER_HOUR);
+        assert_similar(usec_shift_clock(mn + 5*USEC_PER_HOUR, CLOCK_MONOTONIC, clock_boottime_or_monotonic()), bt + 5*USEC_PER_HOUR);
+        assert_se(usec_shift_clock(mn + 6*USEC_PER_HOUR, CLOCK_MONOTONIC, CLOCK_MONOTONIC) == mn + 6*USEC_PER_HOUR);
+
+        assert_similar(usec_shift_clock(bt + 7*USEC_PER_HOUR, clock_boottime_or_monotonic(), CLOCK_MONOTONIC), mn + 7*USEC_PER_HOUR);
+        assert_similar(usec_shift_clock(bt + 8*USEC_PER_HOUR, clock_boottime_or_monotonic(), CLOCK_REALTIME_ALARM), rt + 8*USEC_PER_HOUR);
+        assert_se(usec_shift_clock(bt + 9*USEC_PER_HOUR, clock_boottime_or_monotonic(), clock_boottime_or_monotonic()) == bt + 9*USEC_PER_HOUR);
+
+        if (mn > USEC_PER_MINUTE) {
+                assert_similar(usec_shift_clock(rt - 30 * USEC_PER_SEC, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC), mn - 30 * USEC_PER_SEC);
+                assert_similar(usec_shift_clock(rt - 50 * USEC_PER_SEC, CLOCK_REALTIME, clock_boottime_or_monotonic()), bt - 50 * USEC_PER_SEC);
+        }
+}
+
 int main(int argc, char *argv[]) {
         uintmax_t x;
 
+        log_info("realtime=" USEC_FMT "\n"
+                 "monotonic=" USEC_FMT "\n"
+                 "boottime=" USEC_FMT "\n",
+                 now(CLOCK_REALTIME),
+                 now(CLOCK_MONOTONIC),
+                 now(clock_boottime_or_monotonic()));
+
         test_parse_sec();
+        test_parse_sec_fix_0();
         test_parse_time();
         test_parse_nsec();
         test_format_timespan(1);
@@ -285,9 +402,12 @@ int main(int argc, char *argv[]) {
         test_timezone_is_valid();
         test_get_timezones();
         test_usec_add();
-        test_usec_sub();
+        test_usec_sub_signed();
+        test_usec_sub_unsigned();
         test_format_timestamp();
         test_format_timestamp_utc();
+        test_dual_timestamp_deserialize();
+        test_usec_shift_clock();
 
         /* Ensure time_t is signed */
         assert_cc((time_t) -1 < (time_t) 1);
index e965b4494a34c3fcd4aca40edc52535198d04535..c84bd8991e68a1a3d67cd2e2fef02dab7594b21f 100644 (file)
@@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
         if (udev == NULL)
                 return EXIT_FAILURE;
 
-        log_debug("version %s", VERSION);
+        log_debug("version %s", PACKAGE_VERSION);
         mac_selinux_init();
 
         action = argv[1];
index 12f48bf435580fc7cde9869b31b67c433c61832b..fd797b587ec2cca38ba436b3a9bea1c7dc944d51 100644 (file)
@@ -146,7 +146,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/RValue/ argv0 r1",
                               &c, u);
-        assert_se(r == 0);
+        assert_se(r == -ENOEXEC);
         assert_se(c1->command_next == NULL);
 
         log_info("/* honour_argv0 */");
@@ -161,7 +161,7 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 3, "section", 1,
                               "LValue", 0, "@/RValue",
                               &c, u);
-        assert_se(r == 0);
+        assert_se(r == -ENOEXEC);
         assert_se(c1->command_next == NULL);
 
         log_info("/* no command, whitespace only, reset */");
@@ -220,7 +220,7 @@ static void test_config_parse_exec(void) {
                               "-@/RValue argv0 r1 ; ; "
                               "/goo/goo boo",
                               &c, u);
-        assert_se(r >= 0);
+        assert_se(r == -ENOEXEC);
         c1 = c1->command_next;
         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
 
@@ -374,7 +374,7 @@ static void test_config_parse_exec(void) {
                 r = config_parse_exec(NULL, "fake", 4, "section", 1,
                                       "LValue", 0, path,
                                       &c, u);
-                assert_se(r == 0);
+                assert_se(r == -ENOEXEC);
                 assert_se(c1->command_next == NULL);
         }
 
@@ -401,21 +401,21 @@ static void test_config_parse_exec(void) {
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/path\\",
                               &c, u);
-        assert_se(r == 0);
+        assert_se(r == -ENOEXEC);
         assert_se(c1->command_next == NULL);
 
         log_info("/* missing ending ' */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/path 'foo",
                               &c, u);
-        assert_se(r == 0);
+        assert_se(r == -ENOEXEC);
         assert_se(c1->command_next == NULL);
 
         log_info("/* missing ending ' with trailing backslash */");
         r = config_parse_exec(NULL, "fake", 4, "section", 1,
                               "LValue", 0, "/path 'foo\\",
                               &c, u);
-        assert_se(r == 0);
+        assert_se(r == -ENOEXEC);
         assert_se(c1->command_next == NULL);
 
         log_info("/* invalid space between modifiers */");
diff --git a/src/timedate/meson.build b/src/timedate/meson.build
new file mode 100644 (file)
index 0000000..63124d6
--- /dev/null
@@ -0,0 +1,14 @@
+if conf.get('ENABLE_TIMEDATED', false)
+        install_data('org.freedesktop.timedate1.conf',
+                     install_dir : dbuspolicydir)
+        install_data('org.freedesktop.timedate1.service',
+                     install_dir : dbussystemservicedir)
+
+        custom_target(
+                'org.freedesktop.timedate1.policy',
+                input : 'org.freedesktop.timedate1.policy.in',
+                output : 'org.freedesktop.timedate1.policy',
+                command : intltool_command,
+                install : install_polkit,
+                install_dir : polkitpolicydir)
+endif
diff --git a/src/timesync/meson.build b/src/timesync/meson.build
new file mode 100644 (file)
index 0000000..4391afa
--- /dev/null
@@ -0,0 +1,42 @@
+systemd_timesyncd_sources = files('''
+        timesyncd.c
+        timesyncd-manager.c
+        timesyncd-manager.h
+        timesyncd-conf.c
+        timesyncd-conf.h
+        timesyncd-server.c
+        timesyncd-server.h
+'''.split())
+
+timesyncd_gperf_c = custom_target(
+        'timesyncd-gperf.c',
+        input : 'timesyncd-gperf.gperf',
+        output : 'timesyncd-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+systemd_timesyncd_sources += [timesyncd_gperf_c]
+
+if conf.get('ENABLE_TIMESYNCD', false)
+        timesyncd_conf = configure_file(
+                input : 'timesyncd.conf.in',
+                output : 'timesyncd.conf',
+                configuration : substs)
+        install_data(timesyncd_conf,
+                     install_dir : pkgsysconfdir)
+endif
+
+############################################################
+
+tests += [
+        [['src/timesync/test-timesync.c',
+          'src/timesync/timesyncd-manager.c',
+          'src/timesync/timesyncd-manager.h',
+          'src/timesync/timesyncd-conf.c',
+          'src/timesync/timesyncd-conf.h',
+          'src/timesync/timesyncd-server.c',
+          'src/timesync/timesyncd-server.h',
+          timesyncd_gperf_c],
+         [libshared],
+         [libm],
+         'ENABLE_TIMESYNCD'],
+]
diff --git a/src/timesync/test-timesync.c b/src/timesync/test-timesync.c
new file mode 100644 (file)
index 0000000..a5a3433
--- /dev/null
@@ -0,0 +1,51 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2017 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/>.
+***/
+
+/* Some unit tests for the helper functions in timesyncd. */
+
+#include "log.h"
+#include "macro.h"
+#include "timesyncd-conf.h"
+
+static void test_manager_parse_string(void) {
+        /* Make sure that NTP_SERVERS is configured to something
+         * that we can actually parse successfully. */
+
+        _cleanup_(manager_freep) Manager *m = NULL;
+
+        assert_se(manager_new(&m) == 0);
+
+        assert_se(!m->have_fallbacks);
+        assert_se(manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS) == 0);
+        assert_se(m->have_fallbacks);
+        assert_se(manager_parse_fallback_string(m, NTP_SERVERS) == 0);
+
+        assert_se(manager_parse_server_string(m, SERVER_SYSTEM, "time1.foobar.com time2.foobar.com") == 0);
+        assert_se(manager_parse_server_string(m, SERVER_FALLBACK, "time1.foobar.com time2.foobar.com") == 0);
+        assert_se(manager_parse_server_string(m, SERVER_LINK, "time1.foobar.com time2.foobar.com") == 0);
+}
+
+int main(int argc, char **argv) {
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+
+        test_manager_parse_string();
+
+        return 0;
+}
index bf25b112e16f894a065bc758494f1ba28405890a..f394d0a2af615888d13898e6f071061937e75d58 100644 (file)
@@ -34,6 +34,9 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
 
         first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers;
 
+        if (type == SERVER_FALLBACK)
+                 m->have_fallbacks = true;
+
         for (;;) {
                 _cleanup_free_ char *word = NULL;
                 bool found = false;
@@ -63,6 +66,13 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
         return 0;
 }
 
+int manager_parse_fallback_string(Manager *m, const char *string) {
+        if (m->have_fallbacks)
+                return 0;
+
+        return manager_parse_server_string(m, SERVER_FALLBACK, string);
+}
+
 int config_parse_servers(
                 const char *unit,
                 const char *filename,
@@ -99,8 +109,8 @@ int manager_parse_config_file(Manager *m) {
         assert(m);
 
         return config_parse_many_nulstr(PKGSYSCONFDIR "/timesyncd.conf",
-                                 CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
-                                 "Time\0",
-                                 config_item_perf_lookup, timesyncd_gperf_lookup,
-                                 false, m);
+                                        CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
+                                        "Time\0",
+                                        config_item_perf_lookup, timesyncd_gperf_lookup,
+                                        false, m);
 }
index 0280697e9cc8ef3a986d4af9d93a492747071b63..0c4b44e707cf754f37841a497845c7f0d39a9125 100644 (file)
@@ -29,3 +29,4 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
 int config_parse_servers(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 manager_parse_config_file(Manager *m);
+int manager_parse_fallback_string(Manager *m, const char *string);
index 6a6c1577c64de84287b98f2903babb0e2d3db2d2..a24c821bdcbe66684ad62c0eb01e2ce6319b288c 100644 (file)
@@ -378,10 +378,10 @@ static int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
         m->drift_ppm = tmx.freq / 65536;
 
         log_debug("  status       : %04i %s\n"
-                  "  time now     : %li.%03"PRI_USEC"\n"
-                  "  constant     : %li\n"
+                  "  time now     : %"PRI_TIME".%03"PRI_USEC"\n"
+                  "  constant     : %"PRI_TIMEX"\n"
                   "  offset       : %+.3f sec\n"
-                  "  freq offset  : %+li (%i ppm)\n",
+                  "  freq offset  : %+"PRI_TIMEX" (%i ppm)\n",
                   tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
                   tmx.time.tv_sec, tmx.time.tv_usec / NSEC_PER_MSEC,
                   tmx.constant,
@@ -1124,10 +1124,6 @@ int manager_new(Manager **ret) {
 
         RATELIMIT_INIT(m->ratelimit, RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST);
 
-        r = manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS);
-        if (r < 0)
-                return r;
-
         r = sd_event_default(&m->event);
         if (r < 0)
                 return r;
index efe3e60d3e4ef694d4b556ce977470b71b7ee24e..cf681f6098718f2a89c57c027b3e178351b2c9e1 100644 (file)
@@ -38,6 +38,8 @@ struct Manager {
         LIST_HEAD(ServerName, link_servers);
         LIST_HEAD(ServerName, fallback_servers);
 
+        bool have_fallbacks:1;
+
         RateLimit ratelimit;
         bool exhausted_servers;
 
index b67d672a6ade4c15384888bf0768994df4a28667..ff90f04070cab7695d7891b2eead570aaa10f0b3 100644 (file)
@@ -132,6 +132,12 @@ int main(int argc, char *argv[]) {
         if (r < 0)
                 log_warning_errno(r, "Failed to parse configuration file: %m");
 
+        r = manager_parse_fallback_string(m, NTP_SERVERS);
+        if (r < 0) {
+                log_error_errno(r, "Failed to parse fallback server strings: %m");
+                goto finish;
+        }
+
         log_debug("systemd-timesyncd running as pid " PID_FMT, getpid());
         sd_notify(false,
                   "READY=1\n"
index 7326597b8c35eba060a19fc2bab6f07bcfebd8de..9419c99e28e93e0d3465fd56a09cb1d74686d456 100644 (file)
@@ -724,10 +724,9 @@ static int path_set_xattrs(Item *i, const char *path) {
 
                 n = strlen(*value);
                 log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
-                if (lsetxattr(path, *name, *value, n, 0) < 0) {
-                        log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path);
-                        return -errno;
-                }
+                if (lsetxattr(path, *name, *value, n, 0) < 0)
+                        return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m",
+                                               *name, *value, path);
         }
         return 0;
 }
@@ -973,7 +972,7 @@ static int path_set_attribute(Item *item, const char *path) {
 
         r = chattr_fd(fd, f, item->attribute_mask);
         if (r < 0)
-                log_full_errno(r == -ENOTTY ? LOG_DEBUG : LOG_WARNING,
+                log_full_errno(r == -ENOTTY || r == -EOPNOTSUPP ? 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);
@@ -1093,19 +1092,14 @@ static int item_do_children(Item *i, const char *path, action_t action) {
 
 static int glob_item(Item *i, action_t action, bool recursive) {
         _cleanup_globfree_ glob_t g = {
-                .gl_closedir = (void (*)(void *)) closedir,
-                .gl_readdir = (struct dirent *(*)(void *)) readdir,
                 .gl_opendir = (void *(*)(const char *)) opendir_nomod,
-                .gl_lstat = lstat,
-                .gl_stat = stat,
         };
         int r = 0, k;
         char **fn;
 
-        errno = 0;
-        k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
-        if (k != 0 && k != GLOB_NOMATCH)
-                return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
+        k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
+        if (k < 0 && k != -ENOENT)
+                return log_error_errno(k, "glob(%s) failed: %m", i->path);
 
         STRV_FOREACH(fn, g.gl_pathv) {
                 k = action(i, *fn);
index 1e414664ce74bc12551fef57ad4711d789be522a..ad152b9d316413272b132c7f377d689e514d33b1 100644 (file)
@@ -427,6 +427,8 @@ int main(int argc, char *argv[])
                 {}
         };
 
+        log_set_target(LOG_TARGET_AUTO);
+        udev_parse_config();
         log_parse_environment();
         log_open();
 
index 72f284f71082cf51da598a0da1db88f8c53ed412..1f906a85258f511dc36830d9a96d14e2dbfbd212 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "libudev-private.h"
 #include "random-util.h"
+#include "udev-util.h"
 
 /* device info */
 static unsigned int cd_cd_rom;
@@ -843,8 +844,7 @@ static int cd_media_toc(struct udev *udev, int fd)
         return 0;
 }
 
-int main(int argc, char *argv[])
-{
+int main(int argc, char *argv[]) {
         struct udev *udev;
         static const struct option options[] = {
                 { "lock-media", no_argument, NULL, 'l' },
@@ -862,6 +862,8 @@ int main(int argc, char *argv[])
         int cnt;
         int rc = 0;
 
+        log_set_target(LOG_TARGET_AUTO);
+        udev_parse_config();
         log_parse_environment();
         log_open();
 
index 0e973cd521893dbc3befbedeec35416ff9fc5baa..57dfb016f9bbc7fc62b57ea25b783432d47b46c0 100644 (file)
@@ -29,6 +29,7 @@
 #include "macro.h"
 #include "stdio-util.h"
 #include "string-util.h"
+#include "udev-util.h"
 
 #define BUFSIZE 16
 #define UDEV_ALARM_TIMEOUT 180
@@ -343,9 +344,7 @@ static void everybody(void)
         }
 }
 
-int main(int argc, char **argv)
-{
-        struct udev *udev;
+int main(int argc, char **argv) {
         static const struct option options[] = {
                 { "add", no_argument, NULL, 'a' },
                 { "remove", no_argument, NULL, 'r' },
@@ -361,11 +360,10 @@ int main(int argc, char **argv)
         int prune = 0;
         char tmpdir[UTIL_PATH_SIZE];
 
-        udev = udev_new();
-        if (udev == NULL) {
-                ret = EXIT_FAILURE;
-                goto exit;
-        }
+        log_set_target(LOG_TARGET_AUTO);
+        udev_parse_config();
+        log_parse_environment();
+        log_open();
 
         for (;;) {
                 int option;
@@ -386,26 +384,23 @@ int main(int argc, char **argv)
                         break;
                 case 'h':
                         usage();
-                        goto exit;
+                        return 0;
                 default:
-                        ret = 1;
-                        goto exit;
+                        return 1;
                 }
         }
 
         argi = optind;
         if (argi + 2 > argc) {
                 printf("Missing parameter(s)\n");
-                ret = 1;
-                goto exit;
+                return 1;
         }
         checkpoint = argv[argi++];
         us = argv[argi++];
 
         if (signal(SIGALRM, sig_alrm) == SIG_ERR) {
                 fprintf(stderr, "Cannot set SIGALRM: %m\n");
-                ret = 2;
-                goto exit;
+                return 2;
         }
 
         udev_list_node_init(&bunch);
@@ -485,7 +480,5 @@ out:
                 everybody();
         if (ret >= 0)
                 printf("COLLECT_%s=%d\n", checkpoint, ret);
-exit:
-        udev_unref(udev);
         return ret;
 }
diff --git a/src/udev/generate-keyboard-keys-gperf.sh b/src/udev/generate-keyboard-keys-gperf.sh
new file mode 100755 (executable)
index 0000000..5724e4e
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh -eu
+awk '   BEGIN {
+                print "struct key_name { const char* name; unsigned short id; };"
+                print "%null-strings"
+                print "%%"
+        }
+
+        /^KEY_/ { print tolower(substr($1 ,5)) ", " $1 }
+                { print tolower($1) ", " $1 }
+' < "$1"
diff --git a/src/udev/generate-keyboard-keys-list.sh b/src/udev/generate-keyboard-keys-list.sh
new file mode 100755 (executable)
index 0000000..7a74e0d
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh -eu
+
+$1 -dM -include linux/input.h - </dev/null | awk '
+        /\<(KEY_(MAX|MIN_INTERESTING))|(BTN_(MISC|MOUSE|JOYSTICK|GAMEPAD|DIGI|WHEEL|TRIGGER_HAPPY))\>/  { next }
+        /^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/                                                    { print $2 }
+'
diff --git a/src/udev/meson.build b/src/udev/meson.build
new file mode 100644 (file)
index 0000000..eeb341f
--- /dev/null
@@ -0,0 +1,152 @@
+udevadm_sources = files('''
+        udevadm.c
+        udevadm-info.c
+        udevadm-control.c
+        udevadm-monitor.c
+        udevadm-hwdb.c
+        udevadm-settle.c
+        udevadm-trigger.c
+        udevadm-test.c
+        udevadm-test-builtin.c
+        udevadm-util.c
+        udevadm-util.h
+'''.split())
+
+systemd_udevd_sources = files('udevd.c')
+
+libudev_core_sources = '''
+        udev.h
+        udev-event.c
+        udev-watch.c
+        udev-node.c
+        udev-rules.c
+        udev-ctrl.c
+        udev-builtin.c
+        udev-builtin-btrfs.c
+        udev-builtin-hwdb.c
+        udev-builtin-input_id.c
+        udev-builtin-keyboard.c
+        udev-builtin-net_id.c
+        udev-builtin-net_setup_link.c
+        udev-builtin-path_id.c
+        udev-builtin-usb_id.c
+        net/link-config.c
+        net/link-config.h
+        net/ethtool-util.c
+        net/ethtool-util.h
+'''.split()
+
+if conf.get('HAVE_KMOD', false)
+        libudev_core_sources += ['udev-builtin-kmod.c']
+endif
+
+if conf.get('HAVE_BLKID', false)
+        libudev_core_sources += ['udev-builtin-blkid.c']
+endif
+
+if conf.get('HAVE_ACL', false)
+        libudev_core_sources += ['udev-builtin-uaccess.c',
+                                logind_acl_c,
+                                 sd_login_c]
+endif
+
+############################################################
+
+generate_keyboard_keys_list = find_program('generate-keyboard-keys-list.sh')
+keyboard_keys_list_txt = custom_target(
+        'keyboard-keys-list.txt',
+        output : 'keyboard-keys-list.txt',
+        command : [generate_keyboard_keys_list, cpp],
+        capture : true)
+
+generate_keyboard_keys_gperf = find_program('generate-keyboard-keys-gperf.sh')
+fname = 'keyboard-keys-from-name.gperf'
+gperf_file = custom_target(
+        fname,
+        input : keyboard_keys_list_txt,
+        output : fname,
+        command : [generate_keyboard_keys_gperf, '@INPUT@'],
+        capture : true)
+
+fname = 'keyboard-keys-from-name.h'
+keyboard_keys_from_name_h = custom_target(
+        fname,
+        input : gperf_file,
+        output : fname,
+        command : [gperf,
+                   '-L', 'ANSI-C', '-t',
+                   '-N', 'keyboard_lookup_key',
+                   '-H', 'hash_key_name',
+                   '-p', '-C',
+                   '@INPUT@'],
+        capture : true)
+
+############################################################
+
+link_config_gperf_c = custom_target(
+        'link-config-gperf.c',
+        input : 'net/link-config-gperf.gperf',
+        output : 'link-config-gperf.c',
+        command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+############################################################
+
+if get_option('link-udev-shared')
+        udev_link_with = [libshared]
+        udev_rpath = rootlibexecdir
+else
+        udev_link_with = [libshared_static,
+                          libsystemd_internal]
+        udev_rpath = ''
+endif
+
+libudev_internal = static_library(
+        'udev',
+        libudev_sources,
+        include_directories : includes,
+        link_with : udev_link_with)
+
+libudev_core_includes = [includes, include_directories('net')]
+libudev_core = static_library(
+        'udev-core',
+        libudev_core_sources,
+        link_config_gperf_c,
+        keyboard_keys_from_name_h,
+        include_directories : libudev_core_includes,
+        link_with : udev_link_with,
+        dependencies : [libblkid, libkmod])
+
+foreach prog : [['ata_id/ata_id.c'],
+                ['cdrom_id/cdrom_id.c'],
+                ['collect/collect.c'],
+                ['scsi_id/scsi_id.c',
+                 'scsi_id/scsi_id.h',
+                 'scsi_id/scsi_serial.c',
+                 'scsi_id/scsi.h'],
+                ['v4l_id/v4l_id.c'],
+                ['mtd_probe/mtd_probe.c',
+                 'mtd_probe/mtd_probe.h',
+                 'mtd_probe/probe_smartmedia.c']]
+
+        executable(prog[0].split('/')[0],
+                   prog,
+                   include_directories : includes,
+                   c_args : ['-DLOG_REALM=LOG_REALM_UDEV'],
+                   link_with : [libudev_internal],
+                   install_rpath : udev_rpath,
+                   install : true,
+                   install_dir : udevlibexecdir)
+endforeach
+
+install_data('udev.conf',
+             install_dir : join_paths(sysconfdir, 'udev'))
+
+udev_pc = configure_file(
+        input : 'udev.pc.in',
+        output : 'udev.pc',
+        configuration : substs)
+install_data(udev_pc,
+             install_dir : pkgconfigdatadir)
+
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(sysconfdir, 'udev/rules.d')))
index d7edbb396bc6ce7a0f23dd9a4e5058a8c397e1e7..201fc2343726f3ffdbf3d132a2ab7d351fe09951 100644 (file)
@@ -25,6 +25,7 @@
 #include "conf-parser.h"
 #include "ethtool-util.h"
 #include "log.h"
+#include "link-config.h"
 #include "socket-util.h"
 #include "string-table.h"
 #include "strxcpyx.h"
@@ -48,6 +49,17 @@ static const char* const wol_table[_WOL_MAX] = {
 DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting");
 
+static const char* const port_table[_NET_DEV_PORT_MAX] = {
+        [NET_DEV_PORT_TP]     = "tp",
+        [NET_DEV_PORT_AUI]    = "aui",
+        [NET_DEV_PORT_MII]    = "mii",
+        [NET_DEV_PORT_FIBRE]  = "fibre",
+        [NET_DEV_PORT_BNC]    = "bnc"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");
+
 static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {
         [NET_DEV_FEAT_GSO] = "tx-generic-segmentation",
         [NET_DEV_FEAT_GRO] = "rx-gro",
@@ -488,12 +500,12 @@ static int set_sset(int *fd, struct ifreq *ifr, const struct ethtool_link_usetti
  * enabled speed and @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode.
  */
 
-int ethtool_set_glinksettings(int *fd, const char *ifname, unsigned int speed, Duplex duplex, int autonegotiation) {
+int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link) {
         _cleanup_free_ struct ethtool_link_usettings *u = NULL;
         struct ifreq ifr = {};
         int r;
 
-        if (autonegotiation != 0) {
+        if (link->autonegotiation != 0) {
                 log_info("link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.");
                 return 0;
         }
@@ -514,13 +526,16 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, unsigned int speed, D
                         return log_warning_errno(r, "link_config: Cannot get device settings for %s : %m", ifname);
         }
 
-        if (speed)
-                u->base.speed = speed;
+        if (link->speed)
+                u->base.speed = DIV_ROUND_UP(link->speed, 1000000);
+
+        if (link->duplex != _DUP_INVALID)
+                u->base.duplex = link->duplex;
 
-        if (duplex != _DUP_INVALID)
-                u->base.duplex = duplex;
+        if (link->port != _NET_DEV_PORT_INVALID)
+              u->base.port = link->port;
 
-        u->base.autoneg = autonegotiation;
+        u->base.autoneg = link->autonegotiation;
 
         if (u->base.cmd == ETHTOOL_GLINKSETTINGS)
                 r = set_slinksettings(fd, &ifr, u);
index 75d6af396b0ab543c7ca0a29b929047b165977cb..27ce0e0abada70dc772d3eca06953b9fafbb2f64 100644 (file)
 
 #include "missing.h"
 
+struct link_config;
+
 /* we can't use DUPLEX_ prefix, as it
  * clashes with <linux/ethtool.h> */
 typedef enum Duplex {
-        DUP_FULL,
-        DUP_HALF,
+        DUP_HALF = DUPLEX_HALF,
+        DUP_FULL = DUPLEX_FULL,
         _DUP_MAX,
         _DUP_INVALID = -1
 } Duplex;
@@ -51,6 +53,18 @@ typedef enum NetDevFeature {
         _NET_DEV_FEAT_INVALID = -1
 } NetDevFeature;
 
+typedef enum NetDevPort {
+        NET_DEV_PORT_TP     = 0x00,
+        NET_DEV_PORT_AUI    = 0x01,
+        NET_DEV_PORT_MII    = 0x02,
+        NET_DEV_PORT_FIBRE  = 0x03,
+        NET_DEV_PORT_BNC    = 0x04,
+        NET_DEV_PORT_DA     = 0x05,
+        NET_DEV_PORT_NONE   = 0xef,
+        NET_DEV_PORT_OTHER  = 0xff,
+        _NET_DEV_PORT_MAX,
+        _NET_DEV_PORT_INVALID = -1
+} NetDevPort;
 
 #define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32    (SCHAR_MAX)
 
@@ -71,7 +85,7 @@ int ethtool_get_driver(int *fd, const char *ifname, char **ret);
 int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex duplex);
 int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol);
 int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features);
-int ethtool_set_glinksettings(int *fd, const char *ifname, unsigned int speed, Duplex duplex, int autoneg);
+int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link);
 
 const char *duplex_to_string(Duplex d) _const_;
 Duplex duplex_from_string(const char *d) _pure_;
@@ -79,5 +93,9 @@ Duplex duplex_from_string(const char *d) _pure_;
 const char *wol_to_string(WakeOnLan wol) _const_;
 WakeOnLan wol_from_string(const char *wol) _pure_;
 
+const char *port_to_string(NetDevPort port) _const_;
+NetDevPort port_from_string(const char *port) _pure_;
+
 int config_parse_duplex(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_wol(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_port(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);
index 78e551df22c4851c10b94f9feafaa46dc63a9420..5488867ba71fb8b0ecd0112108f805592b9dc1aa 100644 (file)
@@ -36,6 +36,7 @@ Link.BitsPerSecond,              config_parse_si_size,       0,
 Link.Duplex,                     config_parse_duplex,        0,                             offsetof(link_config, duplex)
 Link.AutoNegotiation,            config_parse_tristate,      0,                             offsetof(link_config, autonegotiation)
 Link.WakeOnLan,                  config_parse_wol,           0,                             offsetof(link_config, wol)
+Link.Port,                       config_parse_port,          0,                             offsetof(link_config, port)
 Link.GenericSegmentationOffload, config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_GSO])
 Link.TCPSegmentationOffload,     config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_TSO])
 Link.UDPSegmentationOffload,     config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_UFO])
index 3af87f13883d1f3d0c1d9c825a483023b2636a0c..05a186357c5233fb8d31d09c944ddab9d29fb81f 100644 (file)
@@ -167,6 +167,7 @@ static int load_link(link_config_ctx *ctx, const char *filename) {
         link->mac_policy = _MACPOLICY_INVALID;
         link->wol = _WOL_INVALID;
         link->duplex = _DUP_INVALID;
+        link->port = _NET_DEV_PORT_INVALID;
         link->autonegotiation = -1;
 
         memset(&link->features, -1, sizeof(link->features));
@@ -377,12 +378,13 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
         if (!old_name)
                 return -EINVAL;
 
-
-        speed = DIV_ROUND_UP(config->speed, 1000000);
-
-        r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, speed, config->duplex, config->autonegotiation);
+        r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config);
         if (r < 0) {
 
+                if (config->port != _NET_DEV_PORT_INVALID)
+                        log_warning_errno(r,  "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name);
+
+                speed = DIV_ROUND_UP(config->speed, 1000000);
                 if (r == -EOPNOTSUPP)
                         r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex);
 
index 5a25cec6fdac7336efefdcc4534cdfe4e5b75c70..ff91a65135f42a10dc616c509b6210694e5c99b6 100644 (file)
@@ -71,6 +71,7 @@ struct link_config {
         Duplex duplex;
         int autonegotiation;
         WakeOnLan wol;
+        NetDevPort port;
         NetDevFeature features[_NET_DEV_FEAT_MAX];
 
         LIST_FIELDS(link_config, links);
index 46556916429b6352424b34e7e880332003e0ae56..3c3d7a6b3315b2672e362fc0b91d8e7bbbc58802 100644 (file)
@@ -391,7 +391,7 @@ static int set_options(struct udev *udev,
                         break;
 
                 case 'V':
-                        printf("%s\n", VERSION);
+                        printf("%s\n", PACKAGE_VERSION);
                         exit(0);
 
                 case 'x':
@@ -577,6 +577,8 @@ int main(int argc, char **argv)
         int newargc;
         char **newargv = NULL;
 
+        log_set_target(LOG_TARGET_AUTO);
+        udev_parse_config();
         log_parse_environment();
         log_open();
 
index 9037aa1304d68a3b31c626babf73b961715ee59d..11d7085153fdea9b983f495d36777ff83bc99482 100644 (file)
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <blkid/blkid.h>
+#include <blkid.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
@@ -30,6 +30,7 @@
 #include "sd-id128.h"
 
 #include "alloc-util.h"
+#include "blkid-util.h"
 #include "efivars.h"
 #include "fd-util.h"
 #include "gpt.h"
@@ -225,10 +226,9 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
         int64_t offset = 0;
         bool noraid = false;
         _cleanup_close_ int fd = -1;
-        blkid_probe pr;
+        _cleanup_blkid_free_probe_ blkid_probe pr = NULL;
         const char *data;
         const char *name;
-        const char *prtype = NULL;
         int nvals;
         int i;
         int err = 0;
@@ -264,8 +264,7 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
         blkid_probe_set_superblocks_flags(pr,
                 BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
                 BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
-                BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION |
-                BLKID_SUBLKS_BADCSUM);
+                BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION);
 
         if (noraid)
                 blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID);
@@ -287,15 +286,6 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
         err = probe_superblocks(pr);
         if (err < 0)
                 goto out;
-        if (blkid_probe_has_value(pr, "SBBADCSUM")) {
-                if (!blkid_probe_lookup_value(pr, "TYPE", &prtype, NULL))
-                        log_warning("incorrect %s checksum on %s",
-                                    prtype, udev_device_get_devnode(dev));
-                else
-                        log_warning("incorrect checksum on %s",
-                                    udev_device_get_devnode(dev));
-                goto out;
-        }
 
         /* If we are a partition then our parent passed on the root
          * partition UUID to us */
@@ -321,7 +311,6 @@ static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool t
         if (is_gpt)
                 find_gpt_root(dev, pr, test);
 
-        blkid_free_probe(pr);
 out:
         if (err < 0)
                 return EXIT_FAILURE;
index 51f364bf94fd027f0ed8c32ec636f1811522e786..60f760ef77021268aed977ebedc8bcb2b14c71f7 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/input.h>
 
 #include "fd-util.h"
+#include "missing.h"
 #include "stdio-util.h"
 #include "string-util.h"
 #include "udev.h"
 #define LONG(x) ((x)/BITS_PER_LONG)
 #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
 
+struct range {
+        unsigned start;
+        unsigned end;
+};
+
+/* key code ranges above BTN_MISC (start is inclusive, stop is exclusive)*/
+static const struct range high_key_blocks[] = {
+        { KEY_OK, BTN_DPAD_UP },
+        { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY }
+};
+
 static inline int abs_size_mm(const struct input_absinfo *absinfo) {
         /* Resolution is defined to be in units/mm for ABS_X/Y */
         return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
@@ -137,6 +149,7 @@ static bool test_pointers(struct udev_device *dev,
                           const unsigned long* bitmask_rel,
                           const unsigned long* bitmask_props,
                           bool test) {
+        int button, axis;
         bool has_abs_coordinates = false;
         bool has_rel_coordinates = false;
         bool has_mt_coordinates = false;
@@ -172,7 +185,8 @@ static bool test_pointers(struct udev_device *dev,
         is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props);
         stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key);
         finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key);
-        has_mouse_button = test_bit(BTN_LEFT, bitmask_key);
+        for (button = BTN_MOUSE; button < BTN_JOYSTICK && !has_mouse_button; button++)
+                has_mouse_button = test_bit(button, bitmask_key);
         has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel);
         has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs);
 
@@ -183,18 +197,15 @@ static bool test_pointers(struct udev_device *dev,
         has_touch = test_bit(BTN_TOUCH, bitmask_key);
         /* joysticks don't necessarily have buttons; e. g.
          * rudders/pedals are joystick-like, but buttonless; they have
-         * other fancy axes */
-        has_joystick_axes_or_buttons = test_bit(BTN_TRIGGER, bitmask_key) ||
-                                       test_bit(BTN_A, bitmask_key) ||
-                                       test_bit(BTN_1, bitmask_key) ||
-                                       test_bit(ABS_RX, bitmask_abs) ||
-                                       test_bit(ABS_RY, bitmask_abs) ||
-                                       test_bit(ABS_RZ, bitmask_abs) ||
-                                       test_bit(ABS_THROTTLE, bitmask_abs) ||
-                                       test_bit(ABS_RUDDER, bitmask_abs) ||
-                                       test_bit(ABS_WHEEL, bitmask_abs) ||
-                                       test_bit(ABS_GAS, bitmask_abs) ||
-                                       test_bit(ABS_BRAKE, bitmask_abs);
+         * other fancy axes. Others have buttons only but no axes. */
+        for (button = BTN_JOYSTICK; button < BTN_DIGI && !has_joystick_axes_or_buttons; button++)
+                has_joystick_axes_or_buttons = test_bit(button, bitmask_key);
+        for (button = BTN_TRIGGER_HAPPY1; button <= BTN_TRIGGER_HAPPY40 && !has_joystick_axes_or_buttons; button++)
+                has_joystick_axes_or_buttons = test_bit(button, bitmask_key);
+        for (button = BTN_DPAD_UP; button <= BTN_DPAD_RIGHT && !has_joystick_axes_or_buttons; button++)
+                has_joystick_axes_or_buttons = test_bit(button, bitmask_key);
+        for (axis = ABS_RX; axis < ABS_PRESSURE && !has_joystick_axes_or_buttons; axis++)
+                has_joystick_axes_or_buttons = test_bit(axis, bitmask_abs);
 
         if (has_abs_coordinates) {
                 if (stylus_or_pen)
@@ -209,7 +220,10 @@ static bool test_pointers(struct udev_device *dev,
                         is_touchscreen = true;
                 else if (has_joystick_axes_or_buttons)
                         is_joystick = true;
+        } else if (has_joystick_axes_or_buttons) {
+                is_joystick = true;
         }
+
         if (has_mt_coordinates) {
                 if (stylus_or_pen)
                         is_tablet = true;
@@ -219,7 +233,9 @@ static bool test_pointers(struct udev_device *dev,
                         is_touchscreen = true;
         }
 
-        if (has_rel_coordinates && has_mouse_button)
+        if (has_mouse_button &&
+            (has_rel_coordinates ||
+            !has_abs_coordinates)) /* mouse buttons and no axis */
                 is_mouse = true;
 
         if (is_pointing_stick)
@@ -260,13 +276,16 @@ static bool test_key(struct udev_device *dev,
                 found |= bitmask_key[i];
                 log_debug("test_key: checking bit block %lu for any keys; found=%i", (unsigned long)i*BITS_PER_LONG, found > 0);
         }
-        /* If there are no keys in the lower block, check the higher block */
+        /* If there are no keys in the lower block, check the higher blocks */
         if (!found) {
-                for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i) {
-                        if (test_bit(i, bitmask_key)) {
-                                log_debug("test_key: Found key %x in high block", i);
-                                found = 1;
-                                break;
+                unsigned block;
+                for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) {
+                        for (i = high_key_blocks[block].start; i < high_key_blocks[block].end; ++i) {
+                                if (test_bit(i, bitmask_key)) {
+                                        log_debug("test_key: Found key %x in high block", i);
+                                        found = 1;
+                                        break;
+                                }
                         }
                 }
         }
index 09024116f2bf4fcabc349be91904f42ba43012e0..e316bb93ba99841dc00fb5acd6a7fc4d572046be 100644 (file)
@@ -29,7 +29,7 @@
 #include "string-util.h"
 #include "udev.h"
 
-static const struct key *keyboard_lookup_key(const char *str, GPERF_LEN_TYPE len);
+static const struct key_name *keyboard_lookup_key(const char *str, GPERF_LEN_TYPE len);
 #include "keyboard-keys-from-name.h"
 
 static int install_force_release(struct udev_device *dev, const unsigned *release, unsigned release_count) {
@@ -76,7 +76,7 @@ static void map_keycode(int fd, const char *devnode, int scancode, const char *k
                 unsigned key;
         } map;
         char *endptr;
-        const struct key *k;
+        const struct key_name *k;
         unsigned keycode_num;
 
         /* translate identifier to key code */
@@ -173,6 +173,9 @@ static void set_trackpoint_sensitivity(struct udev_device *dev, const char *valu
         if (r < 0) {
                 log_error("Unable to parse POINTINGSTICK_SENSITIVITY '%s' for '%s'", value, udev_device_get_devnode(dev));
                 return;
+        } else if (val_i < 0 || val_i > 255) {
+                log_error("POINTINGSTICK_SENSITIVITY %d outside range [0..255] for '%s' ", val_i, udev_device_get_devnode(dev));
+                return;
         }
 
         xsprintf(val_s, "%d", val_i);
@@ -198,6 +201,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
         unsigned release_count = 0;
         _cleanup_close_ int fd = -1;
         const char *node;
+        int has_abs = -1;
 
         node = udev_device_get_devnode(dev);
         if (!node) {
@@ -258,6 +262,24 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
                                         return EXIT_FAILURE;
                         }
 
+                        if (has_abs == -1) {
+                                unsigned long bits;
+                                int rc;
+
+                                rc = ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits);
+                                if (rc < 0) {
+                                        log_error_errno(errno, "Unable to EVIOCGBIT device \"%s\"", node);
+                                        return EXIT_FAILURE;
+                                }
+
+                                has_abs = !!(bits & (1 << EV_ABS));
+                                if (!has_abs)
+                                        log_warning("EVDEV_ABS override set but no EV_ABS present on device \"%s\"", node);
+                        }
+
+                        if (!has_abs)
+                                continue;
+
                         override_abs(fd, node, evcode, udev_list_entry_get_value(entry));
                 } else if (streq(key, "POINTINGSTICK_SENSITIVITY"))
                         set_trackpoint_sensitivity(dev, udev_list_entry_get_value(entry));
index bd7b789cad921fabab9a5280d2f2b26270952e22..46eb6114ff5799e433846057648034126b247526 100644 (file)
@@ -45,6 +45,8 @@
  *                                         — PCI geographical location
  *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
  *                                         — USB port number chain
+ *   v<slot>                               - VIO slot number (IBM PowerVM)
+ *   a<vendor><model>i<instance>           — Platform bus ACPI instance id
  *
  * All multi-function PCI devices will carry the [f<function>] number in the
  * device name, including the function 0 device.
@@ -122,6 +124,8 @@ enum netname_type{
         NET_BCMA,
         NET_VIRTIO,
         NET_CCW,
+        NET_VIO,
+        NET_PLATFORM,
 };
 
 struct netnames {
@@ -139,6 +143,8 @@ struct netnames {
         char usb_ports[IFNAMSIZ];
         char bcma_core[IFNAMSIZ];
         char ccw_busid[IFNAMSIZ];
+        char vio_slot[IFNAMSIZ];
+        char platform_path[IFNAMSIZ];
 };
 
 /* skip intermediate virtio devices */
@@ -319,6 +325,87 @@ out:
         return err;
 }
 
+static int names_vio(struct udev_device *dev, struct netnames *names) {
+        struct udev_device *parent;
+        unsigned busid, slotid, ethid;
+        const char *syspath;
+
+        /* check if our direct parent is a VIO device with no other bus in-between */
+        parent = udev_device_get_parent(dev);
+        if (!parent)
+                return -ENOENT;
+
+        if (!streq_ptr("vio", udev_device_get_subsystem(parent)))
+                 return -ENOENT;
+
+        /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id
+         * selected in the HMC), thus this provides a reliable naming (e.g.
+         * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as
+         * there should only ever be one bus, and then remove leading zeros. */
+        syspath = udev_device_get_syspath(dev);
+
+        if (sscanf(syspath, "/sys/devices/vio/%4x%4x/net/eth%u", &busid, &slotid, &ethid) != 3)
+                return -EINVAL;
+
+        xsprintf(names->vio_slot, "v%u", slotid);
+        names->type = NET_VIO;
+        return 0;
+}
+
+#define _PLATFORM_TEST "/sys/devices/platform/vvvvPPPP"
+#define _PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
+#define _PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
+
+static int names_platform(struct udev_device *dev, struct netnames *names, bool test) {
+        struct udev_device *parent;
+        char vendor[5];
+        unsigned model, instance, ethid;
+        const char *syspath, *pattern, *validchars;
+
+        /* check if our direct parent is a platform device with no other bus in-between */
+        parent = udev_device_get_parent(dev);
+        if (!parent)
+                return -ENOENT;
+
+        if (!streq_ptr("platform", udev_device_get_subsystem(parent)))
+                 return -ENOENT;
+
+        syspath = udev_device_get_syspath(dev);
+
+        /* syspath is too short, to have a valid ACPI instance */
+        if (strlen(syspath) < sizeof _PLATFORM_TEST)
+                return -EINVAL;
+
+        /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */
+        if (syspath[sizeof _PLATFORM_TEST - 1] == ':') {
+                pattern = _PLATFORM_PATTERN4;
+                validchars = UPPERCASE_LETTERS DIGITS;
+        } else {
+                pattern = _PLATFORM_PATTERN3;
+                validchars = UPPERCASE_LETTERS;
+        }
+
+        /* Platform devices are named after ACPI table match, and instance id
+         * eg. "/sys/devices/platform/HISI00C2:00");
+         * The Vendor (3 or 4 char), followed by hexdecimal model number : instance id.
+         */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+        if (sscanf(syspath, pattern, vendor, &model, &instance, &ethid) != 4)
+                return -EINVAL;
+#pragma GCC diagnostic pop
+
+        if (!in_charset(vendor, validchars))
+                return -ENOENT;
+
+        ascii_strlower(vendor);
+
+        xsprintf(names->platform_path, "a%s%xi%u", vendor, model, instance);
+        names->type = NET_PLATFORM;
+        return 0;
+}
+
 static int names_pci(struct udev_device *dev, struct netnames *names) {
         struct udev_device *parent;
 
@@ -591,6 +678,26 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool
                 goto out;
         }
 
+        /* get ibmveth/ibmvnic slot-based names. */
+        err = names_vio(dev, &names);
+        if (err >= 0 && names.type == NET_VIO) {
+                char str[IFNAMSIZ];
+
+                if (snprintf(str, sizeof(str), "%s%s", prefix, names.vio_slot) < (int)sizeof(str))
+                        udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
+                goto out;
+        }
+
+        /* get ACPI path names for ARM64 platform devices */
+        err = names_platform(dev, &names, test);
+        if (err >= 0 && names.type == NET_PLATFORM) {
+                char str[IFNAMSIZ];
+
+                if (snprintf(str, sizeof(str), "%s%s", prefix, names.platform_path) < (int)sizeof(str))
+                        udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+                goto out;
+        }
+
         /* get PCI based path names, we compose only PCI based paths */
         err = names_pci(dev, &names);
         if (err < 0)
index dbefbbe175da06ba52ab93a9e0c43b43a892687a..92e4f8d9c05d740653868299aff9f6f843ef3e44 100644 (file)
@@ -239,7 +239,7 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int
         int err = 0;
 
         memzero(&ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire));
-        strcpy(ctrl_msg_wire.version, "udev-" VERSION);
+        strcpy(ctrl_msg_wire.version, "udev-" PACKAGE_VERSION);
         ctrl_msg_wire.magic = UDEV_CTRL_MAGIC;
         ctrl_msg_wire.type = type;
 
index 3f9c3ed0cfbfc7e4a4bc7c13a3a19a3eed614db0..601f0ee13d11d396eefc0f6248f5873a43fe6a6e 100644 (file)
@@ -58,7 +58,7 @@ struct udev_event *udev_event_new(struct udev_device *dev) {
         event->udev = udev;
         udev_list_init(udev, &event->run_list, false);
         udev_list_init(udev, &event->seclabel_list, false);
-        event->birth_usec = clock_boottime_or_monotonic();
+        event->birth_usec = now(CLOCK_MONOTONIC);
         return event;
 }
 
@@ -520,7 +520,7 @@ static void spawn_read(struct udev_event *event,
                 if (timeout_usec > 0) {
                         usec_t age_usec;
 
-                        age_usec = clock_boottime_or_monotonic() - event->birth_usec;
+                        age_usec = now(CLOCK_MONOTONIC) - event->birth_usec;
                         if (age_usec >= timeout_usec) {
                                 log_error("timeout '%s'", cmd);
                                 return;
@@ -671,13 +671,13 @@ static int spawn_wait(struct udev_event *event,
         if (timeout_usec > 0) {
                 usec_t usec, age_usec;
 
-                usec = now(clock_boottime_or_monotonic());
+                usec = now(CLOCK_MONOTONIC);
                 age_usec = usec - event->birth_usec;
                 if (age_usec < timeout_usec) {
                         if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) {
                                 spawn.timeout_warn = timeout_warn_usec - age_usec;
 
-                                r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(),
+                                r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
                                                       usec + spawn.timeout_warn, USEC_PER_SEC,
                                                       on_spawn_timeout_warning, &spawn);
                                 if (r < 0)
@@ -686,7 +686,7 @@ static int spawn_wait(struct udev_event *event,
 
                         spawn.timeout = timeout_usec - age_usec;
 
-                        r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(),
+                        r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
                                               usec + spawn.timeout, USEC_PER_SEC, on_spawn_timeout, &spawn);
                         if (r < 0)
                                 return r;
index 4d07b8fce03658fac939080694ca145aeacaaa62..294a3225472fa0ba1394d07bccc39c396038377b 100644 (file)
@@ -474,6 +474,13 @@ static int add_token(struct udev_rules *rules, struct token *token) {
         return 0;
 }
 
+static void log_unknown_owner(int error, const char *entity, const char *owner) {
+        if (IN_SET(abs(error), ENOENT, ESRCH))
+                log_error("Specified %s '%s' unknown", entity, owner);
+        else
+                log_error_errno(error, "Error resolving %s '%s': %m", entity, owner);
+}
+
 static uid_t add_uid(struct udev_rules *rules, const char *owner) {
         unsigned int i;
         uid_t uid = 0;
@@ -489,12 +496,8 @@ static uid_t add_uid(struct udev_rules *rules, const char *owner) {
                 }
         }
         r = get_user_creds(&owner, &uid, NULL, NULL, NULL);
-        if (r < 0) {
-                if (r == -ENOENT || r == -ESRCH)
-                        log_error("specified user '%s' unknown", owner);
-                else
-                        log_error_errno(r, "error resolving user '%s': %m", owner);
-        }
+        if (r < 0)
+                log_unknown_owner(r, "user", owner);
 
         /* grow buffer if needed */
         if (rules->uids_cur+1 >= rules->uids_max) {
@@ -536,12 +539,8 @@ static gid_t add_gid(struct udev_rules *rules, const char *group) {
                 }
         }
         r = get_group_creds(&group, &gid);
-        if (r < 0) {
-                if (r == -ENOENT || r == -ESRCH)
-                        log_error("specified group '%s' unknown", group);
-                else
-                        log_error_errno(r, "error resolving group '%s': %m", group);
-        }
+        if (r < 0)
+                log_unknown_owner(r, "group", group);
 
         /* grow buffer if needed */
         if (rules->gids_cur+1 >= rules->gids_max) {
@@ -814,7 +813,7 @@ static const char *get_key_attribute(struct udev *udev, char *str) {
                 attr++;
                 pos = strchr(attr, '}');
                 if (pos == NULL) {
-                        log_error("missing closing brace for format");
+                        log_error("Missing closing brace for format");
                         return NULL;
                 }
                 pos[0] = '\0';
@@ -2119,11 +2118,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
                         event->owner_set = true;
                         r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL);
                         if (r < 0) {
-                                if (r == -ENOENT || r == -ESRCH)
-                                        log_error("specified user '%s' unknown", owner);
-                                else
-                                        log_error_errno(r, "error resolving user '%s': %m", owner);
-
+                                log_unknown_owner(r, "user", owner);
                                 event->uid = 0;
                         }
                         log_debug("OWNER %u %s:%u",
@@ -2145,11 +2140,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
                         event->group_set = true;
                         r = get_group_creds(&gr, &event->gid);
                         if (r < 0) {
-                                if (r == -ENOENT || r == -ESRCH)
-                                        log_error("specified group '%s' unknown", group);
-                                else
-                                        log_error_errno(r, "error resolving group '%s': %m", group);
-
+                                log_unknown_owner(r, "group", group);
                                 event->gid = 0;
                         }
                         log_debug("GROUP %u %s:%u",
@@ -2536,19 +2527,19 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) {
                         }
                         if (mode != (stats.st_mode & 01777)) {
                                 r = chmod(device_node, mode);
-                                if (r < 0) {
-                                        log_error("failed to chmod '%s' %#o", device_node, mode);
-                                        return -errno;
-                                else
+                                if (r < 0)
+                                        return log_error_errno(errno, "Failed to chmod '%s' %#o: %m",
+                                                               device_node, mode);
+                                else
                                         log_debug("chmod '%s' %#o", device_node, mode);
                         }
 
                         if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) {
                                 r = chown(device_node, uid, gid);
-                                if (r < 0) {
-                                        log_error("failed to chown '%s' %u %u ", device_node, uid, gid);
-                                        return -errno;
-                                else
+                                if (r < 0)
+                                        return log_error_errno(errno, "Failed to chown '%s' %u %u: %m",
+                                                               device_node, uid, gid);
+                                else
                                         log_debug("chown '%s' %u %u", device_node, uid, gid);
                         }
 
index a0c2e82d471e39a8986cec54d99febbde9c73531..e384a6f7c9ca10e7168df9f9d1a4b1a0f751b6c7 100644 (file)
@@ -1,5 +1,5 @@
 Name: udev
 Description: udev
-Version: @VERSION@
+Version: @PACKAGE_VERSION@
 
 udevdir=@udevlibexecdir@
index 70a5fa4d7a2b5ec54549bd783d534f240544332d..69b0b9025c1dc0ea18d70ae6bd03548492fc9260 100644 (file)
@@ -352,7 +352,7 @@ static int trie_store(struct trie *trie, const char *filename) {
         int64_t size;
         struct trie_header_f h = {
                 .signature = HWDB_SIG,
-                .tool_version = htole64(atoi(VERSION)),
+                .tool_version = htole64(atoi(PACKAGE_VERSION)),
                 .header_size = htole64(sizeof(struct trie_header_f)),
                 .node_size = htole64(sizeof(struct trie_node_f)),
                 .child_entry_size = htole64(sizeof(struct trie_child_entry_f)),
index 90cdfa16c7630a58a9ac84e66237e61e707b904a..16b2aab0a19ed5a81af65a2582ecaf05c18c2422 100644 (file)
@@ -376,7 +376,7 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
                         export_prefix = optarg;
                         break;
                 case 'V':
-                        printf("%s\n", VERSION);
+                        printf("%s\n", PACKAGE_VERSION);
                         return 0;
                 case 'h':
                         help();
index f6318343415150369cc8335ca6d32775e9b3415f..94a59186ed83f34f6e2bfe0c08ab8211ea310504 100644 (file)
@@ -41,9 +41,9 @@ static void print_device(struct udev_device *device, const char *source, int pro
         struct timespec ts;
 
         assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
-        printf("%-6s[%"PRI_TIME".%06ld] %-8s %s (%s)\n",
+        printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n",
                source,
-               ts.tv_sec, ts.tv_nsec/1000,
+               ts.tv_sec, (nsec_t)ts.tv_nsec/1000,
                udev_device_get_action(device),
                udev_device_get_devpath(device),
                udev_device_get_subsystem(device));
index 07b667f131965c17ca319c84be61fffa3e6f515e..e8ffe2f309d9161d226cda2298e6ec7ba8590f55 100644 (file)
@@ -59,7 +59,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
                 {}
         };
 
-        log_debug("version %s", VERSION);
+        log_debug("version %s", PACKAGE_VERSION);
 
         while ((c = getopt_long(argc, argv, "a:N:h", options, NULL)) >= 0)
                 switch (c) {
index a6a873e5de7627ef13b0695aa1010f01b5458ed1..befc3bad7b764733946e8f61858d821aa8e5e2cc 100644 (file)
 #include "selinux-util.h"
 #include "string-util.h"
 #include "udev.h"
+#include "udev-util.h"
 
 static int adm_version(struct udev *udev, int argc, char *argv[]) {
-        printf("%s\n", VERSION);
+        printf("%s\n", PACKAGE_VERSION);
         return 0;
 }
 
@@ -87,14 +88,16 @@ int main(int argc, char *argv[]) {
         unsigned int i;
         int rc = 1, c;
 
-        udev = udev_new();
-        if (udev == NULL)
-                goto out;
-
+        udev_parse_config();
         log_parse_environment();
         log_open();
+
         mac_selinux_init();
 
+        udev = udev_new();
+        if (udev == NULL)
+                goto out;
+
         while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
                 switch (c) {
 
index ce2ff89b8548bafab4c561876651f5c8cb0309b8..acbddd41807e8a794e636122b253ef683d42bff3 100644 (file)
@@ -284,12 +284,12 @@ static void worker_attach_event(struct worker *worker, struct event *event) {
 
         e = worker->manager->event;
 
-        assert_se(sd_event_now(e, clock_boottime_or_monotonic(), &usec) >= 0);
+        assert_se(sd_event_now(e, CLOCK_MONOTONIC, &usec) >= 0);
 
-        (void) sd_event_add_time(e, &event->timeout_warning, clock_boottime_or_monotonic(),
+        (void) sd_event_add_time(e, &event->timeout_warning, CLOCK_MONOTONIC,
                                  usec + arg_event_timeout_warn_usec, USEC_PER_SEC, on_event_timeout_warning, event);
 
-        (void) sd_event_add_time(e, &event->timeout, clock_boottime_or_monotonic(),
+        (void) sd_event_add_time(e, &event->timeout, CLOCK_MONOTONIC,
                                  usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event);
 }
 
@@ -755,9 +755,9 @@ static void manager_exit(Manager *manager) {
         event_queue_cleanup(manager, EVENT_QUEUED);
         manager_kill_workers(manager);
 
-        assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
+        assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0);
 
-        r = sd_event_add_time(manager->event, NULL, clock_boottime_or_monotonic(),
+        r = sd_event_add_time(manager->event, NULL, CLOCK_MONOTONIC,
                               usec + 30 * USEC_PER_SEC, USEC_PER_SEC, on_exit_timeout, manager);
         if (r < 0)
                 return;
@@ -791,7 +791,7 @@ static void event_queue_start(Manager *manager) {
             manager->exit || manager->stop_exec_queue)
                 return;
 
-        assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
+        assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0);
         /* check for changed config, every 3 seconds at most */
         if (manager->last_usec == 0 ||
             (usec - manager->last_usec) > 3 * USEC_PER_SEC) {
@@ -1492,7 +1492,7 @@ static int parse_argv(int argc, char *argv[]) {
                         help();
                         return 0;
                 case 'V':
-                        printf("%s\n", VERSION);
+                        printf("%s\n", PACKAGE_VERSION);
                         return 0;
                 case '?':
                         return -EINVAL;
@@ -1663,6 +1663,7 @@ int main(int argc, char *argv[]) {
         int r;
 
         log_set_target(LOG_TARGET_AUTO);
+        udev_parse_config();
         log_parse_environment();
         log_open();
 
@@ -1740,7 +1741,7 @@ int main(int argc, char *argv[]) {
         if (arg_daemonize) {
                 pid_t pid;
 
-                log_info("starting version " VERSION);
+                log_info("starting version " PACKAGE_VERSION);
 
                 /* connect /dev/null to stdin, stdout, stderr */
                 if (log_get_max_level() < LOG_DEBUG) {
index d466e1b759a7c44aeb6b2d5742697a5ea5cff299..ec467f1953a259e442a7bdb9d149be1ba47628eb 100644 (file)
@@ -17,9 +17,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "fd-util.h"
-#include "fileio.h"
-#include "io-util.h"
+#include "alloc-util.h"
+#include "fileio-label.h"
 #include "selinux-util.h"
 #include "util.h"
 
         "# was updated. See man:systemd-update-done.service(8).\n"
 
 static int apply_timestamp(const char *path, struct timespec *ts) {
-        struct timespec twice[2] = {
-                *ts,
-                *ts
-        };
-        _cleanup_fclose_ FILE *f = NULL;
-        int fd = -1;
+        _cleanup_free_ char *message = NULL;
         int r;
 
-        assert(path);
-        assert(ts);
-
         /*
          * We store the timestamp both as mtime of the file and in the file itself,
          * to support filesystems which cannot store nanosecond-precision timestamps.
-         * Hence, don't bother updating the file, let's just rewrite it.
          */
 
-        r = mac_selinux_create_file_prepare(path, S_IFREG);
-        if (r < 0)
-                return log_error_errno(r, "Failed to set SELinux context for %s: %m", path);
-
-        fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
-        mac_selinux_create_file_clear();
-
-        if (fd < 0) {
-                if (errno == EROFS)
-                        return log_debug("Can't create timestamp file %s, file system is read-only.", path);
-
-                return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path);
-        }
+        if (asprintf(&message,
+                     MESSAGE
+                     "TIMESTAMP_NSEC=" NSEC_FMT "\n",
+                     timespec_load_nsec(ts)) < 0)
+                return log_oom();
 
-        f = fdopen(fd, "we");
-        if (!f) {
-                safe_close(fd);
-                return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path);
-        }
-
-        (void) fprintf(f,
-                       MESSAGE
-                       "TIMESTAMP_NSEC=" NSEC_FMT "\n",
-                       timespec_load_nsec(ts));
-
-        r = fflush_and_check(f);
+        r = write_string_file_atomic_label_ts(path, message, ts);
+        if (r == -EROFS)
+                return log_debug("Cannot create \"%s\", file system is read-only.", path);
         if (r < 0)
-                return log_error_errno(r, "Failed to write timestamp file: %m");
-
-        if (futimens(fd, twice) < 0)
-                return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
-
+                return log_error_errno(r, "Failed to write \"%s\": %m", path);
         return 0;
 }
 
diff --git a/src/vconsole/meson.build b/src/vconsole/meson.build
new file mode 100644 (file)
index 0000000..1260b53
--- /dev/null
@@ -0,0 +1,8 @@
+if conf.get('ENABLE_VCONSOLE', false)
+        vconsole_rules = configure_file(
+                input : '90-vconsole.rules.in',
+                output : '90-vconsole.rules',
+                configuration : substs)
+        install_data(vconsole_rules,
+                     install_dir : udevrulesdir)
+endif
index a0ab5990fca7ad838872d47e5de14ab55c43b058..f531aece7f4bc95f765ed26049c8b6b38e3f844f 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
+#include <sysexits.h>
 #include <termios.h>
 #include <unistd.h>
 
 #include "signal-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
+#include "strv.h"
 #include "terminal-util.h"
 #include "util.h"
 #include "virt.h"
 
-static bool is_vconsole(int fd) {
+static int verify_vc_device(int fd) {
         unsigned char data[1];
+        int r;
 
         data[0] = TIOCL_GETFGCONSOLE;
-        return ioctl(fd, TIOCLINUX, data) >= 0;
+        r = ioctl(fd, TIOCLINUX, data);
+        return r < 0 ? -errno : r;
 }
 
-static bool is_allocated(unsigned int idx) {
-        char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)];
+static int verify_vc_allocation(unsigned idx) {
+        char vcname[sizeof("/dev/vcs") + DECIMAL_STR_MAX(unsigned) - 2];
+        int r;
 
-        xsprintf(vcname, "/dev/vcs%i", idx);
-        return access(vcname, F_OK) == 0;
+        xsprintf(vcname, "/dev/vcs%u", idx);
+        r = access(vcname, F_OK);
+        return r < 0 ? -errno : r;
 }
 
-static bool is_allocated_byfd(int fd) {
+static int verify_vc_allocation_byfd(int fd) {
         struct vt_stat vcs = {};
+        int r;
 
-        if (ioctl(fd, VT_GETSTATE, &vcs) < 0) {
-                log_warning_errno(errno, "VT_GETSTATE failed: %m");
-                return false;
-        }
-        return is_allocated(vcs.v_active);
+        r = ioctl(fd, VT_GETSTATE, &vcs);
+        return r < 0 ? -errno : verify_vc_allocation(vcs.v_active);
 }
 
-static bool is_settable(int fd) {
+static int verify_vc_kbmode(int fd) {
         int r, curr_mode;
 
         r = ioctl(fd, KDGKBMODE, &curr_mode);
@@ -80,7 +84,10 @@ static bool is_settable(int fd) {
          *
          * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
          */
-        return r == 0 && IN_SET(curr_mode, K_XLATE, K_UNICODE);
+        if (r < 0)
+                return -errno;
+
+        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
 }
 
 static int toggle_utf8(const char *name, int fd, bool utf8) {
@@ -99,10 +106,7 @@ static int toggle_utf8(const char *name, int fd, bool utf8) {
 
         r = tcgetattr(fd, &tc);
         if (r >= 0) {
-                if (utf8)
-                        tc.c_iflag |= IUTF8;
-                else
-                        tc.c_iflag &= ~IUTF8;
+                SET_FLAG(tc.c_iflag, IUTF8, utf8);
                 r = tcsetattr(fd, TCSANOW, &tc);
         }
         if (r < 0)
@@ -124,8 +128,9 @@ static int toggle_utf8_sysfs(bool utf8) {
 }
 
 static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) {
+        _cleanup_free_ char *cmd = NULL;
         const char *args[8];
-        int i = 0;
+        unsigned i = 0;
         pid_t pid;
 
         /* An empty map means kernel map */
@@ -143,6 +148,9 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
                 args[i++] = map_toggle;
         args[i++] = NULL;
 
+        log_debug("Executing \"%s\"...",
+                  strnull((cmd = strv_join((char**) args, " "))));
+
         pid = fork();
         if (pid < 0)
                 return log_error_errno(errno, "Failed to fork: %m");
@@ -159,8 +167,9 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
 }
 
 static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) {
+        _cleanup_free_ char *cmd = NULL;
         const char *args[9];
-        int i = 0;
+        unsigned i = 0;
         pid_t pid;
 
         /* Any part can be set independently */
@@ -182,6 +191,9 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
                 args[i++] = font;
         args[i++] = NULL;
 
+        log_debug("Executing \"%s\"...",
+                  strnull((cmd = strv_join((char**) args, " "))));
+
         pid = fork();
         if (pid < 0)
                 return log_error_errno(errno, "Failed to fork: %m");
@@ -198,7 +210,7 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
 }
 
 /*
- * A newly allocated VT uses the font from the active VT. Here
+ * A newly allocated VT uses the font from the source VT. Here
  * we update all possibly already allocated VTs with the configured
  * font. It also allows to restart systemd-vconsole-setup.service,
  * to apply a new font to all VTs.
@@ -206,18 +218,18 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
  * We also setup per-console utf8 related stuff: kbdmode, term
  * processing, stty iutf8.
  */
-static void setup_remaining_vcs(int fd, bool utf8) {
+static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
         struct console_font_op cfo = {
                 .op = KD_FONT_OP_GET,
                 .width = UINT_MAX, .height = UINT_MAX,
                 .charcount = UINT_MAX,
         };
-        struct vt_stat vcs = {};
         struct unimapinit adv = {};
         struct unimapdesc unimapd;
         _cleanup_free_ struct unipair* unipairs = NULL;
         _cleanup_free_ void *fontbuf = NULL;
-        int i, r;
+        unsigned i;
+        int r;
 
         unipairs = new(struct unipair, USHRT_MAX);
         if (!unipairs) {
@@ -225,15 +237,8 @@ static void setup_remaining_vcs(int fd, bool utf8) {
                 return;
         }
 
-        /* get active, and 16 bit mask of used VT numbers */
-        r = ioctl(fd, VT_GETSTATE, &vcs);
-        if (r < 0) {
-                log_warning_errno(errno, "VT_GETSTATE failed, ignoring remaining consoles: %m");
-                return;
-        }
-
         /* get metadata of the current font (width, height, count) */
-        r = ioctl(fd, KDFONTOP, &cfo);
+        r = ioctl(src_fd, KDFONTOP, &cfo);
         if (r < 0)
                 log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to get the font metadata: %m");
         else {
@@ -253,15 +258,15 @@ static void setup_remaining_vcs(int fd, bool utf8) {
                                 log_oom();
                                 return;
                         }
-                        /* get fonts from source console */
+                        /* get fonts from the source console */
                         cfo.data = fontbuf;
-                        r = ioctl(fd, KDFONTOP, &cfo);
+                        r = ioctl(src_fd, KDFONTOP, &cfo);
                         if (r < 0)
                                 log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to read the font data: %m");
                         else {
                                 unimapd.entries  = unipairs;
                                 unimapd.entry_ct = USHRT_MAX;
-                                r = ioctl(fd, GIO_UNIMAP, &unimapd);
+                                r = ioctl(src_fd, GIO_UNIMAP, &unimapd);
                                 if (r < 0)
                                         log_warning_errno(errno, "GIO_UNIMAP failed while trying to read unicode mappings: %m");
                                 else
@@ -274,21 +279,21 @@ static void setup_remaining_vcs(int fd, bool utf8) {
                 log_warning("Fonts will not be copied to remaining consoles");
 
         for (i = 1; i <= 63; i++) {
-                char ttyname[strlen("/dev/tty") + DECIMAL_STR_MAX(int)];
+                char ttyname[sizeof("/dev/tty63")];
                 _cleanup_close_ int fd_d = -1;
 
-                if (i == vcs.v_active || !is_allocated(i))
+                if (i == src_idx || verify_vc_allocation(i) < 0)
                         continue;
 
                 /* try to open terminal */
-                xsprintf(ttyname, "/dev/tty%i", i);
-                fd_d = open_terminal(ttyname, O_RDWR|O_CLOEXEC);
+                xsprintf(ttyname, "/dev/tty%u", i);
+                fd_d = open_terminal(ttyname, O_RDWR|O_CLOEXEC|O_NOCTTY);
                 if (fd_d < 0) {
-                        log_warning_errno(fd_d, "Unable to open tty%i, fonts will not be copied: %m", i);
+                        log_warning_errno(fd_d, "Unable to open tty%u, fonts will not be copied: %m", i);
                         continue;
                 }
 
-                if (!is_settable(fd_d))
+                if (verify_vc_kbmode(fd_d) < 0)
                         continue;
 
                 toggle_utf8(ttyname, fd_d, utf8);
@@ -298,22 +303,24 @@ static void setup_remaining_vcs(int fd, bool utf8) {
 
                 r = ioctl(fd_d, KDFONTOP, &cfo);
                 if (r < 0) {
-                        log_warning_errno(errno, "KD_FONT_OP_SET failed, fonts will not be copied to tty%i: %m", i);
+                        log_warning_errno(errno, "KD_FONT_OP_SET failed, fonts will not be copied to tty%u: %m", i);
                         continue;
                 }
 
-                /* copy unicode translation table */
-                /* unimapd is a ushort count and a pointer to an
-                   array of struct unipair { ushort, ushort } */
+                /*
+                 * copy unicode translation table
+                 * unimapd is a ushort count and a pointer to an
+                 * array of struct unipair { ushort, ushort }
+                 */
                 r = ioctl(fd_d, PIO_UNIMAPCLR, &adv);
                 if (r < 0) {
-                        log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%i: %m", i);
+                        log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%u: %m", i);
                         continue;
                 }
 
                 r = ioctl(fd_d, PIO_UNIMAP, &unimapd);
                 if (r < 0) {
-                        log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%i: %m", i);
+                        log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%u: %m", i);
                         continue;
                 }
 
@@ -321,14 +328,91 @@ static void setup_remaining_vcs(int fd, bool utf8) {
         }
 }
 
+static int find_source_vc(char **ret_path, unsigned *ret_idx) {
+        _cleanup_free_ char *path = NULL;
+        unsigned i;
+        int ret_fd, r, err = 0;
+
+        path = new(char, sizeof("/dev/tty63"));
+        if (path == NULL)
+                return log_oom();
+
+        for (i = 1; i <= 63; i++) {
+                _cleanup_close_ int fd = -1;
+
+                r = verify_vc_allocation(i);
+                if (r < 0) {
+                        if (!err)
+                                err = -r;
+                        continue;
+                }
+
+                sprintf(path, "/dev/tty%u", i);
+                fd = open_terminal(path, O_RDWR|O_CLOEXEC|O_NOCTTY);
+                if (fd < 0) {
+                        if (!err)
+                                err = -fd;
+                        continue;
+                }
+                r = verify_vc_kbmode(fd);
+                if (r < 0) {
+                        if (!err)
+                                err = -r;
+                        continue;
+                }
+
+                /* all checks passed, return this one as a source console */
+                *ret_idx = i;
+                *ret_path = path;
+                path = NULL;
+                ret_fd = fd;
+                fd = -1;
+                return ret_fd;
+        }
+
+        return log_error_errno(err, "No usable source console found: %m");
+}
+
+static int verify_source_vc(char **ret_path, const char *src_vc) {
+        char *path;
+        _cleanup_close_ int fd = -1;
+        int ret_fd, r;
+
+        fd = open_terminal(src_vc, O_RDWR|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return log_error_errno(fd, "Failed to open %s: %m", src_vc);
+
+        r = verify_vc_device(fd);
+        if (r < 0)
+                return log_error_errno(r, "Device %s is not a virtual console: %m", src_vc);
+
+        r = verify_vc_allocation_byfd(fd);
+        if (r < 0)
+                return log_error_errno(r, "Virtual console %s is not allocated: %m", src_vc);
+
+        r = verify_vc_kbmode(fd);
+        if (r < 0)
+                return log_error_errno(r, "Virtual console %s is not in K_XLATE or K_UNICODE: %m", src_vc);
+
+        path = strdup(src_vc);
+        if (path == NULL)
+                return log_oom();
+
+        *ret_path = path;
+        ret_fd = fd;
+        fd = -1;
+        return ret_fd;
+}
+
 int main(int argc, char **argv) {
-        const char *vc;
         _cleanup_free_ char
+                *vc = NULL,
                 *vc_keymap = NULL, *vc_keymap_toggle = NULL,
                 *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL;
         _cleanup_close_ int fd = -1;
-        bool utf8, font_copy = false, font_ok, keyboard_ok;
-        int r = EXIT_FAILURE;
+        bool utf8, keyboard_ok;
+        unsigned idx = 0;
+        int r;
 
         log_set_target(LOG_TARGET_AUTO);
         log_parse_environment();
@@ -337,32 +421,12 @@ int main(int argc, char **argv) {
         umask(0022);
 
         if (argv[1])
-                vc = argv[1];
-        else {
-                vc = "/dev/tty0";
-                font_copy = true;
-        }
-
-        fd = open_terminal(vc, O_RDWR|O_CLOEXEC);
-        if (fd < 0) {
-                log_error_errno(fd, "Failed to open %s: %m", vc);
-                return EXIT_FAILURE;
-        }
+                fd = verify_source_vc(&vc, argv[1]);
+        else
+                fd = find_source_vc(&vc, &idx);
 
-        if (!is_vconsole(fd)) {
-                log_error("Device %s is not a virtual console.", vc);
+        if (fd < 0)
                 return EXIT_FAILURE;
-        }
-
-        if (!is_allocated_byfd(fd)) {
-                log_error("Virtual console %s is not allocated.", vc);
-                return EXIT_FAILURE;
-        }
-
-        if (!is_settable(fd)) {
-                log_error("Virtual console %s is not in K_XLATE or K_UNICODE.", vc);
-                return EXIT_FAILURE;
-        }
 
         utf8 = is_locale_utf8();
 
@@ -373,7 +437,6 @@ int main(int argc, char **argv) {
                            "FONT_MAP", &vc_font_map,
                            "FONT_UNIMAP", &vc_font_unimap,
                            NULL);
-
         if (r < 0 && r != -ENOENT)
                 log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m");
 
@@ -390,22 +453,27 @@ int main(int argc, char **argv) {
                                    "vconsole.font.map", &vc_font_map,
                                    "vconsole.font.unimap", &vc_font_unimap,
                                    NULL);
-
                 if (r < 0 && r != -ENOENT)
                         log_warning_errno(r, "Failed to read /proc/cmdline: %m");
         }
 
         toggle_utf8_sysfs(utf8);
         toggle_utf8(vc, fd, utf8);
-        font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) == 0;
+
+        r = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap);
         keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0;
 
-        if (font_copy) {
-                if (font_ok)
-                        setup_remaining_vcs(fd, utf8);
+        if (idx > 0) {
+                if (r == 0)
+                        setup_remaining_vcs(fd, idx, utf8);
+                else if (r == EX_OSERR)
+                        /* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails.
+                         * This might mean various things, but in particular lack of a graphical
+                         * console. Let's be generous and not treat this as an error. */
+                        log_notice("Setting fonts failed with a \"system error\", ignoring.");
                 else
                         log_warning("Setting source virtual console failed, ignoring remaining ones");
         }
 
-        return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE;
+        return IN_SET(r, 0, EX_OSERR) && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build
new file mode 100644 (file)
index 0000000..1b6707d
--- /dev/null
@@ -0,0 +1,21 @@
+install_data(
+        '50-default.conf',
+        install_dir : sysctldir)
+
+in_files = []
+
+if conf.get('ENABLE_COREDUMP', false)
+        in_files += ['50-coredump.conf']
+endif
+
+foreach file : in_files
+        gen = configure_file(
+                input : file + '.in',
+                output : file,
+                configuration : substs)
+        install_data(gen,
+                     install_dir : sysctldir)
+endforeach
+
+meson.add_install_script('sh', '-c',
+                         mkdir_p.format(join_paths(sysconfdir, 'sysctl.d')))
index 6b5349dc8df8e463266aa446695fe83bb18c09c3..3ba4bb760df9a73b143e30407e1429666110a2bb 100644 (file)
@@ -15,7 +15,6 @@ enable getty@.service
 enable systemd-timesyncd.service
 enable systemd-networkd.service
 enable systemd-resolved.service
-enable systemd-networkd-wait-online.service
 
 disable console-getty.service
 disable debug-shell.service
index b2dc5ebd4ffd43304792fcd0943a3aa7b1df7c53..7d6021e855a6e26f15e0b179cb9979c67e0ac059 100644 (file)
@@ -29,6 +29,7 @@ g dialout -     -            -
 g disk    -     -            -
 g input   -     -            -
 g lp      -     -            -
+g kvm     -     -            -
 g tape    -     -            -
 g video   -     -            -
 
diff --git a/sysusers.d/meson.build b/sysusers.d/meson.build
new file mode 100644 (file)
index 0000000..b7c02cf
--- /dev/null
@@ -0,0 +1,31 @@
+in_files = ['basic.conf']
+
+enable_sysusers = conf.get('ENABLE_SYSUSERS', false)
+
+foreach file : in_files
+        gen = configure_file(
+                input : file + '.in',
+                output : file,
+                configuration : substs)
+        if enable_sysusers
+                install_data(gen,
+                             install_dir : sysusersdir)
+        endif
+endforeach
+
+m4_files = ['systemd.conf']
+
+if conf.get('ENABLE_REMOTE', false) and conf.get('HAVE_MICROHTTPD', false)
+        m4_files += ['systemd-remote.conf']
+endif
+
+foreach file : m4_files
+        custom_target(
+                'sysusers.d_' + file,
+                input : file + '.m4',
+                output: file,
+                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                capture : true,
+                install : enable_sysusers,
+                install_dir : sysusersdir)
+endforeach
index fa7e73ce3ad17343c638bef03a5a891b97e028e3..58f67f50fd51b992b1cf32156efe1144ed5fcea2 100644 (file)
@@ -3,7 +3,7 @@ subdirectories named "test/TEST-??-*", which are run one by one.
 
 To run the extended testsuite do the following:
 
-$ make all
+$ make all  # Avoid the "sudo make" below building anything as root
 $ cd test
 $ sudo make clean check
 ...
index e20f47014396257f4e99cebb8f9a2488f8267a7c..c252bdfbad014529e43c038456d82eabf2206db0 100755 (executable)
@@ -67,23 +67,23 @@ EOL
 systemctl start test.socket
 systemctl is-active test.socket
 [[ "$(stat --format='%G' /run/test.socket)" == adm ]]
-echo A | nc -U /run/test.socket
+echo A | nc -w1 -U /run/test.socket
 
 mv $U ${U}.disabled
 systemctl daemon-reload
 systemctl is-active test.socket
 [[ "$(stat --format='%G' /run/test.socket)" == adm ]]
-echo B | nc -U /run/test.socket && exit 1
+echo B | nc -w1 -U /run/test.socket && exit 1
 
 mv ${U}.disabled $U
 systemctl daemon-reload
 systemctl is-active test.socket
-echo C | nc -U /run/test.socket && exit 1
+echo C | nc -w1 -U /run/test.socket && exit 1
 [[ "$(stat --format='%G' /run/test.socket)" == adm ]]
 
 systemctl restart test.socket
 systemctl is-active test.socket
-echo D | nc -U /run/test.socket
+echo D | nc -w1 -U /run/test.socket
 [[ "$(stat --format='%G' /run/test.socket)" == adm ]]
 
 
index 4b7abd24aebf2047742adf3f21853cf888d7734a..402b4f83abd3010901c4ef0b1ced2bf110471eda 100755 (executable)
@@ -1,6 +1,6 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 
-OUTFILE_HEADER = """#!/usr/bin/python3
+OUTFILE_HEADER = """#!/usr/bin/env python3
 #
 # create-sys-script.py
 #
diff --git a/test/meson.build b/test/meson.build
new file mode 100644 (file)
index 0000000..55e693a
--- /dev/null
@@ -0,0 +1,167 @@
+test_data_files = '''
+        a.service
+        basic.target
+        b.service
+        c.service
+        daughter.service
+        d.service
+        end.service
+        e.service
+        f.service
+        grandchild.service
+        g.service
+        hello-after-sleep.target
+        hello.service
+        h.service
+        parent-deep.slice
+        parent.slice
+        sched_idle_bad.service
+        sched_idle_ok.service
+        sched_rr_bad.service
+        sched_rr_change.service
+        sched_rr_ok.service
+        shutdown.target
+        sleep.service
+        sockets.target
+        son.service
+        sysinit.target
+        testsuite.target
+        timers.target
+        unstoppable.service
+        test-path/paths.target
+        test-path/basic.target
+        test-path/sysinit.target
+        test-path/path-changed.service
+        test-path/path-directorynotempty.service
+        test-path/path-existsglob.service
+        test-path/path-exists.service
+        test-path/path-makedirectory.service
+        test-path/path-modified.service
+        test-path/path-mycustomunit.service
+        test-path/path-service.service
+        test-path/path-changed.path
+        test-path/path-directorynotempty.path
+        test-path/path-existsglob.path
+        test-path/path-exists.path
+        test-path/path-makedirectory.path
+        test-path/path-modified.path
+        test-path/path-unit.path
+        test-execute/exec-environment-empty.service
+        test-execute/exec-environment-multiple.service
+        test-execute/exec-environment.service
+        test-execute/exec-passenvironment-absent.service
+        test-execute/exec-passenvironment-empty.service
+        test-execute/exec-passenvironment-repeated.service
+        test-execute/exec-passenvironment.service
+        test-execute/exec-group.service
+        test-execute/exec-group-nfsnobody.service
+        test-execute/exec-supplementarygroups.service
+        test-execute/exec-supplementarygroups-single-group.service
+        test-execute/exec-supplementarygroups-single-group-user.service
+        test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
+        test-execute/exec-supplementarygroups-multiple-groups-withgid.service
+        test-execute/exec-supplementarygroups-multiple-groups-withuid.service
+        test-execute/exec-dynamicuser-fixeduser.service
+        test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service
+        test-execute/exec-dynamicuser-supplementarygroups.service
+        test-execute/exec-ignoresigpipe-no.service
+        test-execute/exec-ignoresigpipe-yes.service
+        test-execute/exec-personality-x86-64.service
+        test-execute/exec-personality-x86.service
+        test-execute/exec-personality-s390.service
+        test-execute/exec-personality-ppc64.service
+        test-execute/exec-personality-ppc64le.service
+        test-execute/exec-personality-aarch64.service
+        test-execute/exec-privatedevices-no.service
+        test-execute/exec-privatedevices-yes.service
+        test-execute/exec-privatedevices-no-capability-mknod.service
+        test-execute/exec-privatedevices-yes-capability-mknod.service
+        test-execute/exec-protectkernelmodules-no-capabilities.service
+        test-execute/exec-protectkernelmodules-yes-capabilities.service
+        test-execute/exec-protectkernelmodules-yes-mount-propagation.service
+        test-execute/exec-privatetmp-no.service
+        test-execute/exec-privatetmp-yes.service
+        test-execute/exec-readonlypaths.service
+        test-execute/exec-readonlypaths-mount-propagation.service
+        test-execute/exec-readwritepaths-mount-propagation.service
+        test-execute/exec-inaccessiblepaths-mount-propagation.service
+        test-execute/exec-inaccessiblepaths-proc.service
+        test-execute/exec-spec-interpolation.service
+        test-execute/exec-systemcallerrornumber.service
+        test-execute/exec-systemcallfilter-failing2.service
+        test-execute/exec-systemcallfilter-failing.service
+        test-execute/exec-systemcallfilter-not-failing2.service
+        test-execute/exec-systemcallfilter-not-failing.service
+        test-execute/exec-systemcallfilter-system-user.service
+        test-execute/exec-systemcallfilter-system-user-nfsnobody.service
+        test-execute/exec-user.service
+        test-execute/exec-user-nfsnobody.service
+        test-execute/exec-workingdirectory.service
+        test-execute/exec-umask-0177.service
+        test-execute/exec-umask-default.service
+        test-execute/exec-privatenetwork-yes.service
+        test-execute/exec-environmentfile.service
+        test-execute/exec-oomscoreadjust-positive.service
+        test-execute/exec-oomscoreadjust-negative.service
+        test-execute/exec-ioschedulingclass-best-effort.service
+        test-execute/exec-ioschedulingclass-idle.service
+        test-execute/exec-ioschedulingclass-none.service
+        test-execute/exec-ioschedulingclass-realtime.service
+        test-execute/exec-capabilityboundingset-invert.service
+        test-execute/exec-capabilityboundingset-merge.service
+        test-execute/exec-capabilityboundingset-reset.service
+        test-execute/exec-capabilityboundingset-simple.service
+        test-execute/exec-capabilityambientset.service
+        test-execute/exec-capabilityambientset-nfsnobody.service
+        test-execute/exec-capabilityambientset-merge.service
+        test-execute/exec-capabilityambientset-merge-nfsnobody.service
+        test-execute/exec-runtimedirectory.service
+        test-execute/exec-runtimedirectory-mode.service
+        test-execute/exec-runtimedirectory-owner.service
+        test-execute/exec-runtimedirectory-owner-nfsnobody.service
+        test-execute/exec-restrict-namespaces-no.service
+        test-execute/exec-restrict-namespaces-yes.service
+        test-execute/exec-restrict-namespaces-mnt.service
+        test-execute/exec-restrict-namespaces-mnt-blacklist.service
+        test-execute/exec-read-only-path-succeed.service
+        test-execute/exec-privatedevices-yes-capability-sys-rawio.service
+        test-execute/exec-privatedevices-no-capability-sys-rawio.service
+        bus-policy/hello.conf
+        bus-policy/methods.conf
+        bus-policy/ownerships.conf
+        bus-policy/signals.conf
+        bus-policy/check-own-rules.conf
+        bus-policy/many-rules.conf
+        bus-policy/test.conf
+        hwdb/10-bad.hwdb
+        journal-data/journal-1.txt
+        journal-data/journal-2.txt
+'''.split()
+
+if conf.get('ENABLE_RESOLVED', false)
+        test_data_files += '''
+                test-resolve/_openpgpkey.fedoraproject.org.pkts
+                test-resolve/fedoraproject.org.pkts
+                test-resolve/gandi.net.pkts
+                test-resolve/google.com.pkts
+                test-resolve/root.pkts
+                test-resolve/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts
+                test-resolve/teamits.com.pkts
+                test-resolve/zbyszek@fedoraproject.org.pkts
+                test-resolve/_443._tcp.fedoraproject.org.pkts
+                test-resolve/kyhwana.org.pkts
+                test-resolve/fake-caa.pkts
+        '''.split()
+endif
+
+if install_tests
+        foreach file : test_data_files
+                subdir = file.split('/')[0]
+                if subdir == file
+                        subdir = ''
+                endif
+
+                install_data(file,
+                             install_dir : testsdir + '/testdata/' + subdir)
+        endforeach
+endif
index e0dddeb05389bc8cc734b3a9309c595bb3f81384..eee8b65ec01050a8cebcac618228e54398033d41 100755 (executable)
@@ -96,10 +96,20 @@ class NetworkdTestingUtilities:
         dropin_path = os.path.join(dropin_dir, "%s.conf" % dropin_name)
 
         os.makedirs(dropin_dir, exist_ok=True)
+        self.addCleanup(os.rmdir, dropin_dir)
         with open(dropin_path, 'w') as dropin:
             dropin.write(contents)
         self.addCleanup(os.remove, dropin_path)
 
+    def read_attr(self, link, attribute):
+        """Read a link attributed from the sysfs."""
+        # Note we we don't want to check if interface `link' is managed, we
+        # want to evaluate link variable and pass the value of the link to
+        # assert_link_states e.g. eth0=managed.
+        self.assert_link_states(**{link:'managed'})
+        with open(os.path.join('/sys/class/net', link, attribute)) as f:
+            return f.readline().strip()
+
     def assert_link_states(self, **kwargs):
         """Match networkctl link states to the given ones.
 
@@ -140,6 +150,74 @@ class NetworkdTestingUtilities:
             self.fail("Missing links in status output: %s" % interfaces)
 
 
+class BridgeTest(NetworkdTestingUtilities, unittest.TestCase):
+    """Provide common methods for testing networkd against servers."""
+
+    def setUp(self):
+        self.write_network('port1.netdev', '''\
+[NetDev]
+Name=port1
+Kind=dummy
+MACAddress=12:34:56:78:9a:bc''')
+        self.write_network('port2.netdev', '''\
+[NetDev]
+Name=port2
+Kind=dummy
+MACAddress=12:34:56:78:9a:bd''')
+        self.write_network('mybridge.netdev', '''\
+[NetDev]
+Name=mybridge
+Kind=bridge''')
+        self.write_network('port1.network', '''\
+[Match]
+Name=port1
+[Network]
+Bridge=mybridge''')
+        self.write_network('port2.network', '''\
+[Match]
+Name=port2
+[Network]
+Bridge=mybridge''')
+        self.write_network('mybridge.network', '''\
+[Match]
+Name=mybridge
+[Network]
+DNS=192.168.250.1
+Address=192.168.250.33/24
+Gateway=192.168.250.1''')
+        subprocess.check_call(['systemctl', 'start', 'systemd-networkd'])
+
+    def tearDown(self):
+        subprocess.check_call(['systemctl', 'stop', 'systemd-networkd'])
+        subprocess.check_call(['ip', 'link', 'del', 'mybridge'])
+        subprocess.check_call(['ip', 'link', 'del', 'port1'])
+        subprocess.check_call(['ip', 'link', 'del', 'port2'])
+
+    def test_bridge_init(self):
+        self.assert_link_states(
+            port1='managed',
+            port2='managed',
+            mybridge='managed')
+
+    def test_bridge_port_priority(self):
+        self.assertEqual(self.read_attr('port1', 'brport/priority'), '32')
+        self.write_network_dropin('port1.network', 'priority', '''\
+[Bridge]
+Priority=28
+''')
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
+        self.assertEqual(self.read_attr('port1', 'brport/priority'), '28')
+
+    def test_bridge_port_priority_set_zero(self):
+        """It should be possible to set the bridge port priority to 0"""
+        self.assertEqual(self.read_attr('port2', 'brport/priority'), '32')
+        self.write_network_dropin('port2.network', 'priority', '''\
+[Bridge]
+Priority=0
+''')
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
+        self.assertEqual(self.read_attr('port2', 'brport/priority'), '0')
+
 class ClientTestBase(NetworkdTestingUtilities):
     """Provide common methods for testing networkd against servers."""
 
index dab01f1d8aca4afb52bbc385f122859ac1336e1a..14739df49321cba8a3194b004bdb9434260fb79e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # Simple udev rules syntax checker
 #
 # (C) 2010 Canonical Ltd.
index a9c0046667c8e354a62fc28fb351a4a7375731ec..6c9ee5ff834c24261bce654a5539ff92f091a75e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #
 # sys-script.py
 #
index 16ea65690a2b9f87832228c8d0776dbc0acd273f..d116fffe38fdb2ec16c6e4df08460475ecac2ad6 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #
 # systemd-sysv-generator integration test
 #
index cd4699dc187eb4d1c5705d4655ca9f36f221be57..0216c83c12d844d794e68cd7a34f6f234a095181 100755 (executable)
@@ -1,30 +1,38 @@
 #!/bin/bash -e
 
+out="$1"
+systemd_efi="$2"
+boot_stub="$3"
+splash_bmp="$4"
+if [ -z "$out" -o -z "$systemd_efi" -o -z "$boot_stub" -o -z "$splash_bmp" ]; then
+        exit 1
+fi
+
 # create GPT table with EFI System Partition
-rm -f test-efi-disk.img
-dd if=/dev/null of=test-efi-disk.img bs=1M seek=512 count=1
-parted --script test-efi-disk.img "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on"
+rm -f "$out"
+dd if=/dev/null of="$out" bs=1M seek=512 count=1 status=none
+parted --script "$out" "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on"
 
 # create FAT32 file system
-LOOP=$(losetup --show -f -P test-efi-disk.img)
+LOOP=$(losetup --show -f -P "$out")
 mkfs.vfat -F32 ${LOOP}p1
 mkdir -p mnt
 mount ${LOOP}p1 mnt
 
 mkdir -p mnt/EFI/{BOOT,systemd}
-cp systemd-bootx64.efi mnt/EFI/BOOT/BOOTX64.efi
+cp "$systemd_efi" mnt/EFI/BOOT/BOOTX64.efi
 
 [ -e /boot/shellx64.efi ] && cp /boot/shellx64.efi mnt/
 
 mkdir mnt/EFI/Linux
-echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" > mnt/cmdline.txt
+echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" >mnt/cmdline.txt
 objcopy \
-  --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \
-  --add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \
-  --add-section .splash=test/splash.bmp --change-section-vma .splash=0x40000 \
-  --add-section .linux=/boot/$(cat /etc/machine-id)/$(uname -r)/linux --change-section-vma .linux=0x2000000 \
-  --add-section .initrd=/boot/$(cat /etc/machine-id)/$(uname -r)/initrd --change-section-vma .initrd=0x3000000 \
-  linuxx64.efi.stub mnt/EFI/Linux/linux-test.efi
+        --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \
+        --add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \
+        --add-section .splash="$splash_bmp" --change-section-vma .splash=0x40000 \
+        --add-section .linux=/boot/$(cat /etc/machine-id)/$(uname -r)/linux --change-section-vma .linux=0x2000000 \
+        --add-section .initrd=/boot/$(cat /etc/machine-id)/$(uname -r)/initrd --change-section-vma .initrd=0x3000000 \
+        "$boot_stub" mnt/EFI/Linux/linux-test.efi
 
 # install entries
 mkdir -p mnt/loader/entries
diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py
new file mode 100755 (executable)
index 0000000..39a9e62
--- /dev/null
@@ -0,0 +1,192 @@
+#!/usr/bin/env python3
+
+#
+#  Copyright 2017 Michal Sekletar <msekleta@redhat.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/>.
+
+# ATTENTION: This uses the *installed* systemd, not the one from the built
+# source tree.
+
+import unittest
+import time
+import os
+import tempfile
+import subprocess
+
+from enum import Enum
+
+class UnitFileChange(Enum):
+    NO_CHANGE = 0
+    LINES_SWAPPED = 1
+    COMMAND_ADDED_BEFORE = 2
+    COMMAND_ADDED_AFTER = 3
+    COMMAND_INTERLEAVED = 4
+    REMOVAL = 5
+
+class ExecutionResumeTest(unittest.TestCase):
+    def setUp(self):
+        self.unit = 'test-issue-518.service'
+        self.unitfile_path = '/run/systemd/system/{0}'.format(self.unit)
+        self.output_file = tempfile.mktemp()
+        self.unit_files = {}
+
+        unit_file_content = '''
+        [Service]
+        Type=oneshot
+        ExecStart=/bin/sleep 2
+        ExecStart=/bin/bash -c "echo foo >> {0}"
+        '''.format(self.output_file)
+        self.unit_files[UnitFileChange.NO_CHANGE] = unit_file_content
+
+        unit_file_content = '''
+        [Service]
+        Type=oneshot
+        ExecStart=/bin/bash -c "echo foo >> {0}"
+        ExecStart=/bin/sleep 2
+        '''.format(self.output_file)
+        self.unit_files[UnitFileChange.LINES_SWAPPED] = unit_file_content
+
+        unit_file_content = '''
+        [Service]
+        Type=oneshot
+        ExecStart=/bin/bash -c "echo bar >> {0}"
+        ExecStart=/bin/sleep 2
+        ExecStart=/bin/bash -c "echo foo >> {0}"
+        '''.format(self.output_file)
+        self.unit_files[UnitFileChange.COMMAND_ADDED_BEFORE] = unit_file_content
+
+        unit_file_content = '''
+        [Service]
+        Type=oneshot
+        ExecStart=/bin/sleep 2
+        ExecStart=/bin/bash -c "echo foo >> {0}"
+        ExecStart=/bin/bash -c "echo bar >> {0}"
+        '''.format(self.output_file)
+        self.unit_files[UnitFileChange.COMMAND_ADDED_AFTER] = unit_file_content
+
+        unit_file_content = '''
+        [Service]
+        Type=oneshot
+        ExecStart=/bin/bash -c "echo baz >> {0}"
+        ExecStart=/bin/sleep 2
+        ExecStart=/bin/bash -c "echo foo >> {0}"
+        ExecStart=/bin/bash -c "echo bar >> {0}"
+        '''.format(self.output_file)
+        self.unit_files[UnitFileChange.COMMAND_INTERLEAVED] = unit_file_content
+
+        unit_file_content = '''
+        [Service]
+        Type=oneshot
+        ExecStart=/bin/bash -c "echo bar >> {0}"
+        ExecStart=/bin/bash -c "echo baz >> {0}"
+        '''.format(self.output_file)
+        self.unit_files[UnitFileChange.REMOVAL] = unit_file_content
+
+    def reload(self):
+        subprocess.check_call(['systemctl', 'daemon-reload'])
+
+    def write_unit_file(self, unit_file_change):
+        if not isinstance(unit_file_change, UnitFileChange):
+            raise ValueError('Unknown unit file change')
+
+        content = self.unit_files[unit_file_change]
+
+        with open(self.unitfile_path, 'w') as f:
+            f.write(content)
+
+        self.reload()
+
+    def check_output(self, expected_output):
+        try:
+            with open(self.output_file, 'r') as log:
+                output = log.read()
+        except IOError:
+            self.fail()
+
+        self.assertEqual(output, expected_output)
+
+    def setup_unit(self):
+        self.write_unit_file(UnitFileChange.NO_CHANGE)
+        subprocess.check_call(['systemctl', '--job-mode=replace', '--no-block', 'start', self.unit])
+
+    def test_no_change(self):
+        expected_output = 'foo\n'
+
+        self.setup_unit()
+        self.reload()
+        time.sleep(4)
+
+        self.check_output(expected_output)
+
+    def test_swapped(self):
+        expected_output = ''
+
+        self.setup_unit()
+        self.write_unit_file(UnitFileChange.LINES_SWAPPED)
+        self.reload()
+        time.sleep(4)
+
+        self.assertTrue(not os.path.exists(self.output_file))
+
+    def test_added_before(self):
+        expected_output = 'foo\n'
+
+        self.setup_unit()
+        self.write_unit_file(UnitFileChange.COMMAND_ADDED_BEFORE)
+        self.reload()
+        time.sleep(4)
+
+        self.check_output(expected_output)
+
+    def test_added_after(self):
+        expected_output = 'foo\nbar\n'
+
+        self.setup_unit()
+        self.write_unit_file(UnitFileChange.COMMAND_ADDED_AFTER)
+        self.reload()
+        time.sleep(4)
+
+        self.check_output(expected_output)
+
+    def test_interleaved(self):
+        expected_output = 'foo\nbar\n'
+
+        self.setup_unit()
+        self.write_unit_file(UnitFileChange.COMMAND_INTERLEAVED)
+        self.reload()
+        time.sleep(4)
+
+        self.check_output(expected_output)
+
+    def test_removal(self):
+        self.setup_unit()
+        self.write_unit_file(UnitFileChange.REMOVAL)
+        self.reload()
+        time.sleep(4)
+
+        self.assertTrue(not os.path.exists(self.output_file))
+
+    def tearDown(self):
+        for f in [self.output_file, self.unitfile_path]:
+            try:
+                os.remove(f)
+            except OSError:
+                # ignore error if log file doesn't exist
+                pass
+
+        self.reload()
+
+if __name__ == '__main__':
+    unittest.main()
index 23c6ff3f93bd0c48781f7443ddbb42967bbf326f..430a6b78c2557e3f9e4462b5aad0154aaeaef1bc 100644 (file)
@@ -3,5 +3,5 @@ Description=Test to make sure that InaccessiblePaths= disconnect mount propagati
 
 [Service]
 InaccessiblePaths=-/i-dont-exist
-ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo'
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
 Type=oneshot
diff --git a/test/test-execute/exec-inaccessiblepaths-proc.service b/test/test-execute/exec-inaccessiblepaths-proc.service
new file mode 100644 (file)
index 0000000..ebdb484
--- /dev/null
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test to make sure that mount namespace setup works properly with the 'InaccessiblePaths=/proc' option
+
+[Service]
+InaccessiblePaths=/proc
+ExecStart=/bin/sh -x -c 'test "$$(stat -c %%a /proc)" = "0"'
+Type=oneshot
index e438783df3aa5cea49378d1bf6cd37176795bf41..07758121cd3b56cf42ed2f15ab982def8873fd8a 100644 (file)
@@ -3,5 +3,5 @@ Description=Test to make sure that passing ProtectKernelModules=yes disconnect m
 
 [Service]
 ProtectKernelModules=yes
-ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo'
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
 Type=oneshot
index 237cbb2efb43ba1bb838ba2dbce5f7a22c5d49b4..7edb0daa36e3f8ebca8f2cf2b5f5adefd3291dcc 100644 (file)
@@ -3,5 +3,5 @@ Description=Test to make sure that passing ReadOnlyPaths= disconnect mount propa
 
 [Service]
 ReadOnlyPaths=-/i-dont-exist
-ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo'
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
 Type=oneshot
index 466ce6c74727940b635fa556d5765dc638a47453..b38978df424acb16e395051089b0637c80d09143 100644 (file)
@@ -3,5 +3,5 @@ Description=Test to make sure that passing ReadWritePaths= disconnect mount prop
 
 [Service]
 ReadWritePaths=-/i-dont-exist
-ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo'
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
 Type=oneshot
index fd7c198166795f5fc2634a8ae630a7d8cd7fb30e..ea4f700841b57e9f2b88cb5798e93f52b3ebe9d6 100644 (file)
@@ -6,12 +6,13 @@ export PATH
 
 LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || "$ID_LIKE" = "debian" ]] && echo yes)
 LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" ]] && echo yes)
+LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ "$ID_LIKE" = "suse" ]] && echo yes)
 KERNEL_VER=${KERNEL_VER-$(uname -r)}
 KERNEL_MODS="/lib/modules/$KERNEL_VER/"
 QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}"
 NSPAWN_TIMEOUT="${NSPAWN_TIMEOUT:-infinity}"
 TIMED_OUT=  # will be 1 after run_* if *_TIMEOUT is set and test timed out
-FSTYPE="${FSTYPE:-ext3}"
+[[ "$LOOKS_LIKE_SUSE" ]] && FSTYPE="${FSTYPE:-btrfs}" || FSTYPE="${FSTYPE:-ext3}"
 UNIFIED_CGROUP_HIERARCHY="${UNIFIED_CGROUP_HIERARCHY:-default}"
 
 if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
@@ -73,6 +74,7 @@ run_qemu() {
     default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img
     default_debian_initrd=/boot/initrd.img-${KERNEL_VER}
     default_arch_initrd=/boot/initramfs-linux.img
+    default_suse_initrd=/boot/initrd-${KERNEL_VER}
     if [[ ! "$INITRD" ]]; then
         if [[ -e "$default_fedora_initrd" ]]; then
             INITRD="$default_fedora_initrd"
@@ -80,6 +82,8 @@ run_qemu() {
             INITRD="$default_debian_initrd"
         elif [[ "$LOOKS_LIKE_ARCH" && -e "$default_arch_initrd" ]]; then
             INITRD="$default_arch_initrd"
+        elif [[ "$LOOKS_LIKE_SUSE" && -e "$default_suse_initrd" ]]; then
+            INITRD="$default_suse_initrd"
         fi
     fi
 
@@ -99,11 +103,17 @@ run_qemu() {
         exit 1
     fi
 
-    KERNEL_APPEND="root=/dev/sda1 \
+if [[ "$LOOKS_LIKE_SUSE" ]]; then
+    PARAMS+="rd.hostonly=0"
+else
+    PARAMS+="ro"
+fi
+
+KERNEL_APPEND="$PARAMS \
+root=/dev/sda1 \
 raid=noautodetect \
 loglevel=2 \
 init=$ROOTLIBDIR/systemd \
-ro \
 console=ttyS0 \
 selinux=0 \
 $_cgroup_args \
@@ -314,6 +324,8 @@ install_systemd() {
     # and it could fill the available space
     strip_binaries
 
+   [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse
+
     # enable debug logging in PID1
     echo LogLevel=debug >> $initdir/etc/systemd/system.conf
 }
@@ -442,8 +454,14 @@ install_config_files() {
     # set the hostname
     echo systemd-testsuite > $initdir/etc/hostname
     # fstab
+    if [[ "$LOOKS_LIKE_SUSE" ]]; then
+       ROOTMOUNT="/dev/sda1           /       ${FSTYPE}    rw 0 1"
+    else
+       ROOTMOUNT="LABEL=systemd           /       ${FSTYPE}    rw 0 1"
+    fi
+
     cat >$initdir/etc/fstab <<EOF
-LABEL=systemd           /       ${FSTYPE}    rw 0 1
+$ROOTMOUNT
 EOF
 }
 
@@ -1336,6 +1354,12 @@ inst_libdir_file() {
     fi
 }
 
+setup_suse() {
+    ln -s ../usr/bin/systemctl $initdir/bin/systemctl
+    ln -s ../usr/lib/systemd $initdir/lib/systemd
+    inst_simple "/usr/lib/systemd/system/haveged.service"
+}
+
 do_test() {
     if [[ $UID != "0" ]]; then
         echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2
index 4f0ecaa9c33e64cdb29983050ff97cea5a5f6907..73c62c104576d8f06dec7953d8f1ac2c4f05ae1e 100644 (file)
@@ -1,2 +1,4 @@
 /etc.conf
 /systemd.conf
+/systemd-remote.conf
+/var.conf
diff --git a/tmpfiles.d/meson.build b/tmpfiles.d/meson.build
new file mode 100644 (file)
index 0000000..29efe21
--- /dev/null
@@ -0,0 +1,51 @@
+enable_tmpfiles = conf.get('ENABLE_TMPFILES', false)
+
+tmpfiles = [['home.conf',            ''],
+            ['journal-nocow.conf',   ''],
+            ['systemd-nologin.conf', ''],
+            ['systemd-nspawn.conf',  ''],
+            ['tmp.conf',             ''],
+            ['x11.conf',             ''],
+            ['legacy.conf',          'HAVE_SYSV_COMPAT'],
+           ]
+
+foreach pair : tmpfiles
+        if not enable_tmpfiles
+                # do nothing
+        elif pair[1] == '' or conf.get(pair[1], false)
+                install_data(pair[0], install_dir : tmpfilesdir)
+        else
+                message('Not installing tmpfiles.d/@0@ because @1@ is @2@'
+                        .format(pair[0], pair[1], conf.get(pair[1], 0)))
+        endif
+endforeach
+
+m4_files = [['etc.conf',             ''],
+            ['systemd.conf',         ''],
+            ['systemd-remote.conf',  'ENABLE_REMOTE'],
+            ['var.conf',             ''],
+           ]
+
+foreach pair : m4_files
+        if not enable_tmpfiles
+                # do nothing
+        elif pair[1] == '' or conf.get(pair[1], false)
+                custom_target(
+                        'tmpfiles.d_' + pair[0],
+                         input : pair[0] + '.m4',
+                         output: pair[0],
+                         command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                         capture : true,
+                         install : true,
+                         install_dir : tmpfilesdir)
+        else
+                message('Not installing tmpfiles.d/@0@.m4 because @1@ is @2@'
+                        .format(pair[0], pair[1], conf.get(pair[1], 0)))
+        endif
+endforeach
+
+if enable_tmpfiles
+        meson.add_install_script(
+                'sh', '-c',
+                mkdir_p.format(join_paths(sysconfdir, 'tmpfiles.d')))
+endif
diff --git a/tmpfiles.d/systemd-remote.conf b/tmpfiles.d/systemd-remote.conf
deleted file mode 100644 (file)
index e19230f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#  This file is part of systemd.
-#
-#  systemd is free software; you can redistribute it and/or modify it
-#  under the terms of the GNU Lesser General Public License as published by
-#  the Free Software Foundation; either version 2.1 of the License, or
-#  (at your option) any later version.
-
-# See tmpfiles.d(5) for details
-
-d /var/lib/systemd/journal-upload 0755 systemd-journal-upload systemd-journal-upload - -
-
-z /var/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - -
-z /run/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - -
diff --git a/tmpfiles.d/systemd-remote.conf.m4 b/tmpfiles.d/systemd-remote.conf.m4
new file mode 100644 (file)
index 0000000..7a0f698
--- /dev/null
@@ -0,0 +1,17 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+# See tmpfiles.d(5) for details
+m4_ifdef(`HAVE_LIBCURL',
+
+d /var/lib/systemd/journal-upload 0755 systemd-journal-upload systemd-journal-upload - -
+)m4_dnl
+m4_ifdef(`HAVE_MICROHTTPD',
+
+z /var/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - -
+z /run/log/journal/remote 2755 systemd-journal-remote systemd-journal-remote - -
+)m4_dnl
diff --git a/tmpfiles.d/var.conf b/tmpfiles.d/var.conf
deleted file mode 100644 (file)
index ae7952e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#  This file is part of systemd.
-#
-#  systemd is free software; you can redistribute it and/or modify it
-#  under the terms of the GNU Lesser General Public License as published by
-#  the Free Software Foundation; either version 2.1 of the License, or
-#  (at your option) any later version.
-
-# See tmpfiles.d(5) for details
-
-q /var 0755 - - -
-
-L /var/run - - - - ../run
-
-d /var/log 0755 - - -
-f /var/log/wtmp 0664 root utmp -
-f /var/log/btmp 0600 root utmp -
-
-d /var/cache 0755 - - -
-
-d /var/lib 0755 - - -
-
-d /var/spool 0755 - - -
diff --git a/tmpfiles.d/var.conf.m4 b/tmpfiles.d/var.conf.m4
new file mode 100644 (file)
index 0000000..e640fcd
--- /dev/null
@@ -0,0 +1,25 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+# See tmpfiles.d(5) for details
+
+q /var 0755 - - -
+
+L /var/run - - - - ../run
+
+d /var/log 0755 - - -
+m4_ifdef(`HAVE_UTMP',
+f /var/log/wtmp 0664 root utmp -
+f /var/log/btmp 0600 root utmp -
+f /var/log/lastlog 0664 root utmp -
+)m4_dnl
+
+d /var/cache 0755 - - -
+
+d /var/lib 0755 - - -
+
+d /var/spool 0755 - - -
old mode 100644 (file)
new mode 100755 (executable)
index b220060..357e498
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 # This file is part of systemd. It is distrubuted under the MIT license, see
index d20016e0058b37993844a8c0ef7d57ca74164fa5..62ce8006f53ab4eef89a87775625f1ee34fcc573 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 #  This file is part of systemd.
index 8ce09ca2fa078a988ceb68eb87552fc86dfa56b7..1b287997fa7e6839e665b2498506020309a07b76 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 #  This file is part of systemd.
index 50ad9532cdc57e3dd885107b6e6e04da86b51c0d..abc33e7394d9a8251c94cc278d920a8afe75d79a 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 #  This file is part of systemd.
old mode 100644 (file)
new mode 100755 (executable)
index 18aa513..e9e39f1
@@ -1,9 +1,9 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 #  This file is part of systemd.
 #
-#  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+#  Copyright 2013, 2017 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
@@ -22,6 +22,7 @@ from __future__ import print_function
 import collections
 import sys
 import os.path
+import pprint
 from xml_helper import *
 
 SECTION = '''\
@@ -66,11 +67,13 @@ EXTRA_DIST += \\
        {dist_files}
 '''
 
+meson = False
+
 def man(page, number):
-    return 'man/{}.{}'.format(page, number)
+    return ('man/' if not meson else '') + '{}.{}'.format(page, number)
 
 def xml(file):
-    return 'man/{}'.format(os.path.basename(file))
+    return ('man/' if not meson else '') + os.path.basename(file)
 
 def add_rules(rules, name):
     xml = xml_parse(name)
@@ -122,9 +125,40 @@ def make_makefile(rules, dist_files):
         for conditional,rulegroup in sorted(rules.items())
         ) + FOOTER.format(dist_files=mjoin(sorted(dist_files)))
 
+MESON_HEADER = '''\
+# Do not edit. Generated by make-man-rules.py.
+manpages = ['''
+
+MESON_FOOTER = '''\
+]
+# Really, do not edit.'''
+
+def make_mesonfile(rules, dist_files):
+    # reformat rules as
+    # grouped = [ [name, section, [alias...], condition], ...]
+    #
+    # but first create a dictionary like
+    # lists = { (name, condition) => [alias...]
+    grouped = collections.defaultdict(list)
+    for condition, items in rules.items():
+        for alias, name in items.items():
+            group = grouped[(name, condition)]
+            if name != alias:
+                group.append(alias)
+
+    lines = [ [p[0][:-2], p[0][-1], sorted(a[:-2] for a in aliases), p[1]]
+              for p, aliases in sorted(grouped.items()) ]
+    return '\n'.join((MESON_HEADER, pprint.pformat(lines)[1:-1], MESON_FOOTER))
+
 if __name__ == '__main__':
-    rules = create_rules(sys.argv[1:])
-    dist_files = (xml(file) for file in sys.argv[1:]
+    meson = sys.argv[1] == '--meson'
+    pages = sys.argv[1+meson:]
+
+    rules = create_rules(pages)
+    dist_files = (xml(file) for file in pages
                   if not file.endswith(".directives.xml") and
                      not file.endswith(".index.xml"))
-    print(make_makefile(rules, dist_files), end='')
+    if meson:
+        print(make_mesonfile(rules, dist_files))
+    else:
+        print(make_makefile(rules, dist_files), end='')
diff --git a/tools/meson-check-compilation.sh b/tools/meson-check-compilation.sh
new file mode 100755 (executable)
index 0000000..d3b2a31
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -eu
+
+"$@" '-' -o/dev/null </dev/null
diff --git a/tools/meson-check-help.sh b/tools/meson-check-help.sh
new file mode 100755 (executable)
index 0000000..47a5099
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh -eu
+
+# output width
+if "$1"  --help | grep -v 'default:' | grep -E -q '.{80}.'; then
+        echo "$(basename "$1") --help output is too wide:"
+        "$1"  --help | awk 'length > 80' | grep -E --color=yes '.{80}'
+        exit 1
+fi
+
+# no --help output to stdout
+if "$1" --help 2>&1 1>/dev/null | grep .; then
+        echo "$(basename "$1") --help prints to stderr"
+        exit 2
+fi
+
+# error output to stderr
+if ! "$1" --no-such-parameter 2>&1 1>/dev/null | grep -q .; then
+        echo "$(basename "$1") with an unknown parameter does not print to stderr"
+        exit 3
+fi
diff --git a/tools/meson-git-contrib.sh b/tools/meson-git-contrib.sh
new file mode 100755 (executable)
index 0000000..c543b3a
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh -eu
+
+git shortlog -s `git describe --abbrev=0`.. | \
+        cut -c8- | \
+        sed 's/ / /g' | \
+        awk '{ print $$0 "," }' | \
+        sed -e 's/ / /g' | \
+        sort -u
diff --git a/tools/meson-hwdb-update.sh b/tools/meson-hwdb-update.sh
new file mode 100755 (executable)
index 0000000..4c91907
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh -eu
+
+cd "$1"
+
+curl -L -o usb.ids 'http://www.linux-usb.org/usb.ids'
+curl -L -o pci.ids 'http://pci-ids.ucw.cz/v2.2/pci.ids'
+curl -L -o ma-large.txt 'http://standards-oui.ieee.org/oui/oui.txt'
+curl -L -o ma-medium.txt 'http://standards-oui.ieee.org/oui28/mam.txt'
+curl -L -o ma-small.txt 'http://standards-oui.ieee.org/oui36/oui36.txt'
+curl -L -o pnp_id_registry.html 'http://www.uefi.org/uefi-pnp-export'
+curl -L -o acpi_id_registry.html 'http://www.uefi.org/uefi-acpi-export'
+./ids-update.pl
+./acpi-update.py > 20-acpi-vendor.hwdb.base
+patch -p0 -o- 20-acpi-vendor.hwdb.base <20-acpi-vendor.hwdb.patch >20-acpi-vendor.hwdb
+diff -u 20-acpi-vendor.hwdb.base 20-acpi-vendor.hwdb >20-acpi-vendor.hwdb.patch
diff --git a/tools/meson-link-test.c b/tools/meson-link-test.c
new file mode 100644 (file)
index 0000000..825bbff
--- /dev/null
@@ -0,0 +1 @@
+int main(void) {return 0;}
diff --git a/tools/meson-make-symlink.sh b/tools/meson-make-symlink.sh
new file mode 100755 (executable)
index 0000000..47a5e70
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -eu
+
+# this is needed mostly because $DESTDIR is provided as a variable,
+# and we need to create the target directory...
+
+mkdir -vp "$(dirname "${DESTDIR:-}$2")"
+if [ "$(dirname $1)" = . ]; then
+        ln -vfs -T "$1" "${DESTDIR:-}$2"
+else
+        ln -vfs -T --relative "${DESTDIR:-}$1" "${DESTDIR:-}$2"
+fi
old mode 100644 (file)
new mode 100755 (executable)
index b2c0369..0088be5
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 #  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 #
 #  This file is part of systemd.
index 413d94094b19a683af2d8a1c951befffb324154c..d9d0cba4d9a4a51a14b51548df761506082ba74b 100644 (file)
@@ -16,7 +16,10 @@ After=rc-local.service
 Before=getty.target
 
 [Service]
-ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM
+# The '-o' option value tells agetty to replace 'login' arguments with an
+# option to preserve environment (-p), followed by '--' for safety, and then
+# the entered username.
+ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear --keep-baud console 115200,38400,9600 $TERM
 Type=idle
 Restart=always
 RestartSec=0
index e126f3a48999c8ce18351a6d33af93243659cd4d..fd0be86ba7f09a70aa5b9e763819703f6bb36060 100644 (file)
@@ -17,7 +17,10 @@ IgnoreOnIsolate=yes
 ConditionPathExists=/dev/pts/%I
 
 [Service]
-ExecStart=-/sbin/agetty --noclear --keep-baud pts/%I 115200,38400,9600 $TERM
+# The '-o' option value tells agetty to replace 'login' arguments with an
+# option to preserve environment (-p), followed by '--' for safety, and then
+# the entered username.
+ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear --keep-baud pts/%I 115200,38400,9600 $TERM
 Type=idle
 Restart=always
 RestartSec=0
index 489cc777e40a2e2233c5247530640106d2770a33..86ad7ac2c921c3389f8a34ca78228943fc5f379b 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Huge Pages File System
 Documentation=https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 Before=sysinit.target
 ConditionPathExists=/sys/kernel/mm/hugepages
index 8d29f96ca62c90160a838c2a8849d66df7e93e9a..b2adfeb8356199abb5a1ea4ada13398fffd38076 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=POSIX Message Queue File System
 Documentation=man:mq_overview(7)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 Before=sysinit.target
 ConditionPathExists=/proc/sys/fs/mqueue
index da68eb8faa0284f7e1bfd52d0c8a883364d07355..e9eb238b98f047ae90cd5a7fb6021be1df430f7b 100644 (file)
@@ -17,9 +17,7 @@ Before=shutdown.target
 [Service]
 Environment=HOME=/root
 WorkingDirectory=-/root
-ExecStartPre=-/bin/plymouth --wait quit
-ExecStartPre=-/bin/echo -e 'You are in 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"
+ExecStart=-@rootlibexecdir@/systemd-sulogin-shell emergency
 Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
index 5b82c13fc5eb08a979625353bf7bbf0509399198..2a84061ed67d3a3468048dfc2114a7121bc16d15 100644 (file)
@@ -33,7 +33,10 @@ ConditionPathExists=/dev/tty0
 
 [Service]
 # the VT is cleared by TTYVTDisallocate
-ExecStart=-/sbin/agetty --noclear %I $TERM
+# The '-o' option value tells agetty to replace 'login' arguments with an
+# option to preserve environment (-p), followed by '--' for safety, and then
+# the entered username.
+ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear %I $TERM
 Type=idle
 Restart=always
 RestartSec=0
diff --git a/units/meson-add-wants.sh b/units/meson-add-wants.sh
new file mode 100755 (executable)
index 0000000..dfd287e
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh -eu
+
+unitdir="$1"
+target="$2"
+unit="$3"
+
+case "$target" in
+        */?*) # a path, but not just a slash at the end
+                dir="${DESTDIR:-}${target}"
+                ;;
+        *)
+                dir="${DESTDIR:-}${unitdir}/${target}"
+                ;;
+esac
+
+unitpath="${DESTDIR:-}${unitdir}/${unit}"
+
+case "$target" in
+        */)
+                mkdir -p -m 0755 "$dir"
+                ;;
+        *)
+                mkdir -p -m 0755 "$(basename "$dir")"
+                ;;
+esac
+
+ln -vfs --relative "$unitpath" "$dir"
diff --git a/units/meson.build b/units/meson.build
new file mode 100644 (file)
index 0000000..e94add6
--- /dev/null
@@ -0,0 +1,329 @@
+units = [
+        ['basic.target',                        ''],
+        ['bluetooth.target',                    ''],
+        ['cryptsetup-pre.target',               'HAVE_LIBCRYPTSETUP'],
+        ['cryptsetup.target',                   'HAVE_LIBCRYPTSETUP',
+         'sysinit.target.wants/'],
+        ['dev-hugepages.mount',                 '',
+         'sysinit.target.wants/'],
+        ['dev-mqueue.mount',                    '',
+         'sysinit.target.wants/'],
+        ['emergency.target',                    ''],
+        ['exit.target',                         ''],
+        ['final.target',                        ''],
+        ['getty.target',                        '',
+         'multi-user.target.wants/'],
+        ['graphical.target',                    '',
+         'runlevel5.target default.target'],
+        ['halt.target',                         ''],
+        ['hibernate.target',                    'ENABLE_HIBERNATE'],
+        ['hybrid-sleep.target',                 'ENABLE_HIBERNATE'],
+        ['initrd-fs.target',                    ''],
+        ['initrd-root-device.target',           ''],
+        ['initrd-root-fs.target',               ''],
+        ['initrd-switch-root.target',           ''],
+        ['initrd.target',                       ''],
+        ['kexec.target',                        ''],
+        ['ldconfig.service',                    'ENABLE_LDCONFIG',
+         'sysinit.target.wants/'],
+        ['local-fs-pre.target',                 ''],
+        ['local-fs.target',                     ''],
+        ['machine.slice',                       'ENABLE_MACHINED'],
+        ['machines.target',                     'ENABLE_MACHINED',
+         join_paths(pkgsysconfdir, 'system/multi-user.target.wants/')],
+        ['multi-user.target',                   '',
+         'runlevel2.target runlevel3.target runlevel4.target'],
+        ['network-online.target',               ''],
+        ['network-pre.target',                  ''],
+        ['network.target',                      ''],
+        ['nss-lookup.target',                   ''],
+        ['nss-user-lookup.target',              ''],
+        ['paths.target',                        ''],
+        ['poweroff.target',                     '',
+         'runlevel0.target'],
+        ['printer.target',                      ''],
+        ['proc-sys-fs-binfmt_misc.automount',   'ENABLE_BINFMT',
+         'sysinit.target.wants/'],
+        ['proc-sys-fs-binfmt_misc.mount',       'ENABLE_BINFMT'],
+        ['reboot.target',                       '',
+         'runlevel6.target ctrl-alt-del.target'],
+        ['remote-fs-pre.target',                ''],
+        ['remote-fs.target',                    '',
+         join_paths(pkgsysconfdir, 'system/multi-user.target.wants/')],
+        ['rescue.target',                       '',
+         'runlevel1.target'],
+        ['rpcbind.target',                      ''],
+        ['shutdown.target',                     ''],
+        ['sigpwr.target',                       ''],
+        ['sleep.target',                        ''],
+        ['slices.target',                       ''],
+        ['smartcard.target',                    ''],
+        ['sockets.target',                      ''],
+        ['sound.target',                        ''],
+        ['suspend.target',                      ''],
+        ['swap.target',                         ''],
+        ['sys-fs-fuse-connections.mount',       '',
+         'sysinit.target.wants/'],
+        ['sys-kernel-config.mount',             '',
+         'sysinit.target.wants/'],
+        ['sys-kernel-debug.mount',              '',
+         'sysinit.target.wants/'],
+        ['sysinit.target',                      ''],
+        ['syslog.socket',                       ''],
+        ['system-update.target',                ''],
+        ['system.slice',                        ''],
+        ['systemd-ask-password-console.path',   '',
+         'sysinit.target.wants/'],
+        ['systemd-ask-password-wall.path',      '',
+         'multi-user.target.wants/'],
+        ['systemd-coredump.socket',             'ENABLE_COREDUMP',
+         'sockets.target.wants/'],
+        ['systemd-initctl.socket',              '',
+         'sockets.target.wants/'],
+        ['systemd-journal-gatewayd.socket',     'ENABLE_REMOTE HAVE_MICROHTTPD'],
+        ['systemd-journal-remote.socket',       'ENABLE_REMOTE HAVE_MICROHTTPD'],
+        ['systemd-journald-audit.socket',       '',
+         'sockets.target.wants/'],
+        ['systemd-journald-dev-log.socket',     '',
+         'sockets.target.wants/'],
+        ['systemd-journald.socket',             '',
+         'sockets.target.wants/'],
+        ['systemd-networkd.socket',             '',
+         join_paths(pkgsysconfdir, 'system/sockets.target.wants/')],
+        ['systemd-rfkill.socket',               'ENABLE_RFKILL'],
+        ['systemd-tmpfiles-clean.timer',        '',
+         'timers.target.wants/'],
+        ['systemd-udevd-control.socket',        '',
+         'sockets.target.wants/'],
+        ['systemd-udevd-kernel.socket',         '',
+         'sockets.target.wants/'],
+        ['time-sync.target',                    ''],
+        ['timers.target',                       ''],
+        ['umount.target',                       ''],
+        ['user.slice',                          ''],
+        ['var-lib-machines.mount',              'ENABLE_MACHINED',
+         'remote-fs.target.wants/ machines.target.wants/'],
+]
+
+in_units = [
+        ['debug-shell.service',                  ''],
+        ['emergency.service',                    ''],
+        ['halt-local.service',                   'HAVE_SYSV_COMPAT'],
+        ['initrd-cleanup.service',               ''],
+        ['initrd-parse-etc.service',             ''],
+        ['initrd-switch-root.service',           ''],
+        ['initrd-udevadm-cleanup-db.service',    ''],
+        ['kmod-static-nodes.service',            'HAVE_KMOD ENABLE_TMPFILES',
+         'sysinit.target.wants/'],
+        ['quotaon.service',                      'ENABLE_QUOTACHECK'],
+        ['rc-local.service',                     'HAVE_SYSV_COMPAT'],
+        ['rescue.service',                       ''],
+        ['system-update-cleanup.service',        ''],
+        ['systemd-ask-password-console.service', ''],
+        ['systemd-ask-password-wall.service',    ''],
+        ['systemd-backlight@.service',           'ENABLE_BACKLIGHT'],
+        ['systemd-binfmt.service',               'ENABLE_BINFMT',
+         'sysinit.target.wants/'],
+        ['systemd-coredump@.service',            'ENABLE_COREDUMP'],
+        ['systemd-exit.service',                 ''],
+        ['systemd-firstboot.service',            'ENABLE_FIRSTBOOT',
+         'sysinit.target.wants/'],
+        ['systemd-fsck-root.service',            ''],
+        ['systemd-fsck@.service',                ''],
+        ['systemd-halt.service',                 ''],
+        ['systemd-hibernate-resume@.service',    'ENABLE_HIBERNATE'],
+        ['systemd-hibernate.service',            'ENABLE_HIBERNATE'],
+        ['systemd-hybrid-sleep.service',         'ENABLE_HIBERNATE'],
+        ['systemd-hostnamed.service',            'ENABLE_HOSTNAMED',
+         'dbus-org.freedesktop.hostname1.service'],
+        ['systemd-hwdb-update.service',          'ENABLE_HWDB',
+         'sysinit.target.wants/'],
+        ['systemd-importd.service',              'ENABLE_IMPORTD',
+         'dbus-org.freedesktop.import1.service'],
+        ['systemd-initctl.service',               ''],
+        ['systemd-journal-catalog-update.service', '',
+         'sysinit.target.wants/'],
+        ['systemd-journal-flush.service',         '',
+         'sysinit.target.wants/'],
+        ['systemd-journal-gatewayd.service',     'ENABLE_REMOTE HAVE_MICROHTTPD'],
+        ['systemd-journal-remote.service',       'ENABLE_REMOTE HAVE_MICROHTTPD'],
+        ['systemd-journal-upload.service',       'ENABLE_REMOTE HAVE_LIBCURL'],
+        ['systemd-journald.service',             '',
+         'sysinit.target.wants/'],
+        ['systemd-kexec.service',                ''],
+        ['systemd-localed.service',              'ENABLE_LOCALED',
+         'dbus-org.freedesktop.locale1.service'],
+        ['systemd-logind.service',               'ENABLE_LOGIND',
+         'multi-user.target.wants/ dbus-org.freedesktop.login1.service'],
+        ['systemd-machine-id-commit.service',    '',
+         'sysinit.target.wants/'],
+        ['systemd-machined.service',             'ENABLE_MACHINED',
+         'dbus-org.freedesktop.machine1.service'],
+        ['systemd-modules-load.service',         'HAVE_KMOD',
+         'sysinit.target.wants/'],
+        ['systemd-networkd-wait-online.service', 'ENABLE_NETWORKD',
+         join_paths(pkgsysconfdir, 'system/network-online.target.wants/')],
+        ['systemd-nspawn@.service',              ''],
+        ['systemd-poweroff.service',             ''],
+        ['systemd-quotacheck.service',           'ENABLE_QUOTACHECK'],
+        ['systemd-random-seed.service',          'ENABLE_RANDOMSEED',
+         'sysinit.target.wants/'],
+        ['systemd-reboot.service',               ''],
+        ['systemd-remount-fs.service',           '',
+         'local-fs.target.wants/'],
+        ['systemd-rfkill.service',               'ENABLE_RFKILL'],
+        ['systemd-suspend.service',              ''],
+        ['systemd-sysctl.service',               '',
+         'sysinit.target.wants/'],
+        ['systemd-sysusers.service',             'ENABLE_SYSUSERS',
+         'sysinit.target.wants/'],
+        ['systemd-timedated.service',            'ENABLE_TIMEDATED',
+         'dbus-org.freedesktop.timedate1.service'],
+        ['systemd-timesyncd.service',            'ENABLE_TIMESYNCD',
+         join_paths(pkgsysconfdir, 'system/sysinit.target.wants/')],
+        ['systemd-tmpfiles-clean.service',       'ENABLE_TMPFILES'],
+        ['systemd-tmpfiles-setup-dev.service',   'ENABLE_TMPFILES',
+         'sysinit.target.wants/'],
+        ['systemd-tmpfiles-setup.service',       'ENABLE_TMPFILES',
+         'sysinit.target.wants/'],
+        ['systemd-udev-settle.service',          ''],
+        ['systemd-udev-trigger.service',         '',
+         'sysinit.target.wants/'],
+        ['systemd-udevd.service',                '',
+         'sysinit.target.wants/'],
+        ['systemd-update-done.service',          '',
+         'sysinit.target.wants/'],
+        ['systemd-update-utmp-runlevel.service', 'HAVE_UTMP HAVE_SYSV_COMPAT',
+         'multi-user.target.wants/ graphical.target.wants/ rescue.target.wants/'],
+        ['systemd-update-utmp.service',          'HAVE_UTMP',
+         'sysinit.target.wants/'],
+        ['systemd-user-sessions.service',        '',
+         'multi-user.target.wants/'],
+        ['systemd-vconsole-setup.service',       'ENABLE_VCONSOLE'],
+        ['systemd-volatile-root.service',        ''],
+]
+
+m4_units = [
+        ['getty@.service',                     '',
+         'autovt@.service ' +
+         join_paths(pkgsysconfdir, 'system/getty.target.wants/getty@tty1.service')],
+        ['serial-getty@.service',              ''],
+        ['tmp.mount',                          '',
+         'local-fs.target.wants/'],
+]
+
+m4_in_units = [
+        ['console-getty.service',              ''],
+        ['container-getty@.service',           ''],
+        ['systemd-networkd.service',           'ENABLE_NETWORKD',
+         join_paths(pkgsysconfdir, 'system/dbus-org.freedesktop.network1.service') + ' ' +
+         join_paths(pkgsysconfdir, 'system/multi-user.target.wants/')],
+        ['systemd-resolved.service',           'ENABLE_RESOLVED',
+         join_paths(pkgsysconfdir, 'system/dbus-org.freedesktop.resolve1.service') + ' ' +
+         join_paths(pkgsysconfdir, 'system/multi-user.target.wants/')],
+        ['user@.service',                      ''],
+]
+
+foreach tuple : m4_in_units
+        file = tuple[0]
+
+        gen = configure_file(
+                input : file + '.m4.in',
+                output : file + '.m4',
+                configuration : substs)
+
+        m4_units += [[file, tuple.get(1, ''), tuple.get(2, ''), gen]]
+endforeach
+
+foreach tuple : in_units
+        file = tuple[0]
+
+        # we do this here because install_data does not accept custom_target output
+        conds = tuple[1].split(' ')
+        install = ((conds.get(0, '') == '' or conf.get(conds[0], false)) and
+                   (conds.get(1, '') == '' or conf.get(conds[1], false)))
+
+        gen1 = configure_file(
+                input : file + '.in',
+                output : file + '.tmp',
+                configuration : substs)
+        gen2 = custom_target(
+                file,
+                input : gen1,
+                output : file,
+                command : [sed, '/^## /d', '@INPUT@'],
+                capture : true,
+                install : install,
+                install_dir : systemunitdir)
+
+        if install and tuple.length() > 2
+                foreach target : tuple[2].split()
+                        meson.add_install_script('meson-add-wants.sh', systemunitdir, target, file)
+                endforeach
+        endif
+endforeach
+
+foreach tuple : m4_units
+        file = tuple[0]
+        input = tuple.get(3, file + '.m4')
+
+        # we do this here because install_data does not accept custom_target output
+        conds = tuple[1].split(' ')
+        install = ((conds.get(0, '') == '' or conf.get(conds[0], false)) and
+                   (conds.get(1, '') == '' or conf.get(conds[1], false)))
+
+        custom_target(
+                file,
+                input : input,
+                output: file,
+                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                capture : true,
+                install : install,
+                install_dir : systemunitdir)
+
+        if tuple.length() > 2 and install
+                foreach target : tuple[2].split()
+                        meson.add_install_script('meson-add-wants.sh', systemunitdir, target, file)
+                endforeach
+        endif
+endforeach
+
+foreach tuple : units
+        file = tuple[0]
+        input = tuple.get(3, file)
+
+        conds = tuple[1].split(' ')
+        install = ((conds.get(0, '') == '' or conf.get(conds[0], false)) and
+                   (conds.get(1, '') == '' or conf.get(conds[1], false)))
+
+        if install
+                install_data(input,
+                             install_dir : systemunitdir)
+
+                if tuple.length() > 2
+                        foreach target : tuple[2].split()
+                                meson.add_install_script(
+                                        'meson-add-wants.sh', systemunitdir, target, file)
+                        endforeach
+                endif
+        endif
+endforeach
+
+############################################################
+
+meson.add_install_script(meson_make_symlink,
+                         join_paths(pkgsysconfdir, 'user'),
+                         join_paths(sysconfdir, 'xdg/systemd/user'))
+meson.add_install_script(meson_make_symlink,
+                         join_paths(dbussystemservicedir, 'org.freedesktop.systemd1.service'),
+                         join_paths(dbussessionservicedir, 'org.freedesktop.systemd1.service'))
+if conf.get('HAVE_SYSV_COMPAT', false)
+        foreach i : [1, 2, 3, 4, 5]
+                meson.add_install_script(
+                        'sh', '-c',
+                        mkdir_p
+                        .format(join_paths(systemunitdir, 'runlevel@0@.target.wants'.format(i))))
+        endforeach
+endif
+
+subdir('user')
index 67bc4fa47168688395752b8713eca167adafa310..5130d8c5e34b2593feb44afa3f987692ec1c5651 100644 (file)
@@ -8,5 +8,5 @@
 [Unit]
 Description=Network is Online
 Documentation=man:systemd.special(7)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
 After=network.target
index 0ea4bc739a9bb588ad08d9841ec3c6a50a795e32..0d54a4cff88c8d24127b9841f968d8377cf1aeb1 100644 (file)
@@ -8,5 +8,5 @@
 [Unit]
 Description=Network (Pre)
 Documentation=man:systemd.special(7)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
 RefuseManualStart=yes
index 61ebdcadd0b39ce0ddff7e34ed4977c24ff8092c..f8331b61242b56aadc3126c38563d8abda1feffb 100644 (file)
@@ -8,6 +8,6 @@
 [Unit]
 Description=Network
 Documentation=man:systemd.special(7)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
 After=network-pre.target
 RefuseManualStart=yes
index d64c36486d84276f4c6cee3f33dd995715a6c407..f7b41331bfc41489c59ccfbf0ca814cada0c7c02 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Hostname Service Bus Name
 Documentation=man:systemd-hostnamed.service(8) man:hostname(5) man:machine-info(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/hostnamed
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/hostnamed
 
 [BusName]
 Service=systemd-hostnamed.service
index 3cd201180bab4be8a7d418affa7494433d440522..e0c498e8ff795830f96b45d1d45855ed30d246dd 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Locale Service Bus Name
 Documentation=man:systemd-localed.service(8) man:locale.conf(5) man:vconsole.conf(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/localed
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/localed
 
 [BusName]
 Service=systemd-localed.service
index d0686b17e0af4b3c9ee13571b1cc199a2324fa34..b169720f8ec85c51ff58df79c4ac816448c9511f 100644 (file)
@@ -8,8 +8,8 @@
 [Unit]
 Description=Login Service Bus Name
 Documentation=man:systemd-logind.service(8) man:logind.conf(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/logind
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/logind
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/multiseat
 
 [BusName]
 Service=systemd-logind.service
index 7df8e9e732bfb934ac6c93707be0b0984c21ec04..a1f0154778b6abf09f564c8f107dd4356a420fc8 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Virtual Machine and Container Registration Service Bus Name
 Documentation=man:systemd-machined.service(8)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/machined
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined
 
 [BusName]
 Service=systemd-machined.service
index 5b7a7fed3f0a04cee95574eadf70967a0d2eaf58..28c8f97037878b2b65fadd91dac0376aa1dbf8af 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Network Name Resolution Service Bus Name
 Documentation=man:systemd-resolved.service(8)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/resolved
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved
 
 # This is pulled in by systemd-resolved.service, since it cannot run
 # without its policy set. However, let's conditionalize this unit on
index 9ec055e3f247c79b2efbdf4098780f57aae36c86..f9f41cbaf05019e4be84a56ea8e5839d967b4ce3 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=System and Service Manager Bus Name
 Documentation=man:systemd(1)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd
+Documentation=https://www.freedesktop.org/wiki/Software/systemd
 
 [BusName]
 Activating=no
index eae4e536b8153cc87f55e46d9a7d86be3da5bf5b..1c962b5f8a96f67e9c59fe54c006ca8deeca5ede 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Time & Date Service Bus Name
 Documentation=man:systemd-timedated.service(8) man:localtime(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/timedated
 
 [BusName]
 Service=systemd-timedated.service
index 6be38937b1c24682454b05d7b8576093a8f9a463..1067bcd839cb85c0afb953c3a916ebc5f49ae0cf 100644 (file)
@@ -7,8 +7,8 @@
 
 [Unit]
 Description=Arbitrary Executable File Formats File System Automount Point
-Documentation=https://www.kernel.org/doc/Documentation/binfmt_misc.txt
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 Before=sysinit.target
 ConditionPathExists=/proc/sys/fs/binfmt_misc/
index 8c7c3863182f3f310dbf84d2ad16ea4978f6ca1c..27773cd4ea06406483bc9f3962d1e3e8088b79e7 100644 (file)
@@ -7,8 +7,8 @@
 
 [Unit]
 Description=Arbitrary Executable File Formats File System
-Documentation=https://www.kernel.org/doc/Documentation/binfmt_misc.txt
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 
 [Mount]
index 7d59a4019547f6f7eff6ce06c113b638b675d880..f3e1e270c984cdbf52dd33411dab986c7dd9d54a 100644 (file)
@@ -10,7 +10,7 @@ Description=Enable File System Quotas
 Documentation=man:quotaon(8)
 DefaultDependencies=no
 After=systemd-quotacheck.service
-Before=local-fs.target shutdown.target
+Before=remote-fs.target shutdown.target
 ConditionPathExists=@QUOTAON@
 
 [Service]
index 5feff69c89a9335668469c6b049bd654dc61f8e8..4ab66f48560a55d8caa1eb03102481a34b64ed46 100644 (file)
@@ -16,9 +16,7 @@ Before=shutdown.target
 [Service]
 Environment=HOME=/root
 WorkingDirectory=-/root
-ExecStartPre=-/bin/plymouth --wait quit
-ExecStartPre=-/bin/echo -e 'You are in rescue mode. After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.'
-ExecStart=-/bin/sh -c "@SULOGIN@; @SYSTEMCTL@ --job-mode=fail --no-block default"
+ExecStart=-@rootlibexecdir@/systemd-sulogin-shell rescue
 Type=idle
 StandardInput=tty-force
 StandardOutput=inherit
index 4522d0d2be30d499194f5e3006be92d134141f87..b7caeaff449a364bc5c18e188b0500253d32d5f6 100644 (file)
@@ -21,8 +21,17 @@ After=rc-local.service
 Before=getty.target
 IgnoreOnIsolate=yes
 
+# IgnoreOnIsolate causes issues with sulogin, if someone isolates
+# rescue.target or starts rescue.service from multi-user.target or
+# graphical.target.
+Conflicts=rescue.service
+Before=rescue.service
+
 [Service]
-ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM
+# The '-o' option value tells agetty to replace 'login' arguments with an
+# option to preserve environment (-p), followed by '--' for safety, and then
+# the entered username.
+ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,38400,9600 %I $TERM
 Type=idle
 Restart=always
 UtmpIdentifier=%I
index 336b5f6277e1f19f3929d6bfa4047fcb356e767e..492ceb16f37ff0d6d13d756d3a2139bce5929647 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=FUSE Control File System
 Documentation=https://www.kernel.org/doc/Documentation/filesystems/fuse.txt
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 ConditionPathExists=/sys/fs/fuse/connections
 ConditionCapability=CAP_SYS_ADMIN
index 21648eff6af7a59ff7cf97f6d2ac419bc461f382..b585f3256106116a58f1499d6c359155fa5292a7 100644 (file)
@@ -6,9 +6,9 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Configuration File System
+Description=Kernel Configuration File System
 Documentation=https://www.kernel.org/doc/Documentation/filesystems/configfs/configfs.txt
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 ConditionPathExists=/sys/kernel/config
 ConditionCapability=CAP_SYS_RAWIO
index 1e94387bacb988b35c76c5781090a10676ff9259..808dbf08f4bd259bc0ea82ace282bce70a47ad07 100644 (file)
@@ -6,9 +6,9 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Debug File System
+Description=Kernel Debug File System
 Documentation=https://www.kernel.org/doc/Documentation/filesystems/debugfs.txt
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 ConditionPathExists=/sys/kernel/debug
 ConditionCapability=CAP_SYS_RAWIO
index e6e9cf8525a66817b7c94f42627dead97a873a96..d3987cb9a877f91fd6136fb3af75651a7a4fd5bc 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Syslog Socket
 Documentation=man:systemd.special(7)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/syslog
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/syslog
 DefaultDependencies=no
 Before=sockets.target shutdown.target
 
@@ -37,4 +37,4 @@ ReceiveBuffer=8M
 # [Install]
 # Alias=syslog.service
 #
-# See http://www.freedesktop.org/wiki/Software/systemd/syslog for details.
+# See https://www.freedesktop.org/wiki/Software/systemd/syslog for details.
index a24fa51903c8aee0b2d20ec4d95eaffd300aa432..adaa60da87f20118096f7cb23efc18c15d1fcf62 100644 (file)
@@ -16,3 +16,4 @@ ConditionPathExists=!/run/plymouth/pid
 
 [Service]
 ExecStart=@rootbindir@/systemd-tty-ask-password-agent --watch --console
+SystemCallArchitectures=native
index 0eaa274794471e1c425358f943c48cc7deaae31a..be380023a7f5059b731d03e93f5a713b48d3a4c4 100644 (file)
@@ -13,3 +13,4 @@ After=systemd-user-sessions.service
 [Service]
 ExecStartPre=-@SYSTEMCTL@ stop systemd-ask-password-console.path systemd-ask-password-console.service systemd-ask-password-plymouth.path systemd-ask-password-plymouth.service
 ExecStart=@rootbindir@/systemd-tty-ask-password-agent --wall
+SystemCallArchitectures=native
index 588c8d629c37527d8ae2d1cbe7acf7055f85a5ce..18f2d2d605c6344446e04d8471b321b2f7278176 100644 (file)
@@ -19,6 +19,19 @@ Before=shutdown.target
 ExecStart=-@rootlibexecdir@/systemd-coredump
 Nice=9
 OOMScoreAdjust=500
-PrivateNetwork=yes
-ProtectSystem=full
 RuntimeMaxSec=5min
+PrivateTmp=yes
+PrivateDevices=yes
+PrivateNetwork=yes
+ProtectSystem=strict
+ProtectHome=yes
+ProtectControlGroups=yes
+ProtectKernelTunables=yes
+ProtectKernelModules=yes
+MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictNamespaces=yes
+RestrictAddressFamilies=AF_UNIX
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/var/lib/systemd/coredump
index edc5a1722ac1fea8b9d70e8b763b8a89c3dbca0b..d29e9ff81be325c849bbebddecdb02b6d5dec99c 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Hostname Service
 Documentation=man:systemd-hostnamed.service(8) man:hostname(5) man:machine-info(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/hostnamed
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/hostnamed
 
 [Service]
 ExecStart=@rootlibexecdir@/systemd-hostnamed
@@ -18,11 +18,15 @@ CapabilityBoundingSet=CAP_SYS_ADMIN
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ProtectSystem=yes
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/etc
index ac27c2bcbabdc32ee3a7da1ae009a7d8727a0957..58762055eb6a569c8e1187ac7fce9ed3c77fbdc8 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Virtual Machine and Container Download Service
 Documentation=man:systemd-importd.service(8)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/importd
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/importd
 
 [Service]
 ExecStart=@rootlibexecdir@/systemd-importd
@@ -19,5 +19,7 @@ CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_
 NoNewPrivileges=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=net
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
index 27e663c8dc4349669cc2ad2a6a6ccb0b59b0988b..5505309e9200a2b302f7420876e5c58d7e86d407 100644 (file)
@@ -11,5 +11,6 @@ Documentation=man:systemd-initctl.service(8)
 DefaultDependencies=no
 
 [Service]
-ExecStart=@rootlibexecdir@/systemd-initctl
 NotifyAccess=all
+ExecStart=@rootlibexecdir@/systemd-initctl
+SystemCallArchitectures=native
index efefaa4244d8c0e7fb04866383a31b90725babbb..99099967e7384c493666b34edcdeedc85f11723c 100644 (file)
@@ -18,13 +18,16 @@ SupplementaryGroups=systemd-journal
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ProtectSystem=full
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+SystemCallArchitectures=native
 
 # If there are many split upjournal files we need a lot of fds to
 # access them all and combine
index 753dd6c1588e3fac526c6e1a2dbe0ad7345fd416..5404bf1c035bb884e3ba60c52aea5d9f34dd604e 100644 (file)
@@ -18,13 +18,17 @@ WatchdogSec=3min
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ProtectSystem=full
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+SystemCallArchitectures=native
+ReadWritePaths=/var/log/journal/remote
 
 [Install]
 Also=systemd-journal-remote.socket
index d8fd24362029c98b8990fac527b2ab0fcfa3cec3..d00b9292117376d19f46c9c6e813d40ead4f4d74 100644 (file)
@@ -18,13 +18,17 @@ SupplementaryGroups=systemd-journal
 WatchdogSec=3min
 PrivateTmp=yes
 PrivateDevices=yes
-ProtectSystem=full
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+SystemCallArchitectures=native
+ReadWritePaths=/var/lib/systemd/journal-upload
 
 # If there are many split up journal files we need a lot of fds to
 # access them all and combine
index 712ce55483378680c43ae4f3bf9b752457189ef7..66b7c6a48e1e691b46989433776677aef251d9dc 100644 (file)
@@ -19,15 +19,16 @@ Sockets=systemd-journald.socket systemd-journald-dev-log.socket systemd-journald
 ExecStart=@rootlibexecdir@/systemd-journald
 Restart=always
 RestartSec=0
-NotifyAccess=all
 StandardOutput=null
 WatchdogSec=3min
 FileDescriptorStoreMax=1024
 CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
 
 # Increase the default a bit in order to allow many simultaneous
 # services being run since we keep one fd open per service. Also, when
index df829e11644f1a6025154a150cc47928238d8ac3..90a913881acdd5924e288760798398eeb6f7964f 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Locale Service
 Documentation=man:systemd-localed.service(8) man:locale.conf(5) man:vconsole.conf(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/localed
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/localed
 
 [Service]
 ExecStart=@rootlibexecdir@/systemd-localed
@@ -18,11 +18,15 @@ CapabilityBoundingSet=
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ProtectSystem=yes
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/etc
index 0b6de35733039b9784f66fc6f365a70fd6329f3f..bb4a23ec83a04beb27ac70577ede432fa3ef10ea 100644 (file)
@@ -8,8 +8,8 @@
 [Unit]
 Description=Login Service
 Documentation=man:systemd-logind.service(8) man:logind.conf(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/logind
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/multiseat
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/logind
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/multiseat
 Wants=user.slice
 After=nss-user-lookup.target user.slice
 
@@ -27,8 +27,11 @@ WatchdogSec=3min
 CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+FileDescriptorStoreMax=512
 
 # Increase the default a bit in order to allow many simultaneous
 # logins since we keep one fd open per session.
index 911ead79eeac146a14ce7d48b8fb698a8c427342..a4f86aa7c87de98b676c689ae711329963d2a150 100644 (file)
@@ -8,9 +8,10 @@
 [Unit]
 Description=Virtual Machine and Container Registration Service
 Documentation=man:systemd-machined.service(8)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/machined
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined
 Wants=machine.slice
 After=machine.slice
+RequiresMountsFor=/var/lib/machines
 
 [Service]
 ExecStart=@rootlibexecdir@/systemd-machined
@@ -20,7 +21,8 @@ CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_C
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
 
 # Note that machined cannot be placed in a mount namespace, since it
 # needs access to the host's mount namespace in order to implement the
index a9bad7aa8f28a4632c59dd5ec54f8cd6546e667b..a84e91906d96a9e4d2a01609b81130846bfaa8d0 100644 (file)
@@ -10,7 +10,7 @@ Description=Wait for Network to be Configured
 Documentation=man:systemd-networkd-wait-online.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
-Requisite=systemd-networkd.service
+Requires=systemd-networkd.service
 After=systemd-networkd.service
 Before=network-online.target
 
index d1cf3fc133ddd191b222c78d8fe4bdc7a60f77e6..15e6ad99d8a7e6bf191789e6f433b4b0e4742280 100644 (file)
@@ -28,14 +28,24 @@ RestartSec=0
 ExecStart=@rootlibexecdir@/systemd-networkd
 WatchdogSec=3min
 CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
-ProtectSystem=full
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/run/systemd
 
 [Install]
 WantedBy=multi-user.target
 Also=systemd-networkd.socket
+Alias=dbus-org.freedesktop.network1.service
+
+# We want to enable systemd-networkd-wait-online.service whenever this service
+# is enabled. systemd-networkd-wait-online.service has
+# WantedBy=network-online.target, so enabling it only has an effect if
+# network-online.target itself is enabled or pulled in by some other unit.
+Also=systemd-networkd-wait-online.service
index 8c0685aef50fef3dd9492f481e8aafc0369b9e07..5e80054a57ee0e98a500190c2984332353d6f670 100644 (file)
@@ -11,6 +11,7 @@ Documentation=man:systemd-nspawn(1)
 PartOf=machines.target
 Before=machines.target
 After=network.target systemd-resolved.service
+RequiresMountsFor=/var/lib/machines
 
 [Service]
 ExecStart=@bindir@/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=%i
index 5cb9bc3bc98d26c9019f11812aa63270b520fb41..6b1999aa516a8206f8c4321afa9638fd92fbed01 100644 (file)
@@ -10,7 +10,7 @@ Description=File System Quota Check
 Documentation=man:systemd-quotacheck.service(8)
 DefaultDependencies=no
 After=systemd-remount-fs.service
-Before=local-fs.target shutdown.target
+Before=remote-fs.target shutdown.target
 ConditionPathExists=@QUOTACHECK@
 
 [Service]
index 8d9daacaa58244bd28fd39f261ba098f7ef6bfe9..29d0674ab3a9fd62ebf3b11acaa183dd25378fa3 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Remount Root and Kernel File Systems
 Documentation=man:systemd-remount-fs.service(8)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 DefaultDependencies=no
 Conflicts=shutdown.target
 After=systemd-fsck-root.service
index d3b8f81601f5192766dee72fbf779e0b0641e817..931156a861778536f53a18b7eecaee824fb86cce 100644 (file)
@@ -8,10 +8,12 @@
 [Unit]
 Description=Network Name Resolution
 Documentation=man:systemd-resolved.service(8)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/resolved
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
 After=systemd-networkd.service network.target
+Before=network-online.target nss-lookup.target
+Wants=nss-lookup.target
 
 # On kdbus systems we pull in the busname explicitly, because it
 # carries policy that allows the daemon to acquire its name.
@@ -27,14 +29,17 @@ WatchdogSec=3min
 CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_NET_RAW CAP_NET_BIND_SERVICE
 PrivateTmp=yes
 PrivateDevices=yes
-ProtectSystem=full
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
-SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/run/systemd
 
 [Install]
 WantedBy=multi-user.target
index e8c4d5ed4ba5f5182ff6c0d0eedc715b63182b82..2b5f0744c9bfa7e7752bbaa896c5cf8c53136b0e 100644 (file)
@@ -8,7 +8,7 @@
 [Unit]
 Description=Time & Date Service
 Documentation=man:systemd-timedated.service(8) man:localtime(5)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/timedated
 
 [Service]
 ExecStart=@rootlibexecdir@/systemd-timedated
@@ -16,11 +16,15 @@ BusName=org.freedesktop.timedate1
 WatchdogSec=3min
 CapabilityBoundingSet=CAP_SYS_TIME
 PrivateTmp=yes
-ProtectSystem=yes
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
-SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/etc
index 9a6c6ea60ddab941c7ea86205a2103166cc79daf..8d328bb80a41326aa2470dff90841bd85b7c289c 100644 (file)
@@ -26,14 +26,18 @@ WatchdogSec=3min
 CapabilityBoundingSet=CAP_SYS_TIME CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
 PrivateTmp=yes
 PrivateDevices=yes
-ProtectSystem=full
+ProtectSystem=strict
 ProtectHome=yes
 ProtectControlGroups=yes
 ProtectKernelTunables=yes
+ProtectKernelModules=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
+RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
-SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
+SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
+SystemCallArchitectures=native
+ReadWritePaths=/var/lib/systemd
 
 [Install]
 WantedBy=sysinit.target
index 46d637883bdebf509f935d32e0cf69b071a7e019..fc037b5a5cd76d31adaf6bd267be9dfc4955b1da 100644 (file)
@@ -28,3 +28,4 @@ MountFlags=slave
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
+SystemCallArchitectures=native
index 0baecfd22f83120f7b281639306bb46393345e6e..3a333d22ecd47f72ed8496986c282c2c5fc063c8 100644 (file)
@@ -6,9 +6,9 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Temporary Directory
+Description=Temporary Directory (/tmp)
 Documentation=man:hier(7)
-Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
+Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
 ConditionPathIsSymbolicLink=!/tmp
 DefaultDependencies=no
 Conflicts=umount.target
diff --git a/units/user/meson.build b/units/user/meson.build
new file mode 100644 (file)
index 0000000..b507144
--- /dev/null
@@ -0,0 +1,33 @@
+units = [
+        'basic.target',
+        'bluetooth.target',
+        'default.target',
+        'exit.target',
+        'graphical-session-pre.target',
+        'graphical-session.target',
+        'paths.target',
+        'printer.target',
+        'shutdown.target',
+        'smartcard.target',
+        'sockets.target',
+        'sound.target',
+        'timers.target',
+]
+
+foreach file : units
+        install_data(file,
+                     install_dir : userunitdir)
+endforeach
+
+in_units = [
+        'systemd-exit.service',
+]
+
+foreach file : in_units
+        gen = configure_file(
+                input : file + '.in',
+                output : file,
+                configuration : substs)
+        install_data(gen,
+                     install_dir : userunitdir)
+endforeach